From 63fff5e05c25bdc067a4cb6493dd8f3c37f151c8 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 27 Mar 2025 17:12:11 +1100 Subject: [PATCH 1/3] core: Remove HFSCR and Hypervisor Facility Unavailable interrupt logic HFSCR is associated with the LPAR (Logical Partitioning) feature, which is not required for SFFS designs, so remove it and the associated logic. Signed-off-by: Paul Mackerras --- common.vhdl | 15 +------ core_debug.vhdl | 3 -- decode1.vhdl | 2 - execute1.vhdl | 82 ++++++------------------------------- scripts/mw_debug/mw_debug.c | 2 +- 5 files changed, 15 insertions(+), 89 deletions(-) diff --git a/common.vhdl b/common.vhdl index 0207fe1..b92b87a 100644 --- a/common.vhdl +++ b/common.vhdl @@ -189,7 +189,6 @@ package common is constant SPRSEL_LOGD : spr_selector := 4x"5"; constant SPRSEL_CFAR : spr_selector := 4x"6"; constant SPRSEL_FSCR : spr_selector := 4x"7"; - constant SPRSEL_HFSCR : spr_selector := 4x"8"; constant SPRSEL_HEIR : spr_selector := 4x"9"; constant SPRSEL_CTRL : spr_selector := 4x"a"; constant SPRSEL_DSCR : spr_selector := 4x"b"; @@ -198,17 +197,11 @@ package common is constant SPRSEL_DEXCR : spr_selector := 4x"e"; constant SPRSEL_XER : spr_selector := 4x"f"; - -- FSCR and HFSCR bit numbers + -- FSCR bit numbers constant FSCR_PREFIX : integer := 63 - 50; constant FSCR_SCV : integer := 63 - 51; constant FSCR_TAR : integer := 63 - 55; constant FSCR_DSCR : integer := 63 - 61; - constant HFSCR_PREFIX : integer := 63 - 50; - constant HFSCR_MSG : integer := 63 - 53; - constant HFSCR_TAR : integer := 63 - 55; - constant HFSCR_PMUSPR : integer := 63 - 60; - constant HFSCR_DSCR : integer := 63 - 61; - constant HFSCR_FP : integer := 63 - 63; -- FPSCR bit numbers constant FPSCR_FX : integer := 63 - 32; @@ -301,11 +294,6 @@ package common is fscr_scv: std_ulogic; fscr_tar: std_ulogic; fscr_dscr: std_ulogic; - hfscr_ic: std_ulogic_vector(3 downto 0); - hfscr_pref: std_ulogic; - hfscr_tar: std_ulogic; - hfscr_dscr: std_ulogic; - hfscr_fp: std_ulogic; heir: std_ulogic_vector(63 downto 0); dscr: std_ulogic_vector(24 downto 0); ciabr: std_ulogic_vector(63 downto 0); @@ -317,7 +305,6 @@ package common is constant ctrl_t_init : ctrl_t := (wait_state => '0', run => '1', xer_low => 18x"0", fscr_ic => x"0", fscr_pref => '1', fscr_scv => '1', fscr_tar => '1', fscr_dscr => '1', - hfscr_ic => x"0", hfscr_pref => '1', hfscr_tar => '1', hfscr_dscr => '1', hfscr_fp => '1', dscr => (others => '0'), dexcr_pnh => aspect_bits_init, dexcr_pro => aspect_bits_init, hdexcr_hyp => aspect_bits_init, hdexcr_enf => aspect_bits_init, diff --git a/core_debug.vhdl b/core_debug.vhdl index 67b41fb..e839832 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -327,9 +327,6 @@ begin when 5x"0e" => isram := '0'; sel := SPRSEL_FSCR; - when 5x"0f" => - isram := '0'; - sel := SPRSEL_HFSCR; when 5x"10" => isram := '0'; sel := SPRSEL_HEIR; diff --git a/decode1.vhdl b/decode1.vhdl index 2fb1ad4..c3f215d 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -490,8 +490,6 @@ architecture behaviour of decode1 is i.sel := SPRSEL_XER; when SPR_FSCR => i.sel := SPRSEL_FSCR; - when SPR_HFSCR => - i.sel := SPRSEL_HFSCR; when SPR_HEIR => i.sel := SPRSEL_HEIR; when SPR_CTRL => diff --git a/execute1.vhdl b/execute1.vhdl index ee38863..cea2f37 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -92,8 +92,6 @@ architecture behaviour of execute1 is mult_32s : std_ulogic; write_fscr : std_ulogic; write_ic : std_ulogic; - write_hfscr : std_ulogic; - write_hic : std_ulogic; write_heir : std_ulogic; set_heir : std_ulogic; write_ctrl : std_ulogic; @@ -410,18 +408,6 @@ architecture behaviour of execute1 is return ret; end; - function assemble_hfscr(c: ctrl_t) return std_ulogic_vector is - variable ret : std_ulogic_vector(63 downto 0); - begin - ret := (others => '0'); - ret(59 downto 56) := c.hfscr_ic; - ret(HFSCR_PREFIX) := c.hfscr_pref; - ret(HFSCR_TAR) := c.hfscr_tar; - ret(HFSCR_DSCR) := c.hfscr_dscr; - ret(HFSCR_FP) := c.hfscr_fp; - return ret; - end; - function assemble_ctrl(c: ctrl_t; msrpr: std_ulogic) return std_ulogic_vector is variable ret : std_ulogic_vector(63 downto 0); begin @@ -796,8 +782,6 @@ begin case dbg_spr_addr(3 downto 0) is when SPRSEL_FSCR => dbg_spr_data <= assemble_fscr(ctrl); - when SPRSEL_HFSCR => - dbg_spr_data <= assemble_hfscr(ctrl); when SPRSEL_HEIR => dbg_spr_data <= ctrl.heir; when SPRSEL_CFAR => @@ -1457,8 +1441,6 @@ begin v.se.write_cfar := '1'; when SPRSEL_FSCR => v.se.write_fscr := '1'; - when SPRSEL_HFSCR => - v.se.write_hfscr := '1'; when SPRSEL_HEIR => v.se.write_heir := '1'; when SPRSEL_CTRL => @@ -1548,22 +1530,15 @@ begin end case; if ex1.msr(MSR_PR) = '1' and e_in.prefixed = '1' and - (ctrl.hfscr_pref = '0' or ctrl.fscr_pref = '0') then - -- [Hypervisor] facility unavailable for prefixed instructions, + ctrl.fscr_pref = '0' then + -- Facility unavailable for prefixed instructions, -- which has higher priority than the alignment interrupt for -- misaligned prefixed instructions, which has higher priority than - -- other [hypervisor] facility unavailable interrupts (e.g. for - -- plfs with HFSCR[FP] = 0). + -- other facility unavailable interrupts. v.exception := '1'; v.ic := x"b"; - if ctrl.hfscr_pref = '0' then - v.e.hv_intr := '1'; - v.e.intr_vec := 16#f80#; - v.se.write_hic := '1'; - else - v.e.intr_vec := 16#f60#; - v.se.write_ic := '1'; - end if; + v.e.intr_vec := 16#f60#; + v.se.write_ic := '1'; elsif misaligned = '1' then -- generate an alignment interrupt @@ -1608,41 +1583,20 @@ begin v.se.write_ic := '1'; elsif ex1.msr(MSR_PR) = '1' and e_in.uses_tar = '1' and - (ctrl.hfscr_tar = '0' or ctrl.fscr_tar = '0') then - -- [Hypervisor] facility unavailable for TAR access + ctrl.fscr_tar = '0' then + -- Facility unavailable for TAR access v.exception := '1'; v.ic := x"8"; - if ctrl.hfscr_tar = '0' then - v.e.hv_intr := '1'; - v.e.intr_vec := 16#f80#; - v.se.write_hic := '1'; - else - v.e.intr_vec := 16#f60#; - v.se.write_ic := '1'; - end if; + v.e.intr_vec := 16#f60#; + v.se.write_ic := '1'; elsif ex1.msr(MSR_PR) = '1' and e_in.uses_dscr = '1' and - (ctrl.hfscr_dscr = '0' or ctrl.fscr_dscr = '0') then - -- [Hypervisor] facility unavailable for DSCR access + ctrl.fscr_dscr = '0' then + -- Facility unavailable for DSCR access v.exception := '1'; v.ic := x"2"; - if ctrl.hfscr_dscr = '0' then - v.e.hv_intr := '1'; - v.e.intr_vec := 16#f80#; - v.se.write_hic := '1'; - else - v.e.intr_vec := 16#f60#; - v.se.write_ic := '1'; - end if; - - elsif HAS_FPU and ex1.msr(MSR_PR) = '1' and e_in.fac = FPU and - ctrl.hfscr_fp = '0' then - -- Hypervisor facility unavailable for FP instructions - v.exception := '1'; - v.ic := x"0"; - v.e.hv_intr := '1'; - v.e.intr_vec := 16#f80#; - v.se.write_hic := '1'; + v.e.intr_vec := 16#f60#; + v.se.write_ic := '1'; elsif HAS_FPU and ex1.msr(MSR_FP) = '0' and e_in.fac = FPU then -- generate a floating-point unavailable interrupt @@ -1977,7 +1931,6 @@ begin log_rd_data when SPRSEL_LOGD, ctrl.cfar when SPRSEL_CFAR, assemble_fscr(ctrl) when SPRSEL_FSCR, - assemble_hfscr(ctrl) when SPRSEL_HFSCR, ctrl.heir when SPRSEL_HEIR, assemble_ctrl(ctrl, ex1.msr(MSR_PR)) when SPRSEL_CTRL, 39x"0" & ctrl.dscr when SPRSEL_DSCR, @@ -2127,15 +2080,6 @@ begin v.log_addr_spr := std_ulogic_vector(unsigned(ex2.log_addr_spr) + 1); end if; x_to_pmu.mtspr <= ex1.se.write_pmuspr; - if ex1.se.write_hfscr = '1' then - ctrl_tmp.hfscr_ic <= ex1.e.write_data(59 downto 56); - ctrl_tmp.hfscr_pref <= ex1.e.write_data(HFSCR_PREFIX); - ctrl_tmp.hfscr_tar <= ex1.e.write_data(HFSCR_TAR); - ctrl_tmp.hfscr_dscr <= ex1.e.write_data(HFSCR_DSCR); - ctrl_tmp.hfscr_fp <= ex1.e.write_data(HFSCR_FP); - elsif ex1.se.write_hic = '1' then - ctrl_tmp.hfscr_ic <= ex1.ic; - end if; if ex1.se.write_fscr = '1' then ctrl_tmp.fscr_ic <= ex1.e.write_data(59 downto 56); ctrl_tmp.fscr_pref <= ex1.e.write_data(FSCR_PREFIX); diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index 1a0b96b..6b82943 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -552,7 +552,7 @@ static const char *fast_spr_names[] = "lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1", "sprg0", "sprg1", "sprg2", "sprg3", "hsprg0", "hsprg1", "xer", "tar", - "fscr", "hfscr", "heir", "cfar", + "fscr", "unused", "heir", "cfar", }; static const char *ldst_spr_names[] = { From 1b6ee631bc31385b213db320a9443d218ad0d4c6 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 28 Mar 2025 17:12:04 +1100 Subject: [PATCH 2/3] core: Implement LPCR register This implements the LPCR (Logical Partition Control Register) with 5 read/write bits. The other 59 bits are read-only; two (HR and UPRT) read as 1 and the rest as 0. The bits that are implemented are: * HAIL - enables taking interrupts with relocation on * LD - enables large decrementer mode * HEIC - disables external interrupts when set * LPES - controls how external interrupts are delivered * HVICE - does nothing at present since there is no source of Hypervisor Virtualization Interrupts. This also fixes a bug where MSR[RI] was getting cleared by the delivery of hypervisor interrupts. Signed-off-by: Paul Mackerras --- common.vhdl | 30 +++++++++++++++---- core_debug.vhdl | 3 ++ decode1.vhdl | 2 ++ execute1.vhdl | 58 ++++++++++++++++++++++++++++++++----- fetch1.vhdl | 4 +-- scripts/mw_debug/mw_debug.c | 2 +- writeback.vhdl | 15 ++++++++-- 7 files changed, 96 insertions(+), 18 deletions(-) diff --git a/common.vhdl b/common.vhdl index b92b87a..4843c3d 100644 --- a/common.vhdl +++ b/common.vhdl @@ -56,6 +56,7 @@ package common is constant SPR_HSPRG1 : spr_num_t := 305; constant SPR_PID : spr_num_t := 48; constant SPR_PTCR : spr_num_t := 464; + constant SPR_LPCR : spr_num_t := 318; constant SPR_PVR : spr_num_t := 287; constant SPR_FSCR : spr_num_t := 153; constant SPR_HFSCR : spr_num_t := 190; @@ -189,6 +190,7 @@ package common is constant SPRSEL_LOGD : 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"; constant SPRSEL_HEIR : spr_selector := 4x"9"; constant SPRSEL_CTRL : spr_selector := 4x"a"; constant SPRSEL_DSCR : spr_selector := 4x"b"; @@ -235,6 +237,15 @@ package common is constant FPSCR_NI : integer := 63 - 61; constant FPSCR_RN : integer := 63 - 63; + -- LPCR bit numbers + constant LPCR_HAIL : integer := 63 - 37; + constant LPCR_UPRT : integer := 63 - 41; + constant LPCR_HR : integer := 63 - 43; + constant LPCR_LD : integer := 63 - 46; + constant LPCR_HEIC : integer := 63 - 59; + constant LPCR_LPES : integer := 63 - 60; + constant LPCR_HVICE : integer := 63 - 62; + -- Real addresses -- REAL_ADDR_BITS is the number of real address bits that we store constant REAL_ADDR_BITS : positive := 56; @@ -301,6 +312,11 @@ package common is dexcr_pro: aspect_bits_t; hdexcr_hyp: aspect_bits_t; hdexcr_enf: aspect_bits_t; + lpcr_hail: std_ulogic; + lpcr_ld: std_ulogic; + lpcr_heic: std_ulogic; + lpcr_lpes: std_ulogic; + lpcr_hvice: std_ulogic; end record; constant ctrl_t_init : ctrl_t := (wait_state => '0', run => '1', xer_low => 18x"0", @@ -308,6 +324,8 @@ package common is dscr => (others => '0'), dexcr_pnh => aspect_bits_init, dexcr_pro => aspect_bits_init, hdexcr_hyp => aspect_bits_init, hdexcr_enf => aspect_bits_init, + lpcr_hail => '0', lpcr_ld => '1', lpcr_heic => '0', + lpcr_lpes => '0', lpcr_hvice => '0', others => (others => '0')); type timebase_ctrl is record @@ -778,6 +796,7 @@ package common is write_xerc_enable : std_ulogic; xerc : xer_common_t; interrupt : std_ulogic; + alt_intr : std_ulogic; hv_intr : std_ulogic; is_scv : std_ulogic; intr_vec : intr_vector_t; @@ -788,7 +807,6 @@ package common is br_taken: std_ulogic; abs_br: std_ulogic; srr1: std_ulogic_vector(15 downto 0); - msr: std_ulogic_vector(63 downto 0); end record; constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', instr_tag => instr_tag_init, rc => '0', mode_32bit => '0', @@ -796,11 +814,11 @@ package common is write_xerc_enable => '0', xerc => xerc_init, write_data => (others => '0'), write_cr_mask => (others => '0'), write_cr_data => (others => '0'), write_reg => (others => '0'), - interrupt => '0', hv_intr => '0', is_scv => '0', intr_vec => 0, + interrupt => '0', alt_intr => '0', hv_intr => '0', is_scv => '0', intr_vec => 0, redirect => '0', redir_mode => "0000", last_nia => (others => '0'), br_last => '0', br_taken => '0', abs_br => '0', - srr1 => (others => '0'), msr => (others => '0')); + srr1 => (others => '0')); type Execute1ToFPUType is record valid : std_ulogic; @@ -885,13 +903,14 @@ package common is br_last : std_ulogic; br_taken : std_ulogic; interrupt : std_ulogic; - intr_vec : std_ulogic_vector(16 downto 0); + alt_intr : std_ulogic; + intr_vec : std_ulogic_vector(63 downto 0); end record; constant WritebackToFetch1Init : WritebackToFetch1Type := (redirect => '0', virt_mode => '0', priv_mode => '0', big_endian => '0', mode_32bit => '0', redirect_nia => (others => '0'), br_last => '0', br_taken => '0', br_nia => (others => '0'), - interrupt => '0', intr_vec => 17x"0"); + interrupt => '0', alt_intr => '0', intr_vec => 64x"0"); type WritebackToRegisterFileType is record write_reg : gspr_index_t; @@ -917,6 +936,7 @@ package common is intr : std_ulogic; hv_intr : std_ulogic; scv_int : std_ulogic; + alt_int : std_ulogic; srr1 : std_ulogic_vector(15 downto 0); end record; diff --git a/core_debug.vhdl b/core_debug.vhdl index e839832..b1abe83 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -327,6 +327,9 @@ begin when 5x"0e" => isram := '0'; sel := SPRSEL_FSCR; + when 5x"0f" => + isram := '0'; + sel := SPRSEL_LPCR; when 5x"10" => isram := '0'; sel := SPRSEL_HEIR; diff --git a/decode1.vhdl b/decode1.vhdl index c3f215d..c684d72 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -490,6 +490,8 @@ architecture behaviour of decode1 is i.sel := SPRSEL_XER; when SPR_FSCR => i.sel := SPRSEL_FSCR; + when SPR_LPCR => + i.sel := SPRSEL_LPCR; when SPR_HEIR => i.sel := SPRSEL_HEIR; when SPR_CTRL => diff --git a/execute1.vhdl b/execute1.vhdl index cea2f37..fcf1df7 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -92,6 +92,7 @@ architecture behaviour of execute1 is mult_32s : std_ulogic; write_fscr : std_ulogic; write_ic : std_ulogic; + write_lpcr : std_ulogic; write_heir : std_ulogic; set_heir : std_ulogic; write_ctrl : std_ulogic; @@ -210,6 +211,7 @@ architecture behaviour of execute1 is signal valid_in : std_ulogic; signal ctrl: ctrl_t := ctrl_t_init; signal ctrl_tmp: ctrl_t := ctrl_t_init; + signal dec_sign: std_ulogic; signal rotator_result: std_ulogic_vector(63 downto 0); signal rotator_carry: std_ulogic; signal logical_result: std_ulogic_vector(63 downto 0); @@ -408,6 +410,20 @@ architecture behaviour of execute1 is return ret; end; + function assemble_lpcr(c: ctrl_t) return std_ulogic_vector is + variable ret : std_ulogic_vector(63 downto 0); + begin + ret := (others => '0'); + ret(LPCR_HAIL) := c.lpcr_hail; + ret(LPCR_UPRT) := '1'; + ret(LPCR_HR) := '1'; + ret(LPCR_LD) := c.lpcr_ld; + ret(LPCR_HEIC) := c.lpcr_heic; + ret(LPCR_LPES) := c.lpcr_lpes; + ret(LPCR_HVICE) := c.lpcr_hvice; + return ret; + end; + function assemble_ctrl(c: ctrl_t; msrpr: std_ulogic) return std_ulogic_vector is variable ret : std_ulogic_vector(63 downto 0); begin @@ -443,6 +459,15 @@ architecture behaviour of execute1 is return ret; end; + function assemble_dec(c: ctrl_t) return std_ulogic_vector is + begin + if c.lpcr_ld = '1' then + return c.dec; + else + return 32x"0" & c.dec(31 downto 0); + end if; + end; + -- Tell vivado to keep the hierarchy for the random module so that the -- net names in the xdc file match. attribute keep_hierarchy : string; @@ -582,6 +607,8 @@ begin tb_next <= thi & tlo; end process; + dec_sign <= (ctrl.dec(63) and ctrl.lpcr_ld) or (ctrl.dec(31) and not ctrl.lpcr_ld); + dbg_ctrl_out <= ctrl; log_rd_addr <= ex2.log_addr_spr; @@ -782,6 +809,8 @@ begin case dbg_spr_addr(3 downto 0) is when SPRSEL_FSCR => dbg_spr_data <= assemble_fscr(ctrl); + when SPRSEL_LPCR => + dbg_spr_data <= assemble_lpcr(ctrl); when SPRSEL_HEIR => dbg_spr_data <= ctrl.heir; when SPRSEL_CFAR => @@ -1173,6 +1202,7 @@ begin v.e.redir_mode := ex1.msr(MSR_IR) & not ex1.msr(MSR_PR) & not ex1.msr(MSR_LE) & not ex1.msr(MSR_SF); v.e.intr_vec := 16#700#; + v.e.alt_intr := ctrl.lpcr_hail and ex1.msr(MSR_IR) and ex1.msr(MSR_DR); v.e.mode_32bit := not ex1.msr(MSR_SF); v.e.instr_tag := e_in.instr_tag; v.e.last_nia := e_in.nia; @@ -1441,6 +1471,8 @@ begin v.se.write_cfar := '1'; when SPRSEL_FSCR => v.se.write_fscr := '1'; + when SPRSEL_LPCR => + v.se.write_lpcr := '1'; when SPRSEL_HEIR => v.se.write_heir := '1'; when SPRSEL_CTRL => @@ -1659,7 +1691,8 @@ begin v.busy := '0'; bypass_valid := actions.bypass_valid; - irq_valid := ex1.msr(MSR_EE) and (pmu_to_x.intr or ctrl.dec(63) or ext_irq_in); + irq_valid := ex1.msr(MSR_EE) and (pmu_to_x.intr or dec_sign or + (ext_irq_in and not ctrl.lpcr_heic)); if valid_in = '1' then v.prev_op := e_in.insn_type; @@ -1701,14 +1734,14 @@ begin if pmu_to_x.intr = '1' then v.e.intr_vec := 16#f00#; report "IRQ valid: PMU"; - elsif ctrl.dec(63) = '1' then + elsif dec_sign = '1' then v.e.intr_vec := 16#900#; report "IRQ valid: DEC"; elsif ext_irq_in = '1' then v.e.intr_vec := 16#500#; report "IRQ valid: External"; v.ext_interrupt := '1'; - v.e.hv_intr := '1'; + v.e.hv_intr := not ctrl.lpcr_lpes; end if; v.e.srr1 := (others => '0'); exception := '1'; @@ -1925,12 +1958,13 @@ begin with ex1.spr_select.sel select spr_result <= timebase when SPRSEL_TB, 32x"0" & timebase(63 downto 32) when SPRSEL_TBU, - ctrl.dec when SPRSEL_DEC, + 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, ctrl.cfar when SPRSEL_CFAR, assemble_fscr(ctrl) when SPRSEL_FSCR, + assemble_lpcr(ctrl) when SPRSEL_LPCR, ctrl.heir when SPRSEL_HEIR, assemble_ctrl(ctrl, ex1.msr(MSR_PR)) when SPRSEL_CTRL, 39x"0" & ctrl.dscr when SPRSEL_DSCR, @@ -2089,6 +2123,13 @@ begin elsif ex1.se.write_ic = '1' then ctrl_tmp.fscr_ic <= ex1.ic; end if; + if ex1.se.write_lpcr = '1' then + ctrl_tmp.lpcr_hail <= ex1.e.write_data(LPCR_HAIL); + ctrl_tmp.lpcr_ld <= ex1.e.write_data(LPCR_LD); + ctrl_tmp.lpcr_heic <= ex1.e.write_data(LPCR_HEIC); + ctrl_tmp.lpcr_lpes <= ex1.e.write_data(LPCR_LPES); + ctrl_tmp.lpcr_hvice <= ex1.e.write_data(LPCR_HVICE); + end if; if ex1.se.write_heir = '1' then ctrl_tmp.heir <= ex1.e.write_data; elsif ex1.se.set_heir = '1' then @@ -2117,7 +2158,7 @@ begin -- pending exceptions clear any wait state -- ex1.fp_exception_next is not tested because it is not possible to -- get into wait state with a pending FP exception. - irq_exc := pmu_to_x.intr or ctrl.dec(63) or ext_irq_in; + irq_exc := pmu_to_x.intr or dec_sign or ext_irq_in; if ex1.trace_next = '1' or irq_exc = '1' or interrupt_in.intr = '1' then ctrl_tmp.wait_state <= '0'; end if; @@ -2130,11 +2171,13 @@ begin ctrl_tmp.msr(MSR_FP) <= '0'; ctrl_tmp.msr(MSR_FE0) <= '0'; ctrl_tmp.msr(MSR_FE1) <= '0'; - ctrl_tmp.msr(MSR_IR) <= '0'; - ctrl_tmp.msr(MSR_DR) <= '0'; + ctrl_tmp.msr(MSR_IR) <= interrupt_in.alt_int; + ctrl_tmp.msr(MSR_DR) <= interrupt_in.alt_int; ctrl_tmp.msr(MSR_LE) <= '1'; if interrupt_in.scv_int = '0' then ctrl_tmp.msr(MSR_EE) <= '0'; + end if; + if interrupt_in.scv_int = '0' and interrupt_in.hv_intr = '0' then ctrl_tmp.msr(MSR_RI) <= '0'; end if; end if; @@ -2158,7 +2201,6 @@ begin -- update outputs e_out <= ex2.e; - e_out.msr <= msr_copy(ctrl.msr); run_out <= ctrl.run; terminate_out <= ex2.se.terminate; diff --git a/fetch1.vhdl b/fetch1.vhdl index f07188d..bd5ca1a 100644 --- a/fetch1.vhdl +++ b/fetch1.vhdl @@ -391,11 +391,11 @@ begin v_int.next_nia := RESET_ADDRESS; end if; elsif w_in.interrupt = '1' then - v_int.next_nia := 47x"0" & w_in.intr_vec(16 downto 2) & "00"; + v_int.next_nia := w_in.intr_vec(63 downto 2) & "00"; end if; if rst /= '0' or w_in.interrupt = '1' then v.req := '0'; - v.virt_mode := '0'; + v.virt_mode := w_in.alt_intr and not rst; v.priv_mode := '1'; v.big_endian := '0'; v_int.mode_32bit := '0'; diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index 6b82943..06822ec 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -552,7 +552,7 @@ static const char *fast_spr_names[] = "lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1", "sprg0", "sprg1", "sprg2", "sprg3", "hsprg0", "hsprg1", "xer", "tar", - "fscr", "unused", "heir", "cfar", + "fscr", "lpcr", "heir", "cfar", }; static const char *ldst_spr_names[] = { diff --git a/writeback.vhdl b/writeback.vhdl index d7690a5..49a53cc 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -75,6 +75,7 @@ begin variable hvi : std_ulogic; variable scv : std_ulogic; variable intr_page : std_ulogic_vector(4 downto 0); + variable intr_seg : std_ulogic_vector(1 downto 0); begin w_out <= WritebackToRegisterFileInit; c_out <= WritebackToCrFileInit; @@ -98,6 +99,10 @@ begin srr1 := (others => '0'); intr_page := 5x"0"; + if e_in.alt_intr = '1' then + intr_page := 5x"4"; + end if; + intr_seg := e_in.alt_intr & e_in.alt_intr; scv := '0'; if e_in.interrupt = '1' then vec := e_in.intr_vec; @@ -105,7 +110,11 @@ begin hvi := e_in.hv_intr; scv := e_in.is_scv; if e_in.is_scv = '1' then - intr_page := 5x"17"; + if e_in.alt_intr = '0' then + intr_page := 5x"17"; + else + intr_page := 5x"3"; + end if; end if; elsif l_in.interrupt = '1' then vec := l_in.intr_vec; @@ -117,6 +126,7 @@ begin interrupt_out.hv_intr <= hvi; interrupt_out.srr1 <= srr1; interrupt_out.scv_int <= scv; + interrupt_out.alt_int <= e_in.alt_intr; if intr = '0' then if e_in.write_enable = '1' then @@ -174,7 +184,8 @@ begin -- Outputs to fetch1 f.interrupt := intr; - f.intr_vec := intr_page & std_ulogic_vector(to_unsigned(vec, 12)); + f.alt_intr := e_in.alt_intr; + f.intr_vec := intr_seg & 45x"0" & intr_page & std_ulogic_vector(to_unsigned(vec, 12)); f.redirect := e_in.redirect; f.redirect_nia := e_in.write_data; f.br_nia := e_in.last_nia; From 8f7326a8246ec92eff97f6f10c27babff3b1c1e0 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 10 Apr 2025 16:22:09 +1000 Subject: [PATCH 3/3] 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;