mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-02-27 00:59:41 +00:00
Improve timing of redirect_nia going from decode1 to fetch1
This moves the addition that computes the branch target address for statically predicted taken branches before a clock edge, so the redirect_nia signal going to fetch1 comes from a clean latch. The address generation logic is also simplified somewhat, and conditional absolute branches to negative addresses are no longer predicted taken (this should have no impact on performance as such branches are basically never used). Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
28
decode1.vhdl
28
decode1.vhdl
@@ -35,8 +35,7 @@ architecture behaviour of decode1 is
|
||||
signal f, fin : Decode1ToFetch1Type;
|
||||
|
||||
type br_predictor_t is record
|
||||
br_nia : std_ulogic_vector(61 downto 0);
|
||||
br_offset : signed(23 downto 0);
|
||||
br_target : signed(61 downto 0);
|
||||
predict : std_ulogic;
|
||||
end record;
|
||||
|
||||
@@ -479,8 +478,6 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
if rst = '1' then
|
||||
br.br_nia <= (others => '0');
|
||||
br.br_offset <= (others => '0');
|
||||
br.predict <= '0';
|
||||
else
|
||||
br <= br_in;
|
||||
@@ -502,8 +499,8 @@ begin
|
||||
decode1_1: process(all)
|
||||
variable v : Decode1ToDecode2Type;
|
||||
variable vr : Decode1ToRegisterFileType;
|
||||
variable br_target : std_ulogic_vector(61 downto 0);
|
||||
variable br_offset : signed(23 downto 0);
|
||||
variable br_nia : std_ulogic_vector(61 downto 0);
|
||||
variable br_offset : std_ulogic_vector(23 downto 0);
|
||||
variable bv : br_predictor_t;
|
||||
variable icode : insn_code;
|
||||
variable sprn : spr_num_t;
|
||||
@@ -597,31 +594,28 @@ begin
|
||||
-- Branch predictor
|
||||
-- Note bclr, bcctr and bctar not predicted as we have no
|
||||
-- count cache or link stack.
|
||||
br_offset := (others => '0');
|
||||
br_offset := f_in.insn(25 downto 2);
|
||||
case icode is
|
||||
when INSN_brel | INSN_babs =>
|
||||
-- Unconditional branches are always taken
|
||||
v.br_pred := '1';
|
||||
br_offset := signed(f_in.insn(25 downto 2));
|
||||
when INSN_bcrel | INSN_bcabs =>
|
||||
-- Predict backward branches as taken, forward as untaken
|
||||
when INSN_bcrel =>
|
||||
-- Predict backward relative branches as taken, others as untaken
|
||||
v.br_pred := f_in.insn(15);
|
||||
br_offset := resize(signed(f_in.insn(15 downto 2)), 24);
|
||||
br_offset(23 downto 14) := (others => '1');
|
||||
when others =>
|
||||
end case;
|
||||
bv.br_nia := f_in.nia(63 downto 2);
|
||||
br_nia := f_in.nia(63 downto 2);
|
||||
if f_in.insn(1) = '1' then
|
||||
bv.br_nia := (others => '0');
|
||||
br_nia := (others => '0');
|
||||
end if;
|
||||
bv.br_offset := br_offset;
|
||||
bv.br_target := signed(br_nia) + signed(br_offset);
|
||||
if f_in.next_predicted = '1' then
|
||||
v.br_pred := '1';
|
||||
elsif f_in.next_pred_ntaken = '1' then
|
||||
v.br_pred := '0';
|
||||
end if;
|
||||
bv.predict := v.br_pred and f_in.valid and not flush_in and not busy_out and not f_in.next_predicted;
|
||||
-- after a clock edge...
|
||||
br_target := std_ulogic_vector(signed(br.br_nia) + br.br_offset);
|
||||
|
||||
-- Work out GPR/FPR read addresses
|
||||
-- Note that for prefixed instructions we are working this out based
|
||||
@@ -668,7 +662,7 @@ begin
|
||||
d_out.decode <= decode;
|
||||
r_out <= vr;
|
||||
f_out.redirect <= br.predict;
|
||||
f_out.redirect_nia <= br_target & "00";
|
||||
f_out.redirect_nia <= std_ulogic_vector(br.br_target) & "00";
|
||||
flush_out <= bv.predict or br.predict;
|
||||
end process;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user