URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_pstllog_2w_p6.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 WARRS1NTIES, INCLUDING, BUT NOT LIMITED -- -- TO, THE IMPLIED WARRS1NTIES 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 CONTRS1CT, 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 Pipeline stall 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_FUNCS_PKG.all; use work.RV01_IDEC_PKG.all; entity RV01_PSTLLOG_2W_P6 is generic( DXE : std_logic := '1'; SIMULATION_ONLY : std_logic := '0' ); port( CLK_i : in std_logic; ID_INSTR_i : in DEC_INSTR_T; ID_V_i : in std_logic; IX1_INSTR0_i : in DEC_INSTR_T; IX1_INSTR1_i : in DEC_INSTR_T; IX1_V_i : in std_logic_vector(2-1 downto 0); IX1_FWDE_i : in std_logic_vector(2-1 downto 0); IX2_INSTR0_i : in DEC_INSTR_T; IX2_INSTR1_i : in DEC_INSTR_T; IX2_V_i : in std_logic_vector(2-1 downto 0); IX2_FWDE_i : in std_logic_vector(2-1 downto 0); IX3_INSTR0_i : in DEC_INSTR_T; IX3_INSTR1_i : in DEC_INSTR_T; IX3_V_i : in std_logic_vector(2-1 downto 0); IX3_FWDE_i : in std_logic_vector(2-1 downto 0); OPA_V_o : out std_logic; OPB_V_o : out std_logic; DSA_o : out std_logic; DSB_o : out std_logic; PSTALL_o : out std_logic ); end RV01_PSTLLOG_2W_P6; architecture ARC of RV01_PSTLLOG_2W_P6 is function dep_a(RMTCH,IDV,IXV : std_logic;IDI,IXI : DEC_INSTR_T) return std_logic is begin if(RMTCH = '1') then return(IDV and IXV and IDI.RRS1 and IXI.WRD); else return('0'); end if; end function; function dep_b(RMTCH,IDV,IXV : std_logic;IDI,IXI : DEC_INSTR_T) return std_logic is begin if(RMTCH = '1') then return(IDV and IXV and IDI.RRS2 and IXI.WRD); else return('0'); end if; end function; function stall_a(DEP,FWDE,IX_2C : std_logic;IDI,IXI : DEC_INSTR_T) return std_logic is begin if( (DEP = '1') -- and ((FWDE = '0') or (IX_2C = '1')) ) then return(qmark((FWDE = '0') or (IX_2C = '1'),'1','0')); else return('0'); end if; end function; function stall_b(DEP,FWDE,IX_2C : std_logic;IDI,IXI : DEC_INSTR_T) return std_logic is begin if( (DEP = '1') -- and ((FWDE = '0') or (IX_2C = '1')) ) then return(qmark((FWDE = '0') or (IX_2C = '1'),'1','0')); else return('0'); end if; end function; signal IX_2C0,IX_2C1 : std_logic; signal DX : std_logic; signal SEQX : std_logic; signal OPA_V_N,OPB_V_N : std_logic; signal DATA_DEPA_IX1_0,DATA_DEPA_IX2_0,DATA_DEPA_IX3_0 : std_logic; signal DATA_DEPB_IX1_0,DATA_DEPB_IX2_0,DATA_DEPB_IX3_0 : std_logic; signal DATA_DEPA_IX1_1,DATA_DEPA_IX2_1,DATA_DEPA_IX3_1 : std_logic; signal DATA_DEPB_IX1_1,DATA_DEPB_IX2_1,DATA_DEPB_IX3_1 : std_logic; signal RMTCH_A_IX1_0,RMTCH_A_IX2_0,RMTCH_A_IX3_0 : std_logic; signal RMTCH_B_IX1_0,RMTCH_B_IX2_0,RMTCH_B_IX3_0 : std_logic; signal RMTCH_A_IX1_1,RMTCH_A_IX2_1,RMTCH_A_IX3_1 : std_logic; signal RMTCH_B_IX1_1,RMTCH_B_IX2_1,RMTCH_B_IX3_1 : std_logic; signal RS1P1,RS2P1 : RID_T; signal RD1P1_0,RD2P1_0,RD3P1_0 : RID_T; signal RD1P1_1,RD2P1_1,RD3P1_1 : RID_T; signal STALL_A_IX1_0,STALL_A_IX2_0,STALL_A_IX3_0 : std_logic; signal STALL_B_IX1_0,STALL_B_IX2_0,STALL_B_IX3_0 : std_logic; signal STALL_A_IX1_1,STALL_A_IX2_1,STALL_A_IX3_1 : std_logic; signal STALL_B_IX1_1,STALL_B_IX2_1,STALL_B_IX3_1 : std_logic; type NVEC is array (8-1 downto 0) of natural; signal STALL_STATS : NVEC := (0,0,0,0,0,0,0,0); begin ---------------------------------------------------- -- Notes: ---------------------------------------------------- -- -- This modules checks if an instruction in ID stage -- has a data dependency from an older instruction -- (in IX* stage) which prevents it from being -- issued. ---------------------------------------------------- -- General rules: ---------------------------------------------------- -- -- Issuing must be stalled if ID stage instruction -- needs result generated by an instruction in IX* -- stage and this instruction is not enabled to -- result forwarding (only add/i, sub, slt/i, sltu/i -- and lw instructions are, and the last type is a -- 2-cycle instructions that allows forwarding only -- from stage IX2). -- -- As a consequence, issuing must be stalled (because -- result forwarding is not possible) if: -- 1) instruction in ID stage needs a result generated by -- an instructions in IX* stage, AND [ -- 2.a) the instruction in IX1, is not enabled to -- result forwarding or is a two-cycle instruction, OR -- 2.b) the instruction in IX2 stage is not enabled -- to result forwarding, OR -- 2.c) the instruction in IX3 stage is not enabled -- to result forwarding. -- ] -- NOTE: only IF* and ID stages get actually stalled, -- allowing IX* stages to proceed. -- This version supports delayed execution by avoiding -- stalling issue when the instruction in ID stage is -- of add/i, sub, slt/i and sltu/i type, and providing -- additional outputs to flag operands status. ---------------------------------------------------- -- two-cycle forward-enabled instruction flags IX_2C0 <= '1' when ( (IX1_INSTR0_i.IMNMC = IM_LW) ) else '0'; IX_2C1 <= '1' when ( (IX1_INSTR1_i.IMNMC = IM_LW) ) else '0'; ---------------------------------------------------- -- Delayed eXecution flag (set to '1' for -- instructions which can be executed in delayed -- mode). GDXE_0 : if(DXE = '0') generate DX <= '0'; end generate; GDXE_1 : if(DXE = '1') generate DX <= '1' when ( (ID_INSTR_i.IMNMC = IM_ADD) or (ID_INSTR_i.IMNMC = IM_ADDI) or (ID_INSTR_i.IMNMC = IM_AND) or (ID_INSTR_i.IMNMC = IM_ANDI) or (ID_INSTR_i.IMNMC = IM_OR) or (ID_INSTR_i.IMNMC = IM_ORI) or (ID_INSTR_i.IMNMC = IM_XOR) or (ID_INSTR_i.IMNMC = IM_XORI) ) else '0'; end generate; ---------------------------------------------------- -- Sequential eXecution flag. -- Sequential execution flag is asserted when: -- 1) ID instruction has SEQX flag set and there's, -- at least, a valid instruction under execution, OR -- 2) there's , at least, a valid instruction under -- execution having SEQX flag set. SEQX <= ( ID_INSTR_i.SEQX and ( IX1_V_i(0) or IX1_V_i(1) or IX2_V_i(0) or IX2_V_i(1) or IX3_V_i(0) or IX3_V_i(1) ) ) or ( (IX1_INSTR0_i.SEQX and IX1_V_i(0)) or (IX1_INSTR1_i.SEQX and IX1_V_i(1)) or (IX2_INSTR0_i.SEQX and IX2_V_i(0)) or (IX2_INSTR1_i.SEQX and IX2_V_i(1)) or (IX3_INSTR0_i.SEQX and IX3_V_i(0)) or (IX3_INSTR1_i.SEQX and IX3_V_i(1)) ); ---------------------------------------------------- -- ID instr. vs. IX1/2/3 instr. register match flags -- (when a flag is asserted, there's a mtach between a -- register read by ID instruction and the register -- written by IX1/2/3 instruction). -- RMTCH_x_IXy_z = '1' when there's a match between ID instruction -- operand register id. x and IXy instruction #z destination -- register id.. RMTCH_A_IX1_0 <= '1' when (ID_INSTR_i.RS1 = IX1_INSTR0_i.RD) else '0'; RMTCH_A_IX2_0 <= '1' when (ID_INSTR_i.RS1 = IX2_INSTR0_i.RD) else '0'; RMTCH_A_IX3_0 <= '1' when (ID_INSTR_i.RS1 = IX3_INSTR0_i.RD) else '0'; RMTCH_B_IX1_0 <= '1' when (ID_INSTR_i.RS2 = IX1_INSTR0_i.RD) else '0'; RMTCH_B_IX2_0 <= '1' when (ID_INSTR_i.RS2 = IX2_INSTR0_i.RD) else '0'; RMTCH_B_IX3_0 <= '1' when (ID_INSTR_i.RS2 = IX3_INSTR0_i.RD) else '0'; RMTCH_A_IX1_1 <= '1' when (ID_INSTR_i.RS1 = IX1_INSTR1_i.RD) else '0'; RMTCH_A_IX2_1 <= '1' when (ID_INSTR_i.RS1 = IX2_INSTR1_i.RD) else '0'; RMTCH_A_IX3_1 <= '1' when (ID_INSTR_i.RS1 = IX3_INSTR1_i.RD) else '0'; RMTCH_B_IX1_1 <= '1' when (ID_INSTR_i.RS2 = IX1_INSTR1_i.RD) else '0'; RMTCH_B_IX2_1 <= '1' when (ID_INSTR_i.RS2 = IX2_INSTR1_i.RD) else '0'; RMTCH_B_IX3_1 <= '1' when (ID_INSTR_i.RS2 = IX3_INSTR1_i.RD) else '0'; ---------------------------------------------------- -- DATA_DEPx_IXy_z = '1' when there's a data dependency between -- ID instruction operand x and IXy instruction #z result DATA_DEPA_IX1_0 <= dep_a(RMTCH_A_IX1_0,ID_V_i,IX1_V_i(0),ID_INSTR_i,IX1_INSTR0_i); DATA_DEPA_IX2_0 <= dep_a(RMTCH_A_IX2_0,ID_V_i,IX2_V_i(0),ID_INSTR_i,IX2_INSTR0_i); DATA_DEPA_IX3_0 <= dep_a(RMTCH_A_IX3_0,ID_V_i,IX3_V_i(0),ID_INSTR_i,IX3_INSTR0_i); DATA_DEPB_IX1_0 <= dep_b(RMTCH_B_IX1_0,ID_V_i,IX1_V_i(0),ID_INSTR_i,IX1_INSTR0_i); DATA_DEPB_IX2_0 <= dep_b(RMTCH_B_IX2_0,ID_V_i,IX2_V_i(0),ID_INSTR_i,IX2_INSTR0_i); DATA_DEPB_IX3_0 <= dep_b(RMTCH_B_IX3_0,ID_V_i,IX3_V_i(0),ID_INSTR_i,IX3_INSTR0_i); DATA_DEPA_IX1_1 <= dep_a(RMTCH_A_IX1_1,ID_V_i,IX1_V_i(1),ID_INSTR_i,IX1_INSTR1_i); DATA_DEPA_IX2_1 <= dep_a(RMTCH_A_IX2_1,ID_V_i,IX2_V_i(1),ID_INSTR_i,IX2_INSTR1_i); DATA_DEPA_IX3_1 <= dep_a(RMTCH_A_IX3_1,ID_V_i,IX3_V_i(1),ID_INSTR_i,IX3_INSTR1_i); DATA_DEPB_IX1_1 <= dep_b(RMTCH_B_IX1_1,ID_V_i,IX1_V_i(1),ID_INSTR_i,IX1_INSTR1_i); DATA_DEPB_IX2_1 <= dep_b(RMTCH_B_IX2_1,ID_V_i,IX2_V_i(1),ID_INSTR_i,IX2_INSTR1_i); DATA_DEPB_IX3_1 <= dep_b(RMTCH_B_IX3_1,ID_V_i,IX3_V_i(1),ID_INSTR_i,IX3_INSTR1_i); ---------------------------------------------------- -- STALL_x_IXy_z = '1' when there's a stall condition caused by -- ID instruction operand x and IXy instruction #z result STALL_A_IX1_0 <= stall_a(DATA_DEPA_IX1_0,IX1_FWDE_i(0),IX_2C0,ID_INSTR_i,IX1_INSTR0_i); STALL_A_IX2_0 <= stall_a(DATA_DEPA_IX2_0,IX2_FWDE_i(0),'0',ID_INSTR_i,IX2_INSTR0_i); STALL_A_IX3_0 <= stall_a(DATA_DEPA_IX3_0,IX3_FWDE_i(0),'0',ID_INSTR_i,IX3_INSTR0_i); STALL_B_IX1_0 <= stall_b(DATA_DEPB_IX1_0,IX1_FWDE_i(0),IX_2C0,ID_INSTR_i,IX1_INSTR0_i); STALL_B_IX2_0 <= stall_b(DATA_DEPB_IX2_0,IX2_FWDE_i(0),'0',ID_INSTR_i,IX2_INSTR0_i); STALL_B_IX3_0 <= stall_b(DATA_DEPB_IX3_0,IX3_FWDE_i(0),'0',ID_INSTR_i,IX3_INSTR0_i); STALL_A_IX1_1 <= stall_a(DATA_DEPA_IX1_1,IX1_FWDE_i(1),IX_2C1,ID_INSTR_i,IX1_INSTR1_i); STALL_A_IX2_1 <= stall_a(DATA_DEPA_IX2_1,IX2_FWDE_i(1),'0',ID_INSTR_i,IX2_INSTR1_i); STALL_A_IX3_1 <= stall_a(DATA_DEPA_IX3_1,IX3_FWDE_i(1),'0',ID_INSTR_i,IX3_INSTR1_i); STALL_B_IX1_1 <= stall_b(DATA_DEPB_IX1_1,IX1_FWDE_i(1),IX_2C1,ID_INSTR_i,IX1_INSTR1_i); STALL_B_IX2_1 <= stall_b(DATA_DEPB_IX2_1,IX2_FWDE_i(1),'0',ID_INSTR_i,IX2_INSTR1_i); STALL_B_IX3_1 <= stall_b(DATA_DEPB_IX3_1,IX3_FWDE_i(1),'0',ID_INSTR_i,IX3_INSTR1_i); ---------------------------------------------------- -- operand valid flags OPA_V_o <= not(OPA_V_N); OPA_V_N <= STALL_A_IX1_0 or STALL_A_IX2_0 or STALL_A_IX3_0 or STALL_A_IX1_1 or STALL_A_IX2_1 or STALL_A_IX3_1; OPB_V_o <= not(OPB_V_N); OPB_V_N <= STALL_B_IX1_0 or STALL_B_IX2_0 or STALL_B_IX3_0 or STALL_B_IX1_1 or STALL_B_IX2_1 or STALL_B_IX3_1; -- Double Stall flags (set to '1' when operand A/B is -- subject to a double (dependency) condition, this -- information must be piped to stage X1 to prevent -- instructions from reading the incorrect result). -- Double Stall can be '1' only for instructions -- which can be executed in delayed mode. DSA_o <= DX when ( (DATA_DEPA_IX1_0= '1' or DATA_DEPA_IX1_1 = '1') and (DATA_DEPA_IX2_0 = '1' or DATA_DEPA_IX2_1 = '1') ) else '0'; DSB_o <= DX when ( (DATA_DEPB_IX1_0 = '1' or DATA_DEPB_IX1_1 = '1') and (DATA_DEPB_IX2_0 = '1' or DATA_DEPB_IX2_1 = '1') ) else '0'; -- pipeline (instr. issue) stall flag PSTALL_o <= (( STALL_A_IX1_0 or STALL_A_IX2_0 or STALL_A_IX3_0 or STALL_B_IX1_0 or STALL_B_IX2_0 or STALL_B_IX3_0 or STALL_A_IX1_1 or STALL_A_IX2_1 or STALL_A_IX3_1 or STALL_B_IX1_1 or STALL_B_IX2_1 or STALL_B_IX3_1 ) and not(DX)) or SEQX; ---------------------------------------------------- -- Generate stall statistics (debug only) ---------------------------------------------------- GSTAT: if(SIMULATION_ONLY = '1') generate process(CLK_i) begin if(CLK_i = '1' and CLK_i'event) then --if(ID_V_i = '1') then if(STALL_A_IX1_0 = '1') then STALL_STATS(0) <= STALL_STATS(0) + 1; end if; if(STALL_A_IX2_0 = '1') then STALL_STATS(1) <= STALL_STATS(1) + 1; end if; if(STALL_B_IX1_0 = '1') then STALL_STATS(2) <= STALL_STATS(2) + 1; end if; if(STALL_B_IX2_0 = '1') then STALL_STATS(3) <= STALL_STATS(3) + 1; end if; if(STALL_A_IX1_1 = '1') then STALL_STATS(4) <= STALL_STATS(4) + 1; end if; if(STALL_A_IX2_1 = '1') then STALL_STATS(5) <= STALL_STATS(5) + 1; end if; if(STALL_B_IX1_1 = '1') then STALL_STATS(6) <= STALL_STATS(6) + 1; end if; if(STALL_B_IX2_1 = '1') then STALL_STATS(7) <= STALL_STATS(7) + 1; end if; --end if; end if; end process; end generate; end;