OpenCores
URL https://opencores.org/ocsvn/core_arm/core_arm/trunk

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [mem/] [cache/] [gendc.vhd] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

-- $(help_generic)
-- $(help_local)
 
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_unsigned.conv_integer;
use IEEE.std_logic_arith.conv_unsigned;
use work.config.all;
use work.int.all;
use work.memdef.all;
use work.corelib.all;
use work.cache_comp.all;
use work.cache_config.all;
use work.genic_lib.all;
use work.gendc_lib.all;
use work.genwb_lib.all;
use work.gencmem_lib.all;
use work.setrepl_lib.all;
use work.arith_cnt_comp.all;
use work.bus_comp.all;
 
entity gendc is
  port ( 
    rst     : in  std_logic; 
    clk     : in  std_logic;
    hold : in cli_hold;
    i  : in  gendc_type_in;
    o  : out gendc_type_out;
    ctrl : in gdcl_ctrl;
    dcmo : in gencmem_type_dc_out;
    dcmi : out gencmem_type_dc_in;
    wbi  : out genwb_type_in;
    wbo  : in genwb_type_out
    );
end gendc;
 
architecture rtl of gendc is
 
  type gendc_dirty_a is array (natural range <>) of std_logic_vector(GCML_DC_TADDR_BSZ-1 downto 0);
 
  type gendc_cmaddrsrc is (gdca_no, gdca_in,  gdca_re,  gdca_lo);
  type gendc_meaddrsrc is (gdcma_no, gdcma_in, gdcma_re, gdcma_lo );
  type gendc_datainsrc is (gdcdi_no, gdcdi_in, gdcdi_re, gdcdi_lo, gdcdi_me );
  type gendc_datapisrc is (gdcdp_cm, gdcdp_me, gdcdp_no );
  type gendc_dbsrc is (gdcdb_mem, gdcdb_cm );
 
  type gendc_validsrc is (gdcvalid_old, gdcvalid_clr, gdcvalid_new, gdcvalid_add );
  type gendc_dirtysrc is (gdcdirty_old, gdcdirty_clr, gdcdirty_new, gdcdirty_add );
 
  constant GCML_DC_DLINE_BSZ_X : integer := lin_log2x(CFG_DC_DLINE_SZ); 
  constant GCML_DC_SETS_X  : integer := lin_log2x(CFG_DC_SETS); 
 
  type gendc_tmp_type is record
    hit, valid, dirty  : std_logic;     -- cache line attr 
    set, setrep  : integer;                     -- hit set
    pos  : integer;                     -- line pos
    ehold, req, reqread, reqwrite : std_logic;
    sethit  : std_logic_vector(CFG_DC_SETS-1 downto 0);
    setvalid   : std_logic_vector(CFG_DC_SETS-1 downto 0);
    newvalid, newdirty : std_logic_vector(CFG_DC_TLINE_SZ-1 downto 0);
    twrite, dwrite : std_logic;
    mexc : std_logic;
 
    setpos : std_logic_vector(lin_log2x(CFG_DC_SETS)-1 downto 0);
 
    cmaddr : std_logic_vector(31 downto 0);
    datain : std_logic_vector(31 downto 0);
    meaddr : std_logic_vector(31 downto 0);
    datapi : std_logic_vector(31 downto 0);
    tvalid_src : gendc_validsrc;
    tdirty_src : gendc_dirtysrc;
    cmaddr_src : gendc_cmaddrsrc;
    datain_src : gendc_datainsrc;
    meaddr_src : gendc_meaddrsrc;
    datapi_src : gendc_datapisrc;
    db_src : gendc_dbsrc;
 
    sign, read, lock, burst : std_logic;
    size : lmd_memsize;       
    linepos : std_logic_vector(GCML_DC_TLINE_BSZ-1 downto 0);
    linepos_lastbit : std_logic_vector(CFG_DC_TLINE_SZ-1 downto 0);
 
    cmset : integer;
 
    si : arith_cnt8_in;
    dcmi : gencmem_type_dc_in;
    wbi  : genwb_type_in;
    o  : gendc_type_out;
 
    sr_setfree : std_logic_vector(CFG_DC_SETS-1 downto 0);
    sr_setlock : std_logic_vector(CFG_DC_SETS-1 downto 0);
    sr_useset : std_logic;
  end record;
  type gendc_state is (gendc_hit, 
                       gendc_wtwb_readdata,
                       gendc_wb_writedata, gendc_wt_writedata,
                       gendc_wb_wbline, gendc_wb_fillline, 
                       gendc_reloadtaddr );
  type gendc_reg_type is record
    setrep : std_logic_vector(lin_log2x(CFG_DC_SETS)-1 downto 0);
    state, state_wbline_next : gendc_state;
    hit, hold : std_logic;
 
    p_address : std_logic_vector(31 downto 0);
    p_data : std_logic_vector(31 downto 0);
    p_sign, p_read, p_lock : std_logic;
    p_size : lmd_memsize; 
 
    stored, wbready, wbnext : std_logic;
    setrep_locked, setrep_free : std_logic;
    o_wr_data : std_logic_vector(31 downto 0);
    addrlo : std_logic_vector(1 downto 0);
    dirty : std_logic_vector(CFG_DC_TLINE_SZ-1 downto 0);
    fill_linepos, linepos : std_logic_vector(GCML_DC_TLINE_BSZ-1 downto 0);
    doaddr : std_logic_vector(1 downto 0);
    mexc : std_logic;
  end record;
  type gendc_dbg_type is record
     dummy : std_logic;
     -- pragma translate_off
     cmaddr : std_logic_vector(31 downto 0);
     dbg : gendc_tmp_type;
     -- pragma translate_on
  end record;
  signal r, c       : gendc_reg_type;
  signal rdbg, cdbg : gendc_dbg_type;
 
  signal si : arith_cnt8_in;
  signal so : arith_cnt8_out;
 
  signal sr_setfree : std_logic_vector(CFG_DC_SETS-1 downto 0);
  signal sr_setlock : std_logic_vector(CFG_DC_SETS-1 downto 0);
  signal sr_useset : std_logic;
  signal sr_locked : std_logic;
  signal sr_free   : std_logic;
  signal sr_setrep_free : std_logic_vector(GCML_DC_SETS_X-1 downto 0);
  signal sr_setrep_repl : std_logic_vector(GCML_DC_SETS_X-1 downto 0);
 
begin  
 
  p0: process (clk, rst, r, hold, i, dcmo, wbo, so,
               sr_locked, sr_free, sr_setrep_free, sr_setrep_repl )
    variable v    : gendc_reg_type;
    variable t    : gendc_tmp_type;
    variable vdbg : gendc_dbg_type;
  begin
 
    -- todo: locking on atomic load store does not work yet
    -- until no multiprocessor system is implemented it's defered to the future
 
    -- $(init(t:gendc_tmp_type))
    v := r;
 
    t.meaddr := i.addr_in;
    t.cmaddr := i.addr_in;
    t.datain := i.data_in;
 
    t.wbi.fifo_write := '0';
    v.stored := r.stored or wbo.fifo_stored_v;
 
    -- write back address
    t.si.data := (others => '0');
    t.si.data(arith_cnt8_SZ-1 downto arith_cnt8_SZ-CFG_DC_TLINE_SZ) := r.dirty;
    t.linepos := so.res(GCML_DC_TLINE_BSZ-1 downto 0);
    t.linepos_lastbit := (others => '0');
 
    t.mexc := '0';
 
    t.datapi_src := gdcdp_no;
    t.db_src := gdcdb_cm;
 
    t.ehold := hold.ihold;
    t.req := (not (t.ehold or i.annul)) and i.addrin_re ;
    t.reqread := i.param_r.read and t.req;
    t.reqwrite := (not i.param_r.read) and t.req;
    t.twrite := '0';
    t.dwrite := '0';
 
    if r.hit = '1' then
      t.tvalid_src := gdcvalid_add;
      t.tdirty_src := gdcdirty_add;
    else
      t.tvalid_src := gdcvalid_new;
      t.tdirty_src := gdcdirty_new;
    end if;
 
    t.burst := '0';
    if (r.hold or t.ehold) = '1' then
      t.cmaddr_src := gdca_re;
      t.meaddr_src := gdcma_lo;
      t.datain_src := gdcdi_lo;
      t.sign := r.p_sign;
      t.size := r.p_size;
      t.read := r.p_read;
      t.lock := r.p_lock;
    else
      t.cmaddr_src := gdca_in;
      t.meaddr_src := gdcma_re;
      t.datain_src := gdcdi_in;
      t.sign := i.param_r.signed;
      t.size := i.param_r.size;
      t.read := i.param_r.read;
      t.lock := i.param_r.lock;
    end if;
 
    if t.read = '1' then
      t.size := lmd_word;
    end if;
 
    -- cmp
    t.hit := '0';
    t.set := 0;
    for j in CFG_DC_SETS-1 downto 0 loop
      -- (note: multiset does not recognice valid zero tags)
      if gdcl_is_taghit(i.addr_re,dcmo.tag_line(j)) then
        t.hit := '1';
        t.sethit(j) := '1';
        t.set := j;
      end if;
    end loop; 
 
    t.sr_setfree := (others => '0');
    for j in CFG_DC_SETS-1 downto 0 loop
      if gdcl_is_free(dcmo.tag_line(j)) then
        t.sr_setfree(j) := '1';
      end if;
    end loop; 
 
    t.sr_setlock := (others => '0');
    for j in CFG_DC_SETS-1 downto 0 loop
      t.sr_setlock(j) := dcmo.tag_line(j).lock;
    end loop; 
 
    t.sr_useset := '0';
 
    t.valid := '0';
    if gdcl_is_linevalid(i.addr_re,dcmo.tag_line(t.set)) then
      t.valid := '1';
    end if;
 
    t.dirty := '0';
    t.setrep := lin_convint(sr_setrep_repl);
    if (sr_free = '1') or (sr_locked = '1') then
      t.dirty := '0';
      if (sr_free = '1') then
        t.setrep := lin_convint(sr_setrep_free);
      end if;
    else
      if gdcl_is_linedirty(i.addr_re,dcmo.tag_line(t.setrep)) then
        t.dirty := '1';
      end if;
    end if;
 
    -- $(del)
    --                read                               write                                                
    --   Writeback     |   Writethrough     Writeback     |   Writethrough                                        
    --        +--------+--------+                +--------+--------+                                                  
    --    hit | miss        hit | miss       hit | miss        hit | miss                                      
    --   +----+----+       +----+----+      +----+----+       +----+----+                               
    --   |     free|dirty  |         |      |     free|dirty  |         |                   
    --   O1     +--+--+    O1        O3    O5      +--+--+   O4/O6     O6                              
    --          |     |              |             |     |                                            
    --          O3<---O2             O4            O5<---O2                                            
    --          |                                                                                                     
    --          O4                                                                                     
    --                                                                                                        
    --  O1: cacheread                                                                                                  
    --  O2: writeback line                                                                                              
    --  O3: memload                                                                                                     
    --  O4: cachewrite clean                                                                                              
    --  O5: cachewrite dirty                                                                                             
    --  O6: writeback single                                                                                            
    -- $(/del)
 
 
    case r.state is
 
      when gendc_hit =>
 
        if t.hit = '1' then
          t.tvalid_src := gdcvalid_add;
          t.tdirty_src := gdcdirty_add;
        else
          t.tvalid_src := gdcvalid_new;
          t.tdirty_src := gdcdirty_new;
        end if;
 
        v.mexc := '0';
        v.wbready := '0';
        v.wbnext := '0';
        v.stored := wbo.fifo_stored_v;
        v.hold := '0';
 
        v.setrep_locked := sr_locked;
        v.setrep_free := sr_free;
 
        v.hit := t.hit;
 
        v.p_address := i.addr_re;
        v.p_data := i.data_in;
        v.p_sign := i.param_r.signed;
        v.p_size := i.param_r.size;
        v.p_read := i.param_r.read;
        v.p_lock := i.param_r.lock;
 
        if t.req = '1' then
 
          t.sr_useset := '1';
 
          if i.param_r.read = '1' then
            if ctrl.writeback = '0' then
              if (not (t.hit and t.valid)) = '1' or (i.forceread = '1') then
 
                -- $(del)
                --                read               
                --   Writeback     |   Writethrough  
                --        +--------+--------+        
                --    hit | miss        hit |<MISS>                   
                --   +----+----+       +----+----+   
                --   |     free|dirty  |         |   
                --   O1     +--+--+    O1        O3  
                --          |     |              |   
                --          O3<---O2             O4  
                --          |                        
                --          O4
                -- $(/del)
 
                -- $(del)
                -- $(/del)
                t.cmaddr_src := gdca_re;
 
                v.hold := '1';
 
                t.wbi.fifo_write := '1';
                v.state := gendc_wtwb_readdata;
 
              else                                                          
 
                -- $(del)
                --                read               
                --   Writeback     |   Writethrough  
                --        +--------+--------+        
                --    hit | miss       <HIT>| miss                   
                --   +----+----+       +----+----+   
                --   |     free|dirty  |         |   
                --   O1     +--+--+    O1        O3  
                --          |     |              |   
                --          O3<---O2             O4  
                --          |                        
                --          O4
                -- $(/del)
 
                t.setrep := t.set;
                t.datapi_src := gdcdp_cm;
 
              end if;
 
            else
              if (not (t.hit and t.valid)) = '1' or (i.forceread = '1') then
 
                -- $(del)
                --                read               
                --   Writeback     |   Writethrough  
                --        +--------+--------+        
                --    hit |<MISS>       hit | miss                   
                --   +----+----+       +----+----+   
                --   |     free|dirty  |         |   
                --   O1     +--+--+    O1        O3  
                --          |     |              |   
                --          O3<---O2             O4  
                --          |                        
                --          O4
                -- $(/del)
 
                v.hold := '1';
 
                if t.dirty = '1' then
                  v.state := gendc_wb_wbline;
                  v.state_wbline_next := gendc_wtwb_readdata;
                else
 
                  t.wbi.fifo_write := '1';
                  v.state := gendc_wtwb_readdata;
 
                end if;
 
 
              else
 
                -- $(del)
                --                read               
                --   Writeback     |   Writethrough  
                --        +--------+--------+        
                --   <HIT>| miss        hit | miss                   
                --   +----+----+       +----+----+   
                --   |     free|dirty  |         |   
                --   O1     +--+--+    O1        O3  
                --          |     |              |   
                --          O3<---O2             O4  
                --          |                        
                --          O4
                -- $(/del)
 
                t.setrep := t.set;
                t.datapi_src := gdcdp_cm;
 
              end if;
 
            end if;
 
 
          else
 
            if ctrl.writeback = '0' then
              if (not (t.hit and t.valid)) = '1' then
                -- $(del)
                --               write                                                
                --    writeback    |   Writethrough                                  
                --        +--------+--------+
                --    hit | miss        hit |<MISS>                                      
                --   +----+----+       +----+----+                               
                --   |     free|dirty  |         |                   
                --  O5      +--+--+   O4/O6     O6                              
                --          |     |                                            
                --          O5<---O2                                        
                -- $(/del)
 
                if ctrl.allocateonstore = '1' then
                  t.twrite := '1';
                  t.dwrite := '1';
                end if;
 
              else                                                          
                -- $(del)
                --               write                                                
                --    writeback    |   writethrough                                    
                --        +--------+--------+                                          
                --    hit | miss       <HIT>| miss                                     
                --   +----+----+       +----+----+                               
                --   |     free|dirty  |         |                   
                --  O5      +--+--+   O4/O6     O6                              
                --          |     |                                            
                --          O5<---O2                                            
                -- $(/del)
 
                t.setrep := t.set;
                t.twrite := '1';
                t.dwrite := '1';
              end if;
 
              v.state := gendc_wt_writedata;
              t.wbi.fifo_write := '1';
 
 
              t.cmaddr_src := gdca_re;   
              t.meaddr_src := gdcma_re;  -- addr cycle 1
              t.datain_src := gdcdi_in;  -- data cycle 2
 
            else
              if (not (t.hit and t.valid)) = '1' then
                -- $(del)
                --               write                                                
                --    writeback    |   writethrough                                  
                --        +--------+--------+
                --    hit |<MISS>       hit | miss                                      
                --   +----+----+       +----+----+                               
                --   |     free|dirty  |         |                   
                --  O5      +--+--+   O4/O6     O6                              
                --          |     |                                            
                --          O5<---O2
                -- $(/del)
                -- 
                if ctrl.allocateonstore = '0' then
                  v.hold := '1';
                  v.setrep_locked := '1';
                  v.state := gendc_wb_writedata;
                  t.wbi.fifo_write := '1';
                else
 
                  if t.dirty = '1' then
                    v.hold := '1';
                    v.state := gendc_wb_wbline;
                    v.state_wbline_next := gendc_wb_writedata;
                  else
 
                    if (sr_locked = '1') then
                      v.hold := '1';
                      v.state := gendc_wb_writedata;
                      t.wbi.fifo_write := '1';
 
                    else
 
                      if i.param_r.size = lmd_word then
 
                        -- note : store is 2 cycle (no reload needed)
                        t.twrite := '1';
                        t.dwrite := '1';
 
                      else
 
                        v.hold := '1';
                        v.state := gendc_wb_writedata;
 
                      end if;
                    end if;
                  end if;
                end if;
              else
                -- $(del)
                --               write                                                
                --    writeback    |   writethrough                                  
                --        +--------+--------+                                  
                --   <HIT>| miss        hit | miss                                      
                --   +----+----+       +----+----+                               
                --   |     free|dirty  |         |                   
                --  O5      +--+--+   O4/O6     O6                              
                --          |     |                                            
                --          O5<---O2                                            
                -- $(/del)
 
                t.setrep := t.set;
                t.twrite := '1';
                t.dwrite := '1';
 
                t.tvalid_src := gdcvalid_old;
                t.tdirty_src := gdcdirty_add;
 
                if i.forcewrite = '1' then
                  v.setrep_locked := '1';
                  v.hold := '1';
                  v.state := gendc_wb_writedata;
                  t.wbi.fifo_write := '1';
                end if;
              end if;
            end if;
          end if;
        end if;
 
        v.setrep := std_logic_vector(conv_unsigned(t.setrep, lin_log2x(CFG_IC_SETS)));
        v.dirty := dcmo.tag_line(t.set).dirty;
 
