mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-10 14:28:53 +00:00
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 <paulus@ozlabs.org>
This commit is contained in:
59
decode1.vhdl
59
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;
|
||||
|
||||
-- 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
|
||||
|
||||
10
decode2.vhdl
10
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;
|
||||
|
||||
Reference in New Issue
Block a user