summaryrefslogtreecommitdiff
path: root/src/cpu/testers/memtest
diff options
context:
space:
mode:
authorBrad Beckmann <Brad.Beckmann@amd.com>2010-08-24 12:07:22 -0700
committerBrad Beckmann <Brad.Beckmann@amd.com>2010-08-24 12:07:22 -0700
commite983ef9e8c6749c1cd0bf083a2092cb4683d0346 (patch)
tree02d262e1b84e5c4675df54cb27678526f756169b /src/cpu/testers/memtest
parent20b2f0ce9f09bc4166bc3ee001eab4d6b2b84a04 (diff)
downloadgem5-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.py52
-rw-r--r--src/cpu/testers/memtest/SConscript38
-rw-r--r--src/cpu/testers/memtest/memtest.cc434
-rw-r--r--src/cpu/testers/memtest/memtest.hh198
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__
+
+
+