core: Improve timing on bypass control paths

In order to improve timing, the bypass paths now carry the register
number being written as well as the tag.  The decisions about which
bypasses to use for which operands are then made by comparing the
register numbers rather than by determining a tag from the register
number and then comparing tags.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/452/head
Paul Mackerras 2 weeks ago
parent f2166d326c
commit 788f7a1755

@ -420,9 +420,11 @@ package common is


type bypass_data_t is record type bypass_data_t is record
tag : instr_tag_t; tag : instr_tag_t;
reg : gspr_index_t;
data : std_ulogic_vector(63 downto 0); data : std_ulogic_vector(63 downto 0);
end record; end record;
constant bypass_data_init : bypass_data_t := (tag => instr_tag_init, data => (others => '0')); constant bypass_data_init : bypass_data_t :=
(tag => instr_tag_init, reg => (others => '0'), data => (others => '0'));


type cr_bypass_data_t is record type cr_bypass_data_t is record
tag : instr_tag_t; tag : instr_tag_t;

@ -32,11 +32,11 @@ entity control is
gpr_c_read_valid_in : in std_ulogic; gpr_c_read_valid_in : in std_ulogic;
gpr_c_read_in : in gspr_index_t; gpr_c_read_in : in gspr_index_t;


execute_next_tag : in instr_tag_t; execute_next_bypass : in bypass_data_t;
execute_next_cr_tag : in instr_tag_t; execute2_next_bypass : in bypass_data_t;
execute2_next_tag : in instr_tag_t; writeback_bypass : in bypass_data_t;
execute_next_cr_tag : in instr_tag_t;
execute2_next_cr_tag : in instr_tag_t; execute2_next_cr_tag : in instr_tag_t;
writeback_tag : in instr_tag_t;


cr_read_in : in std_ulogic; cr_read_in : in std_ulogic;
cr_write_in : in std_ulogic; cr_write_in : in std_ulogic;
@ -164,109 +164,90 @@ begin
variable byp_cr : std_ulogic_vector(1 downto 0); variable byp_cr : std_ulogic_vector(1 downto 0);
variable tag_ov : instr_tag_t; variable tag_ov : instr_tag_t;
variable tag_prev : instr_tag_t; variable tag_prev : instr_tag_t;
variable rma : std_ulogic_vector(TAG_COUNT-1 downto 0);
variable rmb : std_ulogic_vector(TAG_COUNT-1 downto 0);
variable rmc : std_ulogic_vector(TAG_COUNT-1 downto 0);
variable tag_a_stall : std_ulogic;
variable tag_b_stall : std_ulogic;
variable tag_c_stall : std_ulogic;
begin begin
tag_a := instr_tag_init; tag_a := instr_tag_init;
tag_a_stall := '0';
rma := (others => '0');
for i in tag_number_t loop for i in tag_number_t loop
if tag_regs(i).valid = '1' and tag_regs(i).wr_gpr = '1' and if tag_regs(i).valid = '1' and tag_regs(i).recent = '1' and
tag_regs(i).reg = gpr_a_read_in and gpr_a_read_valid_in = '1' then tag_regs(i).reg = gpr_a_read_in and gpr_a_read_valid_in = '1' then
rma(i) := '1'; tag_a.valid := '1';
if tag_regs(i).recent = '1' then tag_a.tag := i;
tag_a_stall := '1'; if (EX1_BYPASS and tag_match(execute_next_bypass.tag, tag_a)) or
(EX1_BYPASS and tag_match(execute2_next_bypass.tag, tag_a)) or
tag_match(complete_in, tag_a) then
tag_a.valid := '0';
end if; end if;
end if; end if;
end loop; end loop;
byp_a := "0000"; byp_a := "0000";
if EX1_BYPASS and execute_next_tag.valid = '1' and if EX1_BYPASS and execute_next_bypass.tag.valid = '1' and
rma(execute_next_tag.tag) = '1' then execute_next_bypass.reg = gpr_a_read_in then
byp_a(1) := '1'; byp_a(1) := '1';
tag_a := execute_next_tag; elsif EX1_BYPASS and execute2_next_bypass.tag.valid = '1' and
elsif EX1_BYPASS and execute2_next_tag.valid = '1' and execute2_next_bypass.reg = gpr_a_read_in then
rma(execute2_next_tag.tag) = '1' then
byp_a(2) := '1'; byp_a(2) := '1';
tag_a := execute2_next_tag; elsif writeback_bypass.tag.valid = '1' and
elsif writeback_tag.valid = '1' and rma(writeback_tag.tag) = '1' then writeback_bypass.reg = gpr_a_read_in then
byp_a(3) := '1'; byp_a(3) := '1';
tag_a := writeback_tag;
end if; end if;
byp_a(0) := gpr_a_read_valid_in and (byp_a(1) or byp_a(2) or byp_a(3)); byp_a(0) := gpr_a_read_valid_in and (byp_a(1) or byp_a(2) or byp_a(3));
if tag_a.valid = '1' and tag_regs(tag_a.tag).valid = '1' and
tag_regs(tag_a.tag).recent = '1' then
tag_a_stall := '0';
end if;


tag_b := instr_tag_init; tag_b := instr_tag_init;
tag_b_stall := '0';
rmb := (others => '0');
for i in tag_number_t loop for i in tag_number_t loop
if tag_regs(i).valid = '1' and tag_regs(i).wr_gpr = '1' and if tag_regs(i).valid = '1' and tag_regs(i).recent = '1' and
tag_regs(i).reg = gpr_b_read_in and gpr_b_read_valid_in = '1' then tag_regs(i).reg = gpr_b_read_in and gpr_b_read_valid_in = '1' then
rmb(i) := '1'; tag_b.valid := '1';
if tag_regs(i).recent = '1' then tag_b.tag := i;
tag_b_stall := '1'; if (EX1_BYPASS and tag_match(execute_next_bypass.tag, tag_b)) or
(EX1_BYPASS and tag_match(execute2_next_bypass.tag, tag_b)) or
tag_match(complete_in, tag_b) then
tag_b.valid := '0';
end if; end if;
end if; end if;
end loop; end loop;
byp_b := "0000"; byp_b := "0000";
if EX1_BYPASS and execute_next_tag.valid = '1' and if EX1_BYPASS and execute_next_bypass.tag.valid = '1' and
rmb(execute_next_tag.tag) = '1' then execute_next_bypass.reg = gpr_b_read_in then
byp_b(1) := '1'; byp_b(1) := '1';
tag_b := execute_next_tag; elsif EX1_BYPASS and execute2_next_bypass.tag.valid = '1' and
elsif EX1_BYPASS and execute2_next_tag.valid = '1' and execute2_next_bypass.reg = gpr_b_read_in then
rmb(execute2_next_tag.tag) = '1' then
byp_b(2) := '1'; byp_b(2) := '1';
tag_b := execute2_next_tag; elsif writeback_bypass.tag.valid = '1' and
elsif writeback_tag.valid = '1' and rmb(writeback_tag.tag) = '1' then writeback_bypass.reg = gpr_b_read_in then
byp_b(3) := '1'; byp_b(3) := '1';
tag_b := writeback_tag;
end if; end if;
byp_b(0) := gpr_b_read_valid_in and (byp_b(1) or byp_b(2) or byp_b(3)); byp_b(0) := gpr_b_read_valid_in and (byp_b(1) or byp_b(2) or byp_b(3));
if tag_b.valid = '1' and tag_regs(tag_b.tag).valid = '1' and
tag_regs(tag_b.tag).recent = '1' then
tag_b_stall := '0';
end if;


tag_c := instr_tag_init; tag_c := instr_tag_init;
tag_c_stall := '0';
rmc := (others => '0');
for i in tag_number_t loop for i in tag_number_t loop
if tag_regs(i).valid = '1' and tag_regs(i).wr_gpr = '1' and if tag_regs(i).valid = '1' and tag_regs(i).recent = '1' and
tag_regs(i).reg = gpr_c_read_in and gpr_c_read_valid_in = '1' then tag_regs(i).reg = gpr_c_read_in and gpr_c_read_valid_in = '1' then
rmc(i) := '1'; tag_c.valid := '1';
if tag_regs(i).recent = '1' then tag_c.tag := i;
tag_c_stall := '1'; if (EX1_BYPASS and tag_match(execute_next_bypass.tag, tag_c)) or
(EX1_BYPASS and tag_match(execute2_next_bypass.tag, tag_c)) or
tag_match(complete_in, tag_c) then
tag_c.valid := '0';
end if; end if;
end if; end if;
end loop; end loop;
byp_c := "0000"; byp_c := "0000";
if EX1_BYPASS and execute_next_tag.valid = '1' and rmc(execute_next_tag.tag) = '1' then if EX1_BYPASS and execute_next_bypass.tag.valid = '1' and
execute_next_bypass.reg = gpr_c_read_in then
byp_c(1) := '1'; byp_c(1) := '1';
tag_c := execute_next_tag; elsif EX1_BYPASS and execute2_next_bypass.tag.valid = '1' and
elsif EX1_BYPASS and execute2_next_tag.valid = '1' and rmc(execute2_next_tag.tag) = '1' then execute2_next_bypass.reg = gpr_c_read_in then
byp_c(2) := '1'; byp_c(2) := '1';
tag_c := execute2_next_tag; elsif writeback_bypass.tag.valid = '1' and
elsif writeback_tag.valid = '1' and rmc(writeback_tag.tag) = '1' then writeback_bypass.reg = gpr_c_read_in then
byp_c(3) := '1'; byp_c(3) := '1';
tag_c := writeback_tag;
end if; end if;
byp_c(0) := gpr_c_read_valid_in and (byp_c(1) or byp_c(2) or byp_c(3)); byp_c(0) := gpr_c_read_valid_in and (byp_c(1) or byp_c(2) or byp_c(3));
if tag_c.valid = '1' and tag_regs(tag_c.tag).valid = '1' and
tag_regs(tag_c.tag).recent = '1' then
tag_c_stall := '0';
end if;


gpr_bypass_a <= byp_a; gpr_bypass_a <= byp_a;
gpr_bypass_b <= byp_b; gpr_bypass_b <= byp_b;
gpr_bypass_c <= byp_c; gpr_bypass_c <= byp_c;


gpr_tag_stall <= tag_a_stall or tag_b_stall or tag_c_stall; gpr_tag_stall <= tag_a.valid or tag_b.valid or tag_c.valid;


incr_tag := curr_tag; incr_tag := curr_tag;
instr_tag.tag <= curr_tag; instr_tag.tag <= curr_tag;

@ -279,11 +279,11 @@ begin
gpr_c_read_valid_in => gpr_c_read_valid, gpr_c_read_valid_in => gpr_c_read_valid,
gpr_c_read_in => gpr_c_read, gpr_c_read_in => gpr_c_read,


execute_next_tag => execute_bypass.tag, execute_next_bypass => execute_bypass,
execute_next_cr_tag => execute_cr_bypass.tag, execute_next_cr_tag => execute_cr_bypass.tag,
execute2_next_tag => execute2_bypass.tag, execute2_next_bypass => execute2_bypass,
execute2_next_cr_tag => execute2_cr_bypass.tag, execute2_next_cr_tag => execute2_cr_bypass.tag,
writeback_tag => writeback_bypass.tag, writeback_bypass => writeback_bypass,


cr_read_in => cr_read_valid, cr_read_in => cr_read_valid,
cr_write_in => cr_write_valid, cr_write_in => cr_write_valid,

@ -1938,8 +1938,9 @@ begin
v.fp_exception_next := '0'; v.fp_exception_next := '0';
end if; end if;


bypass_data.tag.valid <= e_in.write_reg_enable and bypass_valid; bypass_data.tag.valid <= v.e.write_enable and bypass_valid;
bypass_data.tag.tag <= e_in.instr_tag.tag; bypass_data.tag.tag <= v.e.instr_tag.tag;
bypass_data.reg <= v.e.write_reg;
bypass_data.data <= alu_result; bypass_data.data <= alu_result;


bypass_cr_data.tag.valid <= e_in.output_cr and bypass_valid; bypass_cr_data.tag.valid <= e_in.output_cr and bypass_valid;
@ -2250,6 +2251,7 @@ begin


bypass2_data.tag.valid <= ex1.e.write_enable and bypass_valid; bypass2_data.tag.valid <= ex1.e.write_enable and bypass_valid;
bypass2_data.tag.tag <= ex1.e.instr_tag.tag; bypass2_data.tag.tag <= ex1.e.instr_tag.tag;
bypass2_data.reg <= ex1.e.write_reg;
bypass2_data.data <= ex_result; bypass2_data.data <= ex_result;


bypass2_cr_data.tag.valid <= (ex1.e.write_cr_enable or (ex1.e.rc and ex1.e.write_enable)) bypass2_cr_data.tag.valid <= (ex1.e.write_cr_enable or (ex1.e.rc and ex1.e.write_enable))

@ -203,6 +203,7 @@ begin
-- Register write data bypass to decode2 -- Register write data bypass to decode2
wb_bypass.tag.tag <= complete_out.tag; wb_bypass.tag.tag <= complete_out.tag;
wb_bypass.tag.valid <= complete_out.valid and w_out.write_enable; wb_bypass.tag.valid <= complete_out.valid and w_out.write_enable;
wb_bypass.reg <= w_out.write_reg;
wb_bypass.data <= w_out.write_data; wb_bypass.data <= w_out.write_data;


end process; end process;

Loading…
Cancel
Save