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);
fscr_ic: std_ulogic_vector(3 downto 0);
fscr_pref: std_ulogic;
fscr_scv: std_ulogic;
fscr_tar: std_ulogic;
fscr_dscr: std_ulogic;
hfscr_ic: std_ulogic_vector(3 downto 0);
@ -272,7 +273,7 @@ package common is
end record;
constant ctrl_t_init : ctrl_t :=
(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',
dscr => (others => '0'),
others => (others => '0'));
@ -711,6 +712,7 @@ package common is
xerc : xer_common_t;
interrupt : std_ulogic;
hv_intr : std_ulogic;
is_scv : std_ulogic;
intr_vec : intr_vector_t;
redirect: std_ulogic;
redir_mode: std_ulogic_vector(3 downto 0);
@ -727,7 +729,7 @@ package common is
write_xerc_enable => '0', xerc => xerc_init,
write_data => (others => '0'), write_cr_mask => (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",
last_nia => (others => '0'),
br_last => '0', br_taken => '0', abs_br => '0',
@ -816,13 +818,13 @@ package common is
br_last : std_ulogic;
br_taken : std_ulogic;
interrupt : std_ulogic;
intr_vec : std_ulogic_vector(11 downto 0);
intr_vec : std_ulogic_vector(16 downto 0);
end record;
constant WritebackToFetch1Init : WritebackToFetch1Type :=
(redirect => '0', virt_mode => '0', priv_mode => '0', big_endian => '0',
mode_32bit => '0', redirect_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
write_reg : gspr_index_t;
@ -847,6 +849,7 @@ package common is
type WritebackToExecute1Type is record
intr : std_ulogic;
hv_intr : std_ulogic;
scv_int : std_ulogic;
srr1 : std_ulogic_vector(15 downto 0);
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_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_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_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),

@ -553,7 +553,11 @@ begin
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 =>
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
v.e.ramspr_even_rdaddr := RAMSPR_SRR0;
v.e.ramspr_odd_rdaddr := RAMSPR_SRR1;

@ -107,6 +107,7 @@ package decode_types is
INSN_prtyw,
INSN_prtyd, -- 70
INSN_rfid,
INSN_rfscv,
INSN_rldic,
INSN_rldicl,
INSN_rldicr,
@ -114,8 +115,8 @@ package decode_types is
INSN_rlwimi,
INSN_rlwinm,
INSN_rnop,
INSN_sc,
INSN_setb, -- 80
INSN_sc, -- 80
INSN_setb,
INSN_slbia,
INSN_sradi,
INSN_srawi,
@ -124,8 +125,8 @@ package decode_types is
INSN_stdu,
INSN_sthu,
INSN_stwu,
INSN_subfic,
INSN_subfme, -- 90
INSN_subfic, -- 90
INSN_subfme,
INSN_subfze,
INSN_sync,
INSN_tdi,
@ -135,7 +136,7 @@ package decode_types is
INSN_xori,
INSN_xoris,
-- 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
-- their corresponding prefixed instructions.

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

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

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;
v.e.redir_mode := (srr1(MSR_IR) or srr1(MSR_PR)) & not srr1(MSR_PR) &
not srr1(MSR_LE) & not srr1(MSR_SF);
@ -1471,6 +1480,14 @@ begin
report "illegal instruction";
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
(ctrl.hfscr_tar = '0' or ctrl.fscr_tar = '0') then
-- [Hypervisor] facility unavailable for TAR access
@ -1536,6 +1553,7 @@ begin
variable fv : Execute1ToFPUType;
variable go : std_ulogic;
variable bypass_valid : std_ulogic;
variable is_scv : std_ulogic;
begin
v := ex1;
if busy_out = '0' then
@ -1670,6 +1688,7 @@ begin
fv.valid := '1';
end if;
end if;
is_scv := go and actions.se.scv_trap;

if not HAS_FPU and ex1.div_in_progress = '1' then
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
v.e.interrupt := exception;
v.e.is_scv := is_scv;
end if;
if v.e.valid = '0' then
v.e.redirect := '0';
@ -1970,6 +1990,7 @@ begin
if ex1.se.write_fscr = '1' then
ctrl_tmp.fscr_ic <= ex1.e.write_data(59 downto 56);
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_dscr <= ex1.e.write_data(FSCR_DSCR);
elsif ex1.se.write_ic = '1' then
@ -2007,7 +2028,6 @@ begin

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_tmp.msr(MSR_SE) <= '0';
ctrl_tmp.msr(MSR_BE) <= '0';
@ -2016,8 +2036,11 @@ begin
ctrl_tmp.msr(MSR_FE1) <= '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';
if interrupt_in.scv_int = '0' then
ctrl_tmp.msr(MSR_EE) <= '0';
ctrl_tmp.msr(MSR_RI) <= '0';
end if;
end if;

bypass_valid := ex1.e.valid;

@ -391,7 +391,7 @@ begin
v_int.next_nia := RESET_ADDRESS;
end if;
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;
if rst /= '0' or w_in.interrupt = '1' then
v.req := '0';

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

-- Major opcode 59

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

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

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

-- Outputs to fetch1
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_nia := e_in.write_data;
f.br_nia := e_in.last_nia;

Loading…
Cancel
Save