⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icache.vhd

📁 sparc org, vhdl rtl code
💻 VHD
📖 第 1 页 / 共 2 页
字号:

----------------------------------------------------------------------------
--  This file is a part of the LEON VHDL model
--  Copyright (C) 1999  European Space Agency (ESA)
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2 of the License, or (at your option) any later version.
--
--  See the file COPYING.LGPL for the full details of the license.


-----------------------------------------------------------------------------   
-- Entity:      icache
-- File:        icache.vhd
-- Author:      Jiri Gaisler - Gaisler Research
-- Description: This unit implements the instruction cache controller.
------------------------------------------------------------------------------  

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned."+";
use IEEE.std_logic_unsigned.conv_integer;
use IEEE.std_logic_arith.conv_unsigned;
use work.leon_config.all;
use work.sparcv8.all;		-- ASI declarations
use work.leon_iface.all;
use work.macro.all;		-- xorv()
use work.amba.all;
use work.leon_target.all;

entity icache is
  port (
    rst : in  std_logic;
    clk : in  clk_type;
    ici : in  icache_in_type;
    ico : out icache_out_type;
    dci : in  dcache_in_type;
    dco : in  dcache_out_type;
    mcii : out memory_ic_in_type;
    mcio : in  memory_ic_out_type;
    icrami : out icram_in_type;
    icramo : in  icram_out_type;
    fpuholdn : in  std_logic
);
end; 

architecture rtl of icache is

constant TAG_HIGH   : integer := ITAG_HIGH;
constant TAG_LOW    : integer := IOFFSET_BITS + ILINE_BITS + 2;
constant OFFSET_HIGH: integer := TAG_LOW - 1;
constant OFFSET_LOW : integer := ILINE_BITS + 2;
constant LINE_HIGH  : integer := OFFSET_LOW - 1;
constant LINE_LOW   : integer := 2;
constant LRR_BIT    : integer := TAG_HIGH + 1;

constant lline : std_logic_vector((ILINE_BITS -1) downto 0) := (others=>'1');

constant SETBITS : integer := log2x(ISETS); 
subtype lru_type is std_logic_vector(ILRUBITS-1 downto 0);
type lru_array  is array (0 to 2**IOFFSET_BITS-1) of lru_type;  -- lru registers
type rdatatype is (itag, idata, memory);	-- sources during cache read

type lru_table_vector_type is array(0 to 3) of std_logic_vector(4 downto 0);
type lru_table_type is array (0 to 2**IOFFSET_BITS-1) of lru_table_vector_type;

subtype lock_type is std_logic_vector(0 to ISETS-1);
type par_type is array (0 to ISETS-1) of std_logic_vector(1 downto 0);

function lru_set (lru : lru_type; lock : lock_type) return std_logic_vector is
variable xlru : std_logic_vector(4 downto 0);
variable set  : std_logic_vector(SETBITS-1 downto 0);
variable xset : std_logic_vector(1 downto 0);
variable unlocked : integer range 0 to ISETS-1;
begin

  set := (others => '0'); xlru := (others => '0'); xset := (others => '0');
  xlru(ILRUBITS-1 downto 0) := lru; 
  
  if ICLOCK_BIT = 1 then 
    unlocked := ISETS-1;
    for i in ISETS-1 downto 0 loop
      if lock(i) = '0' then unlocked := i; end if;
    end loop;
  end if;
    
  case ISETS is
  when 2 =>
    if ICLOCK_BIT = 1 then
      if lock(0) = '1' then xset(0) := '1'; else xset(0) := xlru(0); end if;
    else xset(0) := xlru(0); end if;
  when 3 =>
    if ICLOCK_BIT = 1 then
      xset := std_logic_vector(conv_unsigned(lru3_repl_table(conv_integer(xlru)) (unlocked), 2));
    else
      xset := std_logic_vector(conv_unsigned(lru3_repl_table(conv_integer(xlru)) (0), 2));
    end if;
  when 4 =>
    if ICLOCK_BIT = 1 then
      xset := std_logic_vector(conv_unsigned(lru4_repl_table(conv_integer(xlru)) (unlocked), 2));
    else
      xset := std_logic_vector(conv_unsigned(lru4_repl_table(conv_integer(xlru)) (0), 2));
    end if;
  when others => 
  end case;
  set := xset(SETBITS-1 downto 0);
  return(set);
