⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statrecord.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -