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 3 weeks ago
parent 52d8f28d03
commit f6a839a86b

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

gpr_bypass_a : out std_ulogic_vector(1 downto 0);
gpr_bypass_b : out std_ulogic_vector(1 downto 0);
gpr_bypass_c : out std_ulogic_vector(1 downto 0);
-- Note on gpr_bypass_*: bits 1 to 3 are a 1-hot encoding of which
-- bypass source we may possibly need to use; bit 0 is 1 if the bypass
-- 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);

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

byp_a := "00";
byp_a := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then
byp_a := "01";
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";
byp_a(1) := '1';
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
byp_b := "01";
elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_b) then
byp_b := "10";
elsif tag_match(complete_in, tag_b) then
byp_b := "11";
byp_b(1) := '1';
end if;
if EX1_BYPASS and tag_match(execute2_next_tag, tag_b) then
byp_b(2) := '1';
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
byp_c := "01";
elsif EX1_BYPASS and tag_match(execute2_next_tag, tag_c) then
byp_c := "10";
elsif tag_match(complete_in, tag_c) then
byp_c := "11";
byp_c(1) := '1';
end if;
if EX1_BYPASS and tag_match(execute2_next_tag, tag_c) then
byp_c(2) := '1';
end if;
if tag_match(complete_in, tag_c) then
byp_c(3) := '1';
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_b <= byp_b;
gpr_bypass_c <= byp_c;

gpr_tag_stall <= (tag_a.valid and not (or (byp_a))) or
(tag_b.valid and not (or (byp_b))) or
(tag_c.valid and not (or (byp_c)));
gpr_tag_stall <= (tag_a.valid and gpr_a_read_valid_in and not byp_a(0)) or
(tag_b.valid and gpr_b_read_valid_in and not byp_b(0)) or
(tag_c.valid and gpr_c_read_valid_in and not byp_c(0));

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

@ -201,6 +201,23 @@ architecture behaviour of decode2 is
end case;
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
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 : 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 : 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 : 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_write_valid : std_ulogic;
@ -694,53 +711,38 @@ begin
ov_write_valid <= v.output_ov;

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

case cr_bypass is

Loading…
Cancel
Save