Implement scv and rfscv

The main quirk here is that scv sets LR and CTR instead of SRR0 and
SRR1, and likewise rfscv uses LR and CTR.  Also, scv uses a set of 128
interrupt vectors starting at 0x17000.  Fortunately, the layout of the
SPR RAM was already such that LR and CTR were in the even and odd
halves respectively at the same index, so reading or writing LR and
CTR instead of SRR0 and SRR1 is quite easy.

Use of scv is subject to an FSCR bit but not an HFSCR bit.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/434/head
Paul Mackerras 1 year ago
parent a88fa9c459
commit d112a7ad94

@ -260,6 +260,7 @@ package common is
xer_low: std_ulogic_vector(17 downto 0); xer_low: std_ulogic_vector(17 downto 0);
fscr_ic: std_ulogic_vector(3 downto 0); fscr_ic: std_ulogic_vector(3 downto 0);
fscr_pref: std_ulogic; fscr_pref: std_ulogic;
fscr_scv: std_ulogic;
fscr_tar: std_ulogic; fscr_tar: std_ulogic;
fscr_dscr: std_ulogic; fscr_dscr: std_ulogic;
hfscr_ic: std_ulogic_vector(3 downto 0); hfscr_ic: std_ulogic_vector(3 downto 0);
@ -272,7 +273,7 @@ package common is
end record; end record;
constant ctrl_t_init : ctrl_t := constant ctrl_t_init : ctrl_t :=
(wait_state => '0', run => '1', xer_low => 18x"0", (wait_state => '0', run => '1', xer_low => 18x"0",
fscr_ic => x"0", fscr_pref => '1', fscr_tar => '1', fscr_dscr => '1', fscr_ic => x"0", fscr_pref => '1', fscr_scv => '1', fscr_tar => '1', fscr_dscr => '1',
hfscr_ic => x"0", hfscr_pref => '1', hfscr_tar => '1', hfscr_dscr => '1', hfscr_fp => '1', hfscr_ic => x"0", hfscr_pref => '1', hfscr_tar => '1', hfscr_dscr => '1', hfscr_fp => '1',
dscr => (others => '0'), dscr => (others => '0'),
others => (others => '0')); others => (others => '0'));
@ -711,6 +712,7 @@ package common is
xerc : xer_common_t; xerc : xer_common_t;
interrupt : std_ulogic; interrupt : std_ulogic;
hv_intr : std_ulogic; hv_intr : std_ulogic;
is_scv : std_ulogic;
intr_vec : intr_vector_t; intr_vec : intr_vector_t;
redirect: std_ulogic; redirect: std_ulogic;
redir_mode: std_ulogic_vector(3 downto 0); redir_mode: std_ulogic_vector(3 downto 0);
@ -727,7 +729,7 @@ package common is
write_xerc_enable => '0', xerc => xerc_init, write_xerc_enable => '0', xerc => xerc_init,
write_data => (others => '0'), write_cr_mask => (others => '0'), write_data => (others => '0'), write_cr_mask => (others => '0'),
write_cr_data => (others => '0'), write_reg => (others => '0'), write_cr_data => (others => '0'), write_reg => (others => '0'),
interrupt => '0', hv_intr => '0', intr_vec => 0, interrupt => '0', hv_intr => '0', is_scv => '0', intr_vec => 0,
redirect => '0', redir_mode => "0000", redirect => '0', redir_mode => "0000",
last_nia => (others => '0'), last_nia => (others => '0'),
br_last => '0', br_taken => '0', abs_br => '0', br_last => '0', br_taken => '0', abs_br => '0',
@ -816,13 +818,13 @@ package common is
br_last : std_ulogic; br_last : std_ulogic;
br_taken : std_ulogic; br_taken : std_ulogic;
interrupt : std_ulogic; interrupt : std_ulogic;
intr_vec : std_ulogic_vector(11 downto 0); intr_vec : std_ulogic_vector(16 downto 0);
end record; end record;
constant WritebackToFetch1Init : WritebackToFetch1Type := constant WritebackToFetch1Init : WritebackToFetch1Type :=
(redirect => '0', virt_mode => '0', priv_mode => '0', big_endian => '0', (redirect => '0', virt_mode => '0', priv_mode => '0', big_endian => '0',
mode_32bit => '0', redirect_nia => (others => '0'), mode_32bit => '0', redirect_nia => (others => '0'),
br_last => '0', br_taken => '0', br_nia => (others => '0'), br_last => '0', br_taken => '0', br_nia => (others => '0'),
interrupt => '0', intr_vec => x"000"); interrupt => '0', intr_vec => 17x"0");


