Update the Memtester, commit a config file/test for it.

src/cpu/SConscript:
    Add memtester to the compilation environment.
    Someone who knows this better should make the MemTest a cpu model parameter.

    For now attached with the build of o3 cpu.
src/cpu/memtest/memtest.cc:
src/cpu/memtest/memtest.hh:
    Update Memtest for new mem system
src/python/m5/objects/MemTest.py:
    Update memtest python description

--HG--
extra : convert_revision : d6a63e08fda0975a7abfb23814a86a0caf53e482
This commit is contained in:
Ron Dreslinski 2006-10-09 00:26:10 -04:00
parent 0a3e4d56e5
commit 6c7ab02682
6 changed files with 392 additions and 165 deletions

View file

@ -158,6 +158,7 @@ if 'O3CPU' in env['CPU_MODELS']:
o3/scoreboard.cc
o3/store_set.cc
''')
sources += Split('memtest/memtest.cc')
if env['USE_CHECKER']:
sources += Split('o3/checker_builder.cc')
else:

View file

@ -38,39 +38,80 @@
#include "base/misc.hh"
#include "base/statistics.hh"
#include "cpu/simple_thread.hh"
//#include "cpu/simple_thread.hh"
#include "cpu/memtest/memtest.hh"
#include "mem/cache/base_cache.hh"
//#include "mem/cache/base_cache.hh"
//#include "mem/physical.hh"
#include "sim/builder.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
#include "mem/port.hh"
#include "mem/mem_object.hh"
using namespace std;
using namespace TheISA;
int TESTER_ALLOCATOR=0;
bool
MemTest::CpuPort::recvTiming(Packet *pkt)
{
memtest->completeRequest(pkt);
return true;
}
Tick
MemTest::CpuPort::recvAtomic(Packet *pkt)
{
panic("MemTest doesn't expect recvAtomic callback!");
return curTick;
}
void
MemTest::CpuPort::recvFunctional(Packet *pkt)
{
memtest->completeRequest(pkt);
}
void
MemTest::CpuPort::recvStatusChange(Status status)
{
if (status == RangeChange)
return;
panic("MemTest doesn't expect recvStatusChange callback!");
}
void
MemTest::CpuPort::recvRetry()
{
memtest->doRetry();
}
MemTest::MemTest(const string &name,
MemInterface *_cache_interface,
FunctionalMemory *main_mem,
FunctionalMemory *check_mem,
// MemInterface *_cache_interface,
// PhysicalMemory *main_mem,
// PhysicalMemory *check_mem,
unsigned _memorySize,
unsigned _percentReads,
unsigned _percentCopies,
// unsigned _percentCopies,
unsigned _percentUncacheable,
unsigned _progressInterval,
unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned,
Addr _traceAddr,
Counter _max_loads)
: SimObject(name),
: MemObject(name),
tickEvent(this),
cacheInterface(_cache_interface),
mainMem(main_mem),
checkMem(check_mem),
cachePort("test", this),
funcPort("functional", this),
retryPkt(NULL),
// mainMem(main_mem),
// checkMem(check_mem),
size(_memorySize),
percentReads(_percentReads),
percentCopies(_percentCopies),
// percentCopies(_percentCopies),
percentUncacheable(_percentUncacheable),
progressInterval(_progressInterval),
nextProgressMessage(_progressInterval),
@ -81,43 +122,52 @@ MemTest::MemTest(const string &name,
vector<string> cmd;
cmd.push_back("/bin/ls");
vector<string> null_vec;
thread = new SimpleThread(NULL, 0, mainMem, 0);
blockSize = cacheInterface->getBlockSize();
blockAddrMask = blockSize - 1;
traceBlockAddr = blockAddr(_traceAddr);
//setup data storage with interesting values
uint8_t *data1 = new uint8_t[size];
uint8_t *data2 = new uint8_t[size];
uint8_t *data3 = new uint8_t[size];
memset(data1, 1, size);
memset(data2, 2, size);
memset(data3, 3, size);
// thread = new SimpleThread(NULL, 0, NULL, 0, mainMem);
curTick = 0;
// Needs to be masked off once we know the block size.
traceBlockAddr = _traceAddr;
baseAddr1 = 0x100000;
baseAddr2 = 0x400000;
uncacheAddr = 0x800000;
// set up intial memory contents here
mainMem->prot_write(baseAddr1, data1, size);
checkMem->prot_write(baseAddr1, data1, size);
mainMem->prot_write(baseAddr2, data2, size);
checkMem->prot_write(baseAddr2, data2, size);
mainMem->prot_write(uncacheAddr, data3, size);
checkMem->prot_write(uncacheAddr, data3, size);
delete [] data1;
delete [] data2;
delete [] data3;
// set up counters
noResponseCycles = 0;
numReads = 0;
tickEvent.schedule(0);
id = TESTER_ALLOCATOR++;
accessRetry = false;
}
Port *
MemTest::getPort(const std::string &if_name, int idx)
{
if (if_name == "functional")
return &funcPort;
else if (if_name == "test")
return &cachePort;
else
panic("No Such Port\n");
}
void
MemTest::init()
{
// By the time init() is called, the ports should be hooked up.
blockSize = cachePort.peerBlockSize();
blockAddrMask = blockSize - 1;
traceBlockAddr = blockAddr(traceBlockAddr);
// set up intial memory contents here
cachePort.memsetBlob(baseAddr1, 1, size);
funcPort.memsetBlob(baseAddr1, 1, size);
cachePort.memsetBlob(baseAddr2, 2, size);
funcPort.memsetBlob(baseAddr2, 2, size);
cachePort.memsetBlob(uncacheAddr, 3, size);
funcPort.memsetBlob(uncacheAddr, 3, size);
}
static void
@ -132,23 +182,31 @@ printData(ostream &os, uint8_t *data, int nbytes)
}
void
MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
MemTest::completeRequest(Packet *pkt)
{
MemTestSenderState *state =
dynamic_cast<MemTestSenderState *>(pkt->senderState);
uint8_t *data = state->data;
uint8_t *pkt_data = pkt->getPtr<uint8_t>();
Request *req = pkt->req;
//Remove the address from the list of outstanding
std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->getPaddr());
assert(removeAddr != outstandingAddrs.end());
outstandingAddrs.erase(removeAddr);
switch (req->cmd) {
case Read:
if (memcmp(req->data, data, req->size) != 0) {
cerr << name() << ": on read of 0x" << hex << req->paddr
<< " (0x" << hex << blockAddr(req->paddr) << ")"
switch (pkt->cmd) {
case Packet::ReadResp:
if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
cerr << name() << ": on read of 0x" << hex << req->getPaddr()
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
<< "@ cycle " << dec << curTick
<< ", cache returns 0x";
printData(cerr, req->data, req->size);
printData(cerr, pkt_data, pkt->getSize());
cerr << ", expected 0x";
printData(cerr, data, req->size);
printData(cerr, data, pkt->getSize());
cerr << endl;
fatal("");
}
@ -163,13 +221,13 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
}
if (numReads >= maxLoads)
SimExit(curTick, "Maximum number of loads reached!");
exitSimLoop("Maximum number of loads reached!");
break;
case Write:
case Packet::WriteResp:
numWritesStat++;
break;
/*
case Copy:
//Also remove dest from outstanding list
removeAddr = outstandingAddrs.find(req->dest);
@ -177,36 +235,37 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
outstandingAddrs.erase(removeAddr);
numCopiesStat++;
break;
*/
default:
panic("invalid command");
}
if (blockAddr(req->paddr) == traceBlockAddr) {
if (blockAddr(req->getPaddr()) == traceBlockAddr) {
cerr << name() << ": completed "
<< (req->cmd.isWrite() ? "write" : "read")
<< (pkt->isWrite() ? "write" : "read")
<< " access of "
<< dec << req->size << " bytes at address 0x"
<< hex << req->paddr
<< " (0x" << hex << blockAddr(req->paddr) << ")"
<< dec << pkt->getSize() << " bytes at address 0x"
<< hex << req->getPaddr()
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
<< ", value = 0x";
printData(cerr, req->data, req->size);
printData(cerr, pkt_data, pkt->getSize());
cerr << " @ cycle " << dec << curTick;
cerr << endl;
}
noResponseCycles = 0;
delete state;
delete [] data;
delete pkt->req;
delete pkt;
}
void
MemTest::regStats()
{
using namespace Stats;
numReadsStat
.name(name() + ".num_reads")
.desc("number of read accesses completed")
@ -234,7 +293,7 @@ MemTest::tick()
fatal("");
}
if (cacheInterface->isBlocked()) {
if (accessRetry) {
return;
}
@ -248,30 +307,30 @@ MemTest::tick()
//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();
Request *req = new Request();
uint32_t flags = 0;
Addr paddr;
if (cacheable < percentUncacheable) {
req->flags |= UNCACHEABLE;
req->paddr = uncacheAddr + offset;
flags |= UNCACHEABLE;
paddr = uncacheAddr + offset;
} else {
req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
}
// bool probe = (random() % 2 == 1) && !req->isUncacheable();
bool probe = false;
req->size = 1 << access_size;
req->data = new uint8_t[req->size];
req->paddr &= ~(req->size - 1);
req->time = curTick;
req->xc = thread->getProxy();
paddr &= ~((1 << access_size) - 1);
req->setPhys(paddr, 1 << access_size, flags);
req->setThreadContext(id,0);
uint8_t *result = new uint8_t[8];
if (cmd < percentReads) {
// read
@ -279,60 +338,81 @@ MemTest::tick()
//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);
if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
else outstandingAddrs.insert(paddr);
req->cmd = Read;
uint8_t *result = new uint8_t[8];
checkMem->access(Read, req->paddr, result, req->size);
if (blockAddr(req->paddr) == traceBlockAddr) {
// ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin
funcPort.readBlob(req->getPaddr(), result, req->getSize());
if (blockAddr(paddr) == traceBlockAddr) {
cerr << name()
<< ": initiating read "
<< ((probe) ? "probe of " : "access of ")
<< dec << req->size << " bytes from addr 0x"
<< hex << req->paddr
<< " (0x" << hex << blockAddr(req->paddr) << ")"
<< dec << req->getSize() << " bytes from addr 0x"
<< hex << paddr
<< " (0x" << hex << blockAddr(paddr) << ")"
<< " at cycle "
<< dec << curTick << endl;
}
Packet *pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
pkt->dataDynamicArray(new uint8_t[req->getSize()]);
MemTestSenderState *state = new MemTestSenderState(result);
pkt->senderState = state;
if (probe) {
cacheInterface->probeAndUpdate(req);
completeRequest(req, result);
cachePort.sendFunctional(pkt);
// completeRequest(pkt, result);
} else {
req->completionEvent = new MemCompleteEvent(req, result, this);
cacheInterface->access(req);
// req->completionEvent = new MemCompleteEvent(req, result, this);
if (!cachePort.sendTiming(pkt)) {
accessRetry = true;
retryPkt = pkt;
}
} else if (cmd < (100 - percentCopies)){
}
} else {
// 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);
if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
else outstandingAddrs.insert(paddr);
req->cmd = Write;
memcpy(req->data, &data, req->size);
checkMem->access(Write, req->paddr, req->data, req->size);
if (blockAddr(req->paddr) == traceBlockAddr) {
/*
if (blockAddr(req->getPaddr()) == traceBlockAddr) {
cerr << name() << ": initiating write "
<< ((probe)?"probe of ":"access of ")
<< dec << req->size << " bytes (value = 0x";
printData(cerr, req->data, req->size);
<< dec << req->getSize() << " bytes (value = 0x";
printData(cerr, data_pkt->getPtr(), req->getSize());
cerr << ") to addr 0x"
<< hex << req->paddr
<< " (0x" << hex << blockAddr(req->paddr) << ")"
<< hex << req->getPaddr()
<< " (0x" << hex << blockAddr(req->getPaddr()) << ")"
<< " at cycle "
<< dec << curTick << endl;
}
*/
Packet *pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
uint8_t *pkt_data = new uint8_t[req->getSize()];
pkt->dataDynamicArray(pkt_data);
memcpy(pkt_data, &data, req->getSize());
MemTestSenderState *state = new MemTestSenderState(result);
pkt->senderState = state;
funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize());
if (probe) {
cacheInterface->probeAndUpdate(req);
completeRequest(req, NULL);
cachePort.sendFunctional(pkt);
// completeRequest(req, NULL);
} else {
req->completionEvent = new MemCompleteEvent(req, NULL, this);
cacheInterface->access(req);
// req->completionEvent = new MemCompleteEvent(req, NULL, this);
if (!cachePort.sendTiming(pkt)) {
accessRetry = true;
retryPkt = pkt;
}
} else {
}
}
/* else {
// copy
unsigned source_align = random() % 100;
unsigned dest_align = random() % 100;
@ -369,38 +449,32 @@ MemTest::tick()
<< " (0x" << hex << blockAddr(dest) << ")"
<< " at cycle "
<< dec << curTick << endl;
}
}*
cacheInterface->access(req);
uint8_t result[blockSize];
checkMem->access(Read, source, &result, blockSize);
checkMem->access(Write, dest, &result, blockSize);
}
*/
}
void
MemCompleteEvent::process()
MemTest::doRetry()
{
tester->completeRequest(req, data);
delete this;
if (cachePort.sendTiming(retryPkt)) {
accessRetry = false;
retryPkt = NULL;
}
}
const char *
MemCompleteEvent::description()
{
return "memory access completion";
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
SimObjectParam<BaseCache *> cache;
SimObjectParam<FunctionalMemory *> main_mem;
SimObjectParam<FunctionalMemory *> check_mem;
// SimObjectParam<BaseCache *> cache;
// SimObjectParam<PhysicalMemory *> main_mem;
// SimObjectParam<PhysicalMemory *> check_mem;
Param<unsigned> memory_size;
Param<unsigned> percent_reads;
Param<unsigned> percent_copies;
// Param<unsigned> percent_copies;
Param<unsigned> percent_uncacheable;
Param<unsigned> progress_interval;
Param<unsigned> percent_source_unaligned;
@ -413,12 +487,12 @@ END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
INIT_PARAM(cache, "L1 cache"),
INIT_PARAM(main_mem, "hierarchical memory"),
INIT_PARAM(check_mem, "check memory"),
// INIT_PARAM(cache, "L1 cache"),
// INIT_PARAM(main_mem, "hierarchical memory"),
// INIT_PARAM(check_mem, "check memory"),
INIT_PARAM(memory_size, "memory size"),
INIT_PARAM(percent_reads, "target read percentage"),
INIT_PARAM(percent_copies, "target copy 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,
@ -433,8 +507,8 @@ END_INIT_SIM_OBJECT_PARAMS(MemTest)
CREATE_SIM_OBJECT(MemTest)
{
return new MemTest(getInstanceName(), cache->getInterface(), main_mem,
check_mem, memory_size, percent_reads, percent_copies,
return new MemTest(getInstanceName(), /*cache->getInterface(),*/ /*main_mem,*/
/*check_mem,*/ memory_size, percent_reads, /*percent_copies,*/
percent_uncacheable, progress_interval,
percent_source_unaligned, percent_dest_unaligned,
trace_addr, max_loads);

View file

@ -35,25 +35,27 @@
#include <set>
#include "base/statistics.hh"
#include "mem/functional/functional.hh"
#include "mem/mem_interface.hh"
//#include "mem/functional/functional.hh"
//#include "mem/mem_interface.hh"
#include "sim/eventq.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "mem/mem_object.hh"
#include "mem/port.hh"
class ThreadContext;
class MemTest : public SimObject
class Packet;
class MemTest : public MemObject
{
public:
MemTest(const std::string &name,
MemInterface *_cache_interface,
FunctionalMemory *main_mem,
FunctionalMemory *check_mem,
// MemInterface *_cache_interface,
// PhysicalMemory *main_mem,
// PhysicalMemory *check_mem,
unsigned _memorySize,
unsigned _percentReads,
unsigned _percentCopies,
// unsigned _percentCopies,
unsigned _percentUncacheable,
unsigned _progressInterval,
unsigned _percentSourceUnaligned,
@ -61,6 +63,8 @@ class MemTest : public SimObject
Addr _traceAddr,
Counter _max_loads);
virtual void init();
// register statistics
virtual void regStats();
@ -69,6 +73,8 @@ class MemTest : public SimObject
// main simulation loop (one cycle)
void tick();
virtual Port *getPort(const std::string &if_name, int idx = -1);
protected:
class TickEvent : public Event
{
@ -82,16 +88,62 @@ class MemTest : public SimObject
};
TickEvent tickEvent;
class CpuPort : public Port
{
MemInterface *cacheInterface;
FunctionalMemory *mainMem;
FunctionalMemory *checkMem;
SimpleThread *thread;
MemTest *memtest;
public:
CpuPort(const std::string &_name, MemTest *_memtest)
: Port(_name), memtest(_memtest)
{ }
protected:
virtual bool recvTiming(Packet *pkt);
virtual Tick recvAtomic(Packet *pkt);
virtual void recvFunctional(Packet *pkt);
virtual void recvStatusChange(Status status);
virtual void recvRetry();
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
};
CpuPort cachePort;
CpuPort funcPort;
class MemTestSenderState : public Packet::SenderState
{
public:
/** Constructor. */
MemTestSenderState(uint8_t *_data)
: data(_data)
{ }
// Hold onto data pointer
uint8_t *data;
};
// Request *dataReq;
Packet *retryPkt;
// MemInterface *cacheInterface;
// PhysicalMemory *mainMem;
// PhysicalMemory *checkMem;
// SimpleThread *thread;
bool accessRetry;
unsigned size; // size of testing memory region
unsigned percentReads; // target percentage of read accesses
unsigned percentCopies; // target percentage of copy accesses
// unsigned percentCopies; // target percentage of copy accesses
unsigned percentUncacheable;
int id;
@ -128,31 +180,13 @@ class MemTest : public SimObject
Stats::Scalar<> numCopiesStat;
// called by MemCompleteEvent::process()
void completeRequest(MemReqPtr &req, uint8_t *data);
void completeRequest(Packet *pkt);
void doRetry();
friend class MemCompleteEvent;
};
class MemCompleteEvent : public Event
{
MemReqPtr req;
uint8_t *data;
MemTest *tester;
public:
MemCompleteEvent(MemReqPtr &_req, uint8_t *_data, MemTest *_tester)
: Event(&mainEventQueue),
req(_req), data(_data), tester(_tester)
{
}
void process();
virtual const char *description();
};
#endif // __CPU_MEMTEST_MEMTEST_HH__

View file

@ -1,13 +1,12 @@
from m5.SimObject import SimObject
from m5.params import *
from m5.proxy import *
from m5 import build_env
class MemTest(SimObject):
type = 'MemTest'
cache = Param.BaseCache("L1 cache")
check_mem = Param.FunctionalMemory("check memory")
main_mem = Param.FunctionalMemory("hierarchical memory")
max_loads = Param.Counter("number of loads to execute")
memory_size = Param.Int(65536, "memory size")
percent_copies = Param.Percent(0, "target copy percentage")
percent_dest_unaligned = Param.Percent(50,
"percent of copy dest address that are unaligned")
percent_reads = Param.Percent(65, "target read percentage")
@ -18,3 +17,6 @@ class MemTest(SimObject):
progress_interval = Param.Counter(1000000,
"progress report interval (in accesses)")
trace_addr = Param.Addr(0, "address to trace")
test = Port("Port to the memory system to test")
functional = Port("Port to the functional memory used for verification")

88
tests/configs/memtest.py Normal file
View file

@ -0,0 +1,88 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Ron Dreslinski
import m5
from m5.objects import *
# --------------------
# Base L1 Cache
# ====================
class L1(BaseCache):
latency = 1
block_size = 64
mshrs = 4
tgts_per_mshr = 8
protocol = CoherenceProtocol(protocol='moesi')
# ----------------------
# Base L2 Cache
# ----------------------
class L2(BaseCache):
block_size = 64
latency = 100
mshrs = 92
tgts_per_mshr = 16
write_buffers = 8
nb_cores = 1
cpus = [ MemTest(max_loads=1e12) for i in xrange(nb_cores) ]
# system simulated
system = System(cpu = cpus, funcmem = PhysicalMemory(),
physmem = PhysicalMemory(), membus = Bus())
# l2cache & bus
system.toL2Bus = Bus()
system.l2c = L2(size='4MB', assoc=8)
system.l2c.cpu_side = system.toL2Bus.port
# connect l2c to membus
system.l2c.mem_side = system.membus.port
# add L1 caches
for cpu in cpus:
cpu.l1c = L1(size = '32kB', assoc = 4)
cpu.l1c.cpu_side = cpu.test
cpu.l1c.mem_side = system.toL2Bus.port
system.funcmem.port = cpu.functional
# connect memory to membus
system.physmem.port = system.membus.port
# -----------------------
# run simulation
# -----------------------
root = Root( system = system )
root.system.mem_mode = 'timing'
#root.trace.flags="InstExec"
root.trace.flags="Bus"

View file

@ -0,0 +1,28 @@
# Copyright (c) 2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Ron Dreslinski