-- 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
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)
);
)
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,
library work;
use work.common.all;
use work.decode_types.all;
+use work.insn_helpers.all;
entity decode1 is
generic (
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;
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);
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;
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;
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
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
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))));
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 =>
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';
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
);
port(
clk : in std_logic;
+ stall : in std_ulogic;
+ d1_in : in Decode1ToRegisterFileType;
d_in : in Decode2ToRegisterFileType;
d_out : out RegisterFileToDecode2Type;
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
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;