type WritebackToRegisterFileType is record type WritebackToRegisterFileType is record
write_reg : gspr_index_t; write_reg : gspr_index_t;
@ -847,6 +849,7 @@ package common is
type WritebackToExecute1Type is record type WritebackToExecute1Type is record
intr : std_ulogic; intr : std_ulogic;
hv_intr : std_ulogic; hv_intr : std_ulogic;
scv_int : std_ulogic;
srr1 : std_ulogic_vector(15 downto 0); srr1 : std_ulogic_vector(15 downto 0);
end record; end record;



@ -302,6 +302,7 @@ architecture behaviour of decode1 is
INSN_prtyd => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_prtyd => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
INSN_prtyw => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_prtyw => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
INSN_rfid => (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), INSN_rfid => (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),
INSN_rfscv => (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),
INSN_rldcl => (ALU, NONE, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_rldcl => (ALU, NONE, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE),
INSN_rldcr => (ALU, NONE, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_rldcr => (ALU, NONE, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE),
INSN_rldic => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_rldic => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE),

@ -553,7 +553,11 @@ begin
v.e.ramspr_write_odd := d_in.ram_spr.valid and 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; v.e.spr_is_ram := d_in.ram_spr.valid;
when OP_RFID => when OP_RFID =>
if d_in.insn(9) = '0' then if d_in.insn(7) = '1' then
-- rfscv
v.e.ramspr_even_rdaddr := RAMSPR_LR;
v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
elsif d_in.insn(9) = '0' then
-- rfid -- rfid
v.e.ramspr_even_rdaddr := RAMSPR_SRR0; v.e.ramspr_even_rdaddr := RAMSPR_SRR0;
v.e.ramspr_odd_rdaddr := RAMSPR_SRR1; v.e.ramspr_odd_rdaddr := RAMSPR_SRR1;

@ -107,6 +107,7 @@ package decode_types is
INSN_prtyw, INSN_prtyw,
INSN_prtyd, -- 70 INSN_prtyd, -- 70
INSN_rfid, INSN_rfid,
INSN_rfscv,
INSN_rldic, INSN_rldic,
INSN_rldicl, INSN_rldicl,
INSN_rldicr, INSN_rldicr,
@ -114,8 +115,8 @@ package decode_types is
INSN_rlwimi, INSN_rlwimi,
INSN_rlwinm, INSN_rlwinm,
INSN_rnop, INSN_rnop,
INSN_sc, INSN_sc, -- 80
INSN_setb, -- 80 INSN_setb,
INSN_slbia, INSN_slbia,
INSN_sradi, INSN_sradi,
INSN_srawi, INSN_srawi,
@ -124,8 +125,8 @@ package decode_types is
INSN_stdu, INSN_stdu,
INSN_sthu, INSN_sthu,
INSN_stwu, INSN_stwu,
INSN_subfic, INSN_subfic, -- 90
INSN_subfme, -- 90 INSN_subfme,
INSN_subfze, INSN_subfze,
INSN_sync, INSN_sync,
INSN_tdi, INSN_tdi,
@ -135,7 +136,7 @@ package decode_types is
INSN_xori, INSN_xori,
INSN_xoris, INSN_xoris,
-- pad to 104 -- pad to 104
INSN_063, INSN_064, INSN_065, INSN_066, INSN_067, INSN_064, INSN_065, INSN_066, INSN_067,


-- Non-prefixed instructions that have a MLS:D prefixed form and -- Non-prefixed instructions that have a MLS:D prefixed form and
-- their corresponding prefixed instructions. -- their corresponding prefixed instructions.

@ -96,6 +96,7 @@ architecture behaviour of execute1 is
write_ctrl : std_ulogic; write_ctrl : std_ulogic;
write_dscr : std_ulogic; write_dscr : std_ulogic;
enter_wait : std_ulogic; enter_wait : std_ulogic;
scv_trap : std_ulogic;
end record; end record;
constant side_effect_init : side_effect_type := (others => '0'); constant side_effect_init : side_effect_type := (others => '0');


@ -393,6 +394,7 @@ architecture behaviour of execute1 is
ret := (others => '0'); ret := (others => '0');
ret(59 downto 56) := c.fscr_ic; ret(59 downto 56) := c.fscr_ic;
ret(FSCR_PREFIX) := c.fscr_pref; ret(FSCR_PREFIX) := c.fscr_pref;
ret(FSCR_SCV) := c.fscr_scv;
ret(FSCR_TAR) := c.fscr_tar; ret(FSCR_TAR) := c.fscr_tar;
ret(FSCR_DSCR) := c.fscr_dscr; ret(FSCR_DSCR) := c.fscr_dscr;
return ret; return ret;
@ -587,10 +589,12 @@ begin
even_wr_enab := (ex1.se.ramspr_write_even and doit) or interrupt_in.intr; 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; odd_wr_enab := (ex1.se.ramspr_write_odd and doit) or interrupt_in.intr;
if interrupt_in.intr = '1' then if interrupt_in.intr = '1' then
if interrupt_in.hv_intr = '0' then if interrupt_in.hv_intr = '1' then
wr_addr := RAMSPR_SRR0;
else
wr_addr := RAMSPR_HSRR0; wr_addr := RAMSPR_HSRR0;
elsif interrupt_in.scv_int = '1' then
wr_addr := RAMSPR_LR;
else
wr_addr := RAMSPR_SRR0;
end if; end if;
else else
wr_addr := ex1.ramspr_wraddr; wr_addr := ex1.ramspr_wraddr;
@ -1127,18 +1131,20 @@ begin
when OP_ILLEGAL => when OP_ILLEGAL =>
illegal := '1'; illegal := '1';
when OP_SC => when OP_SC =>
-- check bit 1 of the instruction is 1 so we know this is sc; -- check bit 1 of the instruction to distinguish sc from scv
-- 0 would mean scv, so generate an illegal instruction interrupt
if e_in.insn(1) = '1' then if e_in.insn(1) = '1' then
v.trap := '1'; -- sc
v.advance_nia := '1';
v.e.intr_vec := 16#C00#; v.e.intr_vec := 16#C00#;
if e_in.valid = '1' then if e_in.valid = '1' then
report "sc"; report "sc";
end if; end if;
else else
illegal := '1'; -- scv
v.se.scv_trap := '1';
v.e.intr_vec := to_integer(unsigned(e_in.insn(11 downto 5))) * 32;
end if; end if;
v.trap := '1';
v.advance_nia := '1';
when OP_ATTN => when OP_ATTN =>
-- check bits 1-10 of the instruction to make sure it's attn -- check bits 1-10 of the instruction to make sure it's attn
-- if not then it is illegal -- if not then it is illegal
@ -1230,6 +1236,9 @@ begin
v.se.set_cfar := v.take_branch; v.se.set_cfar := v.take_branch;


when OP_RFID => when OP_RFID =>
-- rfid, hrfid and rfscv.
-- These all act the same given that we don't have
-- privileged non-hypervisor mode or ultravisor mode.
srr1 := ramspr_odd; srr1 := ramspr_odd;
v.e.redir_mode := (srr1(MSR_IR) or srr1(MSR_PR)) & not srr1(MSR_PR) & v.e.redir_mode := (srr1(MSR_IR) or srr1(MSR_PR)) & not srr1(MSR_PR) &
not srr1(MSR_LE) & not srr1(MSR_SF); not srr1(MSR_LE) & not srr1(MSR_SF);
@ -1471,6 +1480,14 @@ begin
report "illegal instruction"; report "illegal instruction";
end if; end if;


elsif ex1.msr(MSR_PR) = '1' and v.se.scv_trap = '1' and
ctrl.fscr_scv = '0' then
-- Facility unavailable for scv instruction
v.exception := '1';
v.ic := x"c";
v.e.intr_vec := 16#f60#;
v.se.write_ic := '1';

elsif ex1.msr(MSR_PR) = '1' and e_in.uses_tar = '1' and elsif ex1.msr(MSR_PR) = '1' and e_in.uses_tar = '1' and
(ctrl.hfscr_tar = '0' or ctrl.fscr_tar = '0') then (ctrl.hfscr_tar = '0' or ctrl.fscr_tar = '0') then
-- [Hypervisor] facility unavailable for TAR access -- [Hypervisor] facility unavailable for TAR access
@ -1536,6 +1553,7 @@ begin
variable fv : Execute1ToFPUType; variable fv : Execute1ToFPUType;
variable go : std_ulogic; variable go : std_ulogic;
variable bypass_valid : std_ulogic; variable bypass_valid : std_ulogic;
variable is_scv : std_ulogic;
begin begin
v := ex1; v := ex1;
if busy_out = '0' then if busy_out = '0' then
@ -1670,6 +1688,7 @@ begin
fv.valid := '1'; fv.valid := '1';
end if; end if;
end if; end if;
is_scv := go and actions.se.scv_trap;


if not HAS_FPU and ex1.div_in_progress = '1' then if not HAS_FPU and ex1.div_in_progress = '1' then
v.div_in_progress := not divider_to_x.valid; v.div_in_progress := not divider_to_x.valid;
@ -1710,6 +1729,7 @@ begin


if (ex1.busy or l_in.busy or fp_in.busy) = '0' then if (ex1.busy or l_in.busy or fp_in.busy) = '0' then
v.e.interrupt := exception; v.e.interrupt := exception;
v.e.is_scv := is_scv;
end if; end if;
if v.e.valid = '0' then if v.e.valid = '0' then
v.e.redirect := '0'; v.e.redirect := '0';
@ -1970,6 +1990,7 @@ begin
if ex1.se.write_fscr = '1' then if ex1.se.write_fscr = '1' then
ctrl_tmp.fscr_ic <= ex1.e.write_data(59 downto 56); ctrl_tmp.fscr_ic <= ex1.e.write_data(59 downto 56);
ctrl_tmp.fscr_pref <= ex1.e.write_data(FSCR_PREFIX); ctrl_tmp.fscr_pref <= ex1.e.write_data(FSCR_PREFIX);
ctrl_tmp.fscr_scv <= ex1.e.write_data(FSCR_SCV);
ctrl_tmp.fscr_tar <= ex1.e.write_data(FSCR_TAR); ctrl_tmp.fscr_tar <= ex1.e.write_data(FSCR_TAR);
ctrl_tmp.fscr_dscr <= ex1.e.write_data(FSCR_DSCR); ctrl_tmp.fscr_dscr <= ex1.e.write_data(FSCR_DSCR);
elsif ex1.se.write_ic = '1' then elsif ex1.se.write_ic = '1' then
@ -2007,7 +2028,6 @@ begin


if interrupt_in.intr = '1' then if interrupt_in.intr = '1' then
ctrl_tmp.msr(MSR_SF) <= '1'; ctrl_tmp.msr(MSR_SF) <= '1';
ctrl_tmp.msr(MSR_EE) <= '0';
ctrl_tmp.msr(MSR_PR) <= '0'; ctrl_tmp.msr(MSR_PR) <= '0';
ctrl_tmp.msr(MSR_SE) <= '0'; ctrl_tmp.msr(MSR_SE) <= '0';
ctrl_tmp.msr(MSR_BE) <= '0'; ctrl_tmp.msr(MSR_BE) <= '0';
@ -2016,8 +2036,11 @@ begin
ctrl_tmp.msr(MSR_FE1) <= '0'; ctrl_tmp.msr(MSR_FE1) <= '0';
ctrl_tmp.msr(MSR_IR) <= '0'; ctrl_tmp.msr(MSR_IR) <= '0';
ctrl_tmp.msr(MSR_DR) <= '0'; ctrl_tmp.msr(MSR_DR) <= '0';
ctrl_tmp.msr(MSR_RI) <= '0';
ctrl_tmp.msr(MSR_LE) <= '1'; ctrl_tmp.msr(MSR_LE) <= '1';
if interrupt_in.scv_int = '0' then
ctrl_tmp.msr(MSR_EE) <= '0';
ctrl_tmp.msr(MSR_RI) <= '0';
end if;
end if; end if;


bypass_valid := ex1.e.valid; bypass_valid := ex1.e.valid;

@ -391,7 +391,7 @@ begin
v_int.next_nia := RESET_ADDRESS; v_int.next_nia := RESET_ADDRESS;
end if; end if;
elsif w_in.interrupt = '1' then elsif w_in.interrupt = '1' then
v_int.next_nia := 52x"0" & w_in.intr_vec(11 downto 2) & "00"; v_int.next_nia := 47x"0" & w_in.intr_vec(16 downto 2) & "00";
end if; end if;
if rst /= '0' or w_in.interrupt = '1' then if rst /= '0' or w_in.interrupt = '1' then
v.req := '0'; v.req := '0';

@ -447,6 +447,7 @@ architecture behaviour of predecoder is
2#1_00100_11110# => INSN_isync, 2#1_00100_11110# => INSN_isync,
2#1_00000_10000# => INSN_mcrf, 2#1_00000_10000# => INSN_mcrf,
2#1_00000_11010# => INSN_rfid, 2#1_00000_11010# => INSN_rfid,
2#1_00010_11010# => INSN_rfscv,
2#1_01000_11010# => INSN_rfid, -- hrfid 2#1_01000_11010# => INSN_rfid, -- hrfid


-- Major opcode 59 -- Major opcode 59

@ -73,6 +73,8 @@ begin
variable srr1 : std_ulogic_vector(15 downto 0); variable srr1 : std_ulogic_vector(15 downto 0);
variable intr : std_ulogic; variable intr : std_ulogic;
variable hvi : std_ulogic; variable hvi : std_ulogic;
variable scv : std_ulogic;
variable intr_page : std_ulogic_vector(4 downto 0);
begin begin
w_out <= WritebackToRegisterFileInit; w_out <= WritebackToRegisterFileInit;
c_out <= WritebackToCrFileInit; c_out <= WritebackToCrFileInit;
@ -95,10 +97,16 @@ begin
interrupt_out.intr <= intr; interrupt_out.intr <= intr;


srr1 := (others => '0'); srr1 := (others => '0');
intr_page := 5x"0";
scv := '0';
if e_in.interrupt = '1' then if e_in.interrupt = '1' then
vec := e_in.intr_vec; vec := e_in.intr_vec;
srr1 := e_in.srr1; srr1 := e_in.srr1;
hvi := e_in.hv_intr; hvi := e_in.hv_intr;
scv := e_in.is_scv;
if e_in.is_scv = '1' then
intr_page := 5x"17";
end if;
elsif l_in.interrupt = '1' then elsif l_in.interrupt = '1' then
vec := l_in.intr_vec; vec := l_in.intr_vec;
srr1 := l_in.srr1; srr1 := l_in.srr1;
@ -108,6 +116,7 @@ begin
end if; end if;
interrupt_out.hv_intr <= hvi; interrupt_out.hv_intr <= hvi;
interrupt_out.srr1 <= srr1; interrupt_out.srr1 <= srr1;
interrupt_out.scv_int <= scv;


if intr = '0' then if intr = '0' then
if e_in.write_enable = '1' then if e_in.write_enable = '1' then
@ -165,7 +174,7 @@ begin


-- Outputs to fetch1 -- Outputs to fetch1
f.interrupt := intr; f.interrupt := intr;
f.intr_vec := std_ulogic_vector(to_unsigned(vec, 12)); f.intr_vec := intr_page & std_ulogic_vector(to_unsigned(vec, 12));
f.redirect := e_in.redirect; f.redirect := e_in.redirect;
f.redirect_nia := e_in.write_data; f.redirect_nia := e_in.write_data;
f.br_nia := e_in.last_nia; f.br_nia := e_in.last_nia;

Loading…
Cancel
Save