fetch1: Streamline next NIA generation further

This reduces the number of possible sources for the next NIA from 4
down to 3, by routing interrupt vector addresses through the
r_int.next_nia register, as is already done for reset.  This adds one
extra cycle of latency when taking interrupts.  During this extra cycle,
i_out.req is 0.

Writeback now no longer combines redirects (branches, rfid, isync)
with interrupts; they are presented separately to fetch1.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/422/head
Paul Mackerras 1 year ago
parent e92d49375f
commit f34a54d295

@ -758,11 +758,14 @@ package common is
br_nia : std_ulogic_vector(63 downto 0);
br_last : std_ulogic;
br_taken : std_ulogic;
interrupt : std_ulogic;
intr_vec : std_ulogic_vector(11 downto 0);
end record;
constant WritebackToFetch1Init : WritebackToFetch1Type :=
(redirect => '0', virt_mode => '0', priv_mode => '0', big_endian => '0',
mode_32bit => '0', redirect_nia => (others => '0'),
br_last => '0', br_taken => '0', br_nia => (others => '0'));
br_last => '0', br_taken => '0', br_nia => (others => '0'),
interrupt => '0', intr_vec => x"000");

type WritebackToRegisterFileType is record
write_reg : gspr_index_t;

@ -70,6 +70,7 @@ begin
" P:" & std_ulogic'image(r_next.priv_mode) &
" E:" & std_ulogic'image(r_next.big_endian) &
" 32:" & std_ulogic'image(r_next_int.mode_32bit) &
" I:" & std_ulogic'image(w_in.interrupt) &
" R:" & std_ulogic'image(w_in.redirect) & std_ulogic'image(d_in.redirect) &
" S:" & std_ulogic'image(stall_in) &
" T:" & std_ulogic'image(stop_in) &
@ -143,7 +144,7 @@ begin
v_int := r_int;
v.predicted := '0';
v.pred_ntaken := '0';
v.req := not (rst or stop_in);
v.req := not (rst or w_in.interrupt or stop_in);
-- reduce metavalue warnings in sim
if is_X(rst) then
v.req := '0';
@ -175,8 +176,8 @@ begin
v_int.next_nia := std_ulogic_vector(unsigned(next_nia) + 4);

-- Use v_int.next_nia as the BTC read address before it gets possibly
-- overridden with the reset address or the predicted branch target
-- address, in order to improve timing. If it gets overridden then
-- overridden with the reset or interrupt address or the predicted branch
-- target address, in order to improve timing. If it gets overridden then
-- rd_is_niap4 gets cleared to indicate that the BTC data doesn't apply.
btc_rd_addr <= unsigned(v_int.next_nia(BTC_ADDR_BITS + 1 downto 2));
v_int.rd_is_niap4 := '1';
@ -187,6 +188,10 @@ begin
else
v_int.next_nia := RESET_ADDRESS;
end if;
elsif w_in.interrupt = '1' then
v_int.next_nia := 52x"0" & w_in.intr_vec(11 downto 2) & "00";
end if;
if rst /= '0' or w_in.interrupt = '1' then
v.virt_mode := '0';
v.priv_mode := '1';
v.big_endian := '0';
@ -196,7 +201,7 @@ begin

-- If there is a valid entry in the BTC which corresponds to the next instruction,
-- use that to predict the address of the instruction after that.
if rst = '0' and w_in.redirect = '0' and d_in.redirect = '0' and
if rst = '0' and w_in.interrupt = '0' and w_in.redirect = '0' and d_in.redirect = '0' and
btc_rd_valid = '1' and r_int.rd_is_niap4 = '1' and
btc_rd_data(BTC_WIDTH - 2) = r.virt_mode and
btc_rd_data(BTC_WIDTH - 3 downto BTC_TARGET_BITS)
@ -211,7 +216,8 @@ begin

-- If the last NIA value went down with a stop mark, it didn't get
-- executed, and hence we shouldn't increment NIA.
advance_nia <= rst or w_in.redirect or d_in.redirect or (not r.stop_mark and not stall_in);
advance_nia <= rst or w_in.interrupt or w_in.redirect or d_in.redirect or
(not r.stop_mark and not stall_in);
-- reduce metavalue warnings in sim
if is_X(rst) then
advance_nia <= '1';

@ -160,30 +160,21 @@ begin
end if;

-- Outputs to fetch1
f.interrupt := intr;
f.intr_vec := std_ulogic_vector(to_unsigned(vec, 12));
f.redirect := e_in.redirect;
f.redirect_nia := e_in.write_data;
f.br_nia := e_in.last_nia;
f.br_last := e_in.br_last;
f.br_last := e_in.br_last and not intr;
f.br_taken := e_in.br_taken;
if intr = '1' then
f.redirect := '1';
f.br_last := '0';
f.redirect_nia := std_ulogic_vector(to_unsigned(vec, 64));
f.virt_mode := '0';
f.priv_mode := '1';
-- XXX need an interrupt LE bit here, e.g. from LPCR
f.big_endian := '0';
f.mode_32bit := '0';
else
f.redirect_nia := e_in.write_data;
-- send MSR[IR], ~MSR[PR], ~MSR[LE] and ~MSR[SF] up to fetch1
f.virt_mode := e_in.redir_mode(3);
f.priv_mode := e_in.redir_mode(2);
f.big_endian := e_in.redir_mode(1);
f.mode_32bit := e_in.redir_mode(0);
end if;

f_out <= f;
flush_out <= f_out.redirect;
flush_out <= f_out.redirect or intr;

-- Register write data bypass to decode2
wb_bypass.tag.tag <= complete_out.tag;

Loading…
Cancel
Save