diff --git a/common.vhdl b/common.vhdl index 033b004..790d98c 100644 --- a/common.vhdl +++ b/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; diff --git a/decode1.vhdl b/decode1.vhdl index 7fca54b..ccfdf9f 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -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), diff --git a/decode2.vhdl b/decode2.vhdl index b27f563..d094681 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -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; diff --git a/decode_types.vhdl b/decode_types.vhdl index 8cb732a..4f81a36 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -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. diff --git a/execute1.vhdl b/execute1.vhdl index 7d714fb..dad8d72 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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; diff --git a/fetch1.vhdl b/fetch1.vhdl index 96c16fb..f07188d 100644 --- a/fetch1.vhdl +++ b/fetch1.vhdl @@ -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'; diff --git a/predecode.vhdl b/predecode.vhdl index 858910c..1846e3c 100644 --- a/predecode.vhdl +++ b/predecode.vhdl @@ -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 diff --git a/writeback.vhdl b/writeback.vhdl index c479c20..d7690a5 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -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;