From 91f2692c8c9523f0bbb5b6debfed54525d162f0d Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Fri, 6 Mar 2020 13:35:28 +1100 Subject: [PATCH] Decrementer IRQ, rfid, mtmsr implementation The interrupt controller is done in execute1. execute 1 then takes two cycles to write fast SPRS SRR0 and SRR1. MSR is stored in execute1 for now so it can be checked and tested for EE atomically. This may need to move in the future. DEC lives in execute1 also. Signed-off-by: Michael Neuling --- common.vhdl | 3 +++ decode1.vhdl | 9 +++++++ decode_types.vhdl | 9 +++---- execute1.vhdl | 69 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 80 insertions(+), 10 deletions(-) diff --git a/common.vhdl b/common.vhdl index ffddb0b..3589c9d 100644 --- a/common.vhdl +++ b/common.vhdl @@ -16,6 +16,7 @@ package common is constant SPR_LR : spr_num_t := 8; constant SPR_CTR : spr_num_t := 9; constant SPR_TB : spr_num_t := 268; + constant SPR_DEC : spr_num_t := 22; constant SPR_SRR0 : spr_num_t := 26; constant SPR_SRR1 : spr_num_t := 27; constant SPR_HSRR0 : spr_num_t := 314; @@ -65,6 +66,8 @@ package common is -- This needs to die... type ctrl_t is record tb: std_ulogic_vector(63 downto 0); + dec: std_ulogic_vector(63 downto 0); + msr: std_ulogic_vector(63 downto 0); end record; type Fetch1ToIcacheType is record diff --git a/decode1.vhdl b/decode1.vhdl index f1b5ad4..651aada 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -94,6 +94,7 @@ architecture behaviour of decode1 is 2#0011000001# => '1', -- crxor 2#0010010110# => '1', -- isync 2#0000000000# => '1', -- mcrf + 2#0000010010# => '1', -- rfid others => '0' ); @@ -109,6 +110,8 @@ architecture behaviour of decode1 is 2#100# => (ALU, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0'), -- isync 2#111# => (ALU, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), + -- rfid + 2#101# => (ALU, OP_RFID, SPR, SPR, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), others => illegal_inst ); @@ -237,12 +240,14 @@ architecture behaviour of decode1 is -- 2#1000000000# mcrxr -- 2#1001000000# mcrxrx 2#0000010011# => (ALU, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mfcr/mfocrf + 2#0001010011# => (ALU, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mfmsr 2#0101010011# => (ALU, OP_MFSPR, SPR, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mfspr 2#0100001001# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- modud 2#0100001011# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0'), -- moduw 2#1100001001# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0'), -- modsd 2#1100001011# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0'), -- modsw 2#0010010000# => (ALU, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mtcrf/mtocrf + 2#0010110010# => (ALU, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mtmsrd # ignore top bits and d 2#0111010011# => (ALU, OP_MTSPR, NONE, NONE, RS, SPR, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mtspr 2#0001001001# => (ALU, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0'), -- mulhd 2#0000001001# => (ALU, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- mulhdu @@ -425,6 +430,10 @@ begin if is_fast_spr(v.ispr1) = '0' then v.decode.sgl_pipe := '1'; end if; + elsif v.decode.insn_type = OP_RFID then + report "PPC RFID"; + v.ispr1 := fast_spr_num(SPR_SRR0); + v.ispr2 := fast_spr_num(SPR_SRR1); end if; if flush_in = '1' then diff --git a/decode_types.vhdl b/decode_types.vhdl index 21d8b68..35a2ca6 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -9,18 +9,17 @@ package decode_types is OP_CRANDC, OP_CREQV, OP_CRNAND, OP_CRNOR, OP_CROR, OP_CRORC, OP_CRXOR, OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST, OP_DCBZ, OP_DIV, OP_DIVE, OP_EXTS, - OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC, + OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_IRQ_M0, OP_IRQ_M1, OP_ISEL, OP_ISYNC, OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD, OP_MCRF, - OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFSPR, OP_MOD, - OP_MTCRF, OP_MTSPR, OP_MUL_L64, + OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MOD, + OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64, OP_MUL_H64, OP_MUL_H32, OP_OR, - OP_POPCNT, OP_PRTY, + OP_POPCNT, OP_PRTY, OP_RFID, OP_RLC, OP_RLCL, OP_RLCR, OP_SETB, OP_SHL, OP_SHR, OP_SYNC, OP_TD, OP_TDI, OP_TW, OP_TWI, OP_XOR, OP_SIM_CONFIG ); - type input_reg_a_t is (NONE, RA, RA_OR_ZERO, SPR); type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS, CONST_M1, CONST_SH, CONST_SH32, SPR); type input_reg_c_t is (NONE, RS); diff --git a/execute1.vhdl b/execute1.vhdl index ae13c72..9396cef 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -49,6 +49,10 @@ architecture behaviour of execute1 is slow_op_xerc : xer_common_t; end record; + type irq_state_t is (WRITE_SRR0, WRITE_SRR1); + + signal irq_state, irq_state_in : irq_state_t; + signal r, rin : reg_type; signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0); @@ -175,6 +179,7 @@ begin if rising_edge(clk) then r <= rin; ctrl <= ctrl_tmp; + irq_state <= irq_state_in; assert not (r.lr_update = '1' and e_in.valid = '1') report "LR update collision with valid in EX1" severity failure; @@ -214,6 +219,8 @@ begin variable msb_a, msb_b : std_ulogic; variable a_lt : std_ulogic; variable lv : Execute1ToLoadstore1Type; + variable irq_nia : std_ulogic_vector(63 downto 0); + variable irq_valid : std_ulogic; begin result := (others => '0'); result_with_carry := (others => '0'); @@ -340,6 +347,15 @@ begin ctrl_tmp <= ctrl; -- FIXME: run at 512MHz not core freq ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1); + ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1); + + irq_valid := '0'; + irq_nia := (others => '-'); + if ctrl.msr(15) = '1' and ctrl.dec(63) = '1' then + report "IRQ valid"; + irq_valid := '1'; + irq_nia := std_logic_vector(to_unsigned(16#900#, 64)); + end if; terminate_out <= '0'; icache_inval <= '0'; @@ -354,7 +370,33 @@ begin rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0'; rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0'; - if e_in.valid = '1' then + irq_state_in <= WRITE_SRR0; + + if irq_state = WRITE_SRR1 then + v.e.write_reg := fast_spr_num(SPR_SRR1); + result := ctrl.msr; + result_en := '1'; + -- do this second so IRQ is still valid + -- FIXME frob other bits like HV/PR + ctrl_tmp.msr(15) <= '0'; + f_out.redirect <= '1'; + f_out.redirect_nia <= irq_nia; + + elsif irq_valid = '1' then + -- we need two cycles to write srr0 and 1 + -- will need more when we have to write DSISR, DAR and HIER + if irq_state = WRITE_SRR0 then + v.e.write_reg := fast_spr_num(SPR_SRR0); + result := e_in.nia; + if e_in.valid = '1' then + result_en := '1'; + irq_state_in <= WRITE_SRR1; + stall_out <= '1'; + v.e.valid := '1'; + end if; + end if; + + elsif e_in.valid = '1' then v.e.valid := '1'; v.e.write_reg := e_in.write_reg; @@ -473,6 +515,11 @@ begin f_out.redirect <= '1'; f_out.redirect_nia <= b_in(63 downto 2) & "00"; end if; + + when OP_RFID => + f_out.redirect <= '1'; + f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0 + ctrl_tmp.msr <= std_ulogic_vector(signed(b_in)); -- srr1 when OP_CMPB => result := ppc_cmpb(c_in, b_in); result_en := '1'; @@ -562,7 +609,12 @@ begin end if; end loop; end if; + when OP_MFMSR => + result := ctrl.msr; + result_en := '1'; when OP_MFSPR => + report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & + "=" & to_hstring(a_in); if is_fast_spr(e_in.read_reg1) then result := a_in; if decode_spr_num(e_in.insn) = SPR_XER then @@ -579,6 +631,8 @@ begin case decode_spr_num(e_in.insn) is when SPR_TB => result := ctrl.tb; + when SPR_DEC => + result := ctrl.dec; when others => result := (others => '0'); end case; @@ -612,6 +666,9 @@ begin v.e.write_cr_mask := num_to_fxm(crnum); end if; v.e.write_cr_data := c_in(31 downto 0); + when OP_MTMSRD => + -- FIXME handle just the bits we need to. + ctrl_tmp.msr <= e_in.read_data3; when OP_MTSPR => report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & "=" & to_hstring(c_in); @@ -627,10 +684,12 @@ begin v.e.write_xerc_enable := '1'; end if; else --- TODO: Implement slow SPRs --- case decode_spr_num(e_in.insn) is --- when others => --- end case; + -- slow spr + case decode_spr_num(e_in.insn) is + when SPR_DEC => + ctrl_tmp.dec <= c_in; + when others => + end case; end if; when OP_POPCNT => result := popcnt_result;