From 8f7326a8246ec92eff97f6f10c27babff3b1c1e0 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 10 Apr 2025 16:22:09 +1000 Subject: [PATCH] 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 --- common.vhdl | 20 ++++++++++++++------ decode1.vhdl | 9 +++++++-- execute1.vhdl | 17 +++++++++++------ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/common.vhdl b/common.vhdl index 4843c3d..30ff8ef 100644 --- a/common.vhdl +++ b/common.vhdl @@ -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"; diff --git a/decode1.vhdl b/decode1.vhdl index c684d72..3fcf697 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -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; diff --git a/execute1.vhdl b/execute1.vhdl index fcf1df7..a0961f7 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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;