


library ieee;




use ieee.std_logic_1164.all;




use ieee.numeric_std.all;








library work;




use work.common.all;




use work.decode_types.all;








entity pmu is




port (




clk : in std_ulogic;




rst : in std_ulogic;




p_in : in Execute1ToPMUType;




p_out : out PMUToExecute1Type




);




end entity pmu;








architecture behaviour of pmu is








 MMCR0 bit numbers




constant MMCR0_FC : integer := 63  32;




constant MMCR0_FCS : integer := 63  33;




constant MMCR0_FCP : integer := 63  34;




constant MMCR0_FCM1 : integer := 63  35;




constant MMCR0_FCM0 : integer := 63  36;




constant MMCR0_PMAE : integer := 63  37;




constant MMCR0_FCECE : integer := 63  38;




constant MMCR0_TBSEL : integer := 63  40;




constant MMCR0_TBEE : integer := 63  41;




constant MMCR0_BHRBA : integer := 63  42;




constant MMCR0_EBE : integer := 63  43;




constant MMCR0_PMCC : integer := 63  45;




constant MMCR0_PMC1CE : integer := 63  48;




constant MMCR0_PMCjCE : integer := 63  49;




constant MMCR0_TRIGGER : integer := 63  50;




constant MMCR0_FCPC : integer := 63  51;




constant MMCR0_PMAQ : integer := 63  52;




constant MMCR0_PMCCEXT : integer := 63  54;




constant MMCR0_CC56RUN : integer := 63  55;




constant MMCR0_PMAO : integer := 63  56;




constant MMCR0_FC1_4 : integer := 63  58;




constant MMCR0_FC5_6 : integer := 63  59;




constant MMCR0_FC1_4W : integer := 63  62;








 MMCR2 bit numbers




constant MMCR2_FC0S : integer := 63  0;




constant MMCR2_FC0P0 : integer := 63  1;




constant MMCR2_FC0M1 : integer := 63  3;




constant MMCR2_FC0M0 : integer := 63  4;




constant MMCR2_FC0WAIT : integer := 63  5;




constant MMCR2_FC1S : integer := 54  0;




constant MMCR2_FC1P0 : integer := 54  1;




constant MMCR2_FC1M1 : integer := 54  3;




constant MMCR2_FC1M0 : integer := 54  4;




constant MMCR2_FC1WAIT : integer := 54  5;




constant MMCR2_FC2S : integer := 45  0;




constant MMCR2_FC2P0 : integer := 45  1;




constant MMCR2_FC2M1 : integer := 45  3;




constant MMCR2_FC2M0 : integer := 45  4;




constant MMCR2_FC2WAIT : integer := 45  5;




constant MMCR2_FC3S : integer := 36  0;




constant MMCR2_FC3P0 : integer := 36  1;




constant MMCR2_FC3M1 : integer := 36  3;




constant MMCR2_FC3M0 : integer := 36  4;




constant MMCR2_FC3WAIT : integer := 36  5;




constant MMCR2_FC4S : integer := 27  0;




constant MMCR2_FC4P0 : integer := 27  1;




constant MMCR2_FC4M1 : integer := 27  3;




constant MMCR2_FC4M0 : integer := 27  4;




constant MMCR2_FC4WAIT : integer := 27  5;




constant MMCR2_FC5S : integer := 18  0;




constant MMCR2_FC5P0 : integer := 18  1;




constant MMCR2_FC5M1 : integer := 18  3;




constant MMCR2_FC5M0 : integer := 18  4;




constant MMCR2_FC5WAIT : integer := 18  5;




constant MMCR2_FC6S : integer := 9  0;




constant MMCR2_FC6P0 : integer := 9  1;




constant MMCR2_FC6M1 : integer := 9  3;




constant MMCR2_FC6M0 : integer := 9  4;




constant MMCR2_FC6WAIT : integer := 9  5;








 MMCRA bit numbers




constant MMCRA_TECX : integer := 63  36;




constant MMCRA_TECM : integer := 63  44;




constant MMCRA_TECE : integer := 63  47;




constant MMCRA_TS : integer := 63  51;




constant MMCRA_TE : integer := 63  55;




constant MMCRA_ES : integer := 63  59;




constant MMCRA_SM : integer := 63  62;




constant MMCRA_SE : integer := 63  63;








 SIER bit numbers




constant SIER_SAMPPR : integer := 63  38;




constant SIER_SIARV : integer := 63  41;




constant SIER_SDARV : integer := 63  42;




constant SIER_TE : integer := 63  43;




constant SIER_SITYPE : integer := 63  48;




constant SIER_SICACHE : integer := 63  51;




constant SIER_SITAKBR : integer := 63  52;




constant SIER_SIMISPR : integer := 63  53;




constant SIER_SIMISPRI : integer := 63  55;




constant SIER_SIDERAT : integer := 63  56;




constant SIER_SIDAXL : integer := 63  59;




constant SIER_SIDSAI : integer := 63  62;




constant SIER_SICMPL : integer := 63  63;








