core: Implement various SPRs which read zero and ignore writes

This implements [U]SIER2, [U]SIER3, [U]MMCR3, HMER and HMEER as
SPRs which return zero when read, and ignore writes.  The zero value
is provided via the slow SPR read multiplexer.  To avoid increasing
the size of the selector from 4 bits to 5, the (implementation
specific) LOG_ADDR and LOG_DATA SPRs now share a single selector
value.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/443/head
Paul Mackerras 6 days ago
parent 1b6ee631bc
commit 8f7326a824

@ -82,6 +82,8 @@ package common is
constant SPR_NOOP1 : spr_num_t := 809;
constant SPR_NOOP2 : spr_num_t := 810;
constant SPR_NOOP3 : spr_num_t := 811;
constant SPR_HMER : spr_num_t := 336;
constant SPR_HMEER : spr_num_t := 337;

-- PMU registers
constant SPR_UPMC1 : spr_num_t := 771;
@ -97,6 +99,9 @@ package common is
constant SPR_USIER : spr_num_t := 768;
constant SPR_USIAR : spr_num_t := 780;
constant SPR_USDAR : spr_num_t := 781;
constant SPR_USIER2 : spr_num_t := 736;
constant SPR_USIER3 : spr_num_t := 737;
constant SPR_UMMCR3 : spr_num_t := 738;
constant SPR_PMC1 : spr_num_t := 787;
constant SPR_PMC2 : spr_num_t := 788;
constant SPR_PMC3 : spr_num_t := 789;
@ -110,6 +115,9 @@ package common is
constant SPR_SIER : spr_num_t := 784;
constant SPR_SIAR : spr_num_t := 796;
constant SPR_SDAR : spr_num_t := 797;
constant SPR_SIER2 : spr_num_t := 752;
constant SPR_SIER3 : spr_num_t := 753;
constant SPR_MMCR3 : spr_num_t := 754;

-- GPR indices in the register file (GPR only)
subtype gpr_index_t is std_ulogic_vector(4 downto 0);
@ -182,12 +190,12 @@ package common is
end record;
constant spr_id_init : spr_id := (sel => "0000", others => '0');

constant SPRSEL_TB : spr_selector := 4x"0";
constant SPRSEL_TBU : spr_selector := 4x"1";
constant SPRSEL_DEC : spr_selector := 4x"2";
constant SPRSEL_PVR : spr_selector := 4x"3";
constant SPRSEL_LOGA : spr_selector := 4x"4";
constant SPRSEL_LOGD : spr_selector := 4x"5";
constant SPRSEL_ZERO : spr_selector := 4x"0";
constant SPRSEL_TB : spr_selector := 4x"1";
constant SPRSEL_TBU : spr_selector := 4x"2";
constant SPRSEL_DEC : spr_selector := 4x"3";
constant SPRSEL_PVR : spr_selector := 4x"4";
constant SPRSEL_LOGR : spr_selector := 4x"5";
constant SPRSEL_CFAR : spr_selector := 4x"6";
constant SPRSEL_FSCR : spr_selector := 4x"7";
constant SPRSEL_LPCR : spr_selector := 4x"8";

@ -476,14 +476,17 @@ architecture behaviour of decode1 is
when SPR_PVR =>
i.sel := SPRSEL_PVR;
when 724 => -- LOG_ADDR SPR
i.sel := SPRSEL_LOGA;
i.sel := SPRSEL_LOGR;
when 725 => -- LOG_DATA SPR
i.sel := SPRSEL_LOGD;
i.sel := SPRSEL_LOGR;
i.ronly := '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 =>
i.ispmu := '1';
when SPR_USIER2 | SPR_USIER3 | SPR_UMMCR3 | SPR_SIER2 | SPR_SIER3 | SPR_MMCR3 =>
i.sel := SPRSEL_ZERO;
when SPR_CFAR =>
i.sel := SPRSEL_CFAR;
when SPR_XER =>
@ -515,6 +518,8 @@ architecture behaviour of decode1 is
i.ronly := '1';
when SPR_NOOP0 | SPR_NOOP1 | SPR_NOOP2 | SPR_NOOP3 =>
i.noop := '1';
when SPR_HMER | SPR_HMEER =>
i.sel := SPRSEL_ZERO;
when others =>
i.valid := '0';
end case;

@ -224,6 +224,7 @@ architecture behaviour of execute1 is
signal spr_result: std_ulogic_vector(63 downto 0);
signal next_nia : std_ulogic_vector(63 downto 0);
signal s1_sel : std_ulogic_vector(2 downto 0);
signal log_spr_data : std_ulogic_vector(63 downto 0);

signal carry_32 : std_ulogic;
signal carry_64 : std_ulogic;
@ -1401,8 +1402,10 @@ begin
slow_op := '1';
if e_in.spr_select.ispmu = '0' then
case e_in.spr_select.sel is
when SPRSEL_LOGD =>
v.se.inc_loga := '1';
when SPRSEL_LOGR =>
if e_in.insn(16) = '0' then
v.se.inc_loga := '1';
end if;
when others =>
end case;
v.res2_sel := "10";
@ -1465,7 +1468,7 @@ begin
v.se.write_xerlow := '1';
when SPRSEL_DEC =>
v.se.write_dec := '1';
when SPRSEL_LOGA =>
when SPRSEL_LOGR =>
v.se.write_loga := '1';
when SPRSEL_CFAR =>
v.se.write_cfar := '1';
@ -1955,13 +1958,14 @@ begin
end process;

-- Slow SPR read mux
log_spr_data <= (log_wr_addr & ex2.log_addr_spr) when ex1.insn(16) = '0'
else log_rd_data;
with ex1.spr_select.sel select spr_result <=
timebase when SPRSEL_TB,
32x"0" & timebase(63 downto 32) when SPRSEL_TBU,
assemble_dec(ctrl) when SPRSEL_DEC,
32x"0" & PVR_MICROWATT when SPRSEL_PVR,
log_wr_addr & ex2.log_addr_spr when SPRSEL_LOGA,
log_rd_data when SPRSEL_LOGD,
log_spr_data when SPRSEL_LOGR,
ctrl.cfar when SPRSEL_CFAR,
assemble_fscr(ctrl) when SPRSEL_FSCR,
assemble_lpcr(ctrl) when SPRSEL_LPCR,
@ -1971,7 +1975,8 @@ begin
56x"0" & std_ulogic_vector(to_unsigned(CPU_INDEX, 8)) when SPRSEL_PIR,
ctrl.ciabr when SPRSEL_CIABR,
assemble_dexcr(ctrl, ex1.insn) when SPRSEL_DEXCR,
assemble_xer(ex1.e.xerc, ctrl.xer_low) when others;
assemble_xer(ex1.e.xerc, ctrl.xer_low) when SPRSEL_XER,
64x"0" when others;

stage2_stall <= l_in.l2stall or fp_in.f2stall;


Loading…
Cancel
Save