Decrementer IRQ, rfid, mtmsr implementation

The interrupt controller is done in execute1. execute 1 then takes two
cycles to write fast SPRS SRR0 and SRR1.

MSR is stored in execute1 for now so it can be checked and tested for EE
atomically. This may need to move in the future.

DEC lives in execute1 also.

Signed-off-by: Michael Neuling <mikey@neuling.org>
pull/154/head
Michael Neuling 4 years ago
parent cc20989bda
commit 91f2692c8c

@ -16,6 +16,7 @@ package common is
constant SPR_LR : spr_num_t := 8;
constant SPR_CTR : spr_num_t := 9;
constant SPR_TB : spr_num_t := 268;
constant SPR_DEC : spr_num_t := 22;
constant SPR_SRR0 : spr_num_t := 26;
constant SPR_SRR1 : spr_num_t := 27;
constant SPR_HSRR0 : spr_num_t := 314;
@ -65,6 +66,8 @@ package common is
-- This needs to die...
type ctrl_t is record
tb: std_ulogic_vector(63 downto 0);
dec: std_ulogic_vector(63 downto 0);
msr: std_ulogic_vector(63 downto 0);
end record;

type Fetch1ToIcacheType is record

@ -94,6 +94,7 @@ architecture behaviour of decode1 is
2#0011000001# => '1', -- crxor
2#0010010110# => '1', -- isync
2#0000000000# => '1', -- mcrf
2#0000010010# => '1', -- rfid
others => '0'
);

@ -109,6 +110,8 @@ architecture behaviour of decode1 is
2#100# => (ALU, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0'),
-- isync
2#111# => (ALU, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'),
-- rfid
2#101# => (ALU, OP_RFID, SPR, SPR, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'),
others => illegal_inst
);

@ -237,12 +240,14 @@ architecture behaviour of decode1 is
-- 2#1000000000# mcrxr
-- 2#1001000000# mcrxrx
2#0000010011# => (ALU, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mfcr/mfocrf
2#0001010011# => (ALU, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mfmsr
2#0101010011# => (ALU, OP_MFSPR, SPR, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mfspr
2#0100001001# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- modud
2#0100001011# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0'), -- moduw
2#1100001001# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0'), -- modsd
2#1100001011# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0'), -- modsw
2#0010010000# => (ALU, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mtcrf/mtocrf
2#0010110010# => (ALU, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mtmsrd # ignore top bits and d
2#0111010011# => (ALU, OP_MTSPR, NONE, NONE, RS, SPR, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mtspr
2#0001001001# => (ALU, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0'), -- mulhd
2#0000001001# => (ALU, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- mulhdu
@ -425,6 +430,10 @@ begin
if is_fast_spr(v.ispr1) = '0' then
v.decode.sgl_pipe := '1';
end if;
elsif v.decode.insn_type = OP_RFID then
report "PPC RFID";
v.ispr1 := fast_spr_num(SPR_SRR0);
v.ispr2 := fast_spr_num(SPR_SRR1);
end if;

if flush_in = '1' then

@ -9,18 +9,17 @@ package decode_types is
OP_CRANDC, OP_CREQV, OP_CRNAND, OP_CRNOR, OP_CROR, OP_CRORC,
OP_CRXOR, OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST,
OP_DCBZ, OP_DIV, OP_DIVE, OP_EXTS,
OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC,
OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_IRQ_M0, OP_IRQ_M1, OP_ISEL, OP_ISYNC,
OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD, OP_MCRF,
OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFSPR, OP_MOD,
OP_MTCRF, OP_MTSPR, OP_MUL_L64,
OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MOD,
OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64,
OP_MUL_H64, OP_MUL_H32, OP_OR,
OP_POPCNT, OP_PRTY,
OP_POPCNT, OP_PRTY, OP_RFID,
OP_RLC, OP_RLCL, OP_RLCR, OP_SETB,
OP_SHL, OP_SHR,
OP_SYNC, OP_TD, OP_TDI, OP_TW,
OP_TWI, OP_XOR, OP_SIM_CONFIG
);

type input_reg_a_t is (NONE, RA, RA_OR_ZERO, SPR);
type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS, CONST_M1, CONST_SH, CONST_SH32, SPR);
type input_reg_c_t is (NONE, RS);

@ -49,6 +49,10 @@ architecture behaviour of execute1 is
slow_op_xerc : xer_common_t;
end record;

type irq_state_t is (WRITE_SRR0, WRITE_SRR1);

signal irq_state, irq_state_in : irq_state_t;

signal r, rin : reg_type;

signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0);
@ -175,6 +179,7 @@ begin
if rising_edge(clk) then
r <= rin;
ctrl <= ctrl_tmp;
irq_state <= irq_state_in;
assert not (r.lr_update = '1' and e_in.valid = '1')
report "LR update collision with valid in EX1"
severity failure;
@ -214,6 +219,8 @@ begin
variable msb_a, msb_b : std_ulogic;
variable a_lt : std_ulogic;
variable lv : Execute1ToLoadstore1Type;
variable irq_nia : std_ulogic_vector(63 downto 0);
variable irq_valid : std_ulogic;
begin
result := (others => '0');
result_with_carry := (others => '0');
@ -340,6 +347,15 @@ begin
ctrl_tmp <= ctrl;
-- FIXME: run at 512MHz not core freq
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);

irq_valid := '0';
irq_nia := (others => '-');
if ctrl.msr(15) = '1' and ctrl.dec(63) = '1' then
report "IRQ valid";
irq_valid := '1';
irq_nia := std_logic_vector(to_unsigned(16#900#, 64));
end if;

terminate_out <= '0';
icache_inval <= '0';
@ -354,7 +370,33 @@ begin
rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';

if e_in.valid = '1' then
irq_state_in <= WRITE_SRR0;

if irq_state = WRITE_SRR1 then
v.e.write_reg := fast_spr_num(SPR_SRR1);
result := ctrl.msr;
result_en := '1';
-- do this second so IRQ is still valid
-- FIXME frob other bits like HV/PR
ctrl_tmp.msr(15) <= '0';
f_out.redirect <= '1';
f_out.redirect_nia <= irq_nia;

elsif irq_valid = '1' then
-- we need two cycles to write srr0 and 1
-- will need more when we have to write DSISR, DAR and HIER
if irq_state = WRITE_SRR0 then
v.e.write_reg := fast_spr_num(SPR_SRR0);
result := e_in.nia;
if e_in.valid = '1' then
result_en := '1';
irq_state_in <= WRITE_SRR1;
stall_out <= '1';
v.e.valid := '1';
end if;
end if;

elsif e_in.valid = '1' then

v.e.valid := '1';
v.e.write_reg := e_in.write_reg;
@ -473,6 +515,11 @@ begin
f_out.redirect <= '1';
f_out.redirect_nia <= b_in(63 downto 2) & "00";
end if;

when OP_RFID =>
f_out.redirect <= '1';
f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
ctrl_tmp.msr <= std_ulogic_vector(signed(b_in)); -- srr1
when OP_CMPB =>
result := ppc_cmpb(c_in, b_in);
result_en := '1';
@ -562,7 +609,12 @@ begin
end if;
end loop;
end if;
when OP_MFMSR =>
result := ctrl.msr;
result_en := '1';
when OP_MFSPR =>
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
"=" & to_hstring(a_in);
if is_fast_spr(e_in.read_reg1) then
result := a_in;
if decode_spr_num(e_in.insn) = SPR_XER then
@ -579,6 +631,8 @@ begin
case decode_spr_num(e_in.insn) is
when SPR_TB =>
result := ctrl.tb;
when SPR_DEC =>
result := ctrl.dec;
when others =>
result := (others => '0');
end case;
@ -612,6 +666,9 @@ begin
v.e.write_cr_mask := num_to_fxm(crnum);
end if;
v.e.write_cr_data := c_in(31 downto 0);
when OP_MTMSRD =>
-- FIXME handle just the bits we need to.
ctrl_tmp.msr <= e_in.read_data3;
when OP_MTSPR =>
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
"=" & to_hstring(c_in);
@ -627,10 +684,12 @@ begin
v.e.write_xerc_enable := '1';
end if;
else
-- TODO: Implement slow SPRs
-- case decode_spr_num(e_in.insn) is
-- when others =>
-- end case;
-- slow spr
case decode_spr_num(e_in.insn) is
when SPR_DEC =>
ctrl_tmp.dec <= c_in;
when others =>
end case;
end if;
when OP_POPCNT =>
result := popcnt_result;

Loading…
Cancel
Save