end;

function lru_calc (lru : lru_type; set : integer) return lru_type is
variable new_lru : lru_type;
variable xnew_lru: std_logic_vector(4 downto 0);
variable xlru : std_logic_vector(4 downto 0);
begin
  new_lru := (others => '0'); xnew_lru := (others => '0');
  xlru := (others => '0'); xlru(ILRUBITS-1 downto 0) := lru;
  case ISETS is
  when 2 => 
    if set = 0 then xnew_lru(0) := '1'; else xnew_lru(0) := '0'; end if;
  when 3 =>
    xnew_lru(2 downto 0) := lru_3set_table(conv_integer(lru))(set); 
  when 4 => 
    xnew_lru(4 downto 0) := lru_4set_table(conv_integer(lru))(set);
  when others => 
  end case;
  new_lru := xnew_lru(ILRUBITS-1 downto 0);
  return(new_lru);
end;

type icache_control_type is record			-- all registers
  req, burst, holdn : std_logic;
  overrun       : std_logic;			-- 
  underrun      : std_logic;			-- 
  istate 	: std_logic_vector(1 downto 0);		-- FSM vector
  waddress      : std_logic_vector(31 downto PCLOW); -- write address buffer
  valid         : std_logic_vector(ILINE_SIZE-1 downto 0); -- valid bits
  hit           : std_logic;
  su 		: std_logic;
  flush		: std_logic;				-- flush in progress
  flush2	: std_logic;				-- flush in progress
  faddr 	: std_logic_vector(IOFFSET_BITS - 1 downto 0);	-- flush address
  diagrdy  	: std_logic;
  rndcnt        : std_logic_vector(log2x(ISETS)-1 downto 0); -- replace counter
  lrr           : std_logic;
  setrepl       : std_logic_vector(log2x(ISETS)-1 downto 0); -- set to replace
  diagset       : std_logic_vector(log2x(ISETS)-1 downto 0);
  lock          : std_logic;

end record;

type lru_reg_type is record
  write : std_logic;
  waddr : std_logic_vector(IOFFSET_BITS-1 downto 0);
  set   : std_logic_vector(SETBITS-1 downto 0); --integer range 0 to ISETS-1;
  lru   : lru_array;
end record;

signal r, c : icache_control_type;	-- r is registers, c is combinational
signal rl, cl : lru_reg_type;           -- rl is registers, cl is combinational


begin

  ictrl : process(rst, r, rl, mcio, ici, dci, dco, icramo, fpuholdn)
  variable rdatasel : rdatatype;
  variable twrite, diagen, dwrite : std_logic;
  variable taddr : std_logic_vector(TAG_HIGH  downto LINE_LOW); -- tag address
  variable wtag : std_logic_vector(TAG_HIGH downto TAG_LOW); -- write tag value
  variable ddatain : std_logic_vector(31 downto 0);
  variable rdata : std_logic_vector(31 downto 0);
  variable diagdata : std_logic_vector(31 downto 0);
  variable vmaskraw, vmask : std_logic_vector((ILINE_SIZE -1) downto 0);
  variable xaddr_inc : std_logic_vector((ILINE_BITS -1) downto 0);
  variable lastline, nlastline, nnlastline : std_logic;
  variable enable : std_logic;
  variable error : std_logic;
  variable whit, hit, valid : std_logic;
  variable cacheon  : std_logic;
  variable v : icache_control_type;
  variable branch  : std_logic;
  variable eholdn  : std_logic;
  variable mds, write  : std_logic;
  variable memaddr : std_logic_vector(31 downto PCLOW);
  variable set     : integer range 0 to MAXSETS-1;
  variable setrepl : std_logic_vector(log2x(ISETS)-1 downto 0); -- set to replace
  variable ctwrite, cdwrite, validv : std_logic_vector(0 to MAXSETS-1);
  variable wlrr : std_logic;
  variable vl : lru_reg_type;
  variable vdiagset, rdiagset : integer range 0 to ISETS-1;
  variable lock : std_logic_vector(0 to ISETS-1);
  variable wlock : std_logic;

  begin

