constant instr_tag_init : instr_tag_t := (tag => 0, valid => '0');
function tag_match(tag1 : instr_tag_t; tag2 : instr_tag_t) return boolean;
+ subtype intr_vector_t is integer range 0 to 16#fff#;
+
-- For now, fixed 16 sources, make this either a parametric
-- package of some sort or an unconstrainted array.
type ics_to_icp_t is record
rc : std_ulogic;
store_done : std_ulogic;
interrupt : std_ulogic;
- intr_vec : integer range 0 to 16#fff#;
+ intr_vec : intr_vector_t;
srr0: std_ulogic_vector(63 downto 0);
- srr1: std_ulogic_vector(31 downto 0);
+ srr1: std_ulogic_vector(15 downto 0);
end record;
constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType :=
(valid => '0', instr_tag => instr_tag_init, write_enable => '0',
write_xerc_enable : std_ulogic;
xerc : xer_common_t;
interrupt : std_ulogic;
- intr_vec : integer range 0 to 16#fff#;
+ intr_vec : intr_vector_t;
redirect: std_ulogic;
redir_mode: std_ulogic_vector(3 downto 0);
last_nia: std_ulogic_vector(63 downto 0);
br_last: std_ulogic;
br_taken: std_ulogic;
abs_br: std_ulogic;
- srr1: std_ulogic_vector(31 downto 0);
+ srr1: std_ulogic_vector(15 downto 0);
msr: std_ulogic_vector(63 downto 0);
end record;
constant Execute1ToWritebackInit : Execute1ToWritebackType :=
type FPUToExecute1Type is record
busy : std_ulogic;
exception : std_ulogic;
- interrupt : std_ulogic;
- illegal : std_ulogic;
end record;
constant FPUToExecute1Init : FPUToExecute1Type := (others => '0');
type FPUToWritebackType is record
valid : std_ulogic;
+ interrupt : std_ulogic;
instr_tag : instr_tag_t;
write_enable : std_ulogic;
write_reg : gspr_index_t;
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
- end record;
- constant FPUToWritebackInit : FPUToWritebackType := (valid => '0', instr_tag => instr_tag_init,
- write_enable => '0', write_cr_enable => '0',
- others => (others => '0'));
+ intr_vec : intr_vector_t;
+ srr0 : std_ulogic_vector(63 downto 0);
+ srr1 : std_ulogic_vector(15 downto 0);
+ end record;
+ constant FPUToWritebackInit : FPUToWritebackType :=
+ (valid => '0', interrupt => '0', instr_tag => instr_tag_init,
+ write_enable => '0', write_reg => (others => '0'),
+ write_cr_enable => '0', write_cr_mask => (others => '0'),
+ write_cr_data => (others => '0'),
+ intr_vec => 0, srr1 => (others => '0'),
+ others => (others => '0'));
type DividerToExecute1Type is record
valid: std_ulogic;
-- become pending due to MSR[FE0,FE1] changing from 00 to non-zero.
exception := '1';
v.e.intr_vec := 16#700#;
- v.e.srr1(63 - 43) := '1';
- v.e.srr1(63 - 47) := '1';
+ v.e.srr1(47 - 43) := '1';
+ v.e.srr1(47 - 47) := '1';
elsif r.trace_next = '1' then
-- Generate a trace interrupt rather than executing the next instruction
-- or taking any asynchronous interrupt
exception := '1';
v.e.intr_vec := 16#d00#;
- v.e.srr1(63 - 33) := '1';
+ v.e.srr1(47 - 33) := '1';
if r.prev_op = OP_LOAD or r.prev_op = OP_ICBI or r.prev_op = OP_ICBT or
r.prev_op = OP_DCBT or r.prev_op = OP_DCBST or r.prev_op = OP_DCBF then
- v.e.srr1(63 - 35) := '1';
+ v.e.srr1(47 - 35) := '1';
elsif r.prev_op = OP_STORE or r.prev_op = OP_DCBZ or r.prev_op = OP_DCBTST then
- v.e.srr1(63 - 36) := '1';
+ v.e.srr1(47 - 36) := '1';
end if;
elsif irq_valid = '1' then
exception := '1';
v.e.intr_vec := 16#700#;
-- set bit 45 to indicate privileged instruction type interrupt
- v.e.srr1(63 - 45) := '1';
+ v.e.srr1(47 - 45) := '1';
report "privileged instruction";
elsif not HAS_FPU and e_in.fac = FPU then
-- trap instructions (tw, twi, td, tdi)
v.e.intr_vec := 16#700#;
-- set bit 46 to say trap occurred
- v.e.srr1(63 - 46) := '1';
+ v.e.srr1(47 - 46) := '1';
if or (trapval and insn_to(e_in.insn)) = '1' then
-- generate trap-type program interrupt
exception := '1';
v.e.valid := '1';
end if;
- -- Generate FP-type program interrupt. fp_in.interrupt will only
- -- be set during the execution of a FP instruction.
- -- The case where MSR[FE0,FE1] goes from zero to non-zero is
- -- handled above by mtmsrd and rfid setting v.fp_exception_next.
- if HAS_FPU and fp_in.interrupt = '1' then
- v.e.intr_vec := 16#700#;
- v.e.srr1(63 - 43) := '1';
- exception := '1';
- end if;
-
- if illegal = '1' or (HAS_FPU and fp_in.illegal = '1') then
+ if illegal = '1' then
exception := '1';
v.e.intr_vec := 16#700#;
-- Since we aren't doing Hypervisor emulation assist (0xe40) we
-- set bit 44 to indicate we have an illegal
- v.e.srr1(63 - 44) := '1';
+ v.e.srr1(47 - 44) := '1';
report "illegal";
end if;
busy : std_ulogic;
instr_done : std_ulogic;
do_intr : std_ulogic;
+ illegal : std_ulogic;
op : insn_type_t;
insn : std_ulogic_vector(31 downto 0);
+ nia : std_ulogic_vector(63 downto 0);
instr_tag : instr_tag_t;
dest_fpr : gspr_index_t;
fe_mode : std_ulogic;
e_out.busy <= r.busy;
e_out.exception <= r.fpscr(FPSCR_FEX);
- e_out.interrupt <= r.do_intr;
w_out.valid <= r.instr_done and not r.do_intr;
w_out.instr_tag <= r.instr_tag;
w_out.write_cr_mask <= r.cr_mask;
w_out.write_cr_data <= r.cr_result & r.cr_result & r.cr_result & r.cr_result &
r.cr_result & r.cr_result & r.cr_result & r.cr_result;
+ w_out.interrupt <= r.do_intr;
+ w_out.intr_vec <= 16#700#;
+ w_out.srr0 <= r.nia;
+ w_out.srr1 <= (47-44 => r.illegal, 47-43 => not r.illegal, others => '0');
fpu_1: process(all)
variable v : reg_type;
-- capture incoming instruction
if e_in.valid = '1' then
v.insn := e_in.insn;
+ v.nia := e_in.nia;
v.op := e_in.op;
v.instr_tag := e_in.itag;
v.fe_mode := or (e_in.fe_mode);
v.cr_result := v.fpscr(FPSCR_FX downto FPSCR_OX);
end if;
+ v.illegal := illegal;
if illegal = '1' then
v.instr_done := '0';
- v.do_intr := '0';
+ v.do_intr := '1';
v.writing_back := '0';
v.busy := '0';
v.state := IDLE;
end if;
rin <= v;
- e_out.illegal <= illegal;
end process;
end architecture behaviour;
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);
+ srr1 : std_ulogic_vector(15 downto 0);
end record;
signal r, rin : reg_stage_t;
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.srr1(47 - 33) := m_in.invalid;
+ v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
+ v.srr1(47 - 44) := m_in.badtree;
+ v.srr1(47 - 45) := m_in.rc_error;
v.intr_vec := 16#400#;
else
v.intr_vec := 16#480#;
variable sign : std_ulogic;
variable scf : std_ulogic_vector(3 downto 0);
variable vec : integer range 0 to 16#fff#;
+ variable srr1 : std_ulogic_vector(15 downto 0);
+ variable intr : std_ulogic;
begin
w_out <= WritebackToRegisterFileInit;
c_out <= WritebackToCrFileInit;
complete_out <= fp_in.instr_tag;
end if;
+ intr := e_in.interrupt or l_in.interrupt or fp_in.interrupt;
+
if r.state = WRITE_SRR1 then
w_out.write_reg <= fast_spr_num(SPR_SRR1);
w_out.write_data <= r.srr1;
interrupt_out <= '1';
v.state := WRITE_SRR0;
- elsif e_in.interrupt = '1' then
- w_out.write_reg <= fast_spr_num(SPR_SRR0);
- w_out.write_data <= e_in.last_nia;
- 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 e_in.srr1;
- vec := e_in.intr_vec;
-
- elsif l_in.interrupt = '1' then
+ elsif intr = '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;
+ srr1 := (others => '0');
+ if e_in.interrupt = '1' then
+ vec := e_in.intr_vec;
+ w_out.write_data <= e_in.last_nia;
+ srr1 := e_in.srr1;
+ elsif l_in.interrupt = '1' then
+ vec := l_in.intr_vec;
+ w_out.write_data <= l_in.srr0;
+ srr1 := l_in.srr1;
+ elsif fp_in.interrupt = '1' then
+ vec := fp_in.intr_vec;
+ w_out.write_data <= fp_in.srr0;
+ srr1 := fp_in.srr1;
+ end if;
+ v.srr1(63 downto 31) := e_in.msr(63 downto 31);
+ v.srr1(30 downto 27) := srr1(14 downto 11);
+ v.srr1(26 downto 22) := e_in.msr(26 downto 22);
+ v.srr1(21 downto 16) := srr1(5 downto 0);
+ v.srr1(15 downto 0) := e_in.msr(15 downto 0);
else
if e_in.write_enable = '1' then
f.br_nia := e_in.last_nia;
f.br_last := e_in.br_last;
f.br_taken := e_in.br_taken;
- if e_in.interrupt = '1' or l_in.interrupt = '1' then
+ if intr = '1' then
f.redirect := '1';
f.br_last := '0';
f.redirect_nia := std_ulogic_vector(to_unsigned(vec, 64));