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;