URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_excplog_ix1.vhd] - Rev 2
Compare with Previous | Blame | View Log
----------------------------------------------------------------- -- -- ----------------------------------------------------------------- -- -- -- Copyright (C) 2015 Stefano Tonello -- -- -- -- This source file may be used and distributed without -- -- restriction provided that this copyright statement is not -- -- removed from the file and that any derivative work contains -- -- the original copyright notice and the associated disclaimer.-- -- -- -- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY -- -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -- -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- -- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR -- -- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -- -- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -- -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -- -- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -- -- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -- -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -- -- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- -- POSSIBILITY OF SUCH DAMAGE. -- -- -- ----------------------------------------------------------------- --------------------------------------------------------------- -- RV01 Exception processing logic (IX1 stage) --------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; library work; use work.RV01_CONSTS_PKG.all; use work.RV01_TYPES_PKG.all; use work.RV01_OP_PKG.all; use work.RV01_IDEC_PKG.all; use work.RV01_CSR_PKG.all; --use work.RV01_CFG_B_PKG.all; entity RV01_EXCPLOG_IX1 is generic( NW : natural := 2 ); port( INSTR_i : in DEC_INSTR_VEC_T(NW-1 downto 0); -- slot #0/1 inst. MALGN_i : in std_logic_vector(NW-1 downto 0); -- slot #0,1 misalign flag S2LAC_i : in std_logic_vector(NW-1 downto 0); -- slot #0,1 store-2-load conflict flag B2BAC_i : in std_logic; -- branch-2-branch conflict flag DIV_V_i : in std_logic; -- division valid result flag IDADR_CFLT_i : in std_logic; -- inst. mem. concurrent data access flag PSLP_o : out std_logic; INSTR_o : out DEC_INSTR_VEC_T(NW-1 downto 0) -- slot #0/1 inst. ); end RV01_EXCPLOG_IX1; architecture ARC of RV01_EXCPLOG_IX1 is signal INSTR : DEC_INSTR_VEC_T(NW-1 downto 0); signal PSLP : std_logic; function is_store(OP : LS_OP_T) return std_logic is variable S : std_logic; begin if(OP = LS_SB or OP = LS_SH or OP = LS_SW) then S := '1'; else S := '0'; end if; return(S); end function; function is_load(OP : LS_OP_T) return std_logic is variable S : std_logic; begin if(OP = LS_LB or OP = LS_LH or OP = LS_LW) then S := '1'; else S := '0'; end if; return(S); end function; begin ------------------------------------ -- Notes ------------------------------------ -- This module handles exceptions and re-fetching conditions -- generated in stage IX1. -- Exceptions: misaligned L/S address. -- Re-fetching conditions: -- 1) Store-to-load address conflict. -- 2) Branch address conflict (even-even or odd-odd). -- 3) Division. -- 4) Concurrent L/S access to inst. memory. -- Exception may affect both instructions, division -- re-fetching can affect only slot #0 instruction, and -- the other re-fetching condition can affect only slot #1 -- instruction. process(INSTR_i,MALGN_i,S2LAC_i,B2BAC_i,DIV_V_i,IDADR_CFLT_i) variable DIV_RFTCH,LOAD_RFTCH : std_logic; begin INSTR(0) <= INSTR_i(0); if(INSTR_i(0).IMNMC = IM_SCALL and INSTR_i(0).EXCP = '0') then INSTR(0).EXCP <= '1'; INSTR(0).ECAUSE <= UMCALL; elsif(INSTR_i(0).IMNMC = IM_SBREAK and INSTR_i(0).EXCP = '0') then INSTR(0).EXCP <= '1'; INSTR(0).ECAUSE <= BRKPNT; elsif(MALGN_i(0) = '1' and INSTR_i(0).EXCP = '0') then INSTR(0).EXCP <= '1'; if(is_store(INSTR_i(0).LS_OP) = '1') then INSTR(0).ECAUSE <= SADRMIS; else INSTR(0).ECAUSE <= LADRMIS; end if; end if; INSTR(1) <= INSTR_i(1); if(INSTR_i(1).IMNMC = IM_SCALL and INSTR_i(1).EXCP = '0') then INSTR(1).EXCP <= '1'; INSTR(1).ECAUSE <= UMCALL; elsif(INSTR_i(1).IMNMC = IM_SBREAK and INSTR_i(1).EXCP = '0') then INSTR(1).EXCP <= '1'; INSTR(1).ECAUSE <= BRKPNT; elsif(MALGN_i(1) = '1' and INSTR_i(1).EXCP = '0') then INSTR(1).EXCP <= '1'; if(is_store(INSTR_i(1).LS_OP) = '1') then INSTR(1).ECAUSE <= SADRMIS; else INSTR(1).ECAUSE <= LADRMIS; end if; end if; -- Division re-fetch flag if( INSTR_i(0).ALU_OP = ALU_DIV or INSTR_i(0).ALU_OP = ALU_REM ) then DIV_RFTCH := not(DIV_V_i); else DIV_RFTCH := '0'; end if; -- Concurrent access (to inst. memory) re-fetch flag if( INSTR_i(1).LS_OP = LS_LB or INSTR_i(1).LS_OP = LS_LH or INSTR_i(1).LS_OP = LS_LW ) then LOAD_RFTCH := IDADR_CFLT_i; else LOAD_RFTCH := '0'; end if; PSLP <= LOAD_RFTCH; -- Re-fetch flags INSTR(0).RFTCH <= S2LAC_i(0) or DIV_RFTCH; --INSTR(1).RFTCH <= S2LAC_i(1) or LOAD_RFTCH or B2BAC_i; INSTR(1).RFTCH <= S2LAC_i(1) or B2BAC_i; end process; PSLP_o <= PSLP; INSTR_o <= INSTR; end ARC;