|
|
@ -50,6 +50,11 @@ architecture behaviour of execute1 is
|
|
|
|
slow_op_oe : std_ulogic;
|
|
|
|
slow_op_oe : std_ulogic;
|
|
|
|
slow_op_xerc : xer_common_t;
|
|
|
|
slow_op_xerc : xer_common_t;
|
|
|
|
end record;
|
|
|
|
end record;
|
|
|
|
|
|
|
|
constant reg_type_init : reg_type :=
|
|
|
|
|
|
|
|
(e => Execute1ToWritebackInit, lr_update => '0',
|
|
|
|
|
|
|
|
mul_in_progress => '0', div_in_progress => '0', cntz_in_progress => '0',
|
|
|
|
|
|
|
|
slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init,
|
|
|
|
|
|
|
|
others => (others => '0'));
|
|
|
|
|
|
|
|
|
|
|
|
signal r, rin : reg_type;
|
|
|
|
signal r, rin : reg_type;
|
|
|
|
|
|
|
|
|
|
|
@ -73,6 +78,28 @@ architecture behaviour of execute1 is
|
|
|
|
signal x_to_divider: Execute1ToDividerType;
|
|
|
|
signal x_to_divider: Execute1ToDividerType;
|
|
|
|
signal divider_to_x: DividerToExecute1Type;
|
|
|
|
signal divider_to_x: DividerToExecute1Type;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type privilege_level is (USER, SUPER);
|
|
|
|
|
|
|
|
type op_privilege_array is array(insn_type_t) of privilege_level;
|
|
|
|
|
|
|
|
constant op_privilege: op_privilege_array := (
|
|
|
|
|
|
|
|
OP_ATTN => SUPER,
|
|
|
|
|
|
|
|
OP_MFMSR => SUPER,
|
|
|
|
|
|
|
|
OP_MTMSRD => SUPER,
|
|
|
|
|
|
|
|
OP_RFID => SUPER,
|
|
|
|
|
|
|
|
others => USER
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function instr_is_privileged(op: insn_type_t; insn: std_ulogic_vector(31 downto 0))
|
|
|
|
|
|
|
|
return boolean is
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
|
|
|
if op_privilege(op) = SUPER then
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
elsif op = OP_MFSPR or op = OP_MTSPR then
|
|
|
|
|
|
|
|
return insn(20) = '1';
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure set_carry(e: inout Execute1ToWritebackType;
|
|
|
|
procedure set_carry(e: inout Execute1ToWritebackType;
|
|
|
|
carry32 : in std_ulogic;
|
|
|
|
carry32 : in std_ulogic;
|
|
|
|
carry : in std_ulogic) is
|
|
|
|
carry : in std_ulogic) is
|
|
|
@ -126,11 +153,11 @@ architecture behaviour of execute1 is
|
|
|
|
-- tion MSR bits are not saved or restored.
|
|
|
|
-- tion MSR bits are not saved or restored.
|
|
|
|
-- Full function MSR bits lie in the range 0:32, 37:41, and
|
|
|
|
-- Full function MSR bits lie in the range 0:32, 37:41, and
|
|
|
|
-- 48:63, and partial function MSR bits lie in the range
|
|
|
|
-- 48:63, and partial function MSR bits lie in the range
|
|
|
|
-- 33:36 and 42:47.
|
|
|
|
-- 33:36 and 42:47. (Note this is IBM bit numbering).
|
|
|
|
msr_out := (others => '0');
|
|
|
|
msr_out := (others => '0');
|
|
|
|
msr_out(32 downto 0) := msr(32 downto 0);
|
|
|
|
msr_out(63 downto 31) := msr(63 downto 31);
|
|
|
|
msr_out(41 downto 37) := msr(41 downto 37);
|
|
|
|
msr_out(26 downto 22) := msr(26 downto 22);
|
|
|
|
msr_out(63 downto 48) := msr(63 downto 48);
|
|
|
|
msr_out(15 downto 0) := msr(15 downto 0);
|
|
|
|
return msr_out;
|
|
|
|
return msr_out;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
@ -195,14 +222,20 @@ begin
|
|
|
|
execute1_0: process(clk)
|
|
|
|
execute1_0: process(clk)
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
if rising_edge(clk) then
|
|
|
|
if rising_edge(clk) then
|
|
|
|
r <= rin;
|
|
|
|
if rst = '1' then
|
|
|
|
ctrl <= ctrl_tmp;
|
|
|
|
r <= reg_type_init;
|
|
|
|
assert not (r.lr_update = '1' and e_in.valid = '1')
|
|
|
|
ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0');
|
|
|
|
report "LR update collision with valid in EX1"
|
|
|
|
ctrl.irq_state <= WRITE_SRR0;
|
|
|
|
severity failure;
|
|
|
|
else
|
|
|
|
if r.lr_update = '1' then
|
|
|
|
r <= rin;
|
|
|
|
report "LR update to " & to_hstring(r.next_lr);
|
|
|
|
ctrl <= ctrl_tmp;
|
|
|
|
end if;
|
|
|
|
assert not (r.lr_update = '1' and e_in.valid = '1')
|
|
|
|
|
|
|
|
report "LR update collision with valid in EX1"
|
|
|
|
|
|
|
|
severity failure;
|
|
|
|
|
|
|
|
if r.lr_update = '1' then
|
|
|
|
|
|
|
|
report "LR update to " & to_hstring(r.next_lr);
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
|
|
@ -372,7 +405,7 @@ begin
|
|
|
|
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
|
|
|
|
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
|
|
|
|
|
|
|
|
|
|
|
|
irq_valid := '0';
|
|
|
|
irq_valid := '0';
|
|
|
|
if ctrl.msr(63 - 48) = '1' then
|
|
|
|
if ctrl.msr(MSR_EE) = '1' then
|
|
|
|
if ctrl.dec(63) = '1' then
|
|
|
|
if ctrl.dec(63) = '1' then
|
|
|
|
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64));
|
|
|
|
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64));
|
|
|
|
report "IRQ valid: DEC";
|
|
|
|
report "IRQ valid: DEC";
|
|
|
@ -409,21 +442,37 @@ begin
|
|
|
|
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
|
|
|
|
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
|
|
|
|
v.e.exc_write_data := ctrl.srr1;
|
|
|
|
v.e.exc_write_data := ctrl.srr1;
|
|
|
|
v.e.exc_write_enable := '1';
|
|
|
|
v.e.exc_write_enable := '1';
|
|
|
|
ctrl_tmp.msr(63 - 48) <= '0'; -- clear EE
|
|
|
|
ctrl_tmp.msr(MSR_SF) <= '1';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_EE) <= '0';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_PR) <= '0';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_IR) <= '0';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_DR) <= '0';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_RI) <= '0';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_LE) <= '1';
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
f_out.redirect_nia <= ctrl.irq_nia;
|
|
|
|
f_out.redirect_nia <= ctrl.irq_nia;
|
|
|
|
v.e.valid := e_in.valid;
|
|
|
|
v.e.valid := e_in.valid;
|
|
|
|
report "Writing SRR1: " & to_hstring(ctrl.srr1);
|
|
|
|
report "Writing SRR1: " & to_hstring(ctrl.srr1);
|
|
|
|
|
|
|
|
|
|
|
|
elsif irq_valid = '1' then
|
|
|
|
elsif irq_valid = '1' and e_in.valid = '1' then
|
|
|
|
-- we need two cycles to write srr0 and 1
|
|
|
|
-- we need two cycles to write srr0 and 1
|
|
|
|
-- will need more when we have to write DSISR, DAR and HIER
|
|
|
|
-- will need more when we have to write DSISR, DAR and HIER
|
|
|
|
-- Don't deliver the interrupt until we have a valid instruction
|
|
|
|
-- Don't deliver the interrupt until we have a valid instruction
|
|
|
|
-- coming in, so we have a valid NIA to put in SRR0.
|
|
|
|
-- coming in, so we have a valid NIA to put in SRR0.
|
|
|
|
exception := e_in.valid;
|
|
|
|
exception := '1';
|
|
|
|
ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
|
|
|
|
ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
|
|
|
|
|
|
|
|
|
|
|
|
elsif e_in.valid = '1' then
|
|
|
|
elsif e_in.valid = '1' and ctrl.msr(MSR_PR) = '1' and
|
|
|
|
|
|
|
|
instr_is_privileged(e_in.insn_type, e_in.insn) then
|
|
|
|
|
|
|
|
-- generate a program interrupt
|
|
|
|
|
|
|
|
exception := '1';
|
|
|
|
|
|
|
|
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
|
|
|
|
|
|
|
|
ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
|
|
|
|
|
|
|
|
-- set bit 45 to indicate privileged instruction type interrupt
|
|
|
|
|
|
|
|
ctrl_tmp.srr1(63 - 45) <= '1';
|
|
|
|
|
|
|
|
report "privileged instruction";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elsif e_in.valid = '1' and e_in.unit = ALU then
|
|
|
|
|
|
|
|
|
|
|
|
report "execute nia " & to_hstring(e_in.nia);
|
|
|
|
report "execute nia " & to_hstring(e_in.nia);
|
|
|
|
|
|
|
|
|
|
|
@ -555,7 +604,7 @@ begin
|
|
|
|
when OP_B =>
|
|
|
|
when OP_B =>
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
if (insn_aa(e_in.insn)) then
|
|
|
|
if (insn_aa(e_in.insn)) then
|
|
|
|
f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
|
|
|
|
f_out.redirect_nia <= b_in;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
|
|
|
|
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
@ -571,7 +620,7 @@ begin
|
|
|
|
if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
|
|
|
|
if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
if (insn_aa(e_in.insn)) then
|
|
|
|
if (insn_aa(e_in.insn)) then
|
|
|
|
f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
|
|
|
|
f_out.redirect_nia <= b_in;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
|
|
|
|
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
@ -594,7 +643,17 @@ begin
|
|
|
|
when OP_RFID =>
|
|
|
|
when OP_RFID =>
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
f_out.redirect <= '1';
|
|
|
|
f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
|
|
|
|
f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
|
|
|
|
ctrl_tmp.msr <= msr_copy(std_ulogic_vector(signed(b_in))); -- srr1
|
|
|
|
-- Can't use msr_copy here because the partial function MSR
|
|
|
|
|
|
|
|
-- bits should be left unchanged, not zeroed.
|
|
|
|
|
|
|
|
ctrl_tmp.msr(63 downto 31) <= b_in(63 downto 31);
|
|
|
|
|
|
|
|
ctrl_tmp.msr(26 downto 22) <= b_in(26 downto 22);
|
|
|
|
|
|
|
|
ctrl_tmp.msr(15 downto 0) <= b_in(15 downto 0);
|
|
|
|
|
|
|
|
if b_in(MSR_PR) = '1' then
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_EE) <= '1';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_IR) <= '1';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_DR) <= '1';
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
when OP_CMPB =>
|
|
|
|
when OP_CMPB =>
|
|
|
|
result := ppc_cmpb(c_in, b_in);
|
|
|
|
result := ppc_cmpb(c_in, b_in);
|
|
|
|
result_en := '1';
|
|
|
|
result_en := '1';
|
|
|
@ -668,7 +727,7 @@ begin
|
|
|
|
end loop;
|
|
|
|
end loop;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
when OP_MFMSR =>
|
|
|
|
when OP_MFMSR =>
|
|
|
|
result := msr_copy(ctrl.msr);
|
|
|
|
result := ctrl.msr;
|
|
|
|
result_en := '1';
|
|
|
|
result_en := '1';
|
|
|
|
when OP_MFSPR =>
|
|
|
|
when OP_MFSPR =>
|
|
|
|
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
|
|
|
|
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
|
|
|
@ -724,9 +783,23 @@ begin
|
|
|
|
v.e.write_cr_mask := num_to_fxm(crnum);
|
|
|
|
v.e.write_cr_mask := num_to_fxm(crnum);
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
v.e.write_cr_data := c_in(31 downto 0);
|
|
|
|
v.e.write_cr_data := c_in(31 downto 0);
|
|
|
|
when OP_MTMSRD =>
|
|
|
|
when OP_MTMSRD =>
|
|
|
|
-- FIXME handle just the bits we need to.
|
|
|
|
if e_in.insn(16) = '1' then
|
|
|
|
ctrl_tmp.msr <= msr_copy(c_in);
|
|
|
|
-- just update EE and RI
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_EE) <= c_in(MSR_EE);
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_RI) <= c_in(MSR_RI);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
-- Architecture says to leave out bits 3 (HV), 51 (ME)
|
|
|
|
|
|
|
|
-- and 63 (LE) (IBM bit numbering)
|
|
|
|
|
|
|
|
ctrl_tmp.msr(63 downto 61) <= c_in(63 downto 61);
|
|
|
|
|
|
|
|
ctrl_tmp.msr(59 downto 13) <= c_in(59 downto 13);
|
|
|
|
|
|
|
|
ctrl_tmp.msr(11 downto 1) <= c_in(11 downto 1);
|
|
|
|
|
|
|
|
if c_in(MSR_PR) = '1' then
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_EE) <= '1';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_IR) <= '1';
|
|
|
|
|
|
|
|
ctrl_tmp.msr(MSR_DR) <= '1';
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
end if;
|
|
|
|
when OP_MTSPR =>
|
|
|
|
when OP_MTSPR =>
|
|
|
|
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
|
|
|
|
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
|
|
|
|
"=" & to_hstring(c_in);
|
|
|
|
"=" & to_hstring(c_in);
|
|
|
@ -781,11 +854,6 @@ begin
|
|
|
|
stall_out <= '1';
|
|
|
|
stall_out <= '1';
|
|
|
|
x_to_divider.valid <= '1';
|
|
|
|
x_to_divider.valid <= '1';
|
|
|
|
|
|
|
|
|
|
|
|
when OP_LOAD | OP_STORE =>
|
|
|
|
|
|
|
|
-- loadstore/dcache has its own port to writeback
|
|
|
|
|
|
|
|
v.e.valid := '0';
|
|
|
|
|
|
|
|
lv.valid := '1';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when others =>
|
|
|
|
when others =>
|
|
|
|
terminate_out <= '1';
|
|
|
|
terminate_out <= '1';
|
|
|
|
report "illegal";
|
|
|
|
report "illegal";
|
|
|
@ -811,6 +879,14 @@ begin
|
|
|
|
report "Delayed LR update to " & to_hstring(next_nia);
|
|
|
|
report "Delayed LR update to " & to_hstring(next_nia);
|
|
|
|
stall_out <= '1';
|
|
|
|
stall_out <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elsif e_in.valid = '1' then
|
|
|
|
|
|
|
|
-- instruction for other units, i.e. LDST
|
|
|
|
|
|
|
|
v.e.valid := '0';
|
|
|
|
|
|
|
|
if e_in.unit = LDST then
|
|
|
|
|
|
|
|
lv.valid := '1';
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
elsif r.lr_update = '1' then
|
|
|
|
elsif r.lr_update = '1' then
|
|
|
|
result_en := '1';
|
|
|
|
result_en := '1';
|
|
|
|
result := r.next_lr;
|
|
|
|
result := r.next_lr;
|
|
|
@ -877,9 +953,7 @@ begin
|
|
|
|
v.e.write_enable := result_en;
|
|
|
|
v.e.write_enable := result_en;
|
|
|
|
|
|
|
|
|
|
|
|
-- Outputs to loadstore1 (async)
|
|
|
|
-- Outputs to loadstore1 (async)
|
|
|
|
if e_in.insn_type = OP_LOAD then
|
|
|
|
lv.op := e_in.insn_type;
|
|
|
|
lv.load := '1';
|
|
|
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
lv.addr1 := a_in;
|
|
|
|
lv.addr1 := a_in;
|
|
|
|
lv.addr2 := b_in;
|
|
|
|
lv.addr2 := b_in;
|
|
|
|
lv.data := c_in;
|
|
|
|
lv.data := c_in;
|
|
|
|