OpenCores
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;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.