📄 statrecord.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. * */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <stddef.h>#include <stdarg.h>#include "syslimits.h"#include "simtypes.h"#include "sim_error.h"#include "simutil.h"#include "machine_params.h"#include "memstat.h"#include "statrecord.h"#include "simrecord.h"#include "list.h"#include "cpu_interface.h"#define MAX_SWITCHES 16#define MAX_DETAILS 5#define MAX_FIELDS 128#define MAX_RANGES 16#define SNAPSHOT_HASH 10007 /* prime */static void SelectorCB(int cpuNum) ;struct StatRecordSnapshot { List_Links list; /* must be first */ StatRecordBucket *switches[MAX_SWITCHES]; uint detailActive; int refCount;};struct StatRecordSwitch { char *name; int id;};struct StatRecordDetail { char *fileName; int id; int isByPC; int counterSize; int lowRes; int highRes; int active; int initiated; int pos[MAX_FIELDS]; char *fields[MAX_FIELDS]; VA highResAddr[MAX_RANGES]; VA highResLen[MAX_RANGES]; int numPos; int numFields; int numRanges; int numCounters; SimRec table;};struct StatRecordFieldDescStruct { int index; char *fieldName; int fieldFlag;}; static struct StartRecordState { enum {STATREC_INIT,STATREC_EXEC} initState; struct StatRecordFieldDescStruct fieldDesc[MAX_FIELDS]; StatRecordSnapshot cur[SIM_MAXCPUS]; /* current switches */ char *switchNames[MAX_SWITCHES]; int numFields; int numSwitches; int numDetails; int snapshotAllocCount; StatRecordSwitch switchDesc[MAX_SWITCHES]; StatRecordDetail detailDesc[MAX_DETAILS]; StatRecordBucket *trashBucket; StatRecordSnapshot *curSnapshot[SIM_MAXCPUS]; struct List_Links listSnapshots; struct List_Links freeSnapshots; struct StatRecordSnapshot *hash[SNAPSHOT_HASH]; SimTime lastChange[SIM_MAXCPUS]; /* * Disable CPU */ bool disableCPU[SIM_MAXCPUS]; StatRecordSnapshot *disableSnapshot;} statRecord;typedef int64 StatRecordCounter;void StatRecordEarlyInit(void){ ASSERT( !statRecord.trashBucket); statRecord.initState = STATREC_INIT; statRecord.trashBucket = StatRecordNewBucket();}/************************************************************ * Called during the init path of the detailed CPU simulators. ************************************************************/void StatRecordLateInit(void){ /* * this is called when we enter MIPSY (evt. Embra) and * have guaranteed access to lowmem. */ int i,j; statRecord.initState = STATREC_EXEC; List_Init(&statRecord.listSnapshots); List_Init(&statRecord.freeSnapshots); /* CPUWarning(" --- StatRecordSimulatorInit\n"); */ for (i=0; i<statRecord.numDetails; i++) { StatRecordDetail *detail = &statRecord.detailDesc[i]; /* * numPos holds the index to the last * defined field. Increment to get the size */ detail->numCounters = detail->numPos+1; detail->table = SimRecTableInit(detail->fileName,detail->counterSize * detail->numCounters, detail->lowRes,detail->highRes); ASSERT( detail->table ); for (j=0; j<MAX_RANGES; j++) { if (!detail->highResLen[j]) continue; SimRecAddHighResRange(detail->table, detail->highResAddr[j], detail->highResLen[j]); } }}/**************************************************************** * Switch definition and change ****************************************************************/StatRecordSwitch *StatRecordNewSwitch(char *name){ int i; StatRecordSwitch *sw= &statRecord.switchDesc[statRecord.numSwitches]; if (statRecord.numSwitches >= (MAX_SWITCHES - 1)) { CPUError("StartRecord: Restriction. %d state machines is the max!\n", MAX_SWITCHES); } sw->id = statRecord.numSwitches; sw->name = SaveString(name); for (i=0; i<SIM_MAXCPUS; i++) { statRecord.cur[i].switches[statRecord.numSwitches] = statRecord.trashBucket; ASSERT( statRecord.trashBucket ); } statRecord.numSwitches++; return sw;} void StatRecordSetSwitch(StatRecordSwitch *sw, int cpuNum, StatRecordBucket *newBucket){ ASSERT(sw); ASSERT(newBucket); ASSERT( sw->id >= 0 && sw->id < MAX_SWITCHES); /* * The CPU simulator will potentially want to * add stats at this point, for example to keep * exact counts of events. */ if (statRecord.cur[cpuNum].switches[sw->id] != newBucket) { SelectorCB(cpuNum); statRecord.cur[cpuNum].switches[sw->id] = newBucket; if (statRecord.curSnapshot[cpuNum]) { StatRecordFreeSnapshot(statRecord.curSnapshot[cpuNum]); statRecord.curSnapshot[cpuNum] = 0; } }}/************************************************************************ * Detail definition and change. We assume that the character strings * listed in the fields parameter can be referenced in the future. ************************************************************************/StatRecordDetail *StatRecordNewDetail(char *filename,int isByPC, int counterSize, int lowRes, int highRes){ int i; StatRecordDetail *detail = &statRecord.detailDesc[statRecord.numDetails]; if (statRecord.numDetails >= MAX_DETAILS -1) { CPUError("StatRecord: Implementation restriction. %d details breakdowns\n", MAX_DETAILS); /* NOT REACHED */ } detail->id = statRecord.numDetails; detail->fileName = SaveString(filename); detail->isByPC = isByPC; detail->counterSize = counterSize; detail->lowRes = lowRes; detail->highRes = highRes; detail->numPos = 0; detail->numFields =0; for (i=0; i<MAX_FIELDS; i++) { detail->pos[i] = -1; } statRecord.numDetails++; return detail;}/***************************************************************** * StatRecordDetailAddField * * Fields must be added in increasing order. Multiple fields may be * defined for the same position. *****************************************************************/void StatRecordDetailAddField(StatRecordDetail *detail, int pos, char *field){ int i; ASSERT( detail ); ASSERT( pos == detail->numPos || pos==detail->numPos+1); ASSERT( !detail->initiated ); if (pos == (detail->numPos+1)) { /* Apparently leaving one null entry in between... */ detail->numFields++; ASSERT( detail->numFields < MAX_FIELDS ); detail->numPos++; ASSERT( detail->numPos ); } detail->numFields++; for (i=0; i<statRecord.numFields; i++) { if (!statRecord.fieldDesc[i].fieldName) { continue; } if (!strcmp(field, statRecord.fieldDesc[i].fieldName)) { break; } } if (i < statRecord.numFields) { detail->fields[detail->numFields] = statRecord.fieldDesc[i].fieldName; if (detail->pos[i] >= 0) { CPUWarning("StatRecord: field '%s' redefined for pos %i in table '%s' \n", field, pos, detail->fileName); } else { detail->pos[i] = pos; CPUPrint("StatRecord: %-10s :: %s at pos %i \n", detail->fileName,field, pos); if (detail->isByPC && !(statRecord.fieldDesc[i].fieldFlag & STATRECORD_INSTRUCTION)) { CPUWarning("StatRecord: field '%s' has no meaning for byPC tables \n", field); detail->pos[i] = -1; } if (!detail->isByPC && !(statRecord.fieldDesc[i].fieldFlag & STATRECORD_DATA)) { CPUWarning("StatRecord: field '%s' has no meaning in byData tables\n", field); detail->pos[i] = -1; } } } else { CPUWarning("StatRecord: field '%s; not defined \n",field); }}void StatRecordDetailHighResRange(StatRecordDetail *detail, VA addr, uint len){ if (detail->numRanges >= MAX_RANGES -1) { CPUError("StatRecord restriction. Max of %d ranges per table \n", MAX_RANGES); } CPUPrint("StatRecord detail: %-10s (0x%08x 0x%08x) \n", detail->fileName, addr,len); detail->highResAddr[detail->numRanges] = addr; detail->highResLen [detail->numRanges] = len; detail->numRanges++;}void StatRecordDetailSetActive(StatRecordDetail *detail,int cpuNum, bool isActive){ ASSERT(detail); ASSERT( detail->id >= 0 && detail->id < MAX_DETAILS ); ASSERT( MAX_DETAILS < 32 ); if( isActive ) { statRecord.cur[cpuNum].detailActive |= (1<<detail->id); } else { statRecord.cur[cpuNum].detailActive &= (~(1<<detail->id)); } if( statRecord.curSnapshot[cpuNum] ) { StatRecordFreeSnapshot( statRecord.curSnapshot[cpuNum] ); statRecord.curSnapshot[cpuNum] = 0; }} void StatRecordDetailDump(StatRecordDetail *detail, int fd, int reset){ int i; char str[2048]; ASSERT( detail ); ASSERT( detail->table); if (detail->fields[0]) { strcpy(str,detail->fields[0]); } else { strcpy(str,""); } for (i=1; i<=detail->numFields; i++) { if (!detail->fields[i]) { strcat(str,","); } else { if (detail->fields[i-1]) { strcat(str,"+"); } strcat(str,detail->fields[i]); } ASSERT( strlen(str) < 2048 ); } if (fd >= 0) { SimRecDump(detail->table, fd, detail->counterSize, str, reset); } else { fd = open(detail->fileName, O_RDWR|O_CREAT|O_TRUNC, 0666); ASSERT(fd >= 0); SimRecDump(detail->table,fd,detail->counterSize, str, reset); close(fd); }}/* Utility functions for extracting specific information about a bucket */int64 StatRecordDetailCounterByIndex(StatRecordDetail *detail, void *bucketPtr, uint index) { ASSERT(index < detail->numCounters); if (detail->counterSize == 4) { uint *ptr = (uint*) bucketPtr; return (int64) ptr[index]; } else { uint64 *ptr = (uint64*) bucketPtr; ASSERT(detail->counterSize == 8); return (int64) ptr[index]; }}int64 StatRecordDetailCounterByField(StatRecordDetail *detail, void *bucketPtr, char *fieldName) { int i; for (i = 0; i < statRecord.numFields; i++) { if (!statRecord.fieldDesc[i].fieldName) { continue; } if (!strcmp(fieldName, statRecord.fieldDesc[i].fieldName)) { /* pos array maps any field to its counter position */ if (detail->pos[i] == -1) { return -1; } return StatRecordDetailCounterByIndex(detail, bucketPtr, detail->pos[i]); } } return -1;} int StatRecordDetailNumCounters(StatRecordDetail *detail) { return detail->numCounters;}int StatRecordDetailTableOK(StatRecordDetail *detail) { return ( detail->table != 0);}void * StatRecordDetailBucketAddr(StatRecordDetail *detail, VA addr) { if (detail->table == NULL) { return NULL; } return SimRecBucketAddr(detail->table, addr);}/********************************************************************** * Snapshot management **********************************************************************/StatRecordSnapshot *StatRecordAllocSnapshot(int cpuNum){ StatRecordSnapshot *snap, *hashSnap; uint hash,i; /* * is the cpu disabled */ if (statRecord.disableCPU[cpuNum]){ if (!statRecord.disableSnapshot) { statRecord.disableSnapshot = (StatRecordSnapshot *)ZMALLOC(sizeof( StatRecordSnapshot),"StatRecord"); statRecord.disableSnapshot->refCount = 100;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -