forked from cores/microwatt
core: Add a basic performance monitor unit (PMU) implementation
This is the start of an implementation of a PMU according to PowerISA v3.0B. Things not implemented yet include most architected events, the BHRB, event-based branches, thresholding, MMCR0[TBCC] field, etc. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>dcache-nc-fix
parent
f40842d9b2
commit
a7873b45f7
@ -0,0 +1,354 @@
|
||||
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;
|
||||
tbbit := tbdiff(3 - to_integer(unsigned(mmcr0(MMCR0_TBSEL + 1 downto MMCR0_TBSEL))));
|
||||
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) or 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.ld_fill_nocache;
|
||||
when others =>
|
||||
end case;
|
||||
|
||||
case mmcr1(7 downto 0) is
|
||||
when x"f0" =>
|
||||
inc(4) := p_in.occur.dc_store_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;
|
||||
|
||||
if mmcr0(MMCR0_PMCC + 1 downto MMCR0_PMCC) /= "11" then
|
||||
inc(5) := (mmcr0(MMCR0_CC56RUN) or p_in.run) and p_in.occur.instr_complete;
|
||||
inc(6) := mmcr0(MMCR0_CC56RUN) or p_in.run;
|
||||
end if;
|
||||
|
||||
-- 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;
|
||||
|
||||
doinc <= inc;
|
||||
doevent <= event;
|
||||
doalert <= event and mmcr0(MMCR0_PMAE);
|
||||
end process;
|
||||
|
||||
end architecture behaviour;
|
Loading…
Reference in New Issue