end record;
constant xerc_init : xer_common_t := (others => '0');
+ -- Some SPRs are stored in a pair of small RAMs in execute1
+ -- Even half:
+ subtype ramspr_index is natural range 0 to 7;
+ constant RAMSPR_SRR0 : ramspr_index := 0;
+ constant RAMSPR_HSRR0 : ramspr_index := 1;
+ constant RAMSPR_SPRG0 : ramspr_index := 2;
+ constant RAMSPR_SPRG2 : ramspr_index := 3;
+ constant RAMSPR_HSPRG0 : ramspr_index := 4;
+ -- Odd half:
+ constant RAMSPR_SRR1 : ramspr_index := 0;
+ constant RAMSPR_HSRR1 : ramspr_index := 1;
+ constant RAMSPR_SPRG1 : ramspr_index := 2;
+ constant RAMSPR_SPRG3 : ramspr_index := 3;
+ constant RAMSPR_HSPRG1 : ramspr_index := 4;
+
+ type ram_spr_info is record
+ index : ramspr_index;
+ isodd : std_ulogic;
+ valid : std_ulogic;
+ end record;
+ constant ram_spr_info_init: ram_spr_info := (index => 0, others => '0');
+
subtype spr_selector is std_ulogic_vector(2 downto 0);
type spr_id is record
sel : spr_selector;
br_pred: std_ulogic; -- Branch was predicted to be taken
big_endian: std_ulogic;
spr_info : spr_id;
+ ram_spr : ram_spr_info;
end record;
constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
(valid => '0', stop_mark => '0', nia => (others => '0'), insn => (others => '0'),
ispr1 => (others => '0'), ispr2 => (others => '0'), ispro => (others => '0'),
decode => decode_rom_init, br_pred => '0', big_endian => '0',
- spr_info => spr_id_init);
+ spr_info => spr_id_init, ram_spr => ram_spr_info_init);
type Decode1ToFetch1Type is record
redirect : std_ulogic;
repeat : std_ulogic; -- set if instruction is cracked into two ops
second : std_ulogic; -- set if this is the second op
spr_select : spr_id;
+ spr_is_ram : std_ulogic;
+ ramspr_even_rdaddr : ramspr_index;
+ ramspr_odd_rdaddr : ramspr_index;
+ ramspr_rd_odd : std_ulogic;
+ ramspr_wraddr : ramspr_index;
+ ramspr_write_even : std_ulogic;
+ ramspr_write_odd : std_ulogic;
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
(valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'),
result_sel => "000", sub_select => "000",
repeat => '0', second => '0', spr_select => spr_id_init,
+ spr_is_ram => '0',
+ ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0',
+ ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0',
others => (others => '0'));
type MultiplyInputType is record
store_done : std_ulogic;
interrupt : std_ulogic;
intr_vec : intr_vector_t;
- srr0: std_ulogic_vector(63 downto 0);
srr1: std_ulogic_vector(15 downto 0);
end record;
constant Loadstore1ToWritebackInit : Loadstore1ToWritebackType :=
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'));
+ srr1 => (others => '0'));
type Loadstore1EventType is record
load_complete : std_ulogic;
write_xerc : std_ulogic;
xerc : xer_common_t;
intr_vec : intr_vector_t;
- srr0 : std_ulogic_vector(63 downto 0);
srr1 : std_ulogic_vector(15 downto 0);
end record;
constant FPUToWritebackInit : FPUToWritebackType :=
write_cr_mask => (others => '0'),
write_cr_data => (others => '0'));
+ type WritebackToExecute1Type is record
+ intr : std_ulogic;
+ srr1 : std_ulogic_vector(15 downto 0);
+ end record;
+
type WritebackEventType is record
instr_complete : std_ulogic;
fp_complete : std_ulogic;
n := 0; -- N.B. decode2 relies on this specific value
when SPR_CTR =>
n := 1; -- N.B. decode2 relies on this specific value
- when SPR_SRR0 =>
- n := 2;
- when SPR_SRR1 =>
- n := 3;
- when SPR_HSRR0 =>
- n := 4;
- when SPR_HSRR1 =>
- n := 5;
- when SPR_SPRG0 =>
- n := 6;
- when SPR_SPRG1 =>
- n := 7;
- when SPR_SPRG2 =>
- n := 8;
- when SPR_SPRG3 | SPR_SPRG3U =>
- n := 9;
- when SPR_HSPRG0 =>
- n := 10;
- when SPR_HSPRG1 =>
- n := 11;
when SPR_TAR =>
n := 13;
when others =>
-- Writeback signals
signal writeback_bypass: bypass_data_t;
+ signal wb_interrupt: WritebackToExecute1Type;
-- local signals
signal fetch1_stall_in : std_ulogic;
signal complete: instr_tag_t;
signal terminate: std_ulogic;
signal core_rst: std_ulogic;
- signal do_interrupt: std_ulogic;
-- Delayed/Latched resets and alt_reset
signal rst_fetch1 : std_ulogic;
l_in => loadstore1_to_execute1,
fp_in => fpu_to_execute1,
ext_irq_in => ext_irq,
- interrupt_in => do_interrupt,
+ interrupt_in => wb_interrupt,
l_out => execute1_to_loadstore1,
fp_out => execute1_to_fpu,
e_out => execute1_to_writeback,
f_out => writeback_to_fetch1,
wb_bypass => writeback_bypass,
events => writeback_events,
- interrupt_out => do_interrupt,
+ interrupt_out => wb_interrupt,
complete_out => complete
);
-- isync
2#111# => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
-- rfid
- 2#101# => (ALU, NONE, OP_RFID, SPR, SPR, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
+ 2#101# => (ALU, NONE, OP_RFID, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
others => illegal_inst
);
constant nop_instr : decode_rom_t := (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE);
constant fetch_fail_inst: decode_rom_t := (LDST, NONE, OP_FETCH_FAILED, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE);
+ function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is
+ variable ret : ram_spr_info;
+ begin
+ ret := (index => 0, isodd => '0', valid => '1');
+ case sprn is
+ when SPR_SRR0 =>
+ ret.index := RAMSPR_SRR0;
+ when SPR_SRR1 =>
+ ret.index := RAMSPR_SRR1;
+ ret.isodd := '1';
+ when SPR_HSRR0 =>
+ ret.index := RAMSPR_HSRR0;
+ when SPR_HSRR1 =>
+ ret.index := RAMSPR_HSRR1;
+ ret.isodd := '1';
+ when SPR_SPRG0 =>
+ ret.index := RAMSPR_SPRG0;
+ when SPR_SPRG1 =>
+ ret.index := RAMSPR_SPRG1;
+ ret.isodd := '1';
+ when SPR_SPRG2 =>
+ ret.index := RAMSPR_SPRG2;
+ when SPR_SPRG3 | SPR_SPRG3U =>
+ ret.index := RAMSPR_SPRG3;
+ ret.isodd := '1';
+ when SPR_HSPRG0 =>
+ ret.index := RAMSPR_HSPRG0;
+ when SPR_HSPRG1 =>
+ ret.index := RAMSPR_HSPRG1;
+ ret.isodd := '1';
+ when others =>
+ ret.valid := '0';
+ end case;
+ return ret;
+ end;
+
function map_spr(sprn : spr_num_t) return spr_id is
variable i : spr_id;
begin
sprn := decode_spr_num(f_in.insn);
v.spr_info := map_spr(sprn);
+ v.ram_spr := decode_ram_spr(sprn);
case to_integer(unsigned(majorop)) is
when 4 =>
if std_match(f_in.insn(10 downto 1), "01-1010011") then
-- mfspr or mtspr
- if is_fast_spr(v.ispr1) = '0' then
- -- Make mtspr to slow SPRs single issue
+ -- Make mtspr to slow SPRs single issue
+ if v.spr_info.valid = '1' then
vi.force_single := f_in.insn(8);
- -- send MMU-related SPRs to loadstore1
- case sprn is
- when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR =>
- vi.override_decode.unit := LDST;
- vi.override_unit := '1';
- when others =>
- end case;
end if;
+ -- send MMU-related SPRs to loadstore1
+ case sprn is
+ when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR =>
+ vi.override_decode.unit := LDST;
+ vi.override_unit := '1';
+ when others =>
+ end case;
end if;
when 16 =>
else
v.ispr2 := fast_spr_num(SPR_TAR);
end if;
- else
- -- Could be OP_RFID
- v.ispr1 := fast_spr_num(SPR_SRR1);
- v.ispr2 := fast_spr_num(SPR_SRR0);
end if;
when 24 =>
v.e.spr_select := d_in.spr_info;
+ case op is
+ when OP_MFSPR =>
+ v.e.ramspr_even_rdaddr := d_in.ram_spr.index;
+ v.e.ramspr_odd_rdaddr := d_in.ram_spr.index;
+ v.e.ramspr_rd_odd := d_in.ram_spr.isodd;
+ v.e.spr_is_ram := d_in.ram_spr.valid;
+ when OP_MTSPR =>
+ v.e.ramspr_wraddr := d_in.ram_spr.index;
+ v.e.ramspr_write_even := d_in.ram_spr.valid and not d_in.ram_spr.isodd;
+ v.e.ramspr_write_odd := d_in.ram_spr.valid and d_in.ram_spr.isodd;
+ v.e.spr_is_ram := d_in.ram_spr.valid;
+ when OP_RFID =>
+ v.e.ramspr_even_rdaddr := RAMSPR_SRR0;
+ v.e.ramspr_odd_rdaddr := RAMSPR_SRR1;
+ when others =>
+ end case;
+
case d_in.decode.length is
when is1B =>
length := "0001";
if op = OP_MFSPR then
if is_fast_spr(d_in.ispr1) = '1' then
v.e.result_sel := "000"; -- adder_result, effectively a_in
+ elsif d_in.ram_spr.valid = '1' then
+ v.e.result_sel := "101"; -- ramspr_result
elsif d_in.spr_info.valid = '0' then
-- Privileged mfspr to invalid/unimplemented SPR numbers
-- writes the contents of RT back to RT (i.e. it's a no-op)
fp_in : in FPUToExecute1Type;
ext_irq_in : std_ulogic;
- interrupt_in : std_ulogic;
+ interrupt_in : WritebackToExecute1Type;
-- asynchronous
l_out : out Execute1ToLoadstore1Type;
write_loga : std_ulogic;
inc_loga : std_ulogic;
write_pmuspr : std_ulogic;
+ ramspr_write_even : std_ulogic;
+ ramspr_write_odd : std_ulogic;
end record;
constant side_effect_init : side_effect_type := (others => '0');
msr : std_ulogic_vector(63 downto 0);
xerc : xer_common_t;
xerc_valid : std_ulogic;
+ ramspr_wraddr : ramspr_index;
end record;
constant reg_stage1_type_init : reg_stage1_type :=
(e => Execute1ToWritebackInit, se => side_effect_init,
no_instr_avail => '0', instr_dispatch => '0', ext_interrupt => '0',
taken_branch_event => '0', br_mispredict => '0',
msr => 64x"0",
- xerc => xerc_init, xerc_valid => '0');
+ xerc => xerc_init, xerc_valid => '0',
+ ramspr_wraddr => 0);
type reg_stage2_type is record
e : Execute1ToWritebackType;
signal exception_log : std_ulogic;
signal irq_valid_log : std_ulogic;
+ -- SPR-related signals
+ type ramspr_half_t is array(ramspr_index) of std_ulogic_vector(63 downto 0);
+ signal even_sprs : ramspr_half_t := (others => (others => '0'));
+ signal odd_sprs : ramspr_half_t := (others => (others => '0'));
+ signal ramspr_even : std_ulogic_vector(63 downto 0);
+ signal ramspr_odd : std_ulogic_vector(63 downto 0);
+ signal ramspr_result : std_ulogic_vector(63 downto 0);
+ signal ramspr_rd_odd : std_ulogic;
+ signal ramspr_wr_addr : ramspr_index;
+ signal ramspr_even_wr_data : std_ulogic_vector(63 downto 0);
+ signal ramspr_even_wr_enab : std_ulogic;
+ signal ramspr_odd_wr_data : std_ulogic_vector(63 downto 0);
+ signal ramspr_odd_wr_enab : std_ulogic;
+
signal stage2_stall : std_ulogic;
type privilege_level is (USER, SUPER);
return msr_out;
end;
+ function intr_srr1(msr: std_ulogic_vector; flags: std_ulogic_vector)
+ return std_ulogic_vector is
+ variable srr1: std_ulogic_vector(63 downto 0);
+ begin
+ srr1(63 downto 31) := msr(63 downto 31);
+ srr1(30 downto 27) := flags(14 downto 11);
+ srr1(26 downto 22) := msr(26 downto 22);
+ srr1(21 downto 16) := flags(5 downto 0);
+ srr1(15 downto 0) := msr(15 downto 0);
+ return srr1;
+ end;
+
-- Work out whether a signed value fits into n bits,
-- that is, see if it is in the range -2^(n-1) .. 2^(n-1) - 1
function fits_in_n_bits(val: std_ulogic_vector; n: integer) return boolean is
valid_in <= e_in.valid and not (busy_out or flush_in or ex1.e.redirect or ex1.e.interrupt);
+ -- SPRs stored in two small RAM arrays (two so that we can read and write
+ -- two SPRs in each cycle).
+
+ ramspr_read: process(all)
+ variable even_rd_data, odd_rd_data : std_ulogic_vector(63 downto 0);
+ variable wr_addr : ramspr_index;
+ variable even_wr_enab, odd_wr_enab : std_ulogic;
+ variable even_wr_data, odd_wr_data : std_ulogic_vector(63 downto 0);
+ variable doit : std_ulogic;
+ begin
+ -- Read address mux and async RAM reading
+ even_rd_data := even_sprs(e_in.ramspr_even_rdaddr);
+ odd_rd_data := odd_sprs(e_in.ramspr_odd_rdaddr);
+
+ -- Write address and data muxes
+ doit := ex1.e.valid and not stage2_stall and not flush_in;
+ even_wr_enab := (ex1.se.ramspr_write_even and doit) or interrupt_in.intr;
+ odd_wr_enab := (ex1.se.ramspr_write_odd and doit) or interrupt_in.intr;
+ if interrupt_in.intr = '1' then
+ wr_addr := RAMSPR_SRR0;
+ else
+ wr_addr := ex1.ramspr_wraddr;
+ end if;
+ if interrupt_in.intr = '1' then
+ even_wr_data := ex2.e.last_nia;
+ odd_wr_data := intr_srr1(ctrl.msr, interrupt_in.srr1);
+ else
+ even_wr_data := ex1.e.write_data;
+ odd_wr_data := ex1.e.write_data;
+ end if;
+ ramspr_wr_addr <= wr_addr;
+ ramspr_even_wr_data <= even_wr_data;
+ ramspr_even_wr_enab <= even_wr_enab;
+ ramspr_odd_wr_data <= odd_wr_data;
+ ramspr_odd_wr_enab <= odd_wr_enab;
+
+ -- SPR RAM read with write data bypass
+ -- We assume no instruction executes in the cycle immediately following
+ -- an interrupt, so we don't need to bypass interrupt data
+ if ex1.se.ramspr_write_even = '1' and e_in.ramspr_even_rdaddr = ex1.ramspr_wraddr then
+ ramspr_even <= ex1.e.write_data;
+ else
+ ramspr_even <= even_rd_data;
+ end if;
+ if ex1.se.ramspr_write_odd = '1' and e_in.ramspr_odd_rdaddr = ex1.ramspr_wraddr then
+ ramspr_odd <= ex1.e.write_data;
+ else
+ ramspr_odd <= odd_rd_data;
+ end if;
+ if e_in.ramspr_rd_odd = '0' then
+ ramspr_result <= ramspr_even;
+ else
+ ramspr_result <= ramspr_odd;
+ end if;
+ end process;
+
+ ramspr_write: process(clk)
+ begin
+ if rising_edge(clk) then
+ if ramspr_even_wr_enab = '1' then
+ even_sprs(ramspr_wr_addr) <= ramspr_even_wr_data;
+ report "writing even spr " & integer'image(ramspr_wr_addr) & " data=" &
+ to_hstring(ramspr_even_wr_data);
+ end if;
+ if ramspr_odd_wr_enab = '1' then
+ odd_sprs(ramspr_wr_addr) <= ramspr_odd_wr_data;
+ report "writing odd spr " & integer'image(ramspr_wr_addr) & " data=" &
+ to_hstring(ramspr_odd_wr_data);
+ end if;
+ end if;
+ end process;
+
-- First stage result mux
s1_sel <= e_in.result_sel when ex1.busy = '0' else "100";
with s1_sel select alu_result <=
rotator_result when "010",
shortmul_result when "011",
muldiv_result when "100",
+ ramspr_result when "101",
next_nia when "110",
misc_result when others;
variable privileged : std_ulogic;
variable slow_op : std_ulogic;
variable owait : std_ulogic;
+ variable srr1 : std_ulogic_vector(63 downto 0);
begin
v := actions_type_init;
v.e.write_data := alu_result;
v.e.last_nia := e_in.nia;
v.e.br_offset := 64x"4";
+ v.se.ramspr_write_even := e_in.ramspr_write_even;
+ v.se.ramspr_write_odd := e_in.ramspr_write_odd;
+
-- Note the difference between v.exception and v.trap:
-- v.exception signals a condition that prevents execution of the
-- instruction, and hence shouldn't depend on operand data, so as to
end if;
when OP_RFID =>
- v.e.redir_mode := (a_in(MSR_IR) or a_in(MSR_PR)) & not a_in(MSR_PR) &
- not a_in(MSR_LE) & not a_in(MSR_SF);
+ srr1 := ramspr_odd;
+ v.e.redir_mode := (srr1(MSR_IR) or srr1(MSR_PR)) & not srr1(MSR_PR) &
+ not srr1(MSR_LE) & not srr1(MSR_SF);
-- Can't use msr_copy here because the partial function MSR
-- bits should be left unchanged, not zeroed.
- v.new_msr(63 downto 31) := a_in(63 downto 31);
- v.new_msr(26 downto 22) := a_in(26 downto 22);
- v.new_msr(15 downto 0) := a_in(15 downto 0);
- if a_in(MSR_PR) = '1' then
+ v.new_msr(63 downto 31) := srr1(63 downto 31);
+ v.new_msr(26 downto 22) := srr1(26 downto 22);
+ v.new_msr(15 downto 0) := srr1(15 downto 0);
+ if srr1(MSR_PR) = '1' then
v.new_msr(MSR_EE) := '1';
v.new_msr(MSR_IR) := '1';
v.new_msr(MSR_DR) := '1';
end if;
v.se.write_msr := '1';
- v.e.br_offset := b_in;
+ v.e.br_offset := ramspr_even;
v.e.abs_br := '1';
v.e.redirect := '1';
v.se.write_cfar := '1';
if HAS_FPU then
v.fp_intr := fp_in.exception and
- (a_in(MSR_FE0) or a_in(MSR_FE1));
+ (srr1(MSR_FE0) or srr1(MSR_FE1));
end if;
v.do_trace := '0';
when OP_DARN =>
when OP_MFMSR =>
when OP_MFSPR =>
- if is_fast_spr(e_in.read_reg1) = '1' then
+ if is_fast_spr(e_in.read_reg1) = '1' or e_in.spr_is_ram = '1' then
if e_in.valid = '1' then
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
- "=" & to_hstring(a_in);
+ "=" & to_hstring(alu_result);
end if;
elsif e_in.spr_select.valid = '1' then
if e_in.valid = '1' then
v.se.write_loga := '1';
when others =>
end case;
- elsif is_fast_spr(e_in.write_reg) = '0' then
+ end if;
+ if e_in.spr_select.valid = '0' and is_fast_spr(e_in.write_reg) = '0' and
+ e_in.spr_is_ram = '0' then
-- mtspr to unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
if ex1.msr(MSR_PR) = '1' then
v.pmu_spr_num := e_in.insn(20 downto 16);
v.mul_select := e_in.sub_select(1 downto 0);
v.se := side_effect_init;
+ v.ramspr_wraddr := e_in.ramspr_wraddr;
end if;
lv := Execute1ToLoadstore1Init;
v.mul_finish := '0';
v.xerc_valid := '0';
end if;
- if flush_in = '1' or interrupt_in = '1' then
+ if flush_in = '1' or interrupt_in.intr = '1' then
v.msr := ctrl_tmp.msr;
end if;
- if interrupt_in = '1' then
+ if interrupt_in.intr = '1' then
v.trace_next := '0';
v.fp_exception_next := '0';
end if;
-- Outputs to FPU
fv.op := e_in.insn_type;
- fv.nia := e_in.nia;
fv.insn := e_in.insn;
fv.itag := e_in.instr_tag;
fv.single := e_in.is_32bit;
x_to_pmu.mtspr <= ex1.se.write_pmuspr;
end if;
- if interrupt_in = '1' then
+ if interrupt_in.intr = '1' then
ctrl_tmp.msr(MSR_SF) <= '1';
ctrl_tmp.msr(MSR_EE) <= '0';
ctrl_tmp.msr(MSR_PR) <= '0';
ctrl.msr(MSR_IR) & ctrl.msr(MSR_DR) &
exception_log &
irq_valid_log &
- interrupt_in &
+ interrupt_in.intr &
"000" &
ex2.e.write_enable &
ex2.e.valid &
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;
w_out.xerc <= r.xerc_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)
-- 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);
dword_index : std_ulogic;
two_dwords : std_ulogic;
incomplete : std_ulogic;
- nia : std_ulogic_vector(63 downto 0);
end record;
constant request_init : request_t := (valid => '0', dc_req => '0', load => '0', store => '0', tlbie => '0',
dcbz => '0', read_spr => '0', write_spr => '0', mmu_op => '0',
atomic => '0', atomic_last => '0', rc => '0', nc => '0',
virt_mode => '0', priv_mode => '0', load_sp => '0',
sprn => 10x"0", is_slbia => '0', align_intr => '0',
- dword_index => '0', two_dwords => '0', incomplete => '0',
- nia => (others => '0'));
+ dword_index => '0', two_dwords => '0', incomplete => '0');
type reg_stage1_t is record
req : request_t;
stage1_en : std_ulogic;
interrupt : std_ulogic;
intr_vec : integer range 0 to 16#fff#;
- nia : std_ulogic_vector(63 downto 0);
srr1 : std_ulogic_vector(15 downto 0);
events : Loadstore1EventType;
end record;
v.virt_mode := l_in.virt_mode;
v.priv_mode := l_in.priv_mode;
v.sprn := sprn;
- v.nia := l_in.nia;
lsu_sum := std_ulogic_vector(unsigned(l_in.addr1) + unsigned(l_in.addr2));
-- or ISI or ISegI for instruction fetch exceptions
v.interrupt := exception;
if exception = '1' then
- v.nia := r2.req.nia;
if r2.req.align_intr = '1' then
v.intr_vec := 16#600#;
v.dar := r2.req.addr;
l_out.store_done <= d_in.store_done;
l_out.interrupt <= r3.interrupt;
l_out.intr_vec <= r3.intr_vec;
- l_out.srr0 <= r3.nia;
l_out.srr1 <= r3.srr1;
-- update busy signal back to execute1
events : out WritebackEventType;
flush_out : out std_ulogic;
- interrupt_out: out std_ulogic;
+ interrupt_out: out WritebackToExecute1Type;
complete_out : out instr_tag_t
);
end entity writeback;
architecture behaviour of writeback is
- type irq_state_t is (WRITE_SRR0, WRITE_SRR1);
-
- type reg_type is record
- state : irq_state_t;
- srr1 : std_ulogic_vector(63 downto 0);
- end record;
-
- signal r, rin : reg_type;
begin
writeback_0: process(clk)
variable w : std_ulogic_vector(0 downto 0);
begin
if rising_edge(clk) then
- if rst = '1' then
- r.state <= WRITE_SRR0;
- r.srr1 <= (others => '0');
- else
- r <= rin;
- end if;
-
-- Do consistency checks only on the clock edge
x(0) := e_in.valid;
y(0) := l_in.valid;
end process;
writeback_1: process(all)
- variable v : reg_type;
variable f : WritebackToFetch1Type;
variable scf : std_ulogic_vector(3 downto 0);
variable vec : integer range 0 to 16#fff#;
w_out <= WritebackToRegisterFileInit;
c_out <= WritebackToCrFileInit;
f := WritebackToFetch1Init;
- interrupt_out <= '0';
vec := 0;
- v := r;
complete_out <= instr_tag_init;
if e_in.valid = '1' then
events.fp_complete <= fp_in.valid;
intr := e_in.interrupt or l_in.interrupt or fp_in.interrupt;
+ interrupt_out.intr <= intr;
- if r.state = WRITE_SRR1 then
- w_out.write_reg <= fast_spr_num(SPR_SRR1);
- w_out.write_data <= r.srr1;
- w_out.write_enable <= '1';
- interrupt_out <= '1';
- v.state := WRITE_SRR0;
-
- elsif intr = '1' then
- w_out.write_reg <= fast_spr_num(SPR_SRR0);
- w_out.write_enable <= '1';
- v.state := WRITE_SRR1;
+ if intr = '1' then
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);
+ interrupt_out.srr1 <= srr1;
else
if e_in.write_enable = '1' then
wb_bypass.tag.valid <= complete_out.valid and w_out.write_enable;
wb_bypass.data <= w_out.write_data;
- rin <= v;
end process;
end;