type pmc_array is array(1 to 6) of std_ulogic_vector(31 downto 0);




signal pmcs : pmc_array;




signal mmcr0 : std_ulogic_vector(31 downto 0);




signal mmcr1 : std_ulogic_vector(63 downto 0);




signal mmcr2 : std_ulogic_vector(63 downto 0);




signal mmcra : std_ulogic_vector(63 downto 0);




signal siar : std_ulogic_vector(63 downto 0);




signal sdar : std_ulogic_vector(63 downto 0);




signal sier : std_ulogic_vector(63 downto 0);








signal doinc : std_ulogic_vector(1 to 6);




signal doalert : std_ulogic;




signal doevent : std_ulogic;








signal prev_tb : std_ulogic_vector(3 downto 0);








begin




 mfspr mux




with p_in.spr_num(3 downto 0) select p_out.spr_val <=




32x"0" & pmcs(1) when "0011",




32x"0" & pmcs(2) when "0100",




32x"0" & pmcs(3) when "0101",




32x"0" & pmcs(4) when "0110",




32x"0" & pmcs(5) when "0111",




32x"0" & pmcs(6) when "1000",




32x"0" & mmcr0 when "1011",




mmcr1 when "1110",




mmcr2 when "0001",




mmcra when "0010",




siar when "1100",




sdar when "1101",




sier when "0000",




64x"0" when others;








p_out.intr <= mmcr0(MMCR0_PMAO);








pmu_1: process(clk)




begin




if rising_edge(clk) then




if rst = '1' then




mmcr0 <= 32x"80000000";




else




for i in 1 to 6 loop




if p_in.mtspr = '1' and to_integer(unsigned(p_in.spr_num(3 downto 0))) = i + 2 then




pmcs(i) <= p_in.spr_val(31 downto 0);




elsif doinc(i) = '1' then




pmcs(i) <= std_ulogic_vector(unsigned(pmcs(i)) + 1);




end if;




end loop;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1011" then




mmcr0 <= p_in.spr_val(31 downto 0);




mmcr0(MMCR0_BHRBA) <= '0';  no BHRB yet




mmcr0(MMCR0_EBE) <= '0';  no EBBs yet




else




if doalert = '1' then




mmcr0(MMCR0_PMAE) <= '0';




mmcr0(MMCR0_PMAO) <= '1';




mmcr0(MMCR0_PMAQ) <= '0';




end if;




if doevent = '1' and mmcr0(MMCR0_FCECE) = '1' and mmcr0(MMCR0_TRIGGER) = '0' then




mmcr0(MMCR0_FC) <= '1';




end if;




if (doevent = '1' or pmcs(1)(31) = '1') and mmcr0(MMCR0_TRIGGER) = '1' then




mmcr0(MMCR0_TRIGGER) <= '0';




end if;




end if;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1110" then




mmcr1 <= p_in.spr_val;




end if;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0001" then




mmcr2 <= p_in.spr_val;




end if;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0010" then




mmcra <= p_in.spr_val;




 we don't support random sampling yet




mmcra(MMCRA_SE) <= '0';




end if;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1100" then




siar <= p_in.spr_val;




elsif doalert = '1' then




siar <= p_in.nia;




end if;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1101" then




sdar <= p_in.spr_val;




elsif doalert = '1' then




sdar <= p_in.addr;




end if;




if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0000" then




sier <= p_in.spr_val;




elsif doalert = '1' then




sier <= (others => '0');




sier(SIER_SAMPPR) <= p_in.pr_msr;




sier(SIER_SIARV) <= '1';




sier(SIER_SDARV) <= p_in.addr_v;




end if;




end if;




prev_tb <= p_in.tbbits;




end if;




end process;








pmu_2: process(all)




variable tbdiff : std_ulogic_vector(3 downto 0);




variable tbbit : std_ulogic;




variable freeze : std_ulogic;




variable event : std_ulogic;




variable j : integer;




variable inc : std_ulogic_vector(1 to 6);




variable fc14wo : std_ulogic;




begin




event := '0';








 Check for timebase events




tbdiff := p_in.tbbits and not prev_tb;




if is_X(mmcr0) then




tbbit := 'X';




else




tbbit := tbdiff(3  to_integer(unsigned(mmcr0(MMCR0_TBSEL + 1 downto MMCR0_TBSEL))));




end if;




if tbbit = '1' and mmcr0(MMCR0_TBEE) = '1' then




event := '1';




end if;








 Check for counter negative events




if mmcr0(MMCR0_PMC1CE) = '1' and pmcs(1)(31) = '1' then




event := '1';




end if;




if mmcr0(MMCR0_PMCjCE) = '1' and




(pmcs(2)(31) or pmcs(3)(31) or pmcs(4)(31)) = '1' then




event := '1';




end if;




if mmcr0(MMCR0_PMCjCE) = '1' and




mmcr0(MMCR0_PMCC + 1 downto MMCR0_PMCC) /= "11" and




(pmcs(5)(31) or pmcs(6)(31)) = '1' then




event := '1';




end if;








 Event selection




