decode: Work out ispr1/ispr2 in parallel with decode ROM lookup
authorPaul Mackerras <paulus@ozlabs.org>
Tue, 12 May 2020 06:28:42 +0000 (16:28 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Sat, 13 Jun 2020 10:10:37 +0000 (20:10 +1000)
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 <paulus@ozlabs.org>
decode1.vhdl
decode2.vhdl

index 214285e632ee63c199e2bad7f1eae87b3591a463..ae3e97084d294df9a277161a67a47162ea0e0661 100644 (file)
@@ -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
index 5b8cbc1b53a0bb80e46994970fa677a2ba4e52e2..6acbca7de65f7115946c7948c5a0450ed968d27d 100644 (file)
@@ -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;