diff --git a/control.vhdl b/control.vhdl index e8c8068..b75fcc1 100644 --- a/control.vhdl +++ b/control.vhdl @@ -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; diff --git a/decode2.vhdl b/decode2.vhdl index cc241a2..fd7434c 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -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