instr_util.c 4.02 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. 
 *
 */

/*****************************************************************
 * instr_util.c
 *
 * Interface into the instruction utilization package. Here we 
 * measure the amount of each instruction cache line that is 
 * actually accessed.
 *
 * $Author: blythe $
 * $Date: 2002/05/29 01:09:09 $
 ****************************************************************/

#include "simutil.h"
#include "statrecord.h"


#define INSTR_UTIL_MAXCOUNT (64/4+1)
#define PADDR_TO_POS(_pa,_set) \
(((_pa & instrUtilMask) >> CPUVec.log2ICacheLineSize) * CPUVec.ICacheAssoc + _set)

#ifdef INSTR_UTIL
static struct InstrUtilState {
   VA *vAddr;
   StatRecordSnapshot **snapshots;
} instrUtilState[SIM_MAXCPUS];

static char *instrUtilBits[SIM_MAXCPUS];
static uint  instrUtilMask;
#endif

StatRecordFieldDesc instrUtil[INSTR_UTIL_MAXCOUNT];

void InstrUtilEarlyInit(void)
{
#ifdef INSTR_UTIL
   int i;
   for(i=0; i<INSTR_UTIL_MAXCOUNT; i++) { 
      char buf[32];
      sprintf(buf,"instrUtil[%i]",i);
      instrUtil[i] = StatRecordDefineField(buf, STATRECORD_INSTRUCTION);
   } 
#endif
}

void 
InstrUtilLateInit(void)
{
#ifdef INSTR_UTIL
   int i;


   ASSERT(CPUVec.ICacheSize  && CPUVec.ICacheLineSize  && CPUVec.ICacheAssoc);
   ASSERT(CPUVec.ICacheAssoc < 4);
   ASSERT(CPUVec.numCPUs );
   ASSERT(CPUVec.ICacheLineSize < MS_INSTR_MAXCOUNT * 4);

   instrUtilMask = ((CPUVec.ICacheSize / CPUVec.ICacheAssoc)-1) & ~3;

   for(i=0; i<CPUVec.numCPUs; i++) { 
      int lines = CPUVec.ICacheSize / CPUVec.ICacheLineSize;

      instrUtilBits[i] = (char *) 
         ZALLOC_PERM(CPUVec.ICacheSize / CPUVec.ICacheAssoc,"InstrUtil");

      instrUtilState[i].vAddr = (VA *)ZALLOC_PERM(sizeof(VA)*lines,"InstrUtil")

      instrUtilState[i].snapshots = 
         (StatRecordSnapshot **) ZALLOC_PERM(sizeof(void*)*lines,"InstrUtil");
   }
   ASSERT(!instrUtilState[0].vAddr[0]);
#endif
}

void 
InstrUtilNewLine(int cpuNum, VA vAddr, PA pAddr, int setEntry)
{
#ifdef INSTR_UTIL
   PA  allpAddr = pAddr & ~(CPUVec.ICacheLineSize-1);
   int pos      = PADDR_TO_POS(allpAddr, setEntry);

   if (traceBasedSimulator) 
      return;

   if (0 && pos==7) { 
      CPUWarning("XXX %lld cpu=%i new  pA=%8x set=%i pos=%4i vA=%x\n",
                 (uint64)CPUVec.Cycle_Count(),cpuNum,pAddr,setEntry,pos,vAddr);
   }

   ASSERT(!instrUtilState[cpuNum].vAddr[pos] );
   ASSERT(pos < CPUVec.ICacheSize / CPUVec.ICacheLineSize);
   instrUtilState[cpuNum].vAddr[pos]     = vAddr;
   instrUtilState[cpuNum].snapshots[pos] = StatRecordAllocSnapshot(cpuNum);
#endif
}


void
InstrUtilReplaceLine(int cpuNum, PA pAddr, int setEntry) 
{
#ifdef INSTR_UTIL
   int i;
   int count=0;
   uint pLine      = pAddr >> CPUVec.log2ICacheLineSize;
   PA   allpAddr   = pAddr & ~(CPUVec.ICacheLineSize-1);
   int  pos        = PADDR_TO_POS(allpAddr,setEntry);
   VA   replacedVA = instrUtilState[cpuNum].vAddr[pos];

   if (traceBasedSimulator) 
      return;

   ASSERT(pos < CPUVec.ICacheSize / CPUVec.ICacheLineSize);

   for (i=0; i<CPUVec.ICacheLineSize; i+=4) {
      if (instrUtilBits[cpuNum][((allpAddr+i)&instrUtilMask) + setEntry]) {
         count++;
      }
   }

   if (0 && pos==7) { 
      CPUWarning("XXX %lld cpu=%i rpl pA=%8x set=%i pos=%4i count=%i\n",
                 (uint64)CPUVec.Cycle_Count(),cpuNum,pAddr,setEntry,pos,count);
   }

   ASSERT(count < MS_INSTR_MAXCOUNT);
   ASSERT(instrUtilState[cpuNum].vAddr);

   if (instrUtilState[cpuNum].vAddr[pos]) {
      StatRecordIncrement(instrUtilState[cpuNum].snapshots[pos],
                          instrUtilState[cpuNum].vAddr[pos], 0,
                          instrUtil[count], 1);
      StatRecordFreeSnapshot(instrUtilState[cpuNum].snapshots[pos]);
   }
   instrUtilState[cpuNum].vAddr[pos] = 0;
   instrUtilState[cpuNum].snapshots[pos] = 0;
   
   for(i=0; i<CPUVec.ICacheLineSize; i+=4) {
      instrUtilBits[cpuNum][((allpAddr+i)&instrUtilMask) + setEntry] = 0;
   }
#endif
}