@ -8,7 +8,8 @@ use work.common.all;
entity fetch1 is
entity fetch1 is
generic(
generic(
RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0')
ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
HAS_BTC : boolean := true
);
);
port(
port(
clk : in std_ulogic;
clk : in std_ulogic;
@ -17,6 +18,7 @@ entity fetch1 is
-- Control inputs:
-- Control inputs:
stall_in : in std_ulogic;
stall_in : in std_ulogic;
flush_in : in std_ulogic;
flush_in : in std_ulogic;
inval_btc : in std_ulogic;
stop_in : in std_ulogic;
stop_in : in std_ulogic;
alt_reset_in : in std_ulogic;
alt_reset_in : in std_ulogic;
@ -37,10 +39,25 @@ end entity fetch1;
architecture behaviour of fetch1 is
architecture behaviour of fetch1 is
type reg_internal_t is record
type reg_internal_t is record
mode_32bit: std_ulogic;
mode_32bit: std_ulogic;
rd_is_niap4: std_ulogic;
predicted: std_ulogic;
predicted_nia: std_ulogic_vector(63 downto 0);
end record;
end record;
signal r, r_next : Fetch1ToIcacheType;
signal r, r_next : Fetch1ToIcacheType;
signal r_int, r_next_int : reg_internal_t;
signal r_int, r_next_int : reg_internal_t;
signal advance_nia : std_ulogic;
signal log_nia : std_ulogic_vector(42 downto 0);
signal log_nia : std_ulogic_vector(42 downto 0);
constant BTC_ADDR_BITS : integer := 10;
constant BTC_TAG_BITS : integer := 62 - BTC_ADDR_BITS;
constant BTC_TARGET_BITS : integer := 62;
constant BTC_SIZE : integer := 2 ** BTC_ADDR_BITS;
constant BTC_WIDTH : integer := BTC_TAG_BITS + BTC_TARGET_BITS;
type btc_mem_type is array (0 to BTC_SIZE - 1) of std_ulogic_vector(BTC_WIDTH - 1 downto 0);
signal btc_rd_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0) := (others => '0');
signal btc_rd_valid : std_ulogic := '0';
begin
begin
regs : process(clk)
regs : process(clk)
@ -56,15 +73,70 @@ begin
" R:" & std_ulogic'image(e_in.redirect) & std_ulogic'image(d_in.redirect) &
" R:" & std_ulogic'image(e_in.redirect) & std_ulogic'image(d_in.redirect) &
" S:" & std_ulogic'image(stall_in) &
" S:" & std_ulogic'image(stall_in) &
" T:" & std_ulogic'image(stop_in) &
" T:" & std_ulogic'image(stop_in) &
" nia:" & to_hstring(r_next.nia) &
" nia:" & to_hstring(r_next.nia);
" SM:" & std_ulogic'image(r_next.stop_mark);
end if;
if rst = '1' or e_in.redirect = '1' or d_in.redirect = '1' or stall_in = '0' then
r.virt_mode <= r_next.virt_mode;
r.priv_mode <= r_next.priv_mode;
r.big_endian <= r_next.big_endian;
r_int.mode_32bit <= r_next_int.mode_32bit;
end if;
end if;
r <= r_next;
if advance_nia = '1' then
r_int <= r_next_int;
r.predicted <= r_next.predicted;
r.nia <= r_next.nia;
r_int.predicted <= r_next_int.predicted;
r_int.predicted_nia <= r_next_int.predicted_nia;
r_int.rd_is_niap4 <= r_next.sequential;
end if;
r.sequential <= r_next.sequential and advance_nia;
-- always send the up-to-date stop mark and req
r.stop_mark <= stop_in;
r.req <= not rst;
end if;
end if;
end process;
end process;
log_out <= log_nia;
log_out <= log_nia;
btc : if HAS_BTC generate
signal btc_memory : btc_mem_type;
attribute ram_style : string;
attribute ram_style of btc_memory : signal is "block";
signal btc_valids : std_ulogic_vector(BTC_SIZE - 1 downto 0);
attribute ram_style of btc_valids : signal is "distributed";
signal btc_wr : std_ulogic;
signal btc_wr_data : std_ulogic_vector(BTC_WIDTH - 1 downto 0);
signal btc_wr_addr : std_ulogic_vector(BTC_ADDR_BITS - 1 downto 0);
signal btc_wr_v : std_ulogic;
begin
btc_wr_data <= e_in.br_nia(63 downto BTC_ADDR_BITS + 2) &
e_in.redirect_nia(63 downto 2);
btc_wr_addr <= e_in.br_nia(BTC_ADDR_BITS + 1 downto 2);
btc_wr <= e_in.br_last;
btc_wr_v <= e_in.br_taken;
btc_ram : process(clk)
variable raddr : unsigned(BTC_ADDR_BITS - 1 downto 0);
begin
if rising_edge(clk) then
raddr := unsigned(r.nia(BTC_ADDR_BITS + 1 downto 2)) +
to_unsigned(2, BTC_ADDR_BITS);
if advance_nia = '1' then
btc_rd_data <= btc_memory(to_integer(raddr));
btc_rd_valid <= btc_valids(to_integer(raddr));
end if;
if btc_wr = '1' then
btc_memory(to_integer(unsigned(btc_wr_addr))) <= btc_wr_data;
end if;
if inval_btc = '1' or rst = '1' then
btc_valids <= (others => '0');
elsif btc_wr = '1' then
btc_valids(to_integer(unsigned(btc_wr_addr))) <= btc_wr_v;
end if;
end if;
end process;
end generate;
comb : process(all)
comb : process(all)
variable v : Fetch1ToIcacheType;
variable v : Fetch1ToIcacheType;
variable v_int : reg_internal_t;
variable v_int : reg_internal_t;
@ -72,6 +144,8 @@ begin
v := r;
v := r;
v_int := r_int;
v_int := r_int;
v.sequential := '0';
v.sequential := '0';
v.predicted := '0';
v_int.predicted := '0';
if rst = '1' then
if rst = '1' then
if alt_reset_in = '1' then
if alt_reset_in = '1' then
@ -83,6 +157,7 @@ begin
v.priv_mode := '1';
v.priv_mode := '1';
v.big_endian := '0';
v.big_endian := '0';
v_int.mode_32bit := '0';
v_int.mode_32bit := '0';
v_int.predicted_nia := (others => '0');
elsif e_in.redirect = '1' then
elsif e_in.redirect = '1' then
v.nia := e_in.redirect_nia(63 downto 2) & "00";
v.nia := e_in.redirect_nia(63 downto 2) & "00";
if e_in.mode_32bit = '1' then
if e_in.mode_32bit = '1' then
@ -97,22 +172,26 @@ begin
if r_int.mode_32bit = '1' then
if r_int.mode_32bit = '1' then
v.nia(63 downto 32) := (others => '0');
v.nia(63 downto 32) := (others => '0');
end if;
end if;
elsif stall_in = '0' then
elsif r_int.predicted = '1' then
v.nia := r_int.predicted_nia;
-- If the last NIA value went down with a stop mark, it didn't get
v.predicted := '1';
-- executed, and hence we shouldn't increment NIA.
if r.stop_mark = '0' then
if r_int.mode_32bit = '0' then
v.nia := std_ulogic_vector(unsigned(r.nia) + 4);
else
else
v.nia := x"00000000" & std_ulogic_vector(unsigned(r.nia(31 downto 0)) + 4);
end if;
v.sequential := '1';
v.sequential := '1';
v.nia := std_ulogic_vector(unsigned(r.nia) + 4);
if r_int.mode_32bit = '1' then
v.nia(63 downto 32) := x"00000000";
end if;
end if;
if btc_rd_valid = '1' and r_int.rd_is_niap4 = '1' and
btc_rd_data(BTC_WIDTH - 1 downto BTC_TARGET_BITS)
= v.nia(BTC_TAG_BITS + BTC_ADDR_BITS + 1 downto BTC_ADDR_BITS + 2) then
v_int.predicted := '1';
end if;
end if;
end if;
v_int.predicted_nia := btc_rd_data(BTC_TARGET_BITS - 1 downto 0) & "00";
v.req := not rst and not stop_in;
-- If the last NIA value went down with a stop mark, it didn't get
v.stop_mark := stop_in;
-- executed, and hence we shouldn't increment NIA.
advance_nia <= rst or e_in.redirect or d_in.redirect or (not r.stop_mark and not stall_in);
r_next <= v;
r_next <= v;
r_next_int <= v_int;
r_next_int <= v_int;