-------------------------------------------------------------------------------
 
      when gendc_wtwb_readdata => 
 
        -- writethrough and writeback read, load and allocate
        -- $(del)
        --                read               
        --   Writeback     |   Writethrough  
        --        +--------+--------+        
        --    hit |<MISS>       hit |<MISS>                   
        --   +----+----+       +----+----+   
        --   |   <free>|<dirty>|         |   
        --   O1     +--+--+    O1        O3  
        --          |     |              |   
        --          O3<---O2             O4  
        --          |                        
        --          O4
        -- $(/del)
 
        t.datain_src := gdcdi_me;
        t.datapi_src := gdcdp_me;
        t.cmaddr_src := gdca_lo;
 
        if r.stored = '0' then
          t.wbi.fifo_write := '1';
        else
          if wbo.read_finish_v = '1' then
 
            t.mexc := wbo.read_mexc;
            --t.mexc := '1';
 
            if r.setrep_locked = '0' then
              t.twrite := '1';
              t.dwrite := '1';
            end if;
 
            if i.addrin_re = '1' then
              v.state := gendc_reloadtaddr;
            else
              v.state := gendc_hit;
              v.hold := '0';
            end if;
          end if;
        end if;
 
-------------------------------------------------------------------------------
 
      when gendc_wb_writedata =>
 
        -- writeback-write, allocate, allocate word on subword write
        -- $(del)
        --               write                                                
        --    writeback    |   Writethrough                                  
        --        +--------+--------+
        --    hit | miss        hit | miss                                       
        --   +----+----+       +----+----+                               
        --   |   <FREE>|<DIRTY>|         |                   
        --  O5      +--+--+   O4/O6     O6                              
        --          |     |                                            
        --          O5<---O2
        -- $(/del)
 
        -- todo: check for lock on all sets
 
        if r.setrep_locked = '1' then
          t.wbi.fifo_write := '1';
          if wbo.fifo_stored_v = '1' then
            v.hold := '0';
            v.state := gendc_hit;
          end if;
        else
          t.twrite := '1';
 
          -- load word of subword allocate
          if (t.size /= lmd_word) then
            t.twrite := '0';
 
            t.datain_src := gdcdi_me;
            t.cmaddr_src := gdca_lo;
 
            if r.stored = '0' then
 
              t.wbi.fifo_write := '1';
              t.size := lmd_word;
              t.read := '1';
              t.lock := '0';
 
              t.datain_src := gdcdi_me;
              t.datapi_src := gdcdp_me;
              t.cmaddr_src := gdca_lo;
 
            else
 
              if wbo.read_finish_v = '1' then
                t.mexc := wbo.read_mexc;
 
                t.twrite := '1';
                t.db_src := gdcdb_mem;
              end if;
            end if;            
          end if;
 
          if (t.twrite = '1') then
            t.cmaddr_src := gdca_lo;
            t.datain_src := gdcdi_lo;
            t.meaddr_src := gdcma_lo;
            t.twrite := '1';
            t.dwrite := '1';
            v.hold := '0';
            if i.addrin_re = '1' then
              v.state := gendc_reloadtaddr;
            else
              v.state := gendc_hit;
              v.hold := '0';
            end if;
          end if;
        end if;
 
