Updates to make traces work correctly in all circumstances. Add opt set associative simulation.

cpu/trace/opt_cpu.cc:
cpu/trace/opt_cpu.hh:
    Add the ability to simulate less than fully-associative opt caches.
cpu/trace/reader/itx_reader.cc:
    Add writeback to the command list.

--HG--
extra : convert_revision : a9c9c4be3358f4083d7e85772620441a3ad809db
This commit is contained in:
Erik Hallnor 2004-09-30 01:46:48 -04:00
parent 34742515f5
commit f2ac7b645f
3 changed files with 97 additions and 69 deletions

View file

@ -45,34 +45,37 @@ using namespace std;
OptCPU::OptCPU(const string &name, OptCPU::OptCPU(const string &name,
MemTraceReader *_trace, MemTraceReader *_trace,
int log_block_size, int block_size,
int cache_size) int cache_size,
int _assoc)
: BaseCPU(name,1), tickEvent(this), trace(_trace), : BaseCPU(name,1), tickEvent(this), trace(_trace),
numBlks(cache_size/(1<<log_block_size)) numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),
setMask(numSets - 1)
{ {
int log_block_size = (int)(log((double) block_size)/log(2.0));
MemReqPtr req; MemReqPtr req;
trace->getNextReq(req); trace->getNextReq(req);
assert(log_block_size >= 4); refInfo.resize(numSets);
assert(refInfo.size() == 0); while (req) {
while (req && (refInfo.size() < 60000000)) {
RefInfo temp; RefInfo temp;
temp.addr = req->paddr >> log_block_size; temp.addr = req->paddr >> log_block_size;
refInfo.push_back(temp); int set = temp.addr & setMask;
refInfo[set].push_back(temp);
trace->getNextReq(req); trace->getNextReq(req);
} }
// Can't handle more references than "infinity"
assert(refInfo.size() < InfiniteRef);
// Initialize top level of lookup table. // Initialize top level of lookup table.
lookupTable.resize(16); lookupTable.resize(16);
// Annotate references with next ref time. // Annotate references with next ref time.
for (RefIndex i = refInfo.size() - 1; i >= 0; --i) { for (int k = 0; k < numSets; ++k) {
Addr addr = refInfo[i].addr; for (RefIndex i = refInfo[k].size() - 1; i >= 0; --i) {
Addr addr = refInfo[k][i].addr;
initTable(addr, InfiniteRef); initTable(addr, InfiniteRef);
refInfo[i].nextRefTime = lookupValue(addr); refInfo[k][i].nextRefTime = lookupValue(addr);
setValue(addr, i); setValue(addr, i);
} }
}
// Reset the lookup table // Reset the lookup table
for (int j = 0; j < 16; ++j) { for (int j = 0; j < 16; ++j) {
@ -87,9 +90,6 @@ OptCPU::OptCPU(const string &name,
} }
} }
cacheHeap.resize(numBlks);
tickEvent.schedule(0); tickEvent.schedule(0);
hits = 0; hits = 0;
@ -97,57 +97,72 @@ OptCPU::OptCPU(const string &name,
} }
void void
OptCPU::tick() OptCPU::processSet(int set)
{ {
// Do opt simulation
// Initialize cache // Initialize cache
int blks_in_cache = 0; int blks_in_cache = 0;
RefIndex i = 0; RefIndex i = 0;
cacheHeap.clear();
cacheHeap.resize(assoc);
while (blks_in_cache < numBlks) { while (blks_in_cache < assoc) {
RefIndex cache_index = lookupValue(refInfo[i].addr); RefIndex cache_index = lookupValue(refInfo[set][i].addr);
if (cache_index == -1) { if (cache_index == -1) {
// First reference to this block // First reference to this block
misses++; misses++;
cache_index = blks_in_cache++; cache_index = blks_in_cache++;
setValue(refInfo[i].addr, cache_index); setValue(refInfo[set][i].addr, cache_index);
} else { } else {
hits++; hits++;
} }
// update cache heap to most recent reference // update cache heap to most recent reference
cacheHeap[cache_index] = i; cacheHeap[cache_index] = i;
if (++i >= refInfo.size()) { if (++i >= refInfo[set].size()) {
// exit return;
} }
} }
for (int start = numBlks/2; start >= 0; --start) { for (int start = assoc/2; start >= 0; --start) {
heapify(start); heapify(set,start);
} }
//verifyHeap(0); verifyHeap(set,0);
for (; i < refInfo.size(); ++i) { for (; i < refInfo[set].size(); ++i) {
RefIndex cache_index = lookupValue(refInfo[i].addr); RefIndex cache_index = lookupValue(refInfo[set][i].addr);
if (cache_index == -1) { if (cache_index == -1) {
// miss // miss
misses++; misses++;
// replace from cacheHeap[0] // replace from cacheHeap[0]
// mark replaced block as absent // mark replaced block as absent
setValue(refInfo[cacheHeap[0]].addr, -1); setValue(refInfo[set][cacheHeap[0]].addr, -1);
cacheHeap[0] = i; cacheHeap[0] = i;
heapify(0); heapify(set, 0);
} else { } else {
// hit // hit
hits++; hits++;
assert(refInfo[cacheHeap[cache_index]].addr == refInfo[i].addr); assert(refInfo[set][cacheHeap[cache_index]].addr ==
assert(refInfo[cacheHeap[cache_index]].nextRefTime == i); refInfo[set][i].addr);
assert(heapLeft(cache_index) >= numBlks); assert(refInfo[set][cacheHeap[cache_index]].nextRefTime == i);
assert(heapLeft(cache_index) >= assoc);
} }
cacheHeap[cache_index] = i; cacheHeap[cache_index] = i;
processRankIncrease(cache_index); processRankIncrease(set, cache_index);
}
}
void
OptCPU::tick()
{
// Do opt simulation
int references = 0;
for (int set = 0; set < numSets; ++set) {
if (!refInfo[set].empty()) {
processSet(set);
}
references += refInfo[set].size();
} }
// exit; // exit;
fprintf(stderr, "%d, %d, %d\n", misses, hits, refInfo.size()); fprintf(stderr, "OPT Misses: %d\nOPT Hits: %d\nOPT Accesses: %d\n",
misses, hits, references);
new SimExitEvent("Finshed Memory Trace"); new SimExitEvent("Finshed Memory Trace");
} }
@ -185,26 +200,29 @@ OptCPU::TickEvent::description()
BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU) BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU)
SimObjectParam<MemTraceReader *> trace; SimObjectParam<MemTraceReader *> data_trace;
Param<int> size; Param<int> size;
Param<int> log_block_size; Param<int> block_size;
Param<int> assoc;
END_DECLARE_SIM_OBJECT_PARAMS(OptCPU) END_DECLARE_SIM_OBJECT_PARAMS(OptCPU)
BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU) BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU)
INIT_PARAM_DFLT(trace, "instruction cache", NULL), INIT_PARAM_DFLT(data_trace, "memory trace", NULL),
INIT_PARAM(size, "cache size"), INIT_PARAM(size, "cache size"),
INIT_PARAM(log_block_size, "log base 2 of block size") INIT_PARAM(block_size, "block size"),
INIT_PARAM(assoc,"associativity")
END_INIT_SIM_OBJECT_PARAMS(OptCPU) END_INIT_SIM_OBJECT_PARAMS(OptCPU)
CREATE_SIM_OBJECT(OptCPU) CREATE_SIM_OBJECT(OptCPU)
{ {
return new OptCPU(getInstanceName(), return new OptCPU(getInstanceName(),
trace, data_trace,
log_block_size, block_size,
size); size,
assoc);
} }
REGISTER_SIM_OBJECT("OptCPU", OptCPU) REGISTER_SIM_OBJECT("OptCPU", OptCPU)

View file

@ -90,8 +90,8 @@ class OptCPU : public BaseCPU
Addr addr; Addr addr;
}; };
/** Reference Information. */ /** Reference Information, per set. */
std::vector<RefInfo> refInfo; std::vector<std::vector<RefInfo> > refInfo;
/** Lookup table to track blocks in the cache heap */ /** Lookup table to track blocks in the cache heap */
L1Table lookupTable; L1Table lookupTable;
@ -125,63 +125,65 @@ class OptCPU : public BaseCPU
*/ */
void initTable(Addr addr, RefIndex index); void initTable(Addr addr, RefIndex index);
void heapSwap(int a, int b) { void heapSwap(int set, int a, int b) {
RefIndex tmp = cacheHeap[a]; RefIndex tmp = cacheHeap[a];
cacheHeap[a] = cacheHeap[b]; cacheHeap[a] = cacheHeap[b];
cacheHeap[b] = tmp; cacheHeap[b] = tmp;
setValue(refInfo[cacheHeap[a]].addr, a); setValue(refInfo[set][cacheHeap[a]].addr, a);
setValue(refInfo[cacheHeap[b]].addr, b); setValue(refInfo[set][cacheHeap[b]].addr, b);
} }
int heapLeft(int index) { return index + index + 1; } int heapLeft(int index) { return index + index + 1; }
int heapRight(int index) { return index + index + 2; } int heapRight(int index) { return index + index + 2; }
int heapParent(int index) { return (index - 1) >> 1; } int heapParent(int index) { return (index - 1) >> 1; }
RefIndex heapRank(int index) { RefIndex heapRank(int set, int index) {
return refInfo[cacheHeap[index]].nextRefTime; return refInfo[set][cacheHeap[index]].nextRefTime;
} }
void heapify(int start){ void heapify(int set, int start){
int left = heapLeft(start); int left = heapLeft(start);
int right = heapRight(start); int right = heapRight(start);
int max = start; int max = start;
if (left < numBlks && heapRank(left) > heapRank(start)) { if (left < assoc && heapRank(set, left) > heapRank(set, start)) {
max = left; max = left;
} }
if (right < numBlks && heapRank(right) > heapRank(max)) { if (right < assoc && heapRank(set, right) > heapRank(set, max)) {
max = right; max = right;
} }
if (max != start) { if (max != start) {
heapSwap(start, max); heapSwap(set, start, max);
heapify(max); heapify(set, max);
} }
} }
void verifyHeap(int start) { void verifyHeap(int set, int start) {
int left = heapLeft(start); int left = heapLeft(start);
int right = heapRight(start); int right = heapRight(start);
if (left < numBlks) { if (left < assoc) {
assert(heapRank(start) >= heapRank(left)); assert(heapRank(set, start) >= heapRank(set, left));
verifyHeap(left); verifyHeap(set, left);
} }
if (right < numBlks) { if (right < assoc) {
assert(heapRank(start) >= heapRank(right)); assert(heapRank(set, start) >= heapRank(set, right));
verifyHeap(right); verifyHeap(set, right);
} }
} }
void processRankIncrease(int start) { void processRankIncrease(int set, int start) {
int parent = heapParent(start); int parent = heapParent(start);
while (start > 0 && heapRank(parent) < heapRank(start)) { while (start > 0 && heapRank(set,parent) < heapRank(set,start)) {
heapSwap(parent, start); heapSwap(set, parent, start);
start = parent; start = parent;
parent = heapParent(start); parent = heapParent(start);
} }
} }
void processSet(int set);
static const RefIndex InfiniteRef = 0x7fffffff; static const RefIndex InfiniteRef = 0x7fffffff;
/** Memory reference trace. */ /** Memory reference trace. */
@ -193,6 +195,10 @@ class OptCPU : public BaseCPU
/** The number of blocks in the cache. */ /** The number of blocks in the cache. */
const int numBlks; const int numBlks;
const int assoc;
const int numSets;
const int setMask;
int misses; int misses;
int hits; int hits;
@ -203,8 +209,9 @@ class OptCPU : public BaseCPU
*/ */
OptCPU(const std::string &name, OptCPU(const std::string &name,
MemTraceReader *_trace, MemTraceReader *_trace,
int log_block_size, int block_size,
int cache_size); int cache_size,
int assoc);
/** /**
* Perform the optimal replacement simulation. * Perform the optimal replacement simulation.

View file

@ -161,6 +161,9 @@ ITXReader::getNextReq(MemReqPtr &req)
case ITXWrite: case ITXWrite:
tmp_req->cmd = Write; tmp_req->cmd = Write;
break; break;
case ITXWriteback:
tmp_req->cmd = Writeback;
break;
case ITXCode: case ITXCode:
tmp_req->cmd = Read; tmp_req->cmd = Read;
tmp_req->flags |= INST_READ; tmp_req->flags |= INST_READ;