📄 annotations.c
字号:
int num; int found = 0; if ((argc != 2) && (argc != 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[5].usage, "\"", NULL); return TCL_ERROR; } if ((argc == 2) || (!strcmp(argv[2], "list"))) { Tcl_AppendResult(interp, "Annotation List:\n", NULL); entry = Tcl_FirstHashEntry(&types, &search); while (entry) { type = Tcl_GetHashValue(entry); ASSERT(type); for (rec = type->recs; rec; rec = rec->next) { for (cmd = rec->cmds; cmd; cmd = cmd->nextByType) { Tcl_AppendResult(interp, "annotation set ", type->name, " ", NULL); switch (type->argType) { case ANN_ARGTYPE_NUM: case ANN_ARGTYPE_SYMBOL: PrintLLX(buf,rec->arg); strcat(buf," "); Tcl_AppendResult(interp, buf, NULL); break; case ANN_ARGTYPE_ENUM: if ((rec->arg < type->enumCount) && (type->enumList[rec->arg][0])) { Tcl_AppendResult(interp, type->enumList[rec->arg], " ", NULL); } else { PrintLLD(buf,rec->arg); strcat(buf," "); Tcl_AppendResult(interp, buf, NULL); } break; case ANN_ARGTYPE_NONE: break; default: ASSERT(0); break; } if (cmd->tag) { Tcl_AppendResult(interp, "-tag ", cmd->tag->name, " ", NULL); }#ifdef TCL8 Tcl_AppendResult(interp, "{", Tcl_GetStringFromObj(cmd->compiledscript, NULL), "}\n\n", NULL);#else Tcl_AppendResult(interp, "{", (char*)cmd->script, "}\n\n", NULL);#endif } } entry = Tcl_NextHashEntry(&search); } found = 1; } if ((argc == 2) || (!strcmp(argv[2], "tags"))) { Tcl_AppendResult(interp, "\nAnnotation Tags:\n", NULL); entry = Tcl_FirstHashEntry(&tags, &search); while (entry) { tag = Tcl_GetHashValue(entry); ASSERT(tag); Tcl_AppendResult(interp, "\"", tag->name, "\" ", NULL); for (num=0, cmd=tag->cmds; cmd; num++, cmd=cmd->nextByTag); sprintf(buf, "enabled mask 0x%x num %d", tag->enabled, num); Tcl_AppendResult(interp, buf, "\n", NULL); entry = Tcl_NextHashEntry(&search); } Tcl_AppendResult(interp, "\n", NULL); found = 1; } if ((argc == 2) || (!strcmp(argv[2], "types"))) { Tcl_AppendResult(interp, "Annotation Types:\n", NULL); entry = Tcl_FirstHashEntry(&types, &search); while (entry) { type = Tcl_GetHashValue(entry); ASSERT(type); Tcl_AppendResult(interp, "\"", type->name, "\" ", argTypeNames[type->argType], NULL); if (type->argType == ANN_ARGTYPE_ENUM) { Tcl_AppendResult(interp, " {", Tcl_Merge(type->enumCount, type->enumList), "}", NULL); } numst=0; numcmds=0; for (rec=type->recs; rec; numst++, rec=rec->next) { for (cmd=rec->cmds; cmd; numcmds++, cmd=cmd->nextByType); } sprintf(buf, "subtypes %d commands %d", numst, numcmds); Tcl_AppendResult(interp, " ", buf, "\n", NULL); entry = Tcl_NextHashEntry(&search); } Tcl_AppendResult(interp, "\n", NULL); found = 1; } if ((argc == 2) || (!strcmp(argv[2], "fm"))) { AnnFMInfo(interp); found = 1; } if (!found) { Tcl_AppendResult(interp, "arg not recognized \"", argv[2], "\"", NULL); return TCL_ERROR; } return TCL_OK;}int cmdTrace(Tcl_Interp *interp, int argc, char *argv[]){ char *action = argv[2]; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[6].usage, "\"", NULL); return TCL_ERROR; } if (!strcmp(action, "off")) { annTrace.enabled = 0; } else if (!strcmp(action, "on")) { annTrace.enabled = 1; } else { annTrace.enabled = 2;#ifdef TCL8 annTrace.script = Tcl_NewStringObj(SaveString(action),-1); #else annTrace.script = SaveString(action);#endif } return TCL_OK;}/***************************************************************** * Annotation - SimOS Interface ****************************************************************/AnnPtr AnnFind(char *typeName, char *argStr){ Tcl_HashEntry *entry; AnnType *type; AnnRec *rec; uint64 arg; int code; entry = Tcl_FindHashEntry(&types, typeName); ASSERT(entry); type = Tcl_GetHashValue(entry); ASSERT(type); code = TranslateArg(NULL, type, argStr, &arg); ASSERT(code == TCL_OK); for (rec = type->recs; rec; rec = rec->next) { if (rec->arg == arg) { return rec; } } return NULL;}AnnPtr AnnFindInt(char *typeName, uint64 arg){ Tcl_HashEntry *entry; AnnType *type; AnnRec *rec; entry = Tcl_FindHashEntry(&types, typeName); ASSERT(entry); type = Tcl_GetHashValue(entry); ASSERT(type); for (rec = type->recs; rec; rec = rec->next) { if (rec->arg == arg) { return rec; } } return NULL;}uint64 AnnFirst(char *typeName, AnnPtr *iter){ Tcl_HashEntry *entry; AnnType *type; entry = Tcl_FindHashEntry(&types, typeName); ASSERT(entry); type = Tcl_GetHashValue(entry); ASSERT(type); *iter = type->recs; if (*iter) { return (*iter)->arg; } *iter = NULL; return 0;}uint64 AnnNext(AnnPtr *iter){ if (!*iter) return 0; *iter = (*iter)->next; if (*iter) { return (*iter)->arg; } return 0;}int AnnNumArg(char *typeName){ Tcl_HashEntry *entry; AnnType *type; entry = Tcl_FindHashEntry(&types, typeName); ASSERT(entry); type = Tcl_GetHashValue(entry); ASSERT(type); switch (type->argType) { case ANN_ARGTYPE_NUM: case ANN_ARGTYPE_SYMBOL: return -1; case ANN_ARGTYPE_ENUM: return type->enumCount; case ANN_ARGTYPE_NONE: return 1; default: ASSERT(0); break; } return 0;}static void traceAnnotation(AnnCmd* cmd){ AnnPtr rec = cmd->rec; uint64 arg = rec->arg; AnnType* type = rec->type; int cpu = CPUVec.CurrentCpuNum(); char cpuName[32]; char *pid, *proc; uint64 cyclecount; if (CPUVec.CycleCount) { cyclecount = CPUVec.CycleCount(cpu); } else { cyclecount = 0; } sprintf(cpuName,"%d",cpu); pid = Tcl_GetVar2(TCLInterp,"PID",cpuName,0); proc = Tcl_GetVar2(TCLInterp,"PROCESS",cpuName,0); if (!pid) { pid = "-1";} if (!proc) { proc = "NONAME";} CPUPrint("%lld ANN cpu %d %s-%s %s ", cyclecount, cpu, pid, proc, type->name); switch (type->argType) { case ANN_ARGTYPE_NUM: case ANN_ARGTYPE_SYMBOL: CPUPrint("0x%llx ", arg); break; case ANN_ARGTYPE_ENUM: if ((arg < type->enumCount) && (type->enumList[arg][0])) { CPUPrint("%s ", type->enumList[arg]); } else { CPUPrint("%lld ", arg); } break; case ANN_ARGTYPE_NONE: break; default: ASSERT(0); break; }#ifdef TCL8 CPUPrint("{%s}\n", Tcl_GetStringFromObj(cmd->compiledscript, NULL)); if (annTrace.enabled == 2) { extern int Tcl_GlobalEvalObj(Tcl_Interp*, Tcl_Obj*); Tcl_GlobalEvalObj(TCLInterp, annTrace.script); }#else CPUPrint("{%s}\n", (char*) annTrace.script); if (annTrace.enabled == 2) { Tcl_GlobalEval(TCLInterp, annTrace.script); }#endif}void AnnExec(AnnPtr ptr){ AnnCmd *cmd; int code; int oldContext; if (!ptr) { return; } for (cmd = ptr->cmds; cmd; cmd = cmd->nextByType) { if (!cmd->tag || (IS_CPU_ENABLED(cmd->tag->enabled, CPUVec.CurrentCpuNum()))) { if (!VisualSetContext(cmd->context, &oldContext)) continue; if (annTrace.enabled) { traceAnnotation(cmd); }#ifdef TCL8 code = Tcl_GlobalEvalObj(cmd->interp, cmd->compiledscript);#else code = Tcl_GlobalEval(cmd->interp, cmd->script);#endif VisualSetContext(oldContext, NULL); if (code != TCL_OK) {#ifdef TCL8 HandleError(cmd->interp, Tcl_GetStringFromObj(cmd->compiledscript, NULL));#else HandleError(cmd->interp, cmd->script);#endif } } }}int TranslateArg(Tcl_Interp *interp, AnnType *type, char *argStr, uint64 *retval){ int i, code; uint64 val = 0; switch (type->argType) { case ANN_ARGTYPE_NUM: break; case ANN_ARGTYPE_SYMBOL: code = SymInt(interp, argStr, &val); *retval = val; return code; /* break; */ case ANN_ARGTYPE_ENUM: for (i=0; i<type->enumCount; i++) { if (type->enumList[i][0] && (strcmp(type->enumList[i], argStr) == 0)) { *retval = i; return TCL_OK; } } break; case ANN_ARGTYPE_NONE: *retval = 0; return TCL_OK; /* break; */ default: ASSERT(0); return TCL_ERROR; /* break; */ }#ifdef __alpha if (sscanf(argStr, "%li", retval) != 1) {#else if (sscanf(argStr, "%lli", retval) != 1) {#endif ASSERT(interp); Tcl_AppendResult(interp, "bad arg \"", argStr, "\"", NULL); switch (type->argType) { case ANN_ARGTYPE_NUM: Tcl_AppendResult(interp, ": expected a number", NULL); break; case ANN_ARGTYPE_SYMBOL: Tcl_AppendResult(interp, ": expected a symbol", NULL); break; case ANN_ARGTYPE_ENUM: Tcl_AppendResult(interp, ": expected one of ", NULL); for (i=0; i<type->enumCount; i++) { if (i > 0) Tcl_AppendResult(interp, ", ", NULL); Tcl_AppendResult(interp, type->enumList[i], NULL); } break; default: break; } return TCL_ERROR; } return TCL_OK;}/***************************************************************** * Fast Memory (FM) Annotation Lookup * * This module provides a mechanism for cpu simulators * to quickly determine if there is a memory annotation * on a range of addresses. * ****************************************************************/#define NUM_HIST 11#define HASH_TABLE_SIZE 2048#define SECOND_HASH_SHIFT 16#define HASH_FUNC(_va) ((((_va) >> log2RangeSize) \ ^ ((_va) >> SECOND_HASH_SHIFT)) \ % HASH_TABLE_SIZE)typedef struct hashBucket { AnnRec *chain; int typesInChain;} hashBucket;static hashBucket hashTable[HASH_TABLE_SIZE];static uint rangeSize = -1;static uint log2RangeSize = 0;static uint existingAnns = 0; /* Keep track of what's been inserted */void AnnFMInit(uint size){ AnnPtr rec = NULL; VA addr; int bucket, i; if (size == rangeSize) { return; } rangeSize = size; log2RangeSize = GetLog2(rangeSize); for (i=0; i<HASH_TABLE_SIZE; i++) { hashTable[i].chain = NULL; hashTable[i].typesInChain = 0; } for (addr = AnnFirst("pc", &rec); rec; addr = AnnNext(&rec)) { existingAnns |= ANNFM_PC_TYPE; bucket = HASH_FUNC(addr); rec->FMHashType = ANNFM_PC_TYPE; rec->FMHashLink = hashTable[bucket].chain; hashTable[bucket].chain = rec; hashTable[bucket].typesInChain |= ANNFM_PC_TYPE; } for (addr = AnnFirst("pre-pc", &rec); rec; addr = AnnNext(&rec)) { existingAnns |= ANNFM_PRE_PC_TYPE; bucket = HASH_FUNC(addr); rec->FMHashType = ANNFM_PRE_PC_TYPE; rec->FMHashLink = hashTable[bucket].chain; hashTable[bucket].chain = rec; hashTable[bucket].typesInChain |= ANNFM_PRE_PC_TYPE; prePCAnnsExist = TRUE; } for (addr = AnnFirst("load", &rec); rec; addr = AnnNext(&rec)) { existingAnns |= ANNFM_LD_TYPE; bucket = HASH_FUNC(addr); rec->FMHashType = ANNFM_LD_TYPE; rec->FMHashLink = hashTable[bucket].chain; hashTable[bucket].chain = rec; hashTable[bucket].typesInChain |= ANNFM_LD_TYPE; } for (addr = AnnFirst("store", &rec); rec; addr = AnnNext(&rec)) { existingAnns |= ANNFM_ST_TYPE; bucket = HASH_FUNC(addr); rec->FMHashType = ANNFM_ST_TYPE; rec->FMHashLink = hashTable[bucket].chain; hashTable[bucket].chain = rec; hashTable[bucket].typesInChain |= ANNFM_ST_TYPE; }}static void AnnFMAddDynamic(AnnPtr rec, int type){ VA addr = rec->arg; int bucket = HASH_FUNC(addr); /* Check to see if this rec is already in the hash table */ AnnPtr hrec; for (hrec = hashTable[bucket].chain; hrec; hrec = hrec->FMHashLink) { if (hrec == rec) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -