mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-02-26 16:53:16 +00:00
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>
This commit is contained in:
11
common.vhdl
11
common.vhdl
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user