📄 simrecord.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/uio.h>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <errno.h>#ifdef SGI#include <bstrings.h>#endif#include <strings.h>#include "simrecord.h"#include "sim_error.h"#include "simutil.h"#include "cpu_interface.h"#define LOW_RES_INDEX(_a) (_a >>recPtr->log2LowRes)#define HIGH_RES_INDEX(_a) ((_a&(recPtr->lowRes-1))>>recPtr->log2HighRes)typedef char Bucket;typedef struct SimRecord { int bucketSize; long highRes; long lowRes; int log2HighRes; int log2LowRes; Bucket ***firstLevelArray; char *isHighRes; Bucket *lowResBuckets; long lowResEntries, highResEntries; VA lastAddr; Bucket * lastBucket; Bucket *outOfRange; char tableName[32];} SimRecord;#ifdef SIM_ALPHAint VASizeLog2 = 44;#elseint VASizeLog2 = 32;#endifSimRec SimRecTableInit(char *tableName, int bucketSize, long lowRes, long highRes) { SimRecord *recPtr;#ifndef __alpha if (sizeof(VA)!=4) { CPUError("ByPC/ByDdata tables only implemented for 32-bit address spaces\n"); return 0; }#endif recPtr = (struct SimRecord *) ZMALLOC(sizeof(struct SimRecord),"SimRecTable" ); recPtr->bucketSize = bucketSize; strncpy(recPtr->tableName,tableName,sizeof(recPtr->tableName)-1); recPtr->lowRes = lowRes; recPtr->highRes = highRes; recPtr->log2LowRes = GetLog2(lowRes); recPtr->log2HighRes = GetLog2(highRes); /* * data structure sizes */ recPtr->lowResEntries = 1<<(VASizeLog2-recPtr->log2LowRes); recPtr->highResEntries = recPtr->lowRes / recPtr->highRes; /* * allocation */ recPtr->firstLevelArray = (char ***) ZMALLOC(recPtr->lowResEntries*sizeof(void *),"SimRecord"); recPtr->outOfRange = ZMALLOC( bucketSize,"SimRecord"); recPtr->isHighRes = ZMALLOC(recPtr->lowResEntries ,"SimRecord" ); recPtr->lowResBuckets = ZMALLOC( bucketSize*recPtr->lowResEntries,"SimRecord::LowRes"); return recPtr; } voidSimRecAddHighResRange(SimRec recPtr, VA addr, unsigned long size) { int a; VA endAddr = addr + size - 1; for(a=LOW_RES_INDEX(addr);a<=LOW_RES_INDEX(endAddr);++a) { CPUWarning("SimRec: detail 0x%08lx 0x%08lx at %d\n", (Reg64)addr,size,a); recPtr->isHighRes[a] = 1; }}void *SimRecBucketAddr(SimRec recPtr, VA addr){ Bucket **firstLevelPtr; Bucket *bucketPtr; unsigned long long lowInd,highInd; /* * align */ addr = addr & ~(recPtr->highRes-1); /* * cache last translation */ if( addr == recPtr->lastAddr ) { return recPtr->lastBucket; } recPtr->lastAddr = addr; /* * low res */ lowInd = LOW_RES_INDEX(addr); ASSERT( lowInd < recPtr->lowResEntries); if (!recPtr->isHighRes[lowInd]) { recPtr->lastBucket = recPtr->lowResBuckets + (lowInd * recPtr->bucketSize); return recPtr->lastBucket; } /* * high Res */ firstLevelPtr = recPtr->firstLevelArray[lowInd]; if( !firstLevelPtr ) { recPtr->firstLevelArray[lowInd] = (Bucket **) ZMALLOC(recPtr->highResEntries * sizeof(void*),"SimRecord"); firstLevelPtr = recPtr->firstLevelArray[lowInd]; } highInd = HIGH_RES_INDEX(addr); ASSERT( highInd < recPtr->highResEntries ); bucketPtr = firstLevelPtr[highInd]; if( !bucketPtr ) { firstLevelPtr[highInd] = ZMALLOC(recPtr->bucketSize,"SimRecord"); bucketPtr = firstLevelPtr[highInd]; } recPtr->lastBucket = bucketPtr; return bucketPtr;} intSimRecDump(SimRec recPtr, int fd, int entrySize, char *fieldNames, int reset){ int len; uint a,b,start; SimRecHeader hdr; uint startEnd[2]; unsigned long long lowInd, highInd; Bucket **firstLevelPtr; bzero((char *) &hdr, sizeof(hdr)); hdr.magic = SIMREC_MAGIC; hdr.version = 6; strncpy(hdr.tableName, recPtr->tableName, sizeof(hdr.tableName)-1); hdr.addrStart = 0; hdr.lowRes = recPtr->lowRes; hdr.highRes = recPtr->highRes; hdr.bucketSize = recPtr->bucketSize; hdr.entrySize = entrySize; hdr.fieldNamesLen = strlen(fieldNames)+1; if (write(fd, (char *) &hdr, sizeof(hdr)) != sizeof(hdr)) { goto err; } if (write(fd,fieldNames,hdr.fieldNamesLen) != hdr.fieldNamesLen ) { goto err; } /* * lowRes */ len = recPtr->lowResEntries * recPtr->bucketSize; if (write(fd, recPtr->lowResBuckets, len) != len) { goto err; } if (reset) { bzero(recPtr->lowResBuckets, len); } /* out of bounds */ len = recPtr->bucketSize; if (write(fd, recPtr->outOfRange, len) != len) { goto err; } if (reset) { bzero(recPtr->outOfRange, len); } /* * high Res */ for (lowInd=0;lowInd<recPtr->lowResEntries;lowInd++) { a = lowInd * recPtr->lowRes; if( !recPtr->isHighRes[lowInd] ) continue; firstLevelPtr = recPtr->firstLevelArray[lowInd]; if( !firstLevelPtr ) continue; /* * iterate over 1 low res range */ b = a; while( b < a + recPtr->lowRes ) { int count; /* * skip over empty entries */ while( b < a + recPtr->lowRes ) { highInd = HIGH_RES_INDEX(b); if( firstLevelPtr[highInd] ) break; b+= recPtr->highRes; } start = b; while( b < a + recPtr->lowRes ) { highInd = HIGH_RES_INDEX(b); if( !firstLevelPtr[highInd] ) break; b += recPtr->highRes; } /* * now write buckets from start to b */ startEnd[0] = start; startEnd[1] = (b - start) >>recPtr->log2HighRes; if( write(fd,startEnd,2*sizeof(int)) != 2*sizeof(int) ) goto err; count = 0; while( start < b ) { highInd = HIGH_RES_INDEX(start); ASSERT( firstLevelPtr[highInd]); if( write(fd,firstLevelPtr[highInd],recPtr->bucketSize) != recPtr->bucketSize) { goto err; } if (reset) { free(firstLevelPtr[highInd]); firstLevelPtr[highInd] = NULL; } count++; start += recPtr->highRes; } ASSERT( count == startEnd[1]); } } /* * write trailer information */ startEnd[0] = 0; startEnd[1] = 0; if( write(fd,startEnd,2*sizeof(int) )!=2*sizeof(int) ) goto err; return 0; err: CPUWarning("SimRecord: memstat write failed at cycleCount = %lld\n", (uint64)CPUVec.CycleCount(0)); close(fd); return 1; } void SimRecReset(SimRec recPtr){ CPUWarning("SimRecReset is not implemented. Counters are not set to 0\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -