control: Use a 1-hot encoding for bypass enables

Instead of creating a 2-bit encoded bypass selector, we now have a
4-bit encoding where bits 1 to 3 enable separate bypass sources, and
bit 0 indicates if any bypass should be used.  This results in
slightly simpler logic and better timing.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/436/head
Paul Mackerras 4 weeks ago
parent 52d8f28d03
commit f6a839a86b

@ -45,9 +45,13 @@ entity control is
valid_out : out std_ulogic; valid_out : out std_ulogic;
stopped_out : out std_ulogic; stopped_out : out std_ulogic;


gpr_bypass_a : out std_ulogic_vector(1 downto 0); -- Note on gpr_bypass_*: bits 1 to 3 are a 1-hot encoding of which
gpr_bypass_b : out std_ulogic_vector(1 downto 0); -- bypass source we may possibly need to use; bit 0 is 1 if the bypass
gpr_bypass_c : out std_ulogic_vector(1 downto 0); -- value should be used (i.e. any of bits 1-3 are 1 and the
-- corresponding gpr_x_read_valid_in is also 1).
gpr_bypass_a : out std_ulogic_vector(3 downto 0);
gpr_bypass_b : out std_ulogic_vector(3 downto 0);
gpr_bypass_c : out std_ulogic_vector(3 downto 0);
cr_bypass : out std_ulogic_vector(1 downto 0); cr_bypass : out std_ulogic_vector(1 downto 0);


instr_tag_out : out instr_tag_t instr_tag_out : out instr_tag_t
@ -152,9 +156,9 @@ begin
variable tag_s : instr_tag_t; variable tag_s : instr_tag_t;
variable tag_t : instr_tag_t; variable tag_t : instr_tag_t;
variable incr_tag : tag_number_t; variable incr_tag : tag_number_t;
variable byp_a : std_ulogic_vector(1 downto 0); variable byp_a : std_ulogic_vector(3 downto 0);
variable byp_b : std_ulogic_vector(1 downto 0); variable byp_b : std_ulogic_vector(3 downto 0);
variable byp_c : std_ulogic_vector(1 downto 0); variable byp_c : std_ulogic_vector(3 downto 0);
variable tag_cr : instr_tag_t; variable tag_cr : instr_tag_t;
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;
@ -163,57 +167,66 @@ begin
tag_a := instr_tag_init; tag_a := instr_tag_init;
for i in tag_number_t loop for i in tag_number_t loop
if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then
tag_a.valid := gpr_a_read_valid_in; tag_a.valid := '1';
tag_a.tag := i; tag_a.tag := i;
end if; end if;
end loop; end loop;
tag_b := instr_tag_init; tag_b := instr_tag_init;
for i in tag_number_t loop for i in tag_number_t loop
if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_b_read_in then if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_b_read_in then
tag_b.valid := gpr_b_read_valid_in; tag_b.valid := '1';
tag_b.tag := i; tag_b.tag := i;
end if; end if;
end loop; end loop;
tag_c := instr_tag_init; tag_c := instr_tag_init;
for i in tag_number_t loop for i in tag_number_t loop
if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then
tag_c.valid := gpr_c_read_valid_in; tag_c.valid := '1';
tag_c.tag := i; tag_c.tag := i;
end if; end if;
end loop; end loop;


byp_a := "00"; byp_a := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then
byp_a := "01"; byp_a(1) := '1';
elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_a) then
byp_a := "10";
elsif tag_match(complete_in, tag_a) then
byp_a := "11";
end if; end if;
byp_b := "00"; if EX1_BYPASS and tag_match(execute2_next_tag, tag_a) then
byp_a(2) := '1';
end if;
if tag_match(complete_in, tag_a) then
byp_a(3) := '1';
end if;
byp_a(0) := gpr_a_read_valid_in and (byp_a(1) or byp_a(2) or byp_a(3));
byp_b := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_b) then if EX1_BYPASS and tag_match(execute_next_tag, tag_b) then
byp_b := "01"; byp_b(1) := '1';
elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_b) then end if;
byp_b := "10"; if EX1_BYPASS and tag_match(execute2_next_tag, tag_b) then
elsif tag_match(complete_in, tag_b) then byp_b(2) := '1';
byp_b := "11";
end if; end if;
byp_c := "00"; if tag_match(complete_in, tag_b) then
byp_b(3) := '1';
end if;
byp_b(0) := gpr_b_read_valid_in and (byp_b(1) or byp_b(2) or byp_b(3));
byp_c := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_c) then if EX1_BYPASS and tag_match(execute_next_tag, tag_c) then
byp_c := "01"; byp_c(1) := '1';
elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_c) then end if;
byp_c := "10"; if EX1_BYPASS and tag_match(execute2_next_tag, tag_c) then
elsif tag_match(complete_in, tag_c) then byp_c(2) := '1';
byp_c := "11"; end if;
if tag_match(complete_in, tag_c) then
byp_c(3) := '1';
end if; end if;
byp_c(0) := gpr_c_read_valid_in and (byp_c(1) or byp_c(2) or byp_c(3));


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.valid and not (or (byp_a))) or gpr_tag_stall <= (tag_a.valid and gpr_a_read_valid_in and not byp_a(0)) or
(tag_b.valid and not (or (byp_b))) or (tag_b.valid and gpr_b_read_valid_in and not byp_b(0)) or
(tag_c.valid and not (or (byp_c))); (tag_c.valid and gpr_c_read_valid_in and not byp_c(0));


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

@ -201,6 +201,23 @@ architecture behaviour of decode2 is
end case; end case;
end; end;


function andor (mask_a : std_ulogic; val_a : std_ulogic_vector(63 downto 0);
mask_b : std_ulogic; val_b : std_ulogic_vector(63 downto 0);
mask_c : std_ulogic; val_c : std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable t : std_ulogic_vector(63 downto 0) := (others => '0');
begin
if mask_a = '1' then
t := val_a;
end if;
if mask_b = '1' then
t := t or val_b;
end if;
if mask_c = '1' then
t := t or val_c;
end if;
return t;
end;

-- control signals that are derived from insn_type -- control signals that are derived from insn_type
type mux_select_array_t is array(insn_type_t) of std_ulogic_vector(2 downto 0); type mux_select_array_t is array(insn_type_t) of std_ulogic_vector(2 downto 0);


@ -269,15 +286,15 @@ architecture behaviour of decode2 is


signal gpr_a_read_valid : std_ulogic; signal gpr_a_read_valid : std_ulogic;
signal gpr_a_read : gspr_index_t; signal gpr_a_read : gspr_index_t;
signal gpr_a_bypass : std_ulogic_vector(1 downto 0); signal gpr_a_bypass : std_ulogic_vector(3 downto 0);


signal gpr_b_read_valid : std_ulogic; signal gpr_b_read_valid : std_ulogic;
signal gpr_b_read : gspr_index_t; signal gpr_b_read : gspr_index_t;
signal gpr_b_bypass : std_ulogic_vector(1 downto 0); signal gpr_b_bypass : std_ulogic_vector(3 downto 0);


signal gpr_c_read_valid : std_ulogic; signal gpr_c_read_valid : std_ulogic;
signal gpr_c_read : gspr_index_t; signal gpr_c_read : gspr_index_t;
signal gpr_c_bypass : std_ulogic_vector(1 downto 0); signal gpr_c_bypass : std_ulogic_vector(3 downto 0);


signal cr_read_valid : std_ulogic; signal cr_read_valid : std_ulogic;
signal cr_write_valid : std_ulogic; signal cr_write_valid : std_ulogic;
@ -694,53 +711,38 @@ begin
ov_write_valid <= v.output_ov; ov_write_valid <= v.output_ov;


-- See if any of the operands can get their value via the bypass path. -- See if any of the operands can get their value via the bypass path.
if dc2.busy = '0' or gpr_a_bypass /= "00" then if gpr_a_bypass(0) = '1' then
case gpr_a_bypass is v.e.read_data1 := andor(gpr_a_bypass(1), execute_bypass.data,
when "01" => gpr_a_bypass(2), execute2_bypass.data,
v.e.read_data1 := execute_bypass.data; gpr_a_bypass(3), writeback_bypass.data);
when "10" => elsif dc2.busy = '0' then
v.e.read_data1 := execute2_bypass.data;
when "11" =>
v.e.read_data1 := writeback_bypass.data;
when others =>
if decoded_reg_a.reg_valid = '1' then if decoded_reg_a.reg_valid = '1' then
v.e.read_data1 := r_in.read1_data; v.e.read_data1 := r_in.read1_data;
else else
v.e.read_data1 := decoded_reg_a.data; v.e.read_data1 := decoded_reg_a.data;
end if; end if;
end case;
end if; end if;
if dc2.busy = '0' or gpr_b_bypass /= "00" then if gpr_b_bypass(0) = '1' then
case gpr_b_bypass is v.e.read_data2 := andor(gpr_b_bypass(1), execute_bypass.data,
when "01" => gpr_b_bypass(2), execute2_bypass.data,
v.e.read_data2 := execute_bypass.data; gpr_b_bypass(3), writeback_bypass.data);
when "10" => elsif dc2.busy = '0' then
v.e.read_data2 := execute2_bypass.data;
when "11" =>
v.e.read_data2 := writeback_bypass.data;
when others =>
if decoded_reg_b.reg_valid = '1' then if decoded_reg_b.reg_valid = '1' then
v.e.read_data2 := r_in.read2_data; v.e.read_data2 := r_in.read2_data;
else else
v.e.read_data2 := decoded_reg_b.data; v.e.read_data2 := decoded_reg_b.data;
end if; end if;
end case;
end if; end if;
if dc2.busy = '0' or gpr_c_bypass /= "00" then if gpr_c_bypass(0) = '1' then
case gpr_c_bypass is v.e.read_data3 := andor(gpr_c_bypass(1), execute_bypass.data,
when "01" => gpr_c_bypass(2), execute2_bypass.data,
v.e.read_data3 := execute_bypass.data; gpr_c_bypass(3), writeback_bypass.data);
when "10" => elsif dc2.busy = '0' then
v.e.read_data3 := execute2_bypass.data;
when "11" =>
v.e.read_data3 := writeback_bypass.data;
when others =>
if decoded_reg_c.reg_valid = '1' then if decoded_reg_c.reg_valid = '1' then
v.e.read_data3 := r_in.read3_data; v.e.read_data3 := r_in.read3_data;
else else
v.e.read_data3 := decoded_reg_c.data; v.e.read_data3 := decoded_reg_c.data;
end if; end if;
end case;
end if; end if;


case cr_bypass is case cr_bypass is

Loading…
Cancel
Save