/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
-#include <string>
-#include <sstream>
#include <iomanip>
+#include <set>
+#include <sstream>
+#include <string>
#include <vector>
#include "base/misc.hh"
#include "base/statistics.hh"
+#include "cpu/exec_context.hh"
#include "cpu/memtest/memtest.hh"
#include "mem/cache/base_cache.hh"
-#include "mem/functional_mem/main_memory.hh"
#include "sim/builder.hh"
#include "sim/sim_events.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
using namespace std;
+int TESTER_ALLOCATOR=0;
+
MemTest::MemTest(const string &name,
MemInterface *_cache_interface,
FunctionalMemory *main_mem,
unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned,
Addr _traceAddr,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads)
- : BaseCPU(name, 1, 0, 0, max_loads_any_thread, max_loads_all_threads),
+ Counter _max_loads)
+ : SimObject(name),
tickEvent(this),
cacheInterface(_cache_interface),
mainMem(main_mem),
progressInterval(_progressInterval),
nextProgressMessage(_progressInterval),
percentSourceUnaligned(_percentSourceUnaligned),
- percentDestUnaligned(percentDestUnaligned)
+ percentDestUnaligned(percentDestUnaligned),
+ maxLoads(_max_loads)
{
vector<string> cmd;
cmd.push_back("/bin/ls");
vector<string> null_vec;
- xc = new ExecContext(this ,0,mainMem,0);
+ xc = new ExecContext(NULL, 0, mainMem, 0);
blockSize = cacheInterface->getBlockSize();
blockAddrMask = blockSize - 1;
// set up counters
noResponseCycles = 0;
numReads = 0;
- numWrites = 0;
tickEvent.schedule(0);
+
+ id = TESTER_ALLOCATOR++;
}
static void
void
MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
{
+ //Remove the address from the list of outstanding
+ std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
+ assert(removeAddr != outstandingAddrs.end());
+ outstandingAddrs.erase(removeAddr);
+
switch (req->cmd) {
case Read:
if (memcmp(req->data, data, req->size) != 0) {
}
numReads++;
+ numReadsStat++;
- if (numReads.value() == nextProgressMessage) {
- cerr << name() << ": completed " << numReads.value()
- << " read accesses @ " << curTick << endl;
+ if (numReads == nextProgressMessage) {
+ ccprintf(cerr, "%s: completed %d read accesses @%d\n",
+ name(), numReads, curTick);
nextProgressMessage += progressInterval;
}
- comLoadEventQueue[0]->serviceEvents(numReads.value());
+ if (numReads >= maxLoads)
+ SimExit(curTick, "Maximum number of loads reached!");
break;
case Write:
- numWrites++;
+ numWritesStat++;
break;
case Copy:
+ //Also remove dest from outstanding list
+ removeAddr = outstandingAddrs.find(req->dest);
+ assert(removeAddr != outstandingAddrs.end());
+ outstandingAddrs.erase(removeAddr);
+ numCopiesStat++;
break;
default:
void
MemTest::regStats()
{
- using namespace Statistics;
+ using namespace Stats;
+
- numReads
+ numReadsStat
.name(name() + ".num_reads")
.desc("number of read accesses completed")
;
- numWrites
+ numWritesStat
.name(name() + ".num_writes")
.desc("number of write accesses completed")
;
- numCopies
+ numCopiesStat
.name(name() + ".num_copies")
.desc("number of copy accesses completed")
;
MemTest::tick()
{
if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + 1);
+ tickEvent.schedule(curTick + cycles(1));
- if (++noResponseCycles >= 5000) {
+ if (++noResponseCycles >= 500000) {
cerr << name() << ": deadlocked at cycle " << curTick << endl;
fatal("");
}
}
//make new request
- unsigned cmd = rand() % 100;
- unsigned offset1 = random() % size;
- unsigned offset2 = random() % size;
+ unsigned cmd = random() % 100;
+ unsigned offset = random() % size;
unsigned base = random() % 2;
uint64_t data = random();
unsigned access_size = random() % 4;
- unsigned cacheable = rand() % 100;
- unsigned source_align = rand() % 100;
- unsigned dest_align = rand() % 100;
+ unsigned cacheable = random() % 100;
+
+ //If we aren't doing copies, use id as offset, and do a false sharing
+ //mem tester
+ if (percentCopies == 0) {
+ //We can eliminate the lower bits of the offset, and then use the id
+ //to offset within the blks
+ offset &= ~63; //Not the low order bits
+ offset += id;
+ access_size = 0;
+ }
MemReqPtr req = new MemReq();
if (cacheable < percentUncacheable) {
req->flags |= UNCACHEABLE;
- req->paddr = uncacheAddr + offset1;
+ req->paddr = uncacheAddr + offset;
} else {
- req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset1;
+ req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
}
- bool probe = (rand() % 2 == 1) && !req->isUncacheable();
- probe = false;
+ // bool probe = (random() % 2 == 1) && !req->isUncacheable();
+ bool probe = false;
req->size = 1 << access_size;
req->data = new uint8_t[req->size];
if (cmd < percentReads) {
// read
+
+ //For now we only allow one outstanding request per addreess per tester
+ //This means we assume CPU does write forwarding to reads that alias something
+ //in the cpu store buffer.
+ if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(req->paddr);
+
req->cmd = Read;
uint8_t *result = new uint8_t[8];
checkMem->access(Read, req->paddr, result, req->size);
if (blockAddr(req->paddr) == traceBlockAddr) {
cerr << name()
<< ": initiating read "
- << ((probe)?"probe of ":"access of ")
+ << ((probe) ? "probe of " : "access of ")
<< dec << req->size << " bytes from addr 0x"
<< hex << req->paddr
<< " (0x" << hex << blockAddr(req->paddr) << ")"
}
} else if (cmd < (100 - percentCopies)){
// write
+
+ //For now we only allow one outstanding request per addreess per tester
+ //This means we assume CPU does write forwarding to reads that alias something
+ //in the cpu store buffer.
+ if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(req->paddr);
+
req->cmd = Write;
memcpy(req->data, &data, req->size);
checkMem->access(Write, req->paddr, req->data, req->size);
}
} else {
// copy
- Addr source = ((base) ? baseAddr1 : baseAddr2) + offset1;
+ unsigned source_align = random() % 100;
+ unsigned dest_align = random() % 100;
+ unsigned offset2 = random() % size;
+
+ Addr source = ((base) ? baseAddr1 : baseAddr2) + offset;
Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
+ if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(source);
+ if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(dest);
+
if (source_align >= percentSourceUnaligned) {
source = blockAddr(source);
}
Param<unsigned> percent_source_unaligned;
Param<unsigned> percent_dest_unaligned;
Param<Addr> trace_addr;
- Param<Counter> max_loads_any_thread;
- Param<Counter> max_loads_all_threads;
+ Param<Counter> max_loads;
END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
INIT_PARAM(cache, "L1 cache"),
INIT_PARAM(main_mem, "hierarchical memory"),
INIT_PARAM(check_mem, "check memory"),
- INIT_PARAM_DFLT(memory_size, "memory size", 65536),
- INIT_PARAM_DFLT(percent_reads, "target read percentage", 65),
- INIT_PARAM_DFLT(percent_copies, "target copy percentage", 0),
- INIT_PARAM_DFLT(percent_uncacheable, "target uncacheable percentage", 10),
- INIT_PARAM_DFLT(progress_interval,
- "progress report interval (in accesses)", 1000000),
- INIT_PARAM_DFLT(percent_source_unaligned, "percent of copy source address "
- "that are unaligned", 50),
- INIT_PARAM_DFLT(percent_dest_unaligned, "percent of copy dest address "
- "that are unaligned", 50),
- INIT_PARAM_DFLT(trace_addr, "address to trace", 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "terminate when all threads have reached this load count",
- 0)
+ INIT_PARAM(memory_size, "memory size"),
+ INIT_PARAM(percent_reads, "target read percentage"),
+ INIT_PARAM(percent_copies, "target copy percentage"),
+ INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
+ INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
+ INIT_PARAM(percent_source_unaligned,
+ "percent of copy source address that are unaligned"),
+ INIT_PARAM(percent_dest_unaligned,
+ "percent of copy dest address that are unaligned"),
+ INIT_PARAM(trace_addr, "address to trace"),
+ INIT_PARAM(max_loads, "terminate when we have reached this load count")
END_INIT_SIM_OBJECT_PARAMS(MemTest)
check_mem, memory_size, percent_reads, percent_copies,
percent_uncacheable, progress_interval,
percent_source_unaligned, percent_dest_unaligned,
- trace_addr, max_loads_any_thread,
- max_loads_all_threads);
+ trace_addr, max_loads);
}
REGISTER_SIM_OBJECT("MemTest", MemTest)