-------------------------------------------------------------------------------
 
      when gendc_wt_writedata =>
 
        -- writethrough-write, no allocate
        -- $(del)
        --               write                                                
        --    writeback    |   Writethrough                                  
        --        +--------+--------+
        --    hit | miss       <HIT>|<MISS>                                      
        --   +----+----+       +----+----+                               
        --   |     free|dirty  |         |                   
        --  O5      +--+--+   O4/O6     O6                              
        --          |     |                                            
        --          O5<---O2                                        
        -- $(/del)
 
        t.datain_src := gdcdi_lo;
        t.meaddr_src := gdcma_lo;
 
        if r.stored = '0'  then
          v.hold := '1';
          t.wbi.fifo_write := '1';
        end if;
        if v.stored = '1' then
          v.hold := '0';
          v.state := gendc_hit;
        end if;
 
-------------------------------------------------------------------------------
 
        -- writeback, allocte full line
        -- $(del)                                                        
        --                read                              write               
        --   Writeback     |   Writethrough      writeback    |   writethrough  
        --        +--------+--------+                +--------+--------+        
        --    hit |<MISS>       hit | miss       hit |<MISS>       hit | miss                   
        --   +----+----+       +----+----+      +----+----+       +----+----+   
        --   |   <free>|<dirty>|         |      |   <free>|<dirty>|         |   
        --   O1     +--+--+    O1        O3    O5      +--+--+   O4/O6     O6   
        --          |     |              |             |     |                  
        --          O3<---O2             O4            O5<---O2                 
        --          |                                                    
        --          O4
        -- $(/del)
 
      when gendc_wb_fillline =>
 
        t.cmaddr_src := gdca_no;
        t.meaddr_src := gdcma_no;
        t.datain_src := gdcdi_me;
 
        t.cmaddr := r.p_address;
        t.cmaddr(GDCL_TLINE_U downto GDCL_TLINE_D) := r.fill_linepos;
        t.meaddr := (others => '0');
        t.meaddr(GDCL_TTAG_U downto GDCL_TTAG_D) := dcmo.tag_line(lin_convint(r.setrep)).tag;
        t.meaddr(GDCL_TLINE_U downto GDCL_TLINE_D) := r.linepos;
        t.linepos := so.res(GCML_DC_TLINE_BSZ-1 downto 0);
 
        if r.fill_linepos = GDCL_ZERO_C then
          t.tvalid_src := gdcvalid_new;
          t.tdirty_src := gdcdirty_new;
        else
          t.tvalid_src := gdcvalid_add;
          t.tdirty_src := gdcdirty_add;
        end if;
 
        t.size := lmd_word;
        t.read := '1';
        t.lock := '0';
        t.burst := '1';
        if r.linepos = GDCL_LAST_C then
          t.burst := '0';
        end if;
 
        if r.stored = '0' then
          t.wbi.fifo_write := '1';
          v.fill_linepos := r.linepos;
        else
 
          if r.wbnext = '0' then
            v.wbnext := '1';
            lin_incdec(r.linepos,v.linepos,'1','1');
          end if;
 
          if wbo.read_finish_v = '1' then
 
            t.mexc := wbo.read_mexc;
 
            v.stored := '0';
            v.wbnext := '0';
 
            -- return data (on load)
            if t.cmaddr(GDCL_TLINE_U downto GDCL_TLINE_D) = r.p_address(GDCL_TLINE_U downto GDCL_TLINE_D) then
              t.datapi_src := gdcdp_me;
            end if;
 
            t.twrite := '1';
            t.dwrite := '1';
 
            if (r.linepos = GDCL_ZERO_C) then
              v.state := gendc_hit;
            end if;
          end if;
        end if;
 
-------------------------------------------------------------------------------
 
        -- writeback, line flush
        -- $(del)                                                        
        --                read                              write               
        --   Writeback     |   Writethrough      writeback    |   writethrough  
        --        +--------+--------+                +--------+--------+        
        --    hit |<MISS>       hit | miss       hit |<MISS>       hit | miss                   
        --   +----+----+       +----+----+      +----+----+       +----+----+   
        --   |     free|<dirty>|         |      |     free|<dirty>|         |   
        --   O1     +--+--+    O1        O3    O5      +--+--+   O4/O6     O6   
        --          |     |              |             |     |                  
        --          O3<---O2             O4            O5<---O2                 
        --          |                                                    
        --          O4
        -- $(/del)
 
      when gendc_wb_wbline =>
 
        t.cmaddr_src := gdca_no;
        t.meaddr_src := gdcma_no;
        t.datain_src := gdcdi_no;
        t.datapi_src := gdcdp_no;
 
        t.linepos := so.res(GCML_DC_TLINE_BSZ-1 downto 0);
 
        t.cmaddr := r.p_address;
        t.cmaddr(GDCL_TLINE_U downto GDCL_TLINE_D) := t.linepos;
        t.meaddr := (others => '0');
        t.meaddr(GDCL_TTAG_U downto GDCL_TTAG_D) := dcmo.tag_line(lin_convint(r.setrep)).tag;
        t.meaddr(GDCL_TLINE_U downto GDCL_TLINE_D) := r.linepos;
        t.datain := r.o_wr_data;
 
        t.size := lmd_word;
        t.read := '0';
        t.lock := '0';
        t.burst := '0';
 
        if r.wbready = '0' then         --calculating first address
 
          v.wbready := '1';
          v.dirty(lin_convint(t.linepos)) := '0';
          v.linepos := t.linepos;
 
        else
 
          t.wbi.fifo_write := '1';
 
          -- burst calc
          t.linepos_lastbit := lin_decode(r.linepos);
          t.linepos_lastbit := t.linepos_lastbit(CFG_DC_TLINE_SZ-2 downto 0) & "0";
          if (r.dirty and t.linepos_lastbit) /= GDCL_ZERO_C then
            t.burst := '1';
          end if;
 
          -- buffer cm out
          if r.wbnext = '0' then
            v.wbnext := '1';
            v.o_wr_data := dcmo.dat_line(lin_convint(r.setrep)).data(t.pos);
            t.datain := v.o_wr_data;
          end if;
 
          -- next pos
          if wbo.fifo_stored_v = '1' then
            v.wbnext := '0';
            v.dirty(lin_convint(t.linepos)) := '0';
            v.linepos := t.linepos;
            if r.dirty = GDCL_ZERO_C then
              v.state := r.state_wbline_next;
            end if;
          end if;
        end if;
 
        v.stored := '0';
 
-------------------------------------------------------------------------------
 
      when gendc_reloadtaddr =>
 
        t.cmaddr_src := gdca_re;
        v.state := gendc_hit;
        v.hold := '0';
 
-------------------------------------------------------------------------------
 
      when others =>
 
    end case;
 
    if t.mexc = '1' then
      t.twrite := '0';
      t.dwrite := '0';
      v.mexc := '1';
    end if;
 
    -- cm read/write address 
    case t.cmaddr_src is
      when gdca_no => 
      when gdca_in => t.cmaddr := i.addr_in;
      when gdca_re => t.cmaddr := i.addr_re;
      when gdca_lo => t.cmaddr := r.p_address;
      when others => null;
    end case;
 
    -- mem load/store address (wb input)
    case t.meaddr_src is
      when gdcma_no => 
      when gdcma_in => t.meaddr := i.addr_in;
      when gdcma_re => t.meaddr := i.addr_re;
      when gdcma_lo => t.meaddr := r.p_address;
      when others => null;
    end case;
 
    t.setpos := std_logic_vector(conv_unsigned(t.setrep, lin_log2x(CFG_IC_SETS)));
    if r.hold = '1' then
      t.setpos := r.setrep;
    end if;
 
    -- data pipeline: read data output [cm|mem]->pipeline
    t.pos := gdcl_getpos(t.meaddr(GDCL_TLINE_U downto GDCL_TLINE_D));
    case t.datapi_src is
      when gdcdp_no => 
      when gdcdp_me => v.o_wr_data := wbo.read_data;
      when gdcdp_cm => v.o_wr_data := dcmo.dat_line(lin_convint(t.setpos)).data(t.pos);
      when others => 
    end case;
    v.doaddr(1 downto 0) := t.meaddr(1 downto 0);
    t.o.wr_data := gdcl_readdata ( r.doaddr, r.o_wr_data, CFG_BO_BUS, r.p_sign, r.p_size );
 
    -- write data input (from (pipeline or mem) to (cmem or mem))
    case t.datain_src is
      when gdcdi_no =>
      when gdcdi_in => t.datain := i.data_in;
      when gdcdi_re => t.datain := i.data_re;
      when gdcdi_lo => t.datain := r.p_data;
      when gdcdi_me => t.datain := wbo.read_data;
      when others => null;
    end case;
 
    -- input tag/data line
    -- $(del)
    --               read                               write                                                
    --   Writeback     |   Writethrough     Writeback     |   Writethrough                                        
    --        +--------+--------+                +--------+--------+                                                  
    --    hit | miss        hit | miss       hit | miss        hit | miss                                      
    --   +----+----+       +----+----+      +----+----+       +----+----+                               
    --   |     free|dirty  |         |      |     free|dirty  |         |                   
    --   O1     +--+--+    O1        O3   <O5>     +--+--+  <O4>/O6     O6                              
    --          |     |              |             |     |                                            
    --          O3<---O2            <O4>         <O5><---O2                                            
    --          |                                                                                                     
    --         <O4>                                                                                     
    -- $(/del)
 
    -- assemble input tag line    
    t.dcmi.addr := t.cmaddr;
    t.dcmi.tag_line := dcmo.tag_line(lin_convint(t.setpos));
    t.newvalid := (others => '0');
    t.newvalid := lin_decode(t.cmaddr(GDCL_TLINE_U downto GDCL_TLINE_D));
    case t.tvalid_src is
      when gdcvalid_old => 
      when gdcvalid_clr => t.dcmi.tag_line.valid := (others => '0');
      when gdcvalid_new => t.dcmi.tag_line.valid := t.newvalid;
      when gdcvalid_add => t.dcmi.tag_line.valid := t.dcmi.tag_line.valid or t.newvalid;
    end case;
    t.newdirty := (others => '0');
    t.newdirty := lin_decode(t.cmaddr(GDCL_TLINE_U downto GDCL_TLINE_D));
    case t.tdirty_src is
      when gdcdirty_old => 
      when gdcdirty_clr => t.dcmi.tag_line.dirty := (others => '0');
      when gdcdirty_new => t.dcmi.tag_line.dirty := t.newdirty;
      when gdcdirty_add => t.dcmi.tag_line.dirty := t.dcmi.tag_line.dirty or t.newdirty;
    end case;
    t.dcmi.tag_line.tag := t.cmaddr(GDCL_TTAG_U downto GDCL_TTAG_D);
    t.dcmi.tag_write := (others => '0');
    t.dcmi.tag_write(lin_convint(t.setpos)) := t.twrite;
 
    -- assemble input data line [mem->cache]
    t.dcmi.dat_line := dcmo.dat_line(lin_convint(t.setpos));
    case t.db_src is
      when gdcdb_mem => t.dcmi.dat_line.data(t.pos) := wbo.read_data;  -- on allocate subword
      when others => 
    end case;
    t.dcmi.dat_line.data(t.pos) := gdcl_writedata(t.cmaddr(1 downto 0),t.dcmi.dat_line.data(t.pos),t.datain,CFG_BO_BUS,t.size);
    t.dcmi.dat_write := (others => '0');
    t.dcmi.dat_write(lin_convint(t.setpos)) := t.dwrite;
 
    -- write buffer in 
    -- $(del)
    --               read                               write                                                
    --   Writeback     |   Writethrough     Writeback     |   Writethrough                                        
    --        +--------+--------+                +--------+--------+                                                  
    --    hit | miss        hit | miss       hit | miss        hit | miss                                      
    --   +----+----+       +----+----+      +----+----+       +----+----+                               
    --   |     free|dirty  |         |      |     free|dirty  |         |                   
    --   O1     +--+--+    O1        O3    O5      +--+--+   O4/<O6>   <O6>                              
    --          |     |              |             |     |                                            
    --          O3<---<O2>           O4           O5 <---<O2>                                            
    --          |                                                                                                     
    --          O4                                                                                     
    -- $(/del)
 
    t.o.me_mexc := t.mexc;
    t.o.wr_mexc := r.mexc;
 
    t.wbi.fifo_entry.data := t.datain;
    t.wbi.fifo_entry.addr := t.meaddr;
    t.wbi.fifo_entry.size := t.size;
    t.wbi.fifo_entry.read := t.read;
    t.wbi.fifo_entry.lock := t.lock;
    t.wbi.fifo_entry.burst := t.burst;
    case t.wbi.fifo_entry.size is
      when lmd_word => t.wbi.fifo_entry.addr(1 downto 0) := (others => '0');
      when lmd_half => t.wbi.fifo_entry.addr(0) := '0';
      when others => 
    end case;
 
    -- reset
    if ( rst = '0' ) then
      v.hold := '0';
    end if;
 
    t.o.hold := r.hold;
 
    c <= v;
 
    o <= t.o;
    si <= t.si;
    dcmi <= t.dcmi;
    wbi <= t.wbi;
 
    sr_setfree <= t.sr_setfree;
    sr_setlock <= t.sr_setlock;
    sr_useset <= t.sr_useset;
 
    -- pragma translate_off
    vdbg := rdbg;
    vdbg.cmaddr := t.cmaddr;
    vdbg.dbg := t;
    cdbg <= vdbg;
    -- pragma translate_on  end process p0;
 
  end process p0;
 
  pregs : process (clk, c)
  begin
    if rising_edge(clk) then
      r <= c;
      -- pragma translate_off
      rdbg <= cdbg;
      -- pragma translate_on
    end if;
  end process;
 
  cnt0: arith_cnt8 port map (rst, clk, si, so);  
 
  sr0: setrepl generic map ( SETSIZE => CFG_DC_SETS,SETSIZE_logx => GCML_DC_SETS_X )
    port map (rst, clk, sr_setfree, sr_setlock, sr_useset, sr_locked, sr_free, sr_setrep_free, sr_setrep_repl);
 
  -- pragma translate_off
  check0 : process (rst)
  begin
    assert (CFG_DC_TLINE_SZ <= 8) report "Error: current arith_cntxx component can only count up to 8 positions. Replace with a larger one." severity failure;
  end process;
  -- pragma translate_on
 
end rtl;
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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