scache.h 6.03 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*****************************************************************
 * scache.h
 *
 * This is the interface into a second level cache. The goal is to
 * separate it out from the first level cache so that other cpu
 * simulators can use it.
 * 
 * Author: $author$
 * Date: $date$
 *****************************************************************/
#ifndef _SCACHE_H
#define _SCACHE_H

#include "machine_params.h"
#include "pcache.h"
#include "eventcallback.h"
#include "cpu_interface.h"
#include "dma.h"

/*
 * Possible return status from the SCFetch routine.
 * SCSUCCESS - SCache operation completed succesfully.
 * SCSTALL   - SCache operation sent, must wait for it.
 * SCRETRY   - Need to retry this request later.
 * SCBUSERROR - Request suffered a bus error (most likely a firewall violation).
 */
typedef enum { SCSUCCESS = 0, SCSTALL, SCRETRY, SCBUSERROR} SCResult;


#define SCACHE_MAXASSOC         4 

#ifdef SOLO
#define EXCLUSIVE_CMD 0x40
#else 
#define EXCLUSIVE_CMD EXCLUSIVE_TAG
#endif

/* Return types for IsInSCache */
#define SCACHE_PRESENT 1

typedef PA SCacheCmd;

/*
 * SCache Fetch commands. 
 */
#define SC_IGET        0x1     /* First level Icache miss */
#define SC_DGET        0x2     /* First level Dcache read miss */
#define SC_DGETX       ((0x2|EXCLUSIVE_CMD)) /* First level Dcache GETx */
#define SC_DUGETX      (0x4|EXCLUSIVE_CMD) /* First level Dcache upgrade */
#define SC_DSCUGETX    (0x8|EXCLUSIVE_CMD) /* Upgrade from a SC inst */
#define SC_DLLGET      0x10
#define SC_DLLGETX     (0x20|EXCLUSIVE_CMD)
#define SC_NO_CMD      (0xffffffff) /* Uninitialized command */

/* Cache states  -- passed to FlashLite */
/* Don't change these values -- they match the 
   SYSSTATE_* values in flashlite/miscbus.h */
#define SCACHE_INVALID         0
#define SCACHE_SHARED          1
#define SCACHE_CLEAN_EXCLUSIVE 2
#define SCACHE_DIRTY_EXCLUSIVE 3

#define SCACHE_TAG(a)         ((a) >> (log2SCACHE_SIZE - log2SCACHE_ASSOC))
#define SCACHE_TAG_EX(a)      (SCACHE_TAG(a)|EXCLUSIVE_TAG)
#define SCACHE_INDEXOF(a)     ((a >>log2SCACHE_LINE_SIZE) & (SCACHE_INDEX-1))
#define STAG_TO_PA(t,i) ((((~EXCLUSIVE_TAG)&(t))*(SCACHE_SIZE/SCACHE_ASSOC))+ \
                                ((i) <<log2SCACHE_LINE_SIZE))

typedef struct SMHT { 
   EventCallbackHdr evthdr;   /* So we can make this an event callback */
   int mode;                  /* Used for the bus event */
   bool  inuse;               /* TRUE if entry active */
   uint  memsyscmd;           /* Memory system command */
   SimTime startTime;         /* When memory request was started */
   VA    vAddr;
   PA    pAddr;               /* Physical address of miss */
   PA    PC;                  /* PC causing the miss */
   int   ind;                 /* Index in the cache */
   uint scacheLRU;            /* Second level cache LRU bit */
   short numMHTwait;          /* Number of entries in the MHT waiting for us */
   short mhtInd[MHT_SIZE];    /* Indices into MHT of waiters. */
   char *lineData;	      /* Pointer of location to deposit fill data */
   VA    pfvAddr;             /* If a prefetch, virtual address of line */
   int   formerState;         /* Former state of cache line */
} SMHT; 


typedef struct SCache {
   struct SCacheSet {
      PA tags[SCACHE_MAXASSOC];
      uint LRU;
#ifdef DATA_HANDLING
      char *data[SCACHE_MAXASSOC]; 
				/* This is the actual cache line of data */
				/* with one line for each tag.  This memory */
				/* is allocated dynamically at runtime, since */
				/* the cache line size may vary*/
#endif

   } *set;  /* [SCACHE_INDEX]; */

    /*
     * Second level miss handling table. 
     */   
#define SMHT_SIZE 4
   SMHT SMHT[SMHT_SIZE];
   int SMHTnumInuse;            /* Number of active SMHT entries */

   struct {
      SimCounter Igets;
      SimCounter Dgets;
      SimCounter DgetXs;
      SimCounter Dupgrades;
      SimCounter IgetMisses;
      SimCounter DgetMisses;
      SimCounter DgetXMisses;
      SimCounter DupgradeMisses;
      SimCounter MergeMisses;
      SimCounter Writebacks;
      SimCounter Replacements;
      SimCounter Inval;
      SimCounter Downgrade;
      SimCounter LinesInval;
      SimCounter LinesWriteback;
      SimCounter smhtOccupancyHist[SMHT_SIZE+1];
      SimCounter Prefetches;
#ifdef HWBCOPY
#define MAX_STREAM_DEPTH 8      
      SimCounter StreamGets[MAX_STREAM_DEPTH];
      SimCounter StreamGetXs[MAX_STREAM_DEPTH];
#endif
      SimCounter IGetMHTRetries;
      SimCounter DGetMHTRetries;
      SimCounter DGetXMHTRetries;
      SimCounter DUGetXMHTRetries;
      SimCounter NAKs;
   } stats;
   

#ifdef HWBCOPY
   struct {
     uint last_index;
     int consecutive;
      
   } get, getx;
#endif
} SCache;

extern SCache *SCACHE;

/* Global Functions */
/* Interface from CPU into here */
extern void InitSCaches(void);

/* Interface from 1st level cache to here */
extern SCResult SCacheFetch(int cpuNum, VA, PA, SCacheCmd cmd, int mhtind);
extern int IsInSCache(int cpuNum, PA pAddr, int mode, char **data, 
                      int *way);

extern PFResult SCachePrefetch(int cpuNum, VA vAddr, PA pAddr, MCMD mcmd);

extern int CacheInvalidate(int cpuNum, PA paddr, int size, bool writeback, 
                           int *wasDirty);
extern int CacheInvalidateIndex(int cpuNum, PA paddr, int size, bool writeback, 
                                   int *wasDirty);
extern int CacheExtract(int cpuNum, PA paddr, int size, int *writeback,
			byte *data);

/* Called by the cache op */
extern int CacheExtractIndex(int cpuNum, PA paddr, int size,
			     int *writeback, PA *real_paddr,
                             byte *data);

extern int CacheWriteback(int cpuNum, PA paddr, int size, byte *data);
extern int CacheFlush(int cpuNum, PA paddr, int size, byte *data);

#ifdef DATA_HANDLING
extern void FlushEntireCache(int cpuNum, int leaveShared);
#endif

#define GET_SCACHE_NUM(_cpunum)  (_cpunum)

int EmptySMHT(int cpuNum); /* check whether SMHT empty */


#endif