diff --git a/common.vhdl b/common.vhdl index 776d74c..041a5f2 100644 --- a/common.vhdl +++ b/common.vhdl @@ -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; diff --git a/fetch1.vhdl b/fetch1.vhdl index 4980b05..b6c2205 100644 --- a/fetch1.vhdl +++ b/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'; diff --git a/writeback.vhdl b/writeback.vhdl index 2eb9998..6a86fb7 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -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;