URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_excplog_ix3.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 --------------------------------------------------------------- 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; entity RV01_EXCPLOG_IX3 is generic( NW : natural := 2 ); port( V_i : in std_logic_vector(NW-1 downto 0); -- slot #0,1 valid flag EV_i : in std_logic_vector(NW-1 downto 0); -- slot #0,1 valid flag INSTR_i : in DEC_INSTR_VEC_T(NW-1 downto 0); -- slot #0/1 inst. PC0_i : in ADR_T; -- slot #0 pc PC1_i : in ADR_T; -- slot #1 pc DADR0_i : in ADR_T; -- slot #0 L/S addr. DADR1_i : in ADR_T; -- slot #1 L/S addr. HALT_i : in std_logic; -- halt flag HIS_i : in std_logic; -- debug halt instruction selector EXCP_o : out std_logic; -- exc. flag ERET_o : out std_logic; -- return from exc. flag RFTCH_o : out std_logic; -- re-fetch flag KPRD_o : out std_logic_vector(NW-1 downto 0); -- slot #0/1 keep pipe reg. data flag CLRP_o : out std_logic; -- clear pipe flag CLRB_o : out std_logic; -- clear store buffer flag CLRD_o : out std_logic; -- clear divider flag EPC_o : out ADR_T; -- exc. pc ECAUSE_o : out std_logic_vector(5-1 downto 0); -- exc. cause EDADR_o : out ADR_T -- exc. L/S addr. ); end RV01_EXCPLOG_IX3; architecture ARC of RV01_EXCPLOG_IX3 is signal EXCP : std_logic; signal ERET : std_logic; signal RFTCH : std_logic; signal EIS : std_logic; signal DIV_REM : std_logic; begin ------------------------------------ -- Notes ------------------------------------ -- This modules generates most part of signals -- associated with re-fetching and exception -- processing. Such signals are generated in -- stage IX3 to insure that all instructions -- older than the one requiring re-fetching or -- raising an exception have complete their -- execution. -- Exception are raised and re-fetching started -- only when store buffer is empty of pending -- store (which are older than the instructions -- in stage IX3) and fetching is not stalled -- (to insure change of program flow doesn't get -- "ignored" because there's no room for new -- instructions in fetch queue). -- When an exception is raised or an instruction -- is re-fetched all instructions in the pipeline -- are invalidated and store buffer is cleared of -- pending store requests. -- Divider is also reset (aborting possibly ongoing -- operations) in case of exception or re-fetching, -- unless re-fetching is triggered by the same -- division instruction which is under processing. -- EV_i flags are asserted only for instruction -- raising an exception. Instruction eret is not -- treated an exception-raising instruction and -- therefore its valid bit is provided by V_i. -- Exception flag EXCP <= ( (EV_i(0) and INSTR_i(0).EXCP) or (EV_i(1) and INSTR_i(1).EXCP) ) and not(HALT_i); -- Exception is actually raised only when store buffer -- is empty because pending stores are older than -- instructions in IX3. EXCP_o <= EXCP; -- Return from exception flag ERET <= V_i(0) when ( (INSTR_i(0).IMNMC = IM_ERET) and HALT_i = '0' ) else '0'; -- Return from exception can take place only when -- store buffer is empty because pending stores are -- older than instructions in IX3. ERET_o <= ERET; -- Re-fetch flag RFTCH <= ( (EV_i(0) and INSTR_i(0).RFTCH) or (EV_i(1) and INSTR_i(1).RFTCH) ) and not(HALT_i); -- Re-fetching can take place only when -- store buffer is empty because pending stores are -- older than instructions in IX3. RFTCH_o <= RFTCH; -- IX3 instructions must be kept in pipe registers -- until store buffer is empty (to be deleted). KPRD_o(0) <= '0'; KPRD_o(1) <= '0'; -- clear pipe flag CLRP_o <= EXCP or ERET or RFTCH; -- clear store buffer flag CLRB_o <= (EXCP or ERET or RFTCH); -- instruction #0 division/reminder flag DIV_REM <= '1' when ( (INSTR_i(0).ALU_OP = ALU_DIV) or (INSTR_i(0).ALU_OP = ALU_REM) ) else '0'; -- clear divider flag -- a possible division operation in progress must be stopped -- (resetting divider) in case exception, return from exception -- or re-fetching occurs, unless the re-fetching is triggered -- by a division instruction. CLRD_o <= '1' when ( EXCP = '1' or ERET = '1' or (EV_i(0) = '1' and INSTR_i(0).RFTCH = '1' and DIV_REM = '0') or (EV_i(1) = '1' and INSTR_i(1).RFTCH = '1' and INSTR_i(0).RFTCH = '0') )else '0'; -- Exception instruction selector EIS <= HIS_i when (HALT_i = '1') else not(EV_i(0) and INSTR_i(0).EXCP); -- Exception PC EPC_o <= PC0_i when (EIS = '0') else PC1_i; -- Exception cause ECAUSE_o <= INSTR_i(0).ECAUSE when (EIS = '0') else INSTR_i(1).ECAUSE; -- Exception L/S address (aka the "bad addr") EDADR_o <= DADR0_i when (EIS = '0') else DADR1_i; end ARC;