constant MSR_FE1 : integer := (63 - 55); -- Floating Exception mode
constant MSR_IR : integer := (63 - 58); -- Instruction Relocation
constant MSR_DR : integer := (63 - 59); -- Data Relocation
+ constant MSR_PMM : integer := (63 - 61); -- Performance Monitor Mark
constant MSR_RI : integer := (63 - 62); -- Recoverable Interrupt
constant MSR_LE : integer := (63 - 63); -- Little Endian
constant SPR_PTCR : spr_num_t := 464;
constant SPR_PVR : spr_num_t := 287;
+ -- PMU registers
+ constant SPR_UPMC1 : spr_num_t := 771;
+ constant SPR_UPMC2 : spr_num_t := 772;
+ constant SPR_UPMC3 : spr_num_t := 773;
+ constant SPR_UPMC4 : spr_num_t := 774;
+ constant SPR_UPMC5 : spr_num_t := 775;
+ constant SPR_UPMC6 : spr_num_t := 776;
+ constant SPR_UMMCR0 : spr_num_t := 779;
+ constant SPR_UMMCR1 : spr_num_t := 782;
+ constant SPR_UMMCR2 : spr_num_t := 769;
+ constant SPR_UMMCRA : spr_num_t := 770;
+ constant SPR_USIER : spr_num_t := 768;
+ constant SPR_USIAR : spr_num_t := 780;
+ constant SPR_USDAR : spr_num_t := 781;
+ constant SPR_PMC1 : spr_num_t := 787;
+ constant SPR_PMC2 : spr_num_t := 788;
+ constant SPR_PMC3 : spr_num_t := 789;
+ constant SPR_PMC4 : spr_num_t := 790;
+ constant SPR_PMC5 : spr_num_t := 791;
+ constant SPR_PMC6 : spr_num_t := 792;
+ constant SPR_MMCR0 : spr_num_t := 795;
+ constant SPR_MMCR1 : spr_num_t := 798;
+ constant SPR_MMCR2 : spr_num_t := 785;
+ constant SPR_MMCRA : spr_num_t := 786;
+ constant SPR_SIER : spr_num_t := 784;
+ constant SPR_SIAR : spr_num_t := 796;
+ constant SPR_SDAR : spr_num_t := 797;
+
-- GPR indices in the register file (GPR only)
subtype gpr_index_t is std_ulogic_vector(4 downto 0);
is_extended => '0', is_modulus => '0',
neg_result => '0', others => (others => '0'));
+ type PMUEventType is record
+ no_instr_avail : std_ulogic;
+ dispatch : std_ulogic;
+ ext_interrupt : std_ulogic;
+ instr_complete : std_ulogic;
+ fp_complete : std_ulogic;
+ ld_complete : std_ulogic;
+ st_complete : std_ulogic;
+ br_taken_complete : std_ulogic;
+ br_mispredict : std_ulogic;
+ ipref_discard : std_ulogic;
+ itlb_miss : std_ulogic;
+ itlb_miss_resolved : std_ulogic;
+ icache_miss : std_ulogic;
+ dc_miss_resolved : std_ulogic;
+ dc_ld_miss_resolved : std_ulogic;
+ dc_store_miss : std_ulogic;
+ dtlb_miss_resolved : std_ulogic;
+ ld_miss_nocache : std_ulogic;
+ ld_fill_nocache : std_ulogic;
+ end record;
+ constant PMUEventInit : PMUEventType := (others => '0');
+
+ type Execute1ToPMUType is record
+ mfspr : std_ulogic;
+ mtspr : std_ulogic;
+ spr_num : std_ulogic_vector(4 downto 0);
+ spr_val : std_ulogic_vector(63 downto 0);
+ tbbits : std_ulogic_vector(3 downto 0); -- event bits from timebase
+ pmm_msr : std_ulogic; -- PMM bit from MSR
+ pr_msr : std_ulogic; -- PR bit from MSR
+ run : std_ulogic;
+ nia : std_ulogic_vector(63 downto 0);
+ addr : std_ulogic_vector(63 downto 0);
+ addr_v : std_ulogic;
+ occur : PMUEventType;
+ end record;
+
+ type PMUToExecute1Type is record
+ spr_val : std_ulogic_vector(63 downto 0);
+ intr : std_ulogic;
+ end record;
+
type Decode2ToRegisterFileType is record
read1_enable : std_ulogic;
read1_reg : gspr_index_t;
write_cr_mask => (others => '0'),
write_cr_data => (others => '0'));
+ type WritebackEventType is record
+ instr_complete : std_ulogic;
+ end record;
+
end common;
package body common is
icache_inval : out std_ulogic;
terminate_out : out std_ulogic;
+ -- PMU event buses
+ wb_events : in WritebackEventType;
+
log_out : out std_ulogic_vector(14 downto 0);
log_rd_addr : out std_ulogic_vector(31 downto 0);
log_rd_data : in std_ulogic_vector(63 downto 0);
signal random_cond : std_ulogic_vector(63 downto 0);
signal random_err : std_ulogic;
+ -- PMU signals
+ signal x_to_pmu : Execute1ToPMUType;
+ signal pmu_to_x : PMUToExecute1Type;
+
-- signals for logging
signal exception_log : std_ulogic;
signal irq_valid_log : std_ulogic;
err => random_err
);
+ pmu_0: entity work.pmu
+ port map (
+ clk => clk,
+ rst => rst,
+ p_in => x_to_pmu,
+ p_out => pmu_to_x
+ );
+
dbg_msr_out <= ctrl.msr;
log_rd_addr <= r.log_addr_spr;
c_in <= e_in.read_data3;
cr_in <= e_in.cr;
+ x_to_pmu.occur <= (instr_complete => wb_events.instr_complete, others => '0');
+ x_to_pmu.nia <= current.nia;
+ x_to_pmu.addr <= (others => '0');
+ x_to_pmu.addr_v <= '0';
+ x_to_pmu.spr_num <= e_in.insn(20 downto 16);
+ x_to_pmu.spr_val <= c_in;
+ x_to_pmu.run <= '1';
+
-- XER forwarding. To avoid having to track XER hazards, we use
-- the previously latched value. Since the XER common bits
-- (SO, OV[32] and CA[32]) are only modified by instructions that are
v.cntz_in_progress := '0';
v.mul_finish := '0';
+ x_to_pmu.mfspr <= '0';
+ x_to_pmu.mtspr <= '0';
+ x_to_pmu.tbbits(3) <= ctrl.tb(63 - 47);
+ x_to_pmu.tbbits(2) <= ctrl.tb(63 - 51);
+ x_to_pmu.tbbits(1) <= ctrl.tb(63 - 55);
+ x_to_pmu.tbbits(0) <= ctrl.tb(63 - 63);
+ x_to_pmu.pmm_msr <= ctrl.msr(MSR_PMM);
+ x_to_pmu.pr_msr <= ctrl.msr(MSR_PR);
+
spr_result <= (others => '0');
spr_val := (others => '0');
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
- irq_valid := ctrl.msr(MSR_EE) and (ctrl.dec(63) or ext_irq_in);
+ irq_valid := ctrl.msr(MSR_EE) and (pmu_to_x.intr or ctrl.dec(63) or ext_irq_in);
v.terminate := '0';
icache_inval <= '0';
elsif irq_valid = '1' then
-- Don't deliver the interrupt until we have a valid instruction
-- coming in, so we have a valid NIA to put in SRR0.
- if ctrl.dec(63) = '1' then
+ if pmu_to_x.intr = '1' then
+ v.e.intr_vec := 16#f00#;
+ report "IRQ valid: PMU";
+ elsif ctrl.dec(63) = '1' then
v.e.intr_vec := 16#900#;
report "IRQ valid: DEC";
elsif ext_irq_in = '1' then
when 725 => -- LOG_DATA SPR
spr_val := log_rd_data;
v.log_addr_spr := std_ulogic_vector(unsigned(r.log_addr_spr) + 1);
+ when SPR_UPMC1 | SPR_UPMC2 | SPR_UPMC3 | SPR_UPMC4 | SPR_UPMC5 | SPR_UPMC6 |
+ SPR_UMMCR0 | SPR_UMMCR1 | SPR_UMMCR2 | SPR_UMMCRA | SPR_USIER | SPR_USIAR | SPR_USDAR |
+ SPR_PMC1 | SPR_PMC2 | SPR_PMC3 | SPR_PMC4 | SPR_PMC5 | SPR_PMC6 |
+ SPR_MMCR0 | SPR_MMCR1 | SPR_MMCR2 | SPR_MMCRA | SPR_SIER | SPR_SIAR | SPR_SDAR =>
+ x_to_pmu.mfspr <= '1';
+ spr_val := pmu_to_x.spr_val;
when others =>
-- mfspr from unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
ctrl_tmp.dec <= c_in;
when 724 => -- LOG_ADDR SPR
v.log_addr_spr := c_in(31 downto 0);
+ when SPR_UPMC1 | SPR_UPMC2 | SPR_UPMC3 | SPR_UPMC4 | SPR_UPMC5 | SPR_UPMC6 |
+ SPR_UMMCR0 | SPR_UMMCR2 | SPR_UMMCRA |
+ SPR_PMC1 | SPR_PMC2 | SPR_PMC3 | SPR_PMC4 | SPR_PMC5 | SPR_PMC6 |
+ SPR_MMCR0 | SPR_MMCR1 | SPR_MMCR2 | SPR_MMCRA | SPR_SIER | SPR_SIAR | SPR_SDAR =>
+ x_to_pmu.mtspr <= '1';
when others =>
-- mtspr to unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
--- /dev/null
+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;