From 65a36cc0fc65d4a7dbe83b2422b6b819c26d4162 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 12 May 2020 16:28:42 +1000 Subject: [PATCH] decode: Work out ispr1/ispr2 in parallel with decode ROM lookup This makes the logic that calculates which SPRs are being accessed work in parallel with the instruction decode ROM lookup instead of being dependent on the opcode found in the decode ROM. The reason for doing that is that the path from icache through the decode ROM to the ispr1/ispr2 fields has become a critical path. Thus we are now using only a very partial decode of the instruction word in the logic for isp1/isp2, and we therefore can no longer rely on them being zero in all cases where no SPR is being accessed. Instead, decode2 now ignores ispr1/ispr2 in all cases except when the relevant decode.input_reg_a/b or decode.output_reg_a is set to SPR. Signed-off-by: Paul Mackerras --- decode1.vhdl | 59 ++++++++++++++++++++++++++++++---------------------- decode2.vhdl | 10 ++++----- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 214285e..ae3e970 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -398,6 +398,17 @@ begin -- major opcode 31, lots of things v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1)))); + -- Work out ispr1/ispr2 independent of v.decode since they seem to be critical path + sprn := decode_spr_num(f_in.insn); + v.ispr1 := fast_spr_num(sprn); + + elsif majorop = "010000" then + -- CTR may be needed as input to bc + v.decode := major_decode_rom_array(to_integer(majorop)); + if f_in.insn(23) = '0' then + v.ispr1 := fast_spr_num(SPR_CTR); + end if; + elsif majorop = "010011" then if decode_op_19_valid(to_integer(unsigned(f_in.insn(10 downto 1)))) = '0' then report "op 19 illegal subcode"; @@ -408,6 +419,27 @@ begin report "op 19 sub " & to_hstring(op_19_bits); end if; + -- Work out ispr1/ispr2 independent of v.decode since they seem to be critical path + if f_in.insn(2) = '0' then + -- Could be OP_BCREG: bclr, bcctr, bctar + -- Branch uses CTR as condition when BO(2) is 0. This is + -- also used to indicate that CTR is modified (they go + -- together). + if f_in.insn(23) = '0' then + v.ispr1 := fast_spr_num(SPR_CTR); + end if; + -- TODO: Add TAR + if f_in.insn(10) = '0' then + v.ispr2 := fast_spr_num(SPR_LR); + else + v.ispr2 := fast_spr_num(SPR_CTR); + end if; + else + -- Could be OP_RFID + v.ispr1 := fast_spr_num(SPR_SRR0); + v.ispr2 := fast_spr_num(SPR_SRR1); + end if; + elsif majorop = "011110" then v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1)))); @@ -423,30 +455,11 @@ begin else v.decode := major_decode_rom_array(to_integer(majorop)); - end if; - -- Set ISPR1/ISPR2 when needed - if v.decode.insn_type = OP_BC or v.decode.insn_type = OP_BCREG then - -- Branch uses CTR as condition when BO(2) is 0. This is - -- also used to indicate that CTR is modified (they go - -- together). - -- - if f_in.insn(23) = '0' then - v.ispr1 := fast_spr_num(SPR_CTR); - end if; + end if; - -- Branch source register is an SPR - if v.decode.insn_type = OP_BCREG then - -- TODO: Add TAR - if f_in.insn(10) = '0' then - v.ispr2 := fast_spr_num(SPR_LR); - else - v.ispr2 := fast_spr_num(SPR_CTR); - end if; - end if; - elsif v.decode.insn_type = OP_MFSPR or v.decode.insn_type = OP_MTSPR then + if v.decode.insn_type = OP_MFSPR or v.decode.insn_type = OP_MTSPR then sprn := decode_spr_num(f_in.insn); - v.ispr1 := fast_spr_num(sprn); -- Make slow SPRs single issue if is_fast_spr(v.ispr1) = '0' then v.decode.sgl_pipe := '1'; @@ -457,10 +470,6 @@ begin when others => end case; 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/decode2.vhdl b/decode2.vhdl index 5b8cbc1..6acbca7 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -67,8 +67,6 @@ architecture behaviour of decode2 is return decode_input_reg_t is begin if t = RA or (t = RA_OR_ZERO and insn_ra(insn_in) /= "00000") then - assert is_fast_spr(ispr) = '0' report "Decode A says GPR but ISPR says SPR:" & - to_hstring(ispr) severity failure; return ('1', gpr_to_gspr(insn_ra(insn_in)), reg_data); elsif t = SPR then -- ISPR must be either a valid fast SPR number or all 0 for a slow SPR. @@ -93,8 +91,6 @@ architecture behaviour of decode2 is begin case t is when RB => - assert is_fast_spr(ispr) = '0' report "Decode B says GPR but ISPR says SPR:" & - to_hstring(ispr) severity failure; ret := ('1', gpr_to_gspr(insn_rb(insn_in)), reg_data); when CONST_UI => ret := ('0', (others => '0'), std_ulogic_vector(resize(unsigned(insn_ui(insn_in)), 64))); @@ -277,8 +273,10 @@ begin end if; end process; - r_out.read1_reg <= gpr_or_spr_to_gspr(insn_ra(d_in.insn), d_in.ispr1); - r_out.read2_reg <= gpr_or_spr_to_gspr(insn_rb(d_in.insn), d_in.ispr2); + r_out.read1_reg <= d_in.ispr1 when d_in.decode.input_reg_a = SPR + else gpr_to_gspr(insn_ra(d_in.insn)); + r_out.read2_reg <= d_in.ispr2 when d_in.decode.input_reg_b = SPR + else gpr_to_gspr(insn_rb(d_in.insn)); r_out.read3_reg <= insn_rs(d_in.insn); c_out.read <= d_in.decode.input_cr;