URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_bjxlog_bv.vhd] - Rev 2
Compare with Previous | Blame | View Log
----------------------------------------------------------------- -- -- ----------------------------------------------------------------- -- -- -- Copyright (C) 2017 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 Branch/Jump eXecute & branch verificatio nLogic --------------------------------------------------------------- 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_ARITH_PKG.all; use work.RV01_OP_PKG.all; entity RV01_BJXLOG_BV is generic( JRPE : std_logic := '1' ); port( CLK_i : in std_logic; RST_i : in std_logic; BJ_OP_i : in BJ_OP_T; SU_i : in std_logic; PC_i : in ADR_T; OPA_i : in SDWORD_T; OPB_i : in SDWORD_T; IMM_i : in SDWORD_T; IV_i : in std_logic; FSTLL_i : in std_logic; -- verification port BPVD_i : std_logic_vector(3-1 downto 0); MPJRX_i : in std_logic; BJX_o : out std_logic; BJTA_o : out unsigned(ALEN-1 downto 0); -- verification port BHT_WE_o : out std_logic; BHT_TA_o : out ADR_T; BHT_PC_o : out ADR_T; BHT_CNT_o : out std_logic_vector(2-1 downto 0) ); end RV01_BJXLOG_BV; architecture ARC of RV01_BJXLOG_BV is function updt_cnt( CNT : std_logic_vector(2-1 downto 0); TKN : std_logic ) return std_logic_vector is variable TMP : std_logic_vector(3-1 downto 0); variable UCNT : std_logic_vector(2-1 downto 0); begin TMP := CNT & TKN; case TMP is when "000" => UCNT := "11"; when "001" => UCNT := "01"; when "010" => UCNT := "00"; when "011" => UCNT := "01"; when "100" => UCNT := "10"; when "101" => UCNT := "11"; when "110" => UCNT := "10"; when others => UCNT := "00"; end case; return(UCNT); end function; signal BJX,BJX_q : std_logic; signal BX,JX,PBX,MPBX : std_logic; signal BP_HIT : std_logic; signal BP_CNT,BP_UCNT : std_logic_vector(2-1 downto 0); signal BJTA,BJTA_q : ADR_T; signal BJAL_TA,JALR_TA,PCP4 : ADR_T; signal OPB_N,SUB_RES : SDWORD_T; signal AEQB,ALTB : std_logic; begin --------------------------------------- -- Notes --------------------------------------- -- This module performs branch and jal instructions -- prediction verification and jalr instructions -- executions. Jal instructions are treated as -- always-taken branches and are therefore -- assigned an entry in BHT. Jal instructions -- are surely mispredicted as not taken the first -- time they're encountered. -- Jalr instructions are not predicted at all -- and so no entry is assigned to them in BHT. -- If a branch/jal instruction is predicted correctly, -- it's treated as a nop, otherwise a branch is -- executed to the correct target address or to -- the address following the branch instruction -- itself. -- BHT is updated every time a valid branch/jal -- instruction reaches IX1 stage, regardless of -- prediction correctness. --------------------------------------- -- Branch/Jump execution --------------------------------------- -- Calculate B/J target addresses process(OPA_i,PC_i,IMM_i) variable IOPA,IPC,IIMM : signed(SDLEN downto 0); variable TA0,TA1 : signed(SDLEN downto 0); begin -- sign-extend OPA_i by one bit if(OPA_i >= 0) then IOPA := '0' & OPA_i; else IOPA := '1' & OPA_i; end if; -- sign-extend IMM_i by one bit if(IMM_i >= 0) then IIMM := '0' & IMM_i; else IIMM := '1' & IMM_i; end if; -- sign-extend PC_i by one bit IPC := '0' & to_signed(PC_i); -- Note: there's no timing benefit from -- replacing these adders with carry-select -- ones. TA0 := IOPA + IIMM; TA1 := IPC + IIMM; -- Jalr target address JALR_TA <= to_unsigned(TA0(SDLEN-1 downto 0)); -- branch/jal target address BJAL_TA <= to_unsigned(TA1(SDLEN-1 downto 0)); end process; -- Address of instruction following the branch/jal PCP4 <= PC_i + 4; -- Select address to branch at in case of -- misprediction process(BX,JX,MPJRX_i,BJX_q,PCP4,BJAL_TA,JALR_TA,BJTA_q) begin if(BX = '1' and BJX_q = '0') then BJTA <= BJAL_TA; elsif((JX = '1' or MPJRX_i = '1') and BJX_q = '0') then BJTA <= JALR_TA(SDLEN-1 downto 1) & '0' ; elsif(BJX_q = '0') then BJTA <= PCP4; else BJTA <= BJTA_q; end if; end process; ------------------------------------ -- Calculate OPA_i - OPB_i (for blt* and bge*) ------------------------------------ SUB_RES <= OPA_i - OPB_i; ------------------------------------ -- Branch control flags ------------------------------------ -- OPA_i less-than OPB_i flag AEQB <= '1' when (OPA_i = OPB_i) else '0'; -- if OPA > 0 and OPB > 0, then ALTB = sign(SUB_RES) -- if OPA < 0 and OPB < 0, then ALTB = sign(SUB_RES) -- if OPA > 0 and OPB < 0, then ALTB = '0' -- if OPA < 0 and OPB > 0, then ALTB = '1' -- OPA_i less-than OPB_i flag ALTB <= SUB_RES(SDLEN-1) when (OPA_i(SDLEN-1) = OPB_i(SDLEN-1)) else OPA_i(SDLEN-1) when (SU_i = '1') else OPB_i(SDLEN-1) ; ------------------------------------ -- Set branch and jal execute flag ------------------------------------ process(BJ_OP_i,AEQB,ALTB,IV_i) begin if(ALTB = '1') then case BJ_OP_i is when BJ_BEQ => BX <= AEQB and IV_i; when BJ_BNE => BX <= not(AEQB) and IV_i; when BJ_BLT => BX <= IV_i; when BJ_BGE => BX <= '0'; when BJ_JAL => BX <= IV_i; when others => BX <= '0'; end case; else case BJ_OP_i is when BJ_BEQ => BX <= AEQB and IV_i; when BJ_BNE => BX <= not(AEQB) and IV_i; when BJ_BLT => BX <= '0'; when BJ_BGE => BX <= IV_i; when BJ_JAL => BX <= IV_i; when others => BX <= '0'; end case; end if; end process; ------------------------------------ -- Set jalr execute flag ------------------------------------ GJRPE0_1 : if(JRPE = '1') generate JX <= '0'; end generate; GJRPE0_0 : if(JRPE = '0') generate JX <= IV_i when (BJ_OP_i = BJ_JALR) else '0'; end generate; ------------------------------------ -- Set B/J execute flag ------------------------------------ BJX <= (MPBX or JX); -- B/J execute flag and target address register. -- These registers are needed when a B/J is taken -- while fetch is stalled: in such condition B/J -- must deferred to first un-stalled cycle. process(CLK_i) begin if(CLK_i = '1' and CLK_i'event) then if(FSTLL_i = '1') then BJTA_q <= BJTA; end if; if(RST_i = '1' or FSTLL_i = '0') then BJX_q <= '0'; elsif(FSTLL_i = '1') then BJX_q <= (BJX and IV_i); end if; end if; end process; -- A branch/jump is actually executed if: -- 1) there's a valid B/J instruction in IX1 stage, OR -- 2) there's a pending B/J. BJX_o <= BJX or BJX_q; BJTA_o <= BJTA; --------------------------------------- -- Branch verification --------------------------------------- -- branch prediction hit flag BP_HIT <= BPVD_i(0); -- branch prediction count BP_CNT <= BPVD_i(3-1 downto 1); -- branch prediction updated count BP_UCNT <= updt_cnt(BP_CNT,BX) when BP_HIT = '1' else (not(BX) & not(BX)); -- predicted branch execute flag -- (1 -> predicted taken, 0 -> predicted not taken) PBX <= BP_HIT and not(BP_CNT(1)) and IV_i; -- branch mis-prediction flag MPBX <= (PBX xor BX) or MPJRX_i; -- BHT updated data BHT_WE_o <= IV_i when( BJ_OP_i = BJ_BEQ or BJ_OP_i = BJ_BNE or BJ_OP_i = BJ_BLT or BJ_OP_i = BJ_BGE or BJ_OP_i = BJ_JAL ) else '0'; BHT_CNT_o <= BP_UCNT; BHT_TA_o <= JALR_TA when (BJ_OP_i = BJ_JALR) else BJAL_TA; BHT_PC_o <= PC_i; end ARC;