diff options
author | Brad Beckmann <Brad.Beckmann@amd.com> | 2010-08-24 12:07:22 -0700 |
---|---|---|
committer | Brad Beckmann <Brad.Beckmann@amd.com> | 2010-08-24 12:07:22 -0700 |
commit | e983ef9e8c6749c1cd0bf083a2092cb4683d0346 (patch) | |
tree | 02d262e1b84e5c4675df54cb27678526f756169b /src/cpu/testers/memtest | |
parent | 20b2f0ce9f09bc4166bc3ee001eab4d6b2b84a04 (diff) | |
download | gem5-e983ef9e8c6749c1cd0bf083a2092cb4683d0346.tar.xz |
testers: move testers to a new directory
This patch moves the testers to a new subdirectory under src/cpu and includes
the necessary fixes to work with latest m5 initialization patches.
--HG--
rename : configs/example/determ_test.py => configs/example/ruby_direct_test.py
rename : src/cpu/directedtest/DirectedGenerator.cc => src/cpu/testers/directedtest/DirectedGenerator.cc
rename : src/cpu/directedtest/DirectedGenerator.hh => src/cpu/testers/directedtest/DirectedGenerator.hh
rename : src/cpu/directedtest/InvalidateGenerator.cc => src/cpu/testers/directedtest/InvalidateGenerator.cc
rename : src/cpu/directedtest/InvalidateGenerator.hh => src/cpu/testers/directedtest/InvalidateGenerator.hh
rename : src/cpu/directedtest/RubyDirectedTester.cc => src/cpu/testers/directedtest/RubyDirectedTester.cc
rename : src/cpu/directedtest/RubyDirectedTester.hh => src/cpu/testers/directedtest/RubyDirectedTester.hh
rename : src/cpu/directedtest/RubyDirectedTester.py => src/cpu/testers/directedtest/RubyDirectedTester.py
rename : src/cpu/directedtest/SConscript => src/cpu/testers/directedtest/SConscript
rename : src/cpu/directedtest/SeriesRequestGenerator.cc => src/cpu/testers/directedtest/SeriesRequestGenerator.cc
rename : src/cpu/directedtest/SeriesRequestGenerator.hh => src/cpu/testers/directedtest/SeriesRequestGenerator.hh
rename : src/cpu/memtest/MemTest.py => src/cpu/testers/memtest/MemTest.py
rename : src/cpu/memtest/SConscript => src/cpu/testers/memtest/SConscript
rename : src/cpu/memtest/memtest.cc => src/cpu/testers/memtest/memtest.cc
rename : src/cpu/memtest/memtest.hh => src/cpu/testers/memtest/memtest.hh
rename : src/cpu/rubytest/Check.cc => src/cpu/testers/rubytest/Check.cc
rename : src/cpu/rubytest/Check.hh => src/cpu/testers/rubytest/Check.hh
rename : src/cpu/rubytest/CheckTable.cc => src/cpu/testers/rubytest/CheckTable.cc
rename : src/cpu/rubytest/CheckTable.hh => src/cpu/testers/rubytest/CheckTable.hh
rename : src/cpu/rubytest/RubyTester.cc => src/cpu/testers/rubytest/RubyTester.cc
rename : src/cpu/rubytest/RubyTester.hh => src/cpu/testers/rubytest/RubyTester.hh
rename : src/cpu/rubytest/RubyTester.py => src/cpu/testers/rubytest/RubyTester.py
rename : src/cpu/rubytest/SConscript => src/cpu/testers/rubytest/SConscript
Diffstat (limited to 'src/cpu/testers/memtest')
-rw-r--r-- | src/cpu/testers/memtest/MemTest.py | 52 | ||||
-rw-r--r-- | src/cpu/testers/memtest/SConscript | 38 | ||||
-rw-r--r-- | src/cpu/testers/memtest/memtest.cc | 434 | ||||
-rw-r--r-- | src/cpu/testers/memtest/memtest.hh | 198 |
4 files changed, 722 insertions, 0 deletions
diff --git a/src/cpu/testers/memtest/MemTest.py b/src/cpu/testers/memtest/MemTest.py new file mode 100644 index 000000000..957de8088 --- /dev/null +++ b/src/cpu/testers/memtest/MemTest.py @@ -0,0 +1,52 @@ +# Copyright (c) 2005-2007 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: Nathan Binkert + +from MemObject import MemObject +from m5.params import * +from m5.proxy import * + +class MemTest(MemObject): + type = 'MemTest' + max_loads = Param.Counter(0, "number of loads to execute") + atomic = Param.Bool(False, "Execute tester in atomic mode? (or timing)\n") + memory_size = Param.Int(65536, "memory size") + percent_dest_unaligned = Param.Percent(50, + "percent of copy dest address that are unaligned") + percent_reads = Param.Percent(65, "target read percentage") + issue_dmas = Param.Bool(False, "this memtester should issue dma requests") + percent_source_unaligned = Param.Percent(50, + "percent of copy source address that are unaligned") + percent_functional = Param.Percent(50, "percent of access that are functional") + percent_uncacheable = Param.Percent(10, + "target uncacheable percentage") + 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") diff --git a/src/cpu/testers/memtest/SConscript b/src/cpu/testers/memtest/SConscript new file mode 100644 index 000000000..61aa0969e --- /dev/null +++ b/src/cpu/testers/memtest/SConscript @@ -0,0 +1,38 @@ +# -*- mode:python -*- + +# 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: Nathan Binkert + +Import('*') + +#if 'O3CPU' in env['CPU_MODELS']: +SimObject('MemTest.py') + +Source('memtest.cc') + +TraceFlag('MemTest') diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc new file mode 100644 index 000000000..7a8e4cc52 --- /dev/null +++ b/src/cpu/testers/memtest/memtest.cc @@ -0,0 +1,434 @@ +/* + * 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 + * 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: Erik Hallnor + * Steve Reinhardt + */ + +// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded + +#include <iomanip> +#include <set> +#include <string> +#include <vector> + +#include "base/misc.hh" +#include "base/statistics.hh" +#include "cpu/testers/memtest/memtest.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" +#include "mem/packet.hh" +#include "mem/request.hh" +#include "sim/sim_events.hh" +#include "sim/stats.hh" + +using namespace std; + +int TESTER_ALLOCATOR=0; + +bool +MemTest::CpuPort::recvTiming(PacketPtr pkt) +{ + if (pkt->isResponse()) { + memtest->completeRequest(pkt); + } else { + // must be snoop upcall + assert(pkt->isRequest()); + assert(pkt->getDest() == Packet::Broadcast); + } + return true; +} + +Tick +MemTest::CpuPort::recvAtomic(PacketPtr pkt) +{ + // must be snoop upcall + assert(pkt->isRequest()); + assert(pkt->getDest() == Packet::Broadcast); + return curTick; +} + +void +MemTest::CpuPort::recvFunctional(PacketPtr pkt) +{ + //Do nothing if we see one come through +// if (curTick != 0)//Supress warning durring initialization +// warn("Functional Writes not implemented in MemTester\n"); + //Need to find any response values that intersect and update + return; +} + +void +MemTest::CpuPort::recvStatusChange(Status status) +{ + if (status == RangeChange) { + if (!snoopRangeSent) { + snoopRangeSent = true; + sendStatusChange(Port::RangeChange); + } + return; + } + + panic("MemTest doesn't expect recvStatusChange callback!"); +} + +void +MemTest::CpuPort::recvRetry() +{ + memtest->doRetry(); +} + +void +MemTest::sendPkt(PacketPtr pkt) { + if (atomic) { + cachePort.sendAtomic(pkt); + completeRequest(pkt); + } + else if (!cachePort.sendTiming(pkt)) { + DPRINTF(MemTest, "accessRetry setting to true\n"); + + // + // dma requests should never be retried + // + if (issueDmas) { + panic("Nacked DMA requests are not supported\n"); + } + accessRetry = true; + retryPkt = pkt; + } else { + if (issueDmas) { + dmaOutstanding = true; + } + } + +} + +MemTest::MemTest(const Params *p) + : MemObject(p), + tickEvent(this), + cachePort("test", this), + funcPort("functional", this), + retryPkt(NULL), +// mainMem(main_mem), +// checkMem(check_mem), + size(p->memory_size), + percentReads(p->percent_reads), + percentFunctional(p->percent_functional), + percentUncacheable(p->percent_uncacheable), + issueDmas(p->issue_dmas), + progressInterval(p->progress_interval), + nextProgressMessage(p->progress_interval), + percentSourceUnaligned(p->percent_source_unaligned), + percentDestUnaligned(p->percent_dest_unaligned), + maxLoads(p->max_loads), + atomic(p->atomic) +{ + + vector<string> cmd; + cmd.push_back("/bin/ls"); + vector<string> null_vec; + // thread = new SimpleThread(NULL, 0, NULL, 0, mainMem); + curTick = 0; + + cachePort.snoopRangeSent = false; + funcPort.snoopRangeSent = true; + + id = TESTER_ALLOCATOR++; + + // Needs to be masked off once we know the block size. + traceBlockAddr = p->trace_addr; + baseAddr1 = 0x100000; + baseAddr2 = 0x400000; + uncacheAddr = 0x800000; + + // set up counters + noResponseCycles = 0; + numReads = 0; + schedule(tickEvent, 0); + + accessRetry = false; + dmaOutstanding = 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); + + // initial memory contents for both physical memory and functional + // memory should be 0; no need to initialize them. +} + + +void +MemTest::completeRequest(PacketPtr pkt) +{ + Request *req = pkt->req; + + if (issueDmas) { + dmaOutstanding = false; + } + + DPRINTF(MemTest, "completing %s at address %x (blk %x)\n", + pkt->isWrite() ? "write" : "read", + req->getPaddr(), blockAddr(req->getPaddr())); + + MemTestSenderState *state = + dynamic_cast<MemTestSenderState *>(pkt->senderState); + + uint8_t *data = state->data; + uint8_t *pkt_data = pkt->getPtr<uint8_t>(); + + //Remove the address from the list of outstanding + std::set<unsigned>::iterator removeAddr = + outstandingAddrs.find(req->getPaddr()); + assert(removeAddr != outstandingAddrs.end()); + outstandingAddrs.erase(removeAddr); + + assert(pkt->isResponse()); + + if (pkt->isRead()) { + if (memcmp(pkt_data, data, pkt->getSize()) != 0) { + panic("%s: read of %x (blk %x) @ cycle %d " + "returns %x, expected %x\n", name(), + req->getPaddr(), blockAddr(req->getPaddr()), curTick, + *pkt_data, *data); + } + + numReads++; + numReadsStat++; + + if (numReads == (uint64_t)nextProgressMessage) { + ccprintf(cerr, "%s: completed %d read accesses @%d\n", + name(), numReads, curTick); + nextProgressMessage += progressInterval; + } + + if (maxLoads != 0 && numReads >= maxLoads) + exitSimLoop("maximum number of loads reached"); + } else { + assert(pkt->isWrite()); + numWritesStat++; + } + + 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") + ; + + numWritesStat + .name(name() + ".num_writes") + .desc("number of write accesses completed") + ; + + numCopiesStat + .name(name() + ".num_copies") + .desc("number of copy accesses completed") + ; +} + +void +MemTest::tick() +{ + if (!tickEvent.scheduled()) + schedule(tickEvent, curTick + ticks(1)); + + if (++noResponseCycles >= 500000) { + if (issueDmas) { + cerr << "DMA tester "; + } + cerr << name() << ": deadlocked at cycle " << curTick << endl; + fatal(""); + } + + if (accessRetry || (issueDmas && dmaOutstanding)) { + DPRINTF(MemTest, "MemTester waiting on accessRetry or DMA response\n"); + return; + } + + //make new request + unsigned cmd = random() % 100; + unsigned offset = random() % size; + unsigned base = random() % 2; + uint64_t data = random(); + unsigned access_size = random() % 4; + bool uncacheable = (random() % 100) < percentUncacheable; + + unsigned dma_access_size = random() % 4; + + //If we aren't doing copies, use id as offset, and do a false sharing + //mem tester + //We can eliminate the lower bits of the offset, and then use the id + //to offset within the blks + offset = blockAddr(offset); + offset += id; + access_size = 0; + dma_access_size = 0; + + Request *req = new Request(); + Request::Flags flags; + Addr paddr; + + if (uncacheable) { + flags.set(Request::UNCACHEABLE); + paddr = uncacheAddr + offset; + } else { + paddr = ((base) ? baseAddr1 : baseAddr2) + offset; + } + bool probe = (random() % 100 < percentFunctional) && !uncacheable; + + if (issueDmas) { + paddr &= ~((1 << dma_access_size) - 1); + req->setPhys(paddr, 1 << dma_access_size, flags); + req->setThreadContext(id,0); + } else { + paddr &= ~((1 << access_size) - 1); + req->setPhys(paddr, 1 << access_size, flags); + req->setThreadContext(id,0); + } + assert(req->getSize() == 1); + + uint8_t *result = new uint8_t[8]; + + if (cmd < percentReads) { + // read + + // For now we only allow one outstanding request per address + // per tester This means we assume CPU does write forwarding + // to reads that alias something in the cpu store buffer. + if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) { + delete [] result; + delete req; + return; + } + + outstandingAddrs.insert(paddr); + + // ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin + funcPort.readBlob(req->getPaddr(), result, req->getSize()); + + DPRINTF(MemTest, + "id %d initiating read at address %x (blk %x) expecting %x\n", + id, req->getPaddr(), blockAddr(req->getPaddr()), *result); + + PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); + pkt->setSrc(0); + pkt->dataDynamicArray(new uint8_t[req->getSize()]); + MemTestSenderState *state = new MemTestSenderState(result); + pkt->senderState = state; + + if (probe) { + cachePort.sendFunctional(pkt); + completeRequest(pkt); + } else { + sendPkt(pkt); + } + } 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(paddr) != outstandingAddrs.end()) { + delete [] result; + delete req; + return; + } + + outstandingAddrs.insert(paddr); + + DPRINTF(MemTest, "initiating write at address %x (blk %x) value %x\n", + req->getPaddr(), blockAddr(req->getPaddr()), data & 0xff); + + PacketPtr pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); + pkt->setSrc(0); + 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) { + cachePort.sendFunctional(pkt); + completeRequest(pkt); + } else { + sendPkt(pkt); + } + } +} + +void +MemTest::doRetry() +{ + if (cachePort.sendTiming(retryPkt)) { + DPRINTF(MemTest, "accessRetry setting to false\n"); + accessRetry = false; + retryPkt = NULL; + } +} + + +void +MemTest::printAddr(Addr a) +{ + cachePort.printAddr(a); +} + + +MemTest * +MemTestParams::create() +{ + return new MemTest(this); +} diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh new file mode 100644 index 000000000..bb71da355 --- /dev/null +++ b/src/cpu/testers/memtest/memtest.hh @@ -0,0 +1,198 @@ +/* + * 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 + * 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: Erik Hallnor + * Steve Reinhardt + */ + +#ifndef __CPU_MEMTEST_MEMTEST_HH__ +#define __CPU_MEMTEST_MEMTEST_HH__ + +#include <set> + +#include "base/statistics.hh" +#include "base/fast_alloc.hh" +#include "params/MemTest.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 Packet; +class MemTest : public MemObject +{ + public: + typedef MemTestParams Params; + MemTest(const Params *p); + + virtual void init(); + + // register statistics + virtual void regStats(); + + inline Tick ticks(int numCycles) const { return numCycles; } + + // main simulation loop (one cycle) + void tick(); + + virtual Port *getPort(const std::string &if_name, int idx = -1); + + /** + * Print state of address in memory system via PrintReq (for + * debugging). + */ + void printAddr(Addr a); + + protected: + class TickEvent : public Event + { + private: + MemTest *cpu; + + public: + TickEvent(MemTest *c) : Event(CPU_Tick_Pri), cpu(c) {} + void process() { cpu->tick(); } + virtual const char *description() const { return "MemTest tick"; } + }; + + TickEvent tickEvent; + + class CpuPort : public Port + { + MemTest *memtest; + + public: + + CpuPort(const std::string &_name, MemTest *_memtest) + : Port(_name, _memtest), memtest(_memtest) + { } + + bool snoopRangeSent; + + protected: + + virtual bool recvTiming(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt); + + virtual void recvFunctional(PacketPtr pkt); + + virtual void recvStatusChange(Status status); + + virtual void recvRetry(); + + virtual void getDeviceAddressRanges(AddrRangeList &resp, + bool &snoop) + { resp.clear(); snoop = false; } + }; + + CpuPort cachePort; + CpuPort funcPort; + + bool snoopRangeSent; + + class MemTestSenderState : public Packet::SenderState, public FastAlloc + { + public: + /** Constructor. */ + MemTestSenderState(uint8_t *_data) + : data(_data) + { } + + // Hold onto data pointer + uint8_t *data; + }; + + PacketPtr retryPkt; + + bool accessRetry; + + // + // The dmaOustanding flag enforces only one dma at a time + // + bool dmaOutstanding; + + unsigned size; // size of testing memory region + + unsigned percentReads; // target percentage of read accesses + unsigned percentFunctional; // target percentage of functional accesses + unsigned percentUncacheable; + + bool issueDmas; + + int id; + + std::set<unsigned> outstandingAddrs; + + unsigned blockSize; + + Addr blockAddrMask; + + Addr blockAddr(Addr addr) + { + return (addr & ~blockAddrMask); + } + + Addr traceBlockAddr; + + Addr baseAddr1; // fix this to option + Addr baseAddr2; // fix this to option + Addr uncacheAddr; + + unsigned progressInterval; // frequency of progress reports + Tick nextProgressMessage; // access # for next progress report + + unsigned percentSourceUnaligned; + unsigned percentDestUnaligned; + + Tick noResponseCycles; + + uint64_t numReads; + uint64_t maxLoads; + + bool atomic; + + Stats::Scalar numReadsStat; + Stats::Scalar numWritesStat; + Stats::Scalar numCopiesStat; + + // called by MemCompleteEvent::process() + void completeRequest(PacketPtr pkt); + + void sendPkt(PacketPtr pkt); + + void doRetry(); + + friend class MemCompleteEvent; +}; + +#endif // __CPU_MEMTEST_MEMTEST_HH__ + + + |