mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-05 02:35:12 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
|
||||
16
fetch1.vhdl
16
fetch1.vhdl
@@ -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;
|
||||
-- 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);
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user