📄 annotations.c
字号:
break; } } /* If not found, add it to the hash table */ if (hrec != rec) { existingAnns |= type; rec->FMHashType = type; rec->FMHashLink = hashTable[bucket].chain; hashTable[bucket].chain = rec; hashTable[bucket].typesInChain |= type; } /* Flush the annotation cache so the new annotation will be found */ FlushAnnCache();}int AnnFMTypesExist(int types){ return types & existingAnns;}int AnnFMRangeCheck(VA addr, int types){ uint block; int bucket = HASH_FUNC(addr); AnnRec *rec; if (hashTable[bucket].typesInChain & types) { for (rec = hashTable[bucket].chain; rec; rec = rec->FMHashLink) { block = addr >> log2RangeSize; if ((rec->FMHashType & types) && (block == (rec->arg >> log2RangeSize))) { return 1; } } } return 0;}uint AnnFMRangeVector(VA addr, int types){ uint retval = 0; VA block = addr >> log2RangeSize; int bucket = HASH_FUNC(addr); int word; AnnRec *rec; if (hashTable[bucket].typesInChain & types) { for (rec = hashTable[bucket].chain; rec; rec = rec->FMHashLink) { if ((rec->FMHashType & types) && (block == (rec->arg >> log2RangeSize))) { word = (rec->arg & (rangeSize - 1)) >> 2; retval |= (1 << word); } } } return retval; }AnnPtr AnnFMLookup(VA addr, int type){ int bucket = HASH_FUNC(addr); AnnRec *rec; if (hashTable[bucket].typesInChain & type) { for (rec = hashTable[bucket].chain; rec; rec = rec->FMHashLink) { if ((rec->FMHashType & type) && (addr == rec->arg)) { return rec; } } } return NULL;}void AnnFMExec(VA addr, int type){ int bucket = HASH_FUNC(addr); AnnRec *rec; if (hashTable[bucket].typesInChain & type) { for (rec = hashTable[bucket].chain; rec; rec = rec->FMHashLink) { if ((rec->FMHashType & type) && (addr == rec->arg)) { AnnExec(rec); return; } } }}void AnnFMInfo(Tcl_Interp *interp){ AnnRec *rec; char buf[64]; int hist[NUM_HIST]; int i, b, count; Tcl_AppendResult(interp, "\nAnnotation Fast Memory Lookup:\n", NULL); sprintf(buf, "%d", HASH_TABLE_SIZE); Tcl_AppendResult(interp, "Num Buckets: ", buf, "\n", NULL); for (i=0; i<NUM_HIST; i++) { hist[i] = 0; } for (b=0; b<HASH_TABLE_SIZE; b++) { count = 0; for (rec = hashTable[b].chain; rec; rec = rec->FMHashLink) { count++; } hist[(count < NUM_HIST) ? count : NUM_HIST-1]++; } for (i=0; i<NUM_HIST; i++) { if (i<NUM_HIST-1) { sprintf(buf, "%d elems = %d", i, hist[i]); } else { sprintf(buf, "%d+ elems = %d", i, hist[i]); } Tcl_AppendResult(interp, "number of buckets with ", buf, "\n", NULL); } Tcl_AppendResult(interp, "\n", NULL);}/***************************************************************** * Commonly used annotation shortcuts *****************************************************************/#define MAX_CYCLE_ANNS 2000static struct CycleAnnHdr { EventCallbackHdr hdr; AnnPtr ptr;} cycleAnnEvent[MAX_CYCLE_ANNS];static int lastCycleAnn = 0;static voidCycleAnnCallback(int cpuNum, EventCallbackHdr *hdr, void *arg) { struct CycleAnnHdr *cycleAnn = (struct CycleAnnHdr *) hdr; AnnExec(cycleAnn->ptr);}static voidInstallCycleAnnotation(AnnPtr ptr, uint64 count) { SimTime now = CPUVec.CycleCount(0); SimTime when = count; SimTime diff = when - now; cycleAnnEvent[lastCycleAnn].ptr = ptr; EventDoCallback(0, CycleAnnCallback, (EventCallbackHdr *) &cycleAnnEvent[lastCycleAnn], 0, diff); lastCycleAnn++; ASSERT(lastCycleAnn < MAX_CYCLE_ANNS);}#define MAX_PERIODIC_ANNS 2000static struct PeriodicAnnHdr { EventCallbackHdr hdr; SimTime period; AnnPtr ptr;} periodicAnnEvent[MAX_PERIODIC_ANNS];static int lastPeriodicAnn = 0;static voidPeriodicAnnCallback(int cpuNum, EventCallbackHdr *hdr, void *arg) { struct PeriodicAnnHdr *periodicAnn = (struct PeriodicAnnHdr *) hdr; AnnExec(periodicAnn->ptr); EventDoCallback(0, PeriodicAnnCallback, hdr, 0, periodicAnn->period);}static voidInstallPeriodicAnnotation(AnnPtr ptr, uint64 period) { periodicAnnEvent[lastPeriodicAnn].ptr = ptr; periodicAnnEvent[lastPeriodicAnn].period = period; EventDoCallback(0, PeriodicAnnCallback, (EventCallbackHdr *) &periodicAnnEvent[lastPeriodicAnn], 0, period); lastPeriodicAnn++; ASSERT(lastPeriodicAnn < MAX_PERIODIC_ANNS);}AnnPtr *annExcTable;AnnPtr annRFE;AnnPtr annUTLB;int annExcNum, annInstNum;bool annLoads = FALSE;bool annStores = FALSE;bool annPCs = FALSE;bool annWatchpoints = FALSE;void AnnCommonSetup(void) { AnnPtr iter = NULL; AnnPtr load, store; uint64 annCycle, annPeriodic; VA annExc, annMem; int i; annPCs = AnnFMTypesExist(ANNFM_PC_TYPE); AnnFirst("load", &load); AnnFirst("store", &store); /* Do this to keep things fast when there are no watchpoints at all */ if (load || store) { annWatchpoints = TRUE; if (load) { annLoads = TRUE; } if (store) { annStores = TRUE; } for (annMem = AnnFirst("load", &iter);iter;annMem = AnnNext(&iter)) { CPUVec.InstallMemAnnotation(annMem); } for (annMem = AnnFirst("store",&iter);iter;annMem = AnnNext(&iter)) { CPUVec.InstallMemAnnotation(annMem); } } for (annCycle = AnnFirst("cycle", &iter); iter; annCycle = AnnNext(&iter)) { InstallCycleAnnotation(iter, annCycle); } for (annPeriodic = AnnFirst("periodic", &iter); iter; annPeriodic = AnnNext(&iter)) { InstallPeriodicAnnotation(iter, annPeriodic); } annRFE = AnnFind("inst", "rfe"); annUTLB = AnnFind("utlb",""); annExcNum = AnnNumArg("exc"); annExcTable = (AnnPtr*) ZMALLOC (annExcNum * sizeof(AnnPtr),"AnnExcTable"); for(i=0; i < annExcNum; i++) { annExcTable[i] = NULL; } for (annExc = AnnFirst("exc", &iter); iter; annExc = AnnNext(&iter)) { if (annExc < annExcNum) { annExcTable[annExc] = iter; } } staticAnnsInstalled = 1;}/***************************************************************** * Common route for dynamically added annotations. Each annotation * goes through this procedure individually. * We check to see if the is an existing AnnRec: * If so, there's no need to add it again *****************************************************************/static voidAnnAddDynamic(AnnPtr ptr, int newrec){ AnnRec *rec = ptr; if (!strcmp(rec->type->name, "cycle")) { if (newrec) { InstallCycleAnnotation(rec, rec->arg); } } else if (!strcmp(rec->type->name, "periodic")) { if (newrec) { InstallPeriodicAnnotation(rec, rec->arg); } } else if (!strcmp(rec->type->name, "pc")) { if (newrec) { AnnFMAddDynamic(rec, ANNFM_PC_TYPE); } else { FlushAnnCache(); } } else if (!strcmp(rec->type->name, "pre-pc")) { if (newrec) { AnnFMAddDynamic(rec, ANNFM_PRE_PC_TYPE); } else { FlushAnnCache(); } } else if (!strcmp(rec->type->name, "load")) { if (newrec) { AnnFMAddDynamic(rec, ANNFM_LD_TYPE); } else { FlushAnnCache(); } } else if (!strcmp(rec->type->name, "store")) { if (newrec) { AnnFMAddDynamic(rec, ANNFM_ST_TYPE); } else { FlushAnnCache(); } } else if (!strcmp(rec->type->name, "commit")) { /* nothing to do here */ } else if (!strcmp(rec->type->name, "scache")) { ScacheAnnLateInit(TCLInterp); } else { /* nothing to do here */ } }/****************************************************************** * Scache annotations common to mipsy and embra. * Placed here for want of a better place. * ***************************************************************//***************************************************************** * Scache annotation related defines. They are dependent on the * defines of cache events in hw_events.h. *****************************************************************/#define SA_INSTR 0#define SA_READ 1#define SA_WRITE 2#define SA_UPGRADE 6#define SA_SC_UPGRADE 14#define SA_DATAMISSSIZE 16#define SA_DATAMISSSHIFT 4#define SA_DATAMISSMASK 0x0fstatic uint annScacheVaddr = 0; /* information for a Scache miss */static uint annScachePaddr = 0;static uint annScacheType = 0;static uint annScacheCPU = 0;/* Declaration of scacheAnnotation moved up so AnnAddDynamic can set it */static AnnPtr scacheInstrAnn = 0;static AnnPtr scacheDataAnn[SA_DATAMISSSIZE];/* * Init routine for the scache miss annotation. * We set up a table with the appropriate annotation routines * as returned by tcl. In late init also set a variable, if any of the scache * annotations are set. All of this is to reduce the overhead of * of supporting a scache miss annotation */voidScacheAnnInit(Tcl_Interp *interp){ int i; for (i=0;i<(SA_DATAMISSSIZE);i++) { scacheDataAnn[i] = (AnnPtr) 0; } /* Variables to track the Scache miss */ Tcl_SetVar(interp, "ScacheVaddr", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "ScacheVaddr", (char *) &annScacheVaddr, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_SetVar(interp, "ScachePaddr", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "ScachePaddr", (char *) &annScachePaddr, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_SetVar(interp, "ScacheType", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "ScacheType", (char *) &annScacheType, TCL_LINK_INT|TCL_LINK_READ_ONLY); Tcl_SetVar(interp, "ScacheCPU", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "ScacheCPU", (char *) &annScacheCPU, TCL_LINK_INT|TCL_LINK_READ_ONLY);}voidScacheAnnLateInit(Tcl_Interp *interp){ AnnPtr ap; if ((ap = AnnFind("scache", "instr"))) { scacheInstrAnn = ap; scacheAnnotation = 1; } if ((ap = AnnFind("scache", "read"))) { scacheDataAnn[SA_READ] = ap; scacheAnnotation = 1; } if ((ap = AnnFind("scache", "write"))) { scacheDataAnn[SA_WRITE] = ap; scacheAnnotation = 1; } if ((ap = AnnFind("scache", "upg"))) { scacheDataAnn[SA_UPGRADE] = ap; scacheAnnotation = 1; } if ((ap = AnnFind("scache", "sc_upg"))) { scacheDataAnn[SA_SC_UPGRADE] = ap; scacheAnnotation = 1; }}/* * Routine called from hw_events.h to execute the Scache annotation */voidScacheAnnotation(VA vAddr, PA pAddr, uint type, uint cpu){ annScacheVaddr = vAddr; annScachePaddr = pAddr; annScacheType = type; annScacheCPU = cpu; if (type & E_I) { AnnExec(scacheInstrAnn); } else { AnnExec(scacheDataAnn[(type >> SA_DATAMISSSHIFT) & SA_DATAMISSMASK]); }}/***************************************************************** * Complete support for pre- and post- pc annotations. * * This is EXTREMELY optimized and is thus a little confusing. It * works as follows. * - Each time you enter a new range of PC values, you check a tag. * - If you match the tag, then there are no annotations on this * range (and you are looking at an up-to-date range). * - If you don't match the tag, this is considered "Interesting". * It means that either this is a PC value in a range not in the * cache or there is an annotation somewhere in its range. * - The determination of which one of these that it is comes from the * highest bit in the tag... if it is set, then there is an * annotation on it. * ****************************************************************/#define ANN_PRESENT_MASK VA_MASK_HIGH_BIT#define ANN_SET_PRESENT_MASK VA_HIGH_BIT#define ANN_RANGE_INTEREST(_tag, _ind) \ (_tag != (annCache[_ind].postAnnTag & ANN_PRESENT_MASK))#define ANN_SET_PRESENT(_ind) \ (annCache[_ind].postAnnTag |= ANN_SET_PRESENT_MASK)#define ANN_PC_HAS_ANN(_pc, _ind) \ (annCache[_ind].postAnnBitVec & (1 << ((_pc >> 2) & 0x1f)))#define PRE_ANN_RANGE_INTEREST(_tag, _ind) \ (_tag != (annCache[_ind].preAnnTag & ANN_PRESENT_MASK))#define PRE_ANN_SET_PRESENT(_ind) \ (annCache[_ind].preAnnTag |= ANN_SET_PRESENT_MASK)#define PRE_ANN_PC_HAS_ANN(_pc, _ind) \ (annCache[_ind].preAnnBitVec & (1 << ((_pc >> 2) & 0x1f)))AnnCache annCache[ANN_CACHE_SIZE];extern bool tookCheckpoint;static void FlushAnnCache(void){ int i; for (i = 0; i < ANN_CACHE_SIZE; i++) { annCache[i].postAnnTag = 0; annCache[i].preAnnTag = 0; }}#ifdef MIPSY_MXSextern int mxs_annotation;#endif boolRunPCAnnotations(VA pc, VA nPC) { VA tag = ANN_TAG(pc); uint index = ANN_INDEX(tag);#ifdef MIPSY_MXS mxs_annotation = 0; #endif if (tag != annCache[index].postAnnTag) { if (ANN_RANGE_INTEREST(tag, index)) { /* Set up for this new range of PC values for this index. */ annCache[index].postAnnTag = tag; annCache[index].postAnnBitVec = AnnFMRangeVector(pc, ANNFM_PC_TYPE); if (annCache[index].postAnnBitVec) { /* Note that there is an annotation somewhere in this range */ ANN_SET_PRESENT(index); } } if (ANN_PC_HAS_ANN(pc, index)) { AnnExec(AnnFMLookup(pc, ANNFM_PC_TYPE)); /* UGLY: If this was a cpt, we've already moved the PC and nPC forward. */ if (tookCheckpoint) { tookCheckpoint = FALSE; #ifdef MIPSY_MXS mxs_annotation = 1; #endif return TRUE; } } } if (prePCAnnsExist) { tag = ANN_TAG(nPC); index = ANN_INDEX(tag); if (tag != annCache[index].preAnnTag) { if (PRE_ANN_RANGE_INTEREST(tag, index)) { annCache[index].preAnnTag = tag; annCache[index].preAnnBitVec = AnnFMRangeVector(nPC, ANNFM_PRE_PC_TYPE); if (annCache[index].preAnnBitVec) { PRE_ANN_SET_PRESENT(index); } } if (PRE_ANN_PC_HAS_ANN(nPC, index)) { AnnExec(AnnFMLookup(nPC, ANNFM_PRE_PC_TYPE)); } } } return FALSE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -