📄 annotations.c
字号:
/* * 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. * *//***************************************************************** * annotations.c * * ****************************************************************/#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <math.h>#include <setjmp.h>#include <ctype.h>#include <assert.h>#include "sim_error.h"#include "simutil.h"#include "memstat.h"#include "annotations.h"#include "cpu_interface.h"#include "symbols.h"#include "tcl_init.h"#include "hw_events.h"#include "visual.h"RemapVector *remapVec = 0; /* does not belong there, but cannot be * defined in the simos directory (-G0 ) * has to be defined somewhere */struct CPUVector CPUVec; /* has to be defined somewhere *//***************************************************************** * Annotation Private Declarations ****************************************************************/#define MAX_ANN_CPU 32typedef uint CPUBitVec;#define ENABLE_ALL(_vec) {_vec = 0xffffffff;}#define ENABLE_CPU(_vec, _cpu) {_vec |= (1 << (_cpu));} #define DISABLE_ALL(_vec) {_vec = 0x00000000;}#define DISABLE_CPU(_vec, _cpu) {_vec &= ~(1 << (_cpu));} #define IS_CPU_ENABLED(_vec, _cpu) ((_vec) & (1 << (_cpu)))typedef struct AnnType AnnType;typedef struct AnnCmd AnnCmd;typedef struct AnnRec AnnRec;typedef struct AnnTag AnnTag;typedef enum { ANN_ARGTYPE_NUM = 0, ANN_ARGTYPE_SYMBOL, ANN_ARGTYPE_ENUM, ANN_ARGTYPE_NONE, ANN_NUM_ARGTYPES /* must be last */} AnnArgType;struct AnnType { char *name; AnnArgType argType; AnnRec *recs; char **enumList; int enumCount;};struct AnnRec { AnnType *type; uint64 arg; AnnCmd *cmds; AnnRec *next; AnnRec *FMHashLink; int FMHashType;};struct AnnCmd { Tcl_Interp *interp;#ifdef TCL8 Tcl_Obj *compiledscript; #else char *script;#endif int context; AnnRec *rec; AnnCmd *nextByType; AnnTag *tag; AnnCmd *nextByTag;};struct AnnTag { CPUBitVec enabled; char *name; AnnCmd *cmds;}; static Tcl_HashTable types;static Tcl_HashTable tags;static int staticAnnsInstalled = 0;static bool prePCAnnsExist = FALSE;static void SetAnn(Tcl_Interp *interp, char *script, AnnType *type, uint64 arg, AnnTag *tag);static int TranslateArg(Tcl_Interp *interp, AnnType *type, char *argStr, uint64 *retval);static void AnnFMInfo(Tcl_Interp *interp);static void AnnAddDynamic(AnnPtr ptr, int newrec);static void FlushAnnCache(void);/***************************************************************** * Annotation TCL Declarations ****************************************************************/static int cmdSet(Tcl_Interp *interp, int argc, char *argv[]);static int cmdDisable(Tcl_Interp *interp, int argc, char *argv[]);static int cmdEnable(Tcl_Interp *interp, int argc, char *argv[]);static int cmdType(Tcl_Interp *interp, int argc, char *argv[]);static int cmdExec(Tcl_Interp *interp, int argc, char *argv[]);static int cmdInfo(Tcl_Interp *interp, int argc, char *argv[]);static int cmdTrace(Tcl_Interp *interp, int argc, char *argv[]);static tclcmd annCmds[] = {{ "set", -1, cmdSet, " set type ?arg? ?-tag tagname? script"},{ "disable", -1, cmdDisable, " disable tag ?cpu ...?"},{ "enable", -1, cmdEnable, " enable tag ?cpu ...?"},{ "type", -1, cmdType, " type typeName argtype ?enumlist?"},{ "exec", -1, cmdExec, " exec type ?arg?"},{ "info", -1, cmdInfo, " info ?list|tags|types|fm?"},{ "trace", -1, cmdTrace, " trace on|off"},{ NULL, 0, NULL, NULL}};static char *argTypeNames[] = { "num", "symbol", "enum", "none" };/* Boolean indicating whether any scache annotations are defined -- * moved up here since AnnAddDynamic needs is */uint scacheAnnotation = 0;void ScacheAnnLateInit(Tcl_Interp *interp);/***************************************************************** * Annotation tracing support ****************************************************************/static struct annTraceStruct { int enabled;#ifdef TCL8 Tcl_Obj *script;#else char *script;#endif} annTrace;/***************************************************************** * Annotation Initialization ****************************************************************/void AnnotationInit(Tcl_Interp *interp){ /* ASSERT(SIM_MAXCPUS <= MAX_ANN_CPU);*/ ASSERT((sizeof(argTypeNames)/sizeof(char*)) == ANN_NUM_ARGTYPES); Tcl_InitHashTable(&types, TCL_STRING_KEYS); Tcl_InitHashTable(&tags, TCL_STRING_KEYS); Tcl_CreateCommand(interp, "annotation", DispatchCmd, (ClientData)annCmds, NULL);}/***************************************************************** * Annotation - TCL Interface ****************************************************************/int cmdSet(Tcl_Interp *interp, int argc, char *argv[]){ Tcl_HashEntry *entry; AnnTag *tag; AnnType *type; uint64 arg = 0; int i, new; if ((argc < 4) || (argc > 7)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[0].usage, "\"", NULL); return TCL_ERROR; } entry = Tcl_FindHashEntry(&types, argv[2]); if (!entry) { Tcl_AppendResult(interp, "no type named \"", argv[2], "\"", NULL); return TCL_ERROR; } type = Tcl_GetHashValue(entry); ASSERT(type); if (argc > 5) { /* we must have a tag */ if (strcmp(argv[argc-3], "-tag")) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[0].usage, "\"", NULL); return TCL_ERROR; } entry = Tcl_CreateHashEntry(&tags, argv[argc-2], &new); if (new) { tag = (AnnTag*)ZMALLOC(sizeof(AnnTag),"AnnTag"); ENABLE_ALL(tag->enabled); tag->name = Tcl_GetHashKey(&tags, entry); tag->cmds = NULL; Tcl_SetHashValue(entry, tag); } else { tag = Tcl_GetHashValue(entry); ASSERT(tag); } } else { tag = NULL; } if (type->argType == ANN_ARGTYPE_NONE) { if ((argc != 4) && (argc != 6)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[0].usage, "\"", NULL); return TCL_ERROR; } } else { if (((argc == 4) || (argc == 6)) && (type->argType == ANN_ARGTYPE_ENUM)) { char *str = SaveString(argv[argc-1]); for (i=0; i<type->enumCount; i++) { if (type->enumList[i][0]) { SetAnn(interp, str, type, i, tag); } } return TCL_OK; } if ((argc != 5) && (argc != 7)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[0].usage, "\"", NULL); return TCL_ERROR; } if (TranslateArg(interp, type, argv[3], &arg) != TCL_OK) { return TCL_ERROR; } } SetAnn(interp, SaveString(argv[argc-1]), type, arg, tag); return TCL_OK;}void SetAnn(Tcl_Interp *interp, char *script, AnnType *type, uint64 arg, AnnTag *tag){ AnnRec *rec; AnnCmd *cmd, **last; int newrec = 0; cmd = (AnnCmd*)ZMALLOC(sizeof(AnnCmd),"AnnCmd"); cmd->interp = interp;#ifdef TCL8 cmd->compiledscript = Tcl_NewStringObj(script, -1); /* script may now need to be deallocated because newstringobj allocates * an internal buffer */#else cmd->script = script;#endif cmd->context = VisualGetContext(); for (rec = type->recs; rec && (rec->arg != arg); rec = rec->next) ; if (!rec) { rec = (AnnRec*)ZMALLOC(sizeof(AnnRec),"AnnRec"); rec->type = type; rec->arg = arg; rec->cmds = NULL; rec->next = type->recs; type->recs = rec; newrec = 1; } cmd->rec = rec; cmd->nextByType = NULL; for (last = &(rec->cmds); *last; last = &((*last)->nextByType)) ; *last = cmd; if (tag) { cmd->tag = tag; cmd->nextByTag = tag->cmds; tag->cmds = cmd; } else { cmd->tag = NULL; cmd->nextByTag = NULL; } if (staticAnnsInstalled) { AnnAddDynamic((AnnPtr)rec, newrec); }}int cmdDisable(Tcl_Interp *interp, int argc, char *argv[]){ Tcl_HashEntry *entry; AnnTag *tag; char *tagName; int i, cpunum = 0; if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[1].usage, "\"", NULL); return TCL_ERROR; } tagName = argv[2]; entry = Tcl_FindHashEntry(&tags, tagName); if (!entry) { return TCL_OK; } tag = Tcl_GetHashValue(entry); ASSERT(tag); if (argc == 3) { DISABLE_ALL(tag->enabled); } else { for (i=3; i<argc; i++) { if (Tcl_GetInt(interp, argv[i], &cpunum) != TCL_OK) { Tcl_AppendResult(interp, "bad cpunum \"", argv[i], "\"", NULL); return TCL_ERROR; } else { DISABLE_CPU(tag->enabled, cpunum); } } } return TCL_OK;}static int cmdEnable(Tcl_Interp *interp, int argc, char *argv[]){ Tcl_HashEntry *entry; AnnTag *tag; char *tagName; int i, cpunum = 0; if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[2].usage, "\"", NULL); return TCL_ERROR; } tagName = argv[2]; entry = Tcl_FindHashEntry(&tags, tagName); if (!entry) { return TCL_OK; } tag = Tcl_GetHashValue(entry); ASSERT(tag); if (argc == 3) { ENABLE_ALL(tag->enabled); } else { for (i=3; i<argc; i++) { if (Tcl_GetInt(interp, argv[i], &cpunum) != TCL_OK) { Tcl_AppendResult(interp, "bad cpunum \"", argv[i], "\"", NULL); return TCL_ERROR; } else { ENABLE_CPU(tag->enabled, cpunum); } } } return TCL_OK;}int cmdType(Tcl_Interp *interp, int argc, char *argv[]){ AnnType *type; AnnArgType argType; char *typeName; char *argTypeStr; char **enumList = NULL; int enumCount = 0; int new = 0; Tcl_HashEntry *entry; if ((argc != 4) && (argc != 5)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[3].usage, "\"", NULL); return TCL_ERROR; } typeName = argv[2]; argTypeStr = argv[3]; for (argType=ANN_ARGTYPE_NUM; argType<ANN_NUM_ARGTYPES; argType++) { if ((argTypeNames[argType][0] == argTypeStr[0]) && (strcmp(argTypeNames[argType], argTypeStr) == 0)) { break; } } if (argType == ANN_NUM_ARGTYPES) { Tcl_AppendResult(interp, "no such argtype \"", argTypeStr, "\"", NULL); return TCL_ERROR; } if (argType == ANN_ARGTYPE_ENUM) { if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[3].usage, "\"", NULL); return TCL_ERROR; } Tcl_SplitList(interp, argv[4], &enumCount, &enumList); } entry = Tcl_CreateHashEntry(&types, typeName, &new); if (!new) { Tcl_AppendResult(interp, "type name already taken \"", typeName, "\"", NULL); return TCL_ERROR; } type = (AnnType*)ZMALLOC(sizeof(AnnType),"AnnType"); type->name = Tcl_GetHashKey(&types, entry); type->argType = argType; type->recs = NULL; type->enumCount = enumCount; type->enumList = enumList; Tcl_SetHashValue(entry, type); return TCL_OK;}int cmdExec(Tcl_Interp *interp, int argc, char *argv[]){ Tcl_HashEntry *entry; AnnType *type; AnnRec *rec; char *typeName = 0; char *argStr = 0; uint64 arg = 0; if ((argc != 3) && (argc != 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[4].usage, "\"", NULL); return TCL_ERROR; } typeName = argv[2]; entry = Tcl_FindHashEntry(&types, typeName); if (!entry) { Tcl_AppendResult(interp, "no type named \"", typeName, "\"", NULL); return TCL_ERROR; } type = Tcl_GetHashValue(entry); ASSERT(type); if (type->argType == ANN_ARGTYPE_NONE) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[4].usage, "\"", NULL); return TCL_ERROR; } } else { if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], annCmds[4].usage, "\"", NULL); return TCL_ERROR; } argStr = argv[3]; if (TranslateArg(interp, type, argStr, &arg) != TCL_OK) { return TCL_ERROR; } } for (rec = type->recs; rec; rec = rec->next) { if (rec->arg == arg) { AnnExec(rec); } } return TCL_OK;}int cmdInfo(Tcl_Interp *interp, int argc, char *argv[]){ AnnTag *tag; AnnRec *rec; AnnCmd *cmd; AnnType *type; Tcl_HashSearch search; Tcl_HashEntry *entry; char buf[64]; int numst, numcmds;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -