diff --git a/common.vhdl b/common.vhdl index 39ebfb1..0349a6e 100644 --- a/common.vhdl +++ b/common.vhdl @@ -276,6 +276,12 @@ package common is redirect_nia : std_ulogic_vector(63 downto 0); end record; + type Decode1ToRegisterFileType is record + reg_1_addr : gspr_index_t; + reg_2_addr : gspr_index_t; + reg_3_addr : gspr_index_t; + end record; + type bypass_data_t is record tag : instr_tag_t; data : std_ulogic_vector(63 downto 0); diff --git a/core.vhdl b/core.vhdl index 641c12d..764141a 100644 --- a/core.vhdl +++ b/core.vhdl @@ -63,6 +63,7 @@ architecture behave of core is -- decode signals signal decode1_to_decode2: Decode1ToDecode2Type; signal decode1_to_fetch1: Decode1ToFetch1Type; + signal decode1_to_register_file: Decode1ToRegisterFileType; signal decode2_to_execute1: Decode2ToExecute1Type; -- register file signals @@ -285,6 +286,7 @@ begin f_in => icache_to_decode1, d_out => decode1_to_decode2, f_out => decode1_to_fetch1, + r_out => decode1_to_register_file, log_out => log_data(109 downto 97) ); @@ -329,6 +331,8 @@ begin ) port map ( clk => clk, + stall => decode2_stall_out, + d1_in => decode1_to_register_file, d_in => decode2_to_register_file, d_out => register_file_to_decode2, w_in => writeback_to_register_file, diff --git a/decode1.vhdl b/decode1.vhdl index 5ee7b57..36d511b 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -5,6 +5,7 @@ use ieee.numeric_std.all; library work; use work.common.all; use work.decode_types.all; +use work.insn_helpers.all; entity decode1 is generic ( @@ -24,6 +25,7 @@ entity decode1 is f_in : in IcacheToDecode1Type; f_out : out Decode1ToFetch1Type; d_out : out Decode1ToDecode2Type; + r_out : out Decode1ToRegisterFileType; log_out : out std_ulogic_vector(12 downto 0) ); end entity decode1; @@ -628,6 +630,7 @@ begin decode1_1: process(all) variable v : Decode1ToDecode2Type; + variable vr : Decode1ToRegisterFileType; variable vi : reg_internal_t; variable majorop : major_opcode_t; variable minor4op : std_ulogic_vector(10 downto 0); @@ -636,6 +639,8 @@ begin variable br_target : std_ulogic_vector(61 downto 0); variable br_offset : signed(23 downto 0); variable bv : br_predictor_t; + variable fprs, fprabc : std_ulogic; + variable in3rc : std_ulogic; begin v := Decode1ToDecode2Init; vi := reg_internal_t_init; @@ -646,6 +651,10 @@ begin v.stop_mark := f_in.stop_mark; v.big_endian := f_in.big_endian; + fprs := '0'; + fprabc := '0'; + in3rc := '0'; + if f_in.valid = '1' then report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia); end if; @@ -665,6 +674,7 @@ begin minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6); vi.override := not decode_op_4_valid(to_integer(unsigned(minor4op))); v.decode := decode_op_4_array(to_integer(unsigned(f_in.insn(5 downto 0)))); + in3rc := '1'; when 31 => -- major opcode 31, lots of things @@ -688,6 +698,10 @@ begin when others => end case; end if; + if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then + -- lower half of column 23 has FP loads and stores + fprs := '1'; + end if; when 16 => -- Predict backward branches as taken, forward as untaken @@ -715,6 +729,12 @@ begin when 30 => v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1)))); + when 52 | 53 | 54 | 55 => + -- stfd[u] and stfs[u] + if HAS_FPU then + fprs := '1'; + end if; + when 58 => v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0)))); @@ -725,6 +745,9 @@ begin if f_in.insn(5) = '0' and not std_match(f_in.insn(10 downto 1), "11-1001110") then vi.override := '1'; end if; + in3rc := '1'; + fprabc := '1'; + fprs := '1'; end if; when 62 => @@ -738,11 +761,23 @@ begin else v.decode := decode_op_63h_array(to_integer(unsigned(f_in.insn(4 downto 1)))); end if; + in3rc := '1'; + fprabc := '1'; + fprs := '1'; end if; when others => end case; + -- Work out GPR/FPR read addresses + vr.reg_1_addr := fprabc & insn_ra(f_in.insn); + vr.reg_2_addr := fprabc & insn_rb(f_in.insn); + if in3rc = '1' then + vr.reg_3_addr := fprabc & insn_rcreg(f_in.insn); + else + vr.reg_3_addr := fprs & insn_rs(f_in.insn); + end if; + if f_in.fetch_failed = '1' then v.valid := '1'; vi.override := '1'; @@ -788,6 +823,8 @@ begin f_out.redirect <= br.predict; f_out.redirect_nia <= br_target & "00"; flush_out <= bv.predict or br.predict; + + r_out <= vr; end process; d1_log: if LOG_LENGTH > 0 generate diff --git a/register_file.vhdl b/register_file.vhdl index dcce0a4..bc40c3f 100644 --- a/register_file.vhdl +++ b/register_file.vhdl @@ -14,7 +14,9 @@ entity register_file is ); port( clk : in std_logic; + stall : in std_ulogic; + d1_in : in Decode1ToRegisterFileType; d_in : in Decode2ToRegisterFileType; d_out : out RegisterFileToDecode2Type; @@ -39,9 +41,13 @@ architecture behaviour of register_file is signal rd_port_b : std_ulogic_vector(63 downto 0); signal dbg_data : std_ulogic_vector(63 downto 0); signal dbg_ack : std_ulogic; + signal addr_1_reg : gspr_index_t; + signal addr_2_reg : gspr_index_t; + signal addr_3_reg : gspr_index_t; begin -- synchronous writes register_write_0: process(clk) + variable a_addr, b_addr, c_addr : gspr_index_t; variable w_addr : gspr_index_t; begin if rising_edge(clk) then @@ -56,6 +62,19 @@ begin assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure; registers(to_integer(unsigned(w_addr))) <= w_in.write_data; end if; + + a_addr := d1_in.reg_1_addr; + b_addr := d1_in.reg_2_addr; + c_addr := d1_in.reg_3_addr; + + if stall = '0' then + addr_1_reg <= a_addr; + addr_2_reg <= b_addr; + addr_3_reg <= c_addr; + end if; + assert (d_in.read1_enable = '0') or (d_in.read1_reg = addr_1_reg) severity failure; + assert (d_in.read2_enable = '0') or (d_in.read2_reg = addr_2_reg) severity failure; + assert (d_in.read3_enable = '0') or (d_in.read3_reg = addr_3_reg) severity failure; end if; end process register_write_0;