is_32bit : std_ulogic;
repeat : std_ulogic;
second : std_ulogic;
+ msr : std_ulogic_vector(63 downto 0);
end record;
constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type :=
(valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
write_reg => (others => '0'),
length => (others => '0'),
mode_32bit => '0', is_32bit => '0',
- repeat => '0', second => '0');
+ repeat => '0', second => '0',
+ msr => (others => '0'));
type Loadstore1ToExecute1Type is record
busy : std_ulogic;
- exception : std_ulogic;
- alignment : std_ulogic;
- invalid : std_ulogic;
- perm_error : std_ulogic;
- rc_error : std_ulogic;
- badtree : std_ulogic;
- segment_fault : std_ulogic;
- instr_fault : std_ulogic;
end record;
type Loadstore1ToDcacheType is record
xerc : xer_common_t;
rc : std_ulogic;
store_done : std_ulogic;
+ interrupt : std_ulogic;
+ intr_vec : integer range 0 to 16#fff#;
+ srr0: std_ulogic_vector(63 downto 0);
+ srr1: std_ulogic_vector(31 downto 0);
end record;
constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType :=
- (valid => '0', instr_tag => instr_tag_init, write_enable => '0', xerc => xerc_init,
- rc => '0', store_done => '0', write_data => (others => '0'), others => (others => '0'));
+ (valid => '0', instr_tag => instr_tag_init, write_enable => '0',
+ write_reg => (others => '0'), write_data => (others => '0'),
+ xerc => xerc_init, rc => '0', store_done => '0',
+ interrupt => '0', intr_vec => 0,
+ srr0 => (others => '0'), srr1 => (others => '0'));
type Execute1ToWritebackType is record
valid: std_ulogic;
br_last: std_ulogic;
br_taken: std_ulogic;
abs_br: std_ulogic;
- srr1: std_ulogic_vector(63 downto 0);
+ srr1: std_ulogic_vector(31 downto 0);
+ msr: std_ulogic_vector(63 downto 0);
end record;
constant Execute1ToWritebackInit : Execute1ToWritebackType :=
(valid => '0', instr_tag => instr_tag_init, rc => '0', mode_32bit => '0',
write_cr_data => (others => '0'), write_reg => (others => '0'),
interrupt => '0', intr_vec => 0, redirect => '0', redir_mode => "0000",
last_nia => (others => '0'), br_offset => (others => '0'),
- br_last => '0', br_taken => '0', abs_br => '0', srr1 => (others => '0'));
+ br_last => '0', br_taken => '0', abs_br => '0',
+ srr1 => (others => '0'), msr => (others => '0'));
type Execute1ToFPUType is record
valid : std_ulogic;
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
rot_sign_ext <= '1' when e_in.insn_type = OP_EXTSWSLI else '0';
- v.e.srr1 := msr_copy(ctrl.msr);
+ v.e.srr1 := (others => '0');
exception := '0';
illegal := '0';
if valid_in = '1' then
report "illegal";
end if;
- -- generate DSI or DSegI for load/store exceptions
- -- or ISI or ISegI for instruction fetch exceptions
- if l_in.exception = '1' then
- if l_in.alignment = '1' then
- v.e.intr_vec := 16#600#;
- elsif l_in.instr_fault = '0' then
- if l_in.segment_fault = '0' then
- v.e.intr_vec := 16#300#;
- else
- v.e.intr_vec := 16#380#;
- end if;
- else
- if l_in.segment_fault = '0' then
- v.e.srr1(63 - 33) := l_in.invalid;
- v.e.srr1(63 - 35) := l_in.perm_error; -- noexec fault
- v.e.srr1(63 - 44) := l_in.badtree;
- v.e.srr1(63 - 45) := l_in.rc_error;
- v.e.intr_vec := 16#400#;
- else
- v.e.intr_vec := 16#480#;
- end if;
- end if;
- end if;
-
- v.e.interrupt := exception or l_in.exception;
+ v.e.interrupt := exception;
if do_trace = '1' then
v.trace_next := '1';
-- update outputs
l_out <= lv;
e_out <= r.e;
+ e_out.msr <= msr_copy(ctrl.msr);
fp_out <= fv;
exception_log <= exception;
ld_sp_nz : std_ulogic;
ld_sp_lz : std_ulogic_vector(5 downto 0);
wr_sel : std_ulogic_vector(1 downto 0);
+ interrupt : std_ulogic;
+ intr_vec : integer range 0 to 16#fff#;
+ nia : std_ulogic_vector(63 downto 0);
+ srr1 : std_ulogic_vector(31 downto 0);
end record;
signal r, rin : reg_stage_t;
r.state <= IDLE;
r.busy <= '0';
r.do_update <= '0';
+ r.interrupt <= '0';
else
r <= rin;
end if;
v.wait_dcache := '0';
v.wait_mmu := '0';
v.extra_cycle := '0';
+ v.nia := l_in.nia;
+ v.srr1 := (others => '0');
if HAS_FPU and l_in.is_32bit = '1' then
v.store_data := x"00000000" & store_sp_data;
end if;
end loop;
+ -- generate DSI or DSegI for load/store exceptions
+ -- or ISI or ISegI for instruction fetch exceptions
+ v.interrupt := exception;
+ if exception = '1' then
+ if r.align_intr = '1' then
+ v.intr_vec := 16#600#;
+ v.dar := addr;
+ elsif r.instr_fault = '0' then
+ v.dar := addr;
+ if m_in.segerr = '0' then
+ v.intr_vec := 16#300#;
+ v.dsisr := dsisr;
+ else
+ v.intr_vec := 16#380#;
+ end if;
+ else
+ if m_in.segerr = '0' then
+ v.srr1(63 - 33) := m_in.invalid;
+ v.srr1(63 - 35) := m_in.perm_error; -- noexec fault
+ v.srr1(63 - 44) := m_in.badtree;
+ v.srr1(63 - 45) := m_in.rc_error;
+ v.intr_vec := 16#400#;
+ else
+ v.intr_vec := 16#480#;
+ end if;
+ end if;
+ end if;
+
-- Update outputs to dcache
d_out.valid <= req and not v.align_intr;
d_out.load <= v.load;
l_out.xerc <= r.xerc;
l_out.rc <= r.rc and done;
l_out.store_done <= d_in.store_done;
+ l_out.interrupt <= r.interrupt;
+ l_out.intr_vec <= r.intr_vec;
+ l_out.srr0 <= r.nia;
+ l_out.srr1 <= r.srr1;
- -- update exception info back to execute1
+ -- update busy signal back to execute1
e_out.busy <= busy;
- e_out.exception <= exception;
- e_out.alignment <= r.align_intr;
- e_out.instr_fault <= r.instr_fault;
- e_out.invalid <= m_in.invalid;
- e_out.badtree <= m_in.badtree;
- e_out.perm_error <= m_in.perm_error;
- e_out.rc_error <= m_in.rc_error;
- e_out.segment_fault <= m_in.segerr;
- if exception = '1' and r.instr_fault = '0' then
- v.dar := addr;
- if m_in.segerr = '0' and r.align_intr = '0' then
- v.dsisr := dsisr;
- end if;
- end if;
-- Update registers
rin <= v;
begin
if rising_edge(clk) then
log_data <= e_out.busy &
- e_out.exception &
+ l_out.interrupt &
l_out.valid &
m_out.valid &
d_out.valid &
variable zero : std_ulogic;
variable sign : std_ulogic;
variable scf : std_ulogic_vector(3 downto 0);
+ variable vec : integer range 0 to 16#fff#;
begin
w_out <= WritebackToRegisterFileInit;
c_out <= WritebackToCrFileInit;
f := WritebackToFetch1Init;
interrupt_out <= '0';
+ vec := 0;
v := r;
complete_out <= instr_tag_init;
w_out.write_data <= e_in.last_nia;
w_out.write_enable <= '1';
v.state := WRITE_SRR1;
- v.srr1 := e_in.srr1;
+ v.srr1(63 downto 32) := e_in.msr(63 downto 32);
+ v.srr1(31 downto 0) := e_in.msr(31 downto 0) or e_in.srr1;
+ vec := e_in.intr_vec;
+
+ elsif l_in.interrupt = '1' then
+ w_out.write_reg <= fast_spr_num(SPR_SRR0);
+ w_out.write_data <= l_in.srr0;
+ w_out.write_enable <= '1';
+ v.state := WRITE_SRR1;
+ v.srr1(63 downto 32) := e_in.msr(63 downto 32);
+ v.srr1(31 downto 0) := e_in.msr(31 downto 0) or l_in.srr1;
+ vec := l_in.intr_vec;
+
else
if e_in.write_enable = '1' then
w_out.write_reg <= e_in.write_reg;
end if;
-- Outputs to fetch1
- f.redirect := e_in.redirect or e_in.interrupt;
+ f.redirect := e_in.redirect;
f.br_nia := e_in.last_nia;
- f.br_last := e_in.br_last and not e_in.interrupt;
+ f.br_last := e_in.br_last;
f.br_taken := e_in.br_taken;
- if e_in.interrupt = '1' then
- f.redirect_nia := std_ulogic_vector(to_unsigned(e_in.intr_vec, 64));
+ if e_in.interrupt = '1' or l_in.interrupt = '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