inc := (others => '0');




fc14wo := '0';




case mmcr1(31 downto 24) is




when x"f0" =>




inc(1) := '1';




fc14wo := '1';  override MMCR0[FC1_4WAIT]




when x"f2"  x"fe" =>




inc(1) := p_in.occur.instr_complete;




when x"f4" =>




inc(1) := p_in.occur.fp_complete;




when x"f6" =>




inc(1) := p_in.occur.itlb_miss;




when x"f8" =>




inc(1) := p_in.occur.no_instr_avail;




when x"fa" =>




inc(1) := p_in.run;




when x"fc" =>




inc(1) := p_in.occur.ld_complete;




when others =>




end case;








case mmcr1(23 downto 16) is




when x"f0" =>




inc(2) := p_in.occur.st_complete;




when x"f2" =>




inc(2) := p_in.occur.dispatch;




when x"f4" =>




inc(2) := p_in.run;




when x"f6" =>




inc(2) := p_in.occur.dtlb_miss_resolved;




when x"f8" =>




inc(2) := p_in.occur.ext_interrupt;




when x"fa" =>




inc(2) := p_in.occur.br_taken_complete;




when x"fc" =>




inc(2) := p_in.occur.icache_miss;




when x"fe" =>




inc(2) := p_in.occur.dc_miss_resolved;




when others =>




end case;








case mmcr1(15 downto 8) is




when x"f0" =>




inc(3) := p_in.occur.dc_store_miss;




when x"f2" =>




inc(3) := p_in.occur.dispatch;




when x"f4" =>




inc(3) := p_in.occur.instr_complete and p_in.run;




when x"f6" =>




inc(3) := p_in.occur.dc_ld_miss_resolved;




when x"f8" =>




inc(3) := tbbit;




when x"fe" =>




inc(3) := p_in.occur.dtlb_miss;




when others =>




end case;








case mmcr1(7 downto 0) is




when x"f0" =>




inc(4) := p_in.occur.dc_load_miss;




when x"f2" =>




inc(4) := p_in.occur.dispatch;




when x"f4" =>




inc(4) := p_in.run;




when x"f6" =>




inc(4) := p_in.occur.br_mispredict;




when x"f8" =>




inc(4) := p_in.occur.ipref_discard;




when x"fa" =>




inc(4) := p_in.occur.instr_complete and p_in.run;




when x"fc" =>




inc(4) := p_in.occur.itlb_miss_resolved;




when x"fe" =>




inc(4) := p_in.occur.ld_miss_nocache;




when others =>




end case;








inc(5) := (mmcr0(MMCR0_CC56RUN) or p_in.run) and p_in.occur.instr_complete;




inc(6) := mmcr0(MMCR0_CC56RUN) or p_in.run;








 Evaluate freeze conditions




freeze := mmcr0(MMCR0_FC) or




(mmcr0(MMCR0_FCS) and not p_in.pr_msr) or




(mmcr0(MMCR0_FCP) and not mmcr0(MMCR0_FCPC) and p_in.pr_msr) or




(not mmcr0(MMCR0_FCP) and mmcr0(MMCR0_FCPC) and p_in.pr_msr) or




(mmcr0(MMCR0_FCM1) and p_in.pmm_msr) or




(mmcr0(MMCR0_FCM0) and not p_in.pmm_msr);








if freeze = '1' or mmcr0(MMCR0_FC1_4) = '1' or




(mmcr0(MMCR0_FC1_4W) = '1' and p_in.run = '0' and fc14wo = '0') then




inc(1) := '0';




end if;




if freeze = '1' or mmcr0(MMCR0_FC1_4) = '1' or




(mmcr0(MMCR0_FC1_4W) = '1' and p_in.run = '0') then




inc(2 to 4) := "000";




end if;




if freeze = '1' or mmcr0(MMCR0_FC5_6) = '1' then




inc(5 to 6) := "00";




end if;




if mmcr0(MMCR0_TRIGGER) = '1' then




inc(2 to 6) := "00000";




end if;




for i in 1 to 6 loop




j := (i  1) * 9;




if (mmcr2(MMCR2_FC0S  j) = '1' and p_in.pr_msr = '0') or




(mmcr2(MMCR2_FC0P0  j) = '1' and p_in.pr_msr = '1') or




(mmcr2(MMCR2_FC0M1  j) = '1' and p_in.pmm_msr = '1') or




(mmcr2(MMCR2_FC0M1  j) = '1' and p_in.pmm_msr = '1') then




inc(i) := '0';




end if;




end loop;








 When MMCR0[PMCC] = "11", PMC5 and PMC6 are not controlled by the




 MMCRs and don't generate events, but do continue to count run




 instructions and run cycles.




if mmcr0(MMCR0_PMCC + 1 downto MMCR0_PMCC) = "11" then




inc(5) := p_in.run and p_in.occur.instr_complete;




inc(6) := p_in.run;




end if;








doinc <= inc;




doevent <= event;




doalert <= event and mmcr0(MMCR0_PMAE);




end process;








end architecture behaviour;