-- init local variables

    v := r; vl := rl; vl.write := '0'; vl.set := r.setrepl;
    vl.waddr := r.waddress(OFFSET_HIGH downto OFFSET_LOW);

    mds := '1'; dwrite := '0'; twrite := '0'; diagen := '0'; error := '0';
    write := mcio.ready; v.diagrdy := '0'; v.holdn := '1'; 

    cacheon := mcio.ics(0) and not r.flush;
    enable := '1'; branch := '0';
    eholdn := dco.hold and fpuholdn;

    rdatasel := idata;	-- read data from cache as default
    ddatain := mcio.data;	-- load full word from memory
    wtag(TAG_HIGH downto TAG_LOW) := r.waddress(TAG_HIGH downto TAG_LOW);
    wlrr := r.lrr; wlock := r.lock;
    
    set := 0; ctwrite := (others => '0'); cdwrite := (others => '0');
    vdiagset := 0; rdiagset := 0; lock := (others => '0');

-- random replacement counter
    if ISETS > 1 then
-- pragma translate_off
      if not is_x(r.rndcnt) then
-- pragma translate_on
        if conv_integer(r.rndcnt) = (ISETS - 1) then v.rndcnt := (others => '0');
        else v.rndcnt := r.rndcnt + 1; end if;
-- pragma translate_off
      end if;
-- pragma translate_on
    end if;


-- generate lock bits
    if ICLOCK_BIT = 1 then 
      for i in 0 to ISETS-1 loop lock(i) := icramo.itramout(i).lock; end loop;
    end if;
      
-- generate cache hit and valid bits    
    hit := '0';
    for i in ISETS-1 downto 0 loop
      if (icramo.itramout(i).tag = ici.fpc(TAG_HIGH downto TAG_LOW)) 
      then hit := not r.flush; set := i; end if;
      validv(i) := genmux(ici.fpc(LINE_HIGH downto LINE_LOW), 
		          icramo.itramout(i).valid);
    end loop;

    if ici.fpc(LINE_HIGH downto LINE_LOW) = lline then lastline := '1';
    else lastline := '0'; end if;

    if r.waddress(LINE_HIGH downto LINE_LOW) = lline((ILINE_BITS -1) downto 0) then
      nlastline := '1';
    else nlastline := '0'; end if;

    if r.waddress(LINE_HIGH downto LINE_LOW+1) = lline((ILINE_BITS -1) downto 1) then
      nnlastline := '1';
    else nnlastline := '0'; end if;

-- pragma translate_off
    if not is_x(ici.fpc(LINE_HIGH downto LINE_LOW)) then
-- pragma translate_on
      valid := validv(set);
-- pragma translate_off
    end if;
-- pragma translate_on

-- pragma translate_off
    if not is_x(r.waddress) then
-- pragma translate_on
      xaddr_inc := r.waddress(LINE_HIGH downto LINE_LOW) + 1;
-- pragma translate_off
    end if;
-- pragma translate_on

    if mcio.ready = '1' then 
      v.waddress(LINE_HIGH downto LINE_LOW) := xaddr_inc;
    end if;

    taddr := ici.rpc(TAG_HIGH downto LINE_LOW);

-- main Icache state machine

    case r.istate is
    when "00" =>	-- main state and cache hit
      v.valid := icramo.itramout(set).valid;
      v.hit := hit; v.su := ici.su;

      if (ici.nullify or eholdn)  = '0' then 
        taddr := ici.fpc(TAG_HIGH downto LINE_LOW);
      else taddr := ici.rpc(TAG_HIGH downto LINE_LOW); end if;
      v.burst := mcio.burst and not lastline;
      if (eholdn and not ici.nullify ) = '1' then

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -