+++ /dev/null
-# Copyright (c) 2006-2007 The Regents of The University of Michigan
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# 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
-# Brad Beckmann
-
-import m5
-from m5.objects import *
-from m5.defines import buildEnv
-from m5.util import addToPath
-import os, optparse, sys
-addToPath('../common')
-addToPath('../ruby')
-
-import Ruby
-
-if buildEnv['FULL_SYSTEM']:
- panic("This script requires system-emulation mode (*_SE).")
-
-# Get paths we might need. It's expected this file is in m5/configs/example.
-config_path = os.path.dirname(os.path.abspath(__file__))
-config_root = os.path.dirname(config_path)
-m5_root = os.path.dirname(config_root)
-
-parser = optparse.OptionParser()
-
-parser.add_option("-l", "--requests", metavar="N", default=100,
- help="Stop after N requests")
-parser.add_option("-f", "--wakeup_freq", metavar="N", default=10,
- help="Wakeup every N cycles")
-parser.add_option("--test-type", type="string", default="SeriesGetx",
- help="SeriesGetx|SeriesGets|Invalidate")
-
-#
-# Add the ruby specific and protocol specific options
-#
-Ruby.define_options(parser)
-
-execfile(os.path.join(config_root, "common", "Options.py"))
-
-(options, args) = parser.parse_args()
-
-if args:
- print "Error: script doesn't take any positional arguments"
- sys.exit(1)
-
-#
-# Select the directed generator
-#
-if options.test_type == "SeriesGetx":
- generator = SeriesRequestGenerator(num_cpus = options.num_cpus,
- issue_writes = True)
-elif options.test_type == "SeriesGets":
- generator = SeriesRequestGenerator(num_cpus = options.num_cpus,
- issue_writes = False)
-elif options.test_type == "Invalidate":
- generator = InvalidateGenerator(num_cpus = options.num_cpus)
-else:
- print "Error: unknown directed generator"
- sys.exit(1)
-
-#
-# Create the M5 system. Note that the PhysicalMemory Object isn't
-# actually used by the rubytester, but is included to support the
-# M5 memory size == Ruby memory size checks
-#
-system = System(physmem = PhysicalMemory())
-
-#
-# Create the ruby random tester
-#
-system.tester = RubyDirectedTester(requests_to_complete = \
- options.requests,
- generator = generator)
-
-system.ruby = Ruby.create_system(options, system)
-
-assert(options.num_cpus == len(system.ruby.cpu_ruby_ports))
-
-for ruby_port in system.ruby.cpu_ruby_ports:
- #
- # Tie the ruby tester ports to the ruby cpu ports
- #
- system.tester.cpuPort = ruby_port.port
-
-# -----------------------
-# run simulation
-# -----------------------
-
-root = Root( system = system )
-root.system.mem_mode = 'timing'
-
-# Not much point in this being higher than the L1 latency
-m5.ticks.setGlobalFrequency('1ns')
-
-# instantiate configuration
-m5.instantiate()
-
-# simulate until program terminates
-exit_event = m5.simulate(options.maxtick)
-
-print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()
funcmem = PhysicalMemory(),
physmem = PhysicalMemory())
-system.dmas = [ MemTest(atomic = False, \
- max_loads = options.maxloads, \
- issue_dmas = True, \
- percent_functional = 0, \
- percent_uncacheable = 0, \
- progress_interval = options.progress) \
- for i in xrange(options.num_dmas) ]
+if options.num_dmas > 0:
+ dmas = [ MemTest(atomic = False, \
+ max_loads = options.maxloads, \
+ issue_dmas = True, \
+ percent_functional = 0, \
+ percent_uncacheable = 0, \
+ progress_interval = options.progress) \
+ for i in xrange(options.num_dmas) ]
+ system.dma_devices = dmas
+else:
+ dmas = []
system.ruby = Ruby.create_system(options, \
- system.physmem, \
- dma_devices = system.dmas)
+ system, \
+ dma_devices = dmas)
#
# The tester is most effective when randomization is turned on and
cpu.test = system.ruby.cpu_ruby_ports[i].port
cpu.functional = system.funcmem.port
-for (i, dma) in enumerate(system.dmas):
+for (i, dma) in enumerate(dmas):
#
# Tie the dma memtester ports to the correct functional port
# Note that the test port has already been connected to the dma_sequencer
--- /dev/null
+# Copyright (c) 2006-2007 The Regents of The University of Michigan
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# 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
+# Brad Beckmann
+
+import m5
+from m5.objects import *
+from m5.defines import buildEnv
+from m5.util import addToPath
+import os, optparse, sys
+addToPath('../common')
+addToPath('../ruby')
+
+import Ruby
+
+if buildEnv['FULL_SYSTEM']:
+ panic("This script requires system-emulation mode (*_SE).")
+
+# Get paths we might need. It's expected this file is in m5/configs/example.
+config_path = os.path.dirname(os.path.abspath(__file__))
+config_root = os.path.dirname(config_path)
+m5_root = os.path.dirname(config_root)
+
+parser = optparse.OptionParser()
+
+parser.add_option("-l", "--requests", metavar="N", default=100,
+ help="Stop after N requests")
+parser.add_option("-f", "--wakeup_freq", metavar="N", default=10,
+ help="Wakeup every N cycles")
+parser.add_option("--test-type", type="string", default="SeriesGetx",
+ help="SeriesGetx|SeriesGets|Invalidate")
+
+#
+# Add the ruby specific and protocol specific options
+#
+Ruby.define_options(parser)
+
+execfile(os.path.join(config_root, "common", "Options.py"))
+
+(options, args) = parser.parse_args()
+
+if args:
+ print "Error: script doesn't take any positional arguments"
+ sys.exit(1)
+
+#
+# Select the direct test generator
+#
+if options.test_type == "SeriesGetx":
+ generator = SeriesRequestGenerator(num_cpus = options.num_cpus,
+ issue_writes = True)
+elif options.test_type == "SeriesGets":
+ generator = SeriesRequestGenerator(num_cpus = options.num_cpus,
+ issue_writes = False)
+elif options.test_type == "Invalidate":
+ generator = InvalidateGenerator(num_cpus = options.num_cpus)
+else:
+ print "Error: unknown direct test generator"
+ sys.exit(1)
+
+#
+# Create the M5 system. Note that the PhysicalMemory Object isn't
+# actually used by the rubytester, but is included to support the
+# M5 memory size == Ruby memory size checks
+#
+system = System(physmem = PhysicalMemory())
+
+#
+# Create the ruby random tester
+#
+system.tester = RubyDirectedTester(requests_to_complete = \
+ options.requests,
+ generator = generator)
+
+system.ruby = Ruby.create_system(options, system)
+
+assert(options.num_cpus == len(system.ruby.cpu_ruby_ports))
+
+for ruby_port in system.ruby.cpu_ruby_ports:
+ #
+ # Tie the ruby tester ports to the ruby cpu ports
+ #
+ system.tester.cpuPort = ruby_port.port
+
+# -----------------------
+# run simulation
+# -----------------------
+
+root = Root( system = system )
+root.system.mem_mode = 'timing'
+
+# Not much point in this being higher than the L1 latency
+m5.ticks.setGlobalFrequency('1ns')
+
+# instantiate configuration
+m5.instantiate()
+
+# simulate until program terminates
+exit_event = m5.simulate(options.maxtick)
+
+print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()
# actually used by the rubytester, but is included to support the
# M5 memory size == Ruby memory size checks
#
-system = System(physmem = PhysicalMemory())
+system = System(tester = tester, physmem = PhysicalMemory())
system.ruby = Ruby.create_system(options, system)
exec("system.dma_cntrl%d = dma_cntrl" % i)
if dma_device.type == 'MemTest':
- system.dma_cntrl.dma_sequencer.port = dma_device.test
+ exec("system.dma_cntrl%d.dma_sequencer.port = dma_device.test" % i)
else:
- system.dma_cntrl.dma_sequencer.port = dma_device.dma
- dma_cntrl.dma_sequencer.port = dma_device.dma
+ exec("system.dma_cntrl%d.dma_sequencer.port = dma_device.dma" % i)
dma_cntrl_nodes.append(dma_cntrl)
if options.recycle_latency:
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "cpu/directedtest/DirectedGenerator.hh"
-
-DirectedGenerator::DirectedGenerator(const Params *p)
- : SimObject(p)
-{
- m_num_cpus = p->num_cpus;
- m_directed_tester = NULL;
-}
-
-void
-DirectedGenerator::setDirectedTester(RubyDirectedTester* directed_tester)
-{
- assert(m_directed_tester == NULL);
- m_directed_tester = directed_tester;
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * 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.
- */
-
-#ifndef __CPU_DIRECTEDTEST_DIRECTEDGENERATOR_HH__
-#define __CPU_DIRECTEDTEST_DIRECTEDGENERATOR_HH__
-
-#include "cpu/directedtest/DirectedGenerator.hh"
-#include "cpu/directedtest/RubyDirectedTester.hh"
-#include "params/DirectedGenerator.hh"
-#include "sim/sim_object.hh"
-
-class DirectedGenerator : public SimObject
-{
- public:
- typedef DirectedGeneratorParams Params;
- DirectedGenerator(const Params *p);
-
- virtual ~DirectedGenerator() {}
-
- virtual bool initiate() = 0;
- virtual void performCallback(uint proc, Addr address) = 0;
-
- void setDirectedTester(RubyDirectedTester* directed_tester);
-
- protected:
- int m_num_cpus;
- RubyDirectedTester* m_directed_tester;
-};
-
-#endif //__CPU_DIRECTEDTEST_DIRECTEDGENERATOR_HH__
-
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "cpu/directedtest/RubyDirectedTester.hh"
-#include "cpu/directedtest/DirectedGenerator.hh"
-#include "cpu/directedtest/InvalidateGenerator.hh"
-
-InvalidateGenerator::InvalidateGenerator(const Params *p)
- : DirectedGenerator(p)
-{
- //
- // First, issue loads to bring the block into S state
- //
- m_status = InvalidateGeneratorStatus_Load_Waiting;
- m_active_read_node = 0;
- m_active_inv_node = 0;
- m_address = 0x0;
- m_addr_increment_size = p->addr_increment_size;
-}
-
-InvalidateGenerator::~InvalidateGenerator()
-{
-}
-
-bool
-InvalidateGenerator::initiate()
-{
- RubyDirectedTester::CpuPort* port;
- Request::Flags flags;
- PacketPtr pkt;
- Packet::Command cmd;
-
- // For simplicity, requests are assumed to be 1 byte-sized
- Request *req = new Request(m_address, 1, flags);
-
- //
- // Based on the current state, issue a load or a store
- //
- if (m_status == InvalidateGeneratorStatus_Load_Waiting) {
- DPRINTF(DirectedTest, "initiating read\n");
- cmd = MemCmd::ReadReq;
- port = safe_cast<RubyDirectedTester::CpuPort*>(m_directed_tester->
- getCpuPort(m_active_read_node));
- pkt = new Packet(req, cmd, m_active_read_node);
- } else if (m_status == InvalidateGeneratorStatus_Inv_Waiting) {
- DPRINTF(DirectedTest, "initiating invalidating write\n");
- cmd = MemCmd::WriteReq;
- port = safe_cast<RubyDirectedTester::CpuPort*>(m_directed_tester->
- getCpuPort(m_active_inv_node));
- pkt = new Packet(req, cmd, m_active_inv_node);
- } else {
- panic("initiate was unexpectedly called\n");
- }
- uint8_t* dummyData = new uint8_t;
- *dummyData = 0;
- pkt->dataDynamic(dummyData);
-
- if (port->sendTiming(pkt)) {
- DPRINTF(DirectedTest, "initiating request - successful\n");
- if (m_status == InvalidateGeneratorStatus_Load_Waiting) {
- m_status = InvalidateGeneratorStatus_Load_Pending;
- } else {
- m_status = InvalidateGeneratorStatus_Inv_Pending;
- }
- return true;
- } else {
- // If the packet did not issue, must delete
- // Note: No need to delete the data, the packet destructor
- // will delete it
- delete pkt->req;
- delete pkt;
-
- DPRINTF(DirectedTest, "failed to issue request - sequencer not ready\n");
- return false;
- }
-}
-
-void
-InvalidateGenerator::performCallback(uint proc, Addr address)
-{
- assert(m_address == address);
-
- if (m_status == InvalidateGeneratorStatus_Load_Pending) {
- assert(m_active_read_node == proc);
- m_active_read_node++;
- //
- // Once all cpus have the block in S state, issue the invalidate
- //
- if (m_active_read_node == m_num_cpus) {
- m_status = InvalidateGeneratorStatus_Inv_Waiting;
- m_active_read_node = 0;
- } else {
- m_status = InvalidateGeneratorStatus_Load_Waiting;
- }
- } else if (m_status == InvalidateGeneratorStatus_Inv_Pending) {
- assert(m_active_inv_node == proc);
- m_active_inv_node++;
- if (m_active_inv_node == m_num_cpus) {
- m_address += m_addr_increment_size;
- m_active_inv_node = 0;
- }
- //
- // Invalidate completed, send that info to the tester and restart
- // the cycle
- //
- m_directed_tester->incrementCycleCompletions();
- m_status = InvalidateGeneratorStatus_Load_Waiting;
- }
-
-}
-
-InvalidateGenerator *
-InvalidateGeneratorParams::create()
-{
- return new InvalidateGenerator(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * 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.
- */
-
-//
-// This Directed Generator generates GETX requests for all nodes in the
-// system. The GETX requests are generated one at a time in round-robin fashion
-// 0...1...2...etc.
-//
-
-#ifndef __CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__
-#define __CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__
-
-#include "cpu/directedtest/RubyDirectedTester.hh"
-#include "cpu/directedtest/DirectedGenerator.hh"
-#include "mem/protocol/InvalidateGeneratorStatus.hh"
-#include "params/InvalidateGenerator.hh"
-
-class InvalidateGenerator : public DirectedGenerator
-{
- public:
- typedef InvalidateGeneratorParams Params;
- InvalidateGenerator(const Params *p);
-
- ~InvalidateGenerator();
-
- bool initiate();
- void performCallback(uint proc, Addr address);
-
- private:
- InvalidateGeneratorStatus m_status;
- Addr m_address;
- uint m_active_read_node;
- uint m_active_inv_node;
- uint m_addr_increment_size;
-};
-
-#endif //__CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__
-
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "cpu/directedtest/RubyDirectedTester.hh"
-#include "cpu/directedtest/DirectedGenerator.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "sim/sim_exit.hh"
-
-RubyDirectedTester::RubyDirectedTester(const Params *p)
- : MemObject(p), directedStartEvent(this),
- m_requests_to_complete(p->requests_to_complete),
- generator(p->generator)
-{
- m_requests_completed = 0;
-
- // add the check start event to the event queue
- schedule(directedStartEvent, 1);
-}
-
-RubyDirectedTester::~RubyDirectedTester()
-{
- for (int i = 0; i < ports.size(); i++)
- delete ports[i];
-}
-
-void
-RubyDirectedTester::init()
-{
- assert(ports.size() > 0);
- generator->setDirectedTester(this);
-}
-
-Port *
-RubyDirectedTester::getPort(const std::string &if_name, int idx)
-{
- if (if_name != "cpuPort") {
- panic("RubyDirectedTester::getPort: unknown port %s requested", if_name);
- }
-
- if (idx >= (int)ports.size()) {
- ports.resize(idx + 1);
- }
-
- if (ports[idx] != NULL) {
- panic("RubyDirectedTester::getPort: port %d already assigned", idx);
- }
-
- CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
-
- ports[idx] = port;
- return port;
-}
-
-Tick
-RubyDirectedTester::CpuPort::recvAtomic(PacketPtr pkt)
-{
- panic("RubyDirectedTester::CpuPort::recvAtomic() not implemented!\n");
- return 0;
-}
-
-bool
-RubyDirectedTester::CpuPort::recvTiming(PacketPtr pkt)
-{
- tester->hitCallback(idx, pkt->getAddr());
-
- //
- // Now that the tester has completed, delete the packet, then return
- //
- delete pkt->req;
- delete pkt;
- return true;
-}
-
-Port*
-RubyDirectedTester::getCpuPort(int idx)
-{
- assert(idx >= 0 && idx < ports.size());
-
- return ports[idx];
-}
-
-void
-RubyDirectedTester::hitCallback(NodeID proc, Addr addr)
-{
- DPRINTF(DirectedTest,
- "completed request for proc: %d addr: 0x%x\n",
- proc,
- addr);
-
- generator->performCallback(proc, addr);
- schedule(directedStartEvent, curTick);
-}
-
-void
-RubyDirectedTester::wakeup()
-{
- if (m_requests_completed < m_requests_to_complete) {
- if (!generator->initiate()) {
- schedule(directedStartEvent, curTick + 1);
- }
- } else {
- exitSimLoop("Ruby DirectedTester completed");
- }
-}
-
-RubyDirectedTester *
-RubyDirectedTesterParams::create()
-{
- return new RubyDirectedTester(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#ifndef __CPU_DIRECTEDTEST_RUBYDIRECTEDTESTER_HH__
-#define __CPU_DIRECTEDTEST_RUBYDIRECTEDTESTER_HH__
-
-#include <iostream>
-#include <vector>
-#include <string>
-
-#include "mem/mem_object.hh"
-#include "mem/packet.hh"
-#include "mem/ruby/common/DataBlock.hh"
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/system/RubyPort.hh"
-#include "params/RubyDirectedTester.hh"
-
-class DirectedGenerator;
-
-class RubyDirectedTester : public MemObject
-{
- public:
- class CpuPort : public SimpleTimingPort
- {
- private:
- RubyDirectedTester *tester;
-
- public:
- CpuPort(const std::string &_name, RubyDirectedTester *_tester, uint _idx)
- : SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx)
- {}
-
- uint idx;
-
- protected:
- virtual bool recvTiming(PacketPtr pkt);
- virtual Tick recvAtomic(PacketPtr pkt);
- };
-
- typedef RubyDirectedTesterParams Params;
- RubyDirectedTester(const Params *p);
- ~RubyDirectedTester();
-
- virtual Port *getPort(const std::string &if_name, int idx = -1);
-
- Port* getCpuPort(int idx);
-
- virtual void init();
-
- void wakeup();
-
- void incrementCycleCompletions() { m_requests_completed++; }
-
- void printStats(std::ostream& out) const {}
- void clearStats() {}
- void printConfig(std::ostream& out) const {}
-
- void print(std::ostream& out) const;
-
- protected:
- class DirectedStartEvent : public Event
- {
- private:
- RubyDirectedTester *tester;
-
- public:
- DirectedStartEvent(RubyDirectedTester *_tester)
- : Event(CPU_Tick_Pri), tester(_tester)
- {}
- void process() { tester->wakeup(); }
- virtual const char *description() const { return "Directed tick"; }
- };
-
- DirectedStartEvent directedStartEvent;
-
- private:
- void hitCallback(NodeID proc, Addr addr);
-
- void checkForDeadlock();
-
- // Private copy constructor and assignment operator
- RubyDirectedTester(const RubyDirectedTester& obj);
- RubyDirectedTester& operator=(const RubyDirectedTester& obj);
-
- uint64 m_requests_completed;
- std::vector<CpuPort*> ports;
- uint64 m_requests_to_complete;
- DirectedGenerator* generator;
-};
-
-#endif // __CPU_DIRECTEDTEST_RUBYDIRECTEDTESTER_HH__
+++ /dev/null
-# Copyright (c) 2010 Advanced Micro Devices, Inc.
-# 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: Brad Beckmann
-
-from m5.SimObject import SimObject
-from MemObject import MemObject
-from m5.params import *
-from m5.proxy import *
-
-class DirectedGenerator(SimObject):
- type = 'DirectedGenerator'
- abstract = True
- num_cpus = Param.Int("num of cpus")
-
-class SeriesRequestGenerator(DirectedGenerator):
- type = 'SeriesRequestGenerator'
- addr_increment_size = Param.Int(64, "address increment size")
- issue_writes = Param.Bool(True, "issue writes if true, otherwise reads")
-
-class InvalidateGenerator(DirectedGenerator):
- type = 'InvalidateGenerator'
- addr_increment_size = Param.Int(64, "address increment size")
-
-class RubyDirectedTester(MemObject):
- type = 'RubyDirectedTester'
- cpuPort = VectorPort("the cpu ports")
- requests_to_complete = Param.Int("checks to complete")
- generator = Param.DirectedGenerator("the request generator")
+++ /dev/null
-# -*- mode:python -*-
-
-# Copyright (c) 2006 The Regents of The University of Michigan
-# Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
-# 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.
-#
-
-Import('*')
-
-#
-# Currently the ruby testser relies on Ruby specific objects (SubBlock, etc.)
-# When this dependency is removed, the ruby tester should be compiled
-# independently from Ruby
-#
-if not env['RUBY']:
- Return()
-
-SimObject('RubyDirectedTester.py')
-
-Source('RubyDirectedTester.cc')
-Source('DirectedGenerator.cc')
-Source('SeriesRequestGenerator.cc')
-Source('InvalidateGenerator.cc')
-
-TraceFlag('DirectedTest')
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "cpu/directedtest/RubyDirectedTester.hh"
-#include "cpu/directedtest/DirectedGenerator.hh"
-#include "cpu/directedtest/SeriesRequestGenerator.hh"
-
-SeriesRequestGenerator::SeriesRequestGenerator(const Params *p)
- : DirectedGenerator(p)
-{
- m_status = SeriesRequestGeneratorStatus_Thinking;
- m_active_node = 0;
- m_address = 0x0;
- m_addr_increment_size = p->addr_increment_size;
- m_issue_writes = p->issue_writes;
-}
-
-SeriesRequestGenerator::~SeriesRequestGenerator()
-{
-}
-
-bool
-SeriesRequestGenerator::initiate()
-{
- DPRINTF(DirectedTest, "initiating request\n");
- assert(m_status == SeriesRequestGeneratorStatus_Thinking);
-
- RubyDirectedTester::CpuPort* port =
- safe_cast<RubyDirectedTester::CpuPort*>(m_directed_tester->
- getCpuPort(m_active_node));
-
- Request::Flags flags;
-
- // For simplicity, requests are assumed to be 1 byte-sized
- Request *req = new Request(m_address, 1, flags);
-
- Packet::Command cmd;
- if (m_issue_writes) {
- cmd = MemCmd::WriteReq;
- } else {
- cmd = MemCmd::ReadReq;
- }
- PacketPtr pkt = new Packet(req, cmd, m_active_node);
- uint8_t* dummyData = new uint8_t;
- *dummyData = 0;
- pkt->dataDynamic(dummyData);
-
- if (port->sendTiming(pkt)) {
- DPRINTF(DirectedTest, "initiating request - successful\n");
- m_status = SeriesRequestGeneratorStatus_Request_Pending;
- return true;
- } else {
- // If the packet did not issue, must delete
- // Note: No need to delete the data, the packet destructor
- // will delete it
- delete pkt->req;
- delete pkt;
-
- DPRINTF(DirectedTest, "failed to initiate request - sequencer not ready\n");
- return false;
- }
-}
-
-void
-SeriesRequestGenerator::performCallback(uint proc, Addr address)
-{
- assert(m_active_node == proc);
- assert(m_address == address);
- assert(m_status == SeriesRequestGeneratorStatus_Request_Pending);
-
- m_status = SeriesRequestGeneratorStatus_Thinking;
- m_active_node++;
- if (m_active_node == m_num_cpus) {
- //
- // Cycle of requests completed, increment cycle completions and restart
- // at cpu zero
- //
- m_directed_tester->incrementCycleCompletions();
- m_address += m_addr_increment_size;
- m_active_node = 0;
- }
-}
-
-SeriesRequestGenerator *
-SeriesRequestGeneratorParams::create()
-{
- return new SeriesRequestGenerator(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * 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.
- */
-
-//
-// This Deterministic Generator generates GETX requests for all nodes in the
-// system. The GETX requests are generated one at a time in round-robin fashion
-// 0...1...2...etc.
-//
-
-#ifndef __CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__
-#define __CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__
-
-#include "cpu/directedtest/RubyDirectedTester.hh"
-#include "cpu/directedtest/DirectedGenerator.hh"
-#include "mem/protocol/SeriesRequestGeneratorStatus.hh"
-#include "params/SeriesRequestGenerator.hh"
-
-class SeriesRequestGenerator : public DirectedGenerator
-{
- public:
- typedef SeriesRequestGeneratorParams Params;
- SeriesRequestGenerator(const Params *p);
-
- ~SeriesRequestGenerator();
-
- bool initiate();
- void performCallback(uint proc, Addr address);
-
- private:
- SeriesRequestGeneratorStatus m_status;
- Addr m_address;
- uint m_active_node;
- uint m_addr_increment_size;
- bool m_issue_writes;
-};
-
-#endif //__CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__
-
+++ /dev/null
-# 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")
+++ /dev/null
-# -*- 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')
+++ /dev/null
-/*
- * 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/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);
-}
+++ /dev/null
-/*
- * 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__
-
-
-
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "cpu/rubytest/Check.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-
-typedef RubyTester::SenderState SenderState;
-
-Check::Check(const Address& address, const Address& pc,
- int _num_cpu_sequencers, RubyTester* _tester)
- : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
-{
- m_status = TesterStatus_Idle;
-
- pickValue();
- pickInitiatingNode();
- changeAddress(address);
- m_pc = pc;
- m_access_mode = AccessModeType(random() % AccessModeType_NUM);
- m_store_count = 0;
-}
-
-void
-Check::initiate()
-{
- DPRINTF(RubyTest, "initiating\n");
- debugPrint();
-
- // currently no protocols support prefetches
- if (false && (random() & 0xf) == 0) {
- initiatePrefetch(); // Prefetch from random processor
- }
-
- if (m_status == TesterStatus_Idle) {
- initiateAction();
- } else if (m_status == TesterStatus_Ready) {
- initiateCheck();
- } else {
- // Pending - do nothing
- DPRINTF(RubyTest,
- "initiating action/check - failed: action/check is pending\n");
- }
-}
-
-void
-Check::initiatePrefetch()
-{
- DPRINTF(RubyTest, "initiating prefetch\n");
-
- int index = random() % m_num_cpu_sequencers;
- RubyTester::CpuPort* port =
- safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
-
- Request::Flags flags;
- flags.set(Request::PREFETCH);
-
- Packet::Command cmd;
-
- // 1 in 8 chance this will be an exclusive prefetch
- if ((random() & 0x7) != 0) {
- cmd = MemCmd::ReadReq;
-
- // 50% chance that the request will be an instruction fetch
- if ((random() & 0x1) == 0) {
- flags.set(Request::INST_FETCH);
- }
- } else {
- cmd = MemCmd::WriteReq;
- flags.set(Request::PF_EXCLUSIVE);
- }
-
- // Prefetches are assumed to be 0 sized
- Request *req = new Request(m_address.getAddress(), 0, flags, curTick,
- m_pc.getAddress());
-
- PacketPtr pkt = new Packet(req, cmd, port->idx);
-
- // push the subblock onto the sender state. The sequencer will
- // update the subblock on the return
- pkt->senderState =
- new SenderState(m_address, req->getSize(), pkt->senderState);
-
- if (port->sendTiming(pkt)) {
- DPRINTF(RubyTest, "successfully initiated prefetch.\n");
- } else {
- // If the packet did not issue, must delete
- SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
- pkt->senderState = senderState->saved;
- delete senderState;
- delete pkt->req;
- delete pkt;
-
- DPRINTF(RubyTest,
- "prefetch initiation failed because Port was busy.\n");
- }
-}
-
-void
-Check::initiateAction()
-{
- DPRINTF(RubyTest, "initiating Action\n");
- assert(m_status == TesterStatus_Idle);
-
- int index = random() % m_num_cpu_sequencers;
- RubyTester::CpuPort* port =
- safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
-
- Request::Flags flags;
-
- // Create the particular address for the next byte to be written
- Address writeAddr(m_address.getAddress() + m_store_count);
-
- // Stores are assumed to be 1 byte-sized
- Request *req = new Request(writeAddr.getAddress(), 1, flags, curTick,
- m_pc.getAddress());
-
- Packet::Command cmd;
-
- // 1 out of 8 chance, issue an atomic rather than a write
- // if ((random() & 0x7) == 0) {
- // cmd = MemCmd::SwapReq;
- // } else {
- cmd = MemCmd::WriteReq;
- // }
-
- PacketPtr pkt = new Packet(req, cmd, port->idx);
- uint8_t* writeData = new uint8_t;
- *writeData = m_value + m_store_count;
- pkt->dataDynamic(writeData);
-
- DPRINTF(RubyTest, "data 0x%x check 0x%x\n",
- *(pkt->getPtr<uint8_t>()), *writeData);
-
- // push the subblock onto the sender state. The sequencer will
- // update the subblock on the return
- pkt->senderState =
- new SenderState(writeAddr, req->getSize(), pkt->senderState);
-
- if (port->sendTiming(pkt)) {
- DPRINTF(RubyTest, "initiating action - successful\n");
- DPRINTF(RubyTest, "status before action update: %s\n",
- (TesterStatus_to_string(m_status)).c_str());
- m_status = TesterStatus_Action_Pending;
- } else {
- // If the packet did not issue, must delete
- // Note: No need to delete the data, the packet destructor
- // will delete it
- SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
- pkt->senderState = senderState->saved;
- delete senderState;
- delete pkt->req;
- delete pkt;
-
- DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n");
- }
-
- DPRINTF(RubyTest, "status after action update: %s\n",
- (TesterStatus_to_string(m_status)).c_str());
-}
-
-void
-Check::initiateCheck()
-{
- DPRINTF(RubyTest, "Initiating Check\n");
- assert(m_status == TesterStatus_Ready);
-
- int index = random() % m_num_cpu_sequencers;
- RubyTester::CpuPort* port =
- safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
-
- Request::Flags flags;
-
- // 50% chance that the request will be an instruction fetch
- if ((random() & 0x1) == 0) {
- flags.set(Request::INST_FETCH);
- }
-
- // Checks are sized depending on the number of bytes written
- Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags,
- curTick, m_pc.getAddress());
-
- PacketPtr pkt = new Packet(req, MemCmd::ReadReq, port->idx);
- uint8_t* dataArray = new uint8_t[CHECK_SIZE];
- pkt->dataDynamicArray(dataArray);
-
- // push the subblock onto the sender state. The sequencer will
- // update the subblock on the return
- pkt->senderState =
- new SenderState(m_address, req->getSize(), pkt->senderState);
-
- if (port->sendTiming(pkt)) {
- DPRINTF(RubyTest, "initiating check - successful\n");
- DPRINTF(RubyTest, "status before check update: %s\n",
- TesterStatus_to_string(m_status).c_str());
- m_status = TesterStatus_Check_Pending;
- } else {
- // If the packet did not issue, must delete
- // Note: No need to delete the data, the packet destructor
- // will delete it
- SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
- pkt->senderState = senderState->saved;
- delete senderState;
- delete pkt->req;
- delete pkt;
-
- DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n");
- }
-
- DPRINTF(RubyTest, "status after check update: %s\n",
- TesterStatus_to_string(m_status).c_str());
-}
-
-void
-Check::performCallback(NodeID proc, SubBlock* data)
-{
- Address address = data->getAddress();
-
- // This isn't exactly right since we now have multi-byte checks
- // assert(getAddress() == address);
-
- assert(getAddress().getLineAddress() == address.getLineAddress());
- assert(data != NULL);
-
- DPRINTF(RubyTest, "RubyTester Callback\n");
- debugPrint();
-
- if (m_status == TesterStatus_Action_Pending) {
- DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n",
- (m_value + m_store_count), data->getByte(0));
- // Perform store one byte at a time
- data->setByte(0, (m_value + m_store_count));
- m_store_count++;
- if (m_store_count == CHECK_SIZE) {
- m_status = TesterStatus_Ready;
- } else {
- m_status = TesterStatus_Idle;
- }
- DPRINTF(RubyTest, "Action callback return data now %d\n",
- data->getByte(0));
- } else if (m_status == TesterStatus_Check_Pending) {
- DPRINTF(RubyTest, "Check callback\n");
- // Perform load/check
- for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
- if (uint8(m_value + byte_number) != data->getByte(byte_number)) {
- WARN_EXPR(proc);
- WARN_EXPR(address);
- WARN_EXPR(data);
- WARN_EXPR(byte_number);
- WARN_EXPR((int)m_value + byte_number);
- WARN_EXPR((int)data->getByte(byte_number));
- WARN_EXPR(*this);
- WARN_EXPR(g_eventQueue_ptr->getTime());
- ERROR_MSG("Action/check failure");
- }
- }
- DPRINTF(RubyTest, "Action/check success\n");
- debugPrint();
-
- // successful check complete, increment complete
- m_tester_ptr->incrementCheckCompletions();
-
- m_status = TesterStatus_Idle;
- pickValue();
-
- } else {
- WARN_EXPR(*this);
- WARN_EXPR(proc);
- WARN_EXPR(data);
- WARN_EXPR(m_status);
- WARN_EXPR(g_eventQueue_ptr->getTime());
- ERROR_MSG("Unexpected TesterStatus");
- }
-
- DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc,
- getAddress().getLineAddress());
- DPRINTF(RubyTest, "Callback done\n");
- debugPrint();
-}
-
-void
-Check::changeAddress(const Address& address)
-{
- assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
- m_status = TesterStatus_Idle;
- m_address = address;
- m_store_count = 0;
-}
-
-void
-Check::pickValue()
-{
- assert(m_status == TesterStatus_Idle);
- m_status = TesterStatus_Idle;
- m_value = random() & 0xff; // One byte
- m_store_count = 0;
-}
-
-void
-Check::pickInitiatingNode()
-{
- assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
- m_status = TesterStatus_Idle;
- m_initiatingNode = (random() % m_num_cpu_sequencers);
- DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode);
- m_store_count = 0;
-}
-
-void
-Check::print(std::ostream& out) const
-{
- out << "["
- << m_address << ", value: "
- << (int)m_value << ", status: "
- << m_status << ", initiating node: "
- << m_initiatingNode << ", store_count: "
- << m_store_count
- << "]" << std::flush;
-}
-
-void
-Check::debugPrint()
-{
- DPRINTF(RubyTest,
- "[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n",
- m_address.getAddress(), (int)m_value,
- TesterStatus_to_string(m_status).c_str(),
- m_initiatingNode, m_store_count);
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#ifndef __CPU_RUBYTEST_CHECK_HH__
-#define __CPU_RUBYTEST_CHECK_HH__
-
-#include <iostream>
-
-#include "cpu/rubytest/RubyTester.hh"
-#include "mem/protocol/AccessModeType.hh"
-#include "mem/protocol/TesterStatus.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/NodeID.hh"
-
-class SubBlock;
-
-const int CHECK_SIZE_BITS = 2;
-const int CHECK_SIZE = (1 << CHECK_SIZE_BITS);
-
-class Check
-{
- public:
- Check(const Address& address, const Address& pc, int _num_cpu_sequencer,
- RubyTester* _tester);
-
- void initiate(); // Does Action or Check or nether
- void performCallback(NodeID proc, SubBlock* data);
- const Address& getAddress() { return m_address; }
- void changeAddress(const Address& address);
-
- void print(std::ostream& out) const;
-
- private:
- void initiatePrefetch();
- void initiateAction();
- void initiateCheck();
-
- void pickValue();
- void pickInitiatingNode();
-
- void debugPrint();
-
- TesterStatus m_status;
- uint8 m_value;
- int m_store_count;
- NodeID m_initiatingNode;
- Address m_address;
- Address m_pc;
- AccessModeType m_access_mode;
- int m_num_cpu_sequencers;
- RubyTester* m_tester_ptr;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const Check& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif // __CPU_RUBYTEST_CHECK_HH__
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "base/intmath.hh"
-#include "cpu/rubytest/Check.hh"
-#include "cpu/rubytest/CheckTable.hh"
-#include "cpu/rubytest/CheckTable.hh"
-
-CheckTable::CheckTable(int _num_cpu_sequencers, RubyTester* _tester)
- : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
-{
- physical_address_t physical = 0;
- Address address;
-
- const int size1 = 32;
- const int size2 = 100;
-
- // The first set is to get some false sharing
- physical = 1000;
- for (int i = 0; i < size1; i++) {
- // Setup linear addresses
- address.setAddress(physical);
- addCheck(address);
- physical += CHECK_SIZE;
- }
-
- // The next two sets are to get some limited false sharing and
- // cache conflicts
- physical = 1000;
- for (int i = 0; i < size2; i++) {
- // Setup linear addresses
- address.setAddress(physical);
- addCheck(address);
- physical += 256;
- }
-
- physical = 1000 + CHECK_SIZE;
- for (int i = 0; i < size2; i++) {
- // Setup linear addresses
- address.setAddress(physical);
- addCheck(address);
- physical += 256;
- }
-}
-
-CheckTable::~CheckTable()
-{
- int size = m_check_vector.size();
- for (int i = 0; i < size; i++)
- delete m_check_vector[i];
-}
-
-void
-CheckTable::addCheck(const Address& address)
-{
- if (floorLog2(CHECK_SIZE) != 0) {
- if (address.bitSelect(0, CHECK_SIZE_BITS - 1) != 0) {
- ERROR_MSG("Check not aligned");
- }
- }
-
- for (int i = 0; i < CHECK_SIZE; i++) {
- if (m_lookup_map.count(Address(address.getAddress()+i))) {
- // A mapping for this byte already existed, discard the
- // entire check
- return;
- }
- }
-
- Check* check_ptr = new Check(address, Address(100 + m_check_vector.size()),
- m_num_cpu_sequencers, m_tester_ptr);
- for (int i = 0; i < CHECK_SIZE; i++) {
- // Insert it once per byte
- m_lookup_map[Address(address.getAddress() + i)] = check_ptr;
- }
- m_check_vector.push_back(check_ptr);
-}
-
-Check*
-CheckTable::getRandomCheck()
-{
- return m_check_vector[random() % m_check_vector.size()];
-}
-
-Check*
-CheckTable::getCheck(const Address& address)
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "Looking for check by address");
- DEBUG_EXPR(TESTER_COMP, MedPrio, address);
-
- m5::hash_map<Address, Check*>::iterator i = m_lookup_map.find(address);
-
- if (i == m_lookup_map.end())
- return NULL;
-
- Check* check = i->second;
- assert(check != NULL);
- return check;
-}
-
-void
-CheckTable::print(std::ostream& out) const
-{
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#ifndef __CPU_RUBYTEST_CHECKTABLE_HH__
-#define __CPU_RUBYTEST_CHECKTABLE_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "base/hashmap.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/common/Global.hh"
-
-class Check;
-class RubyTester;
-
-class CheckTable
-{
- public:
- CheckTable(int _num_cpu_sequencers, RubyTester* _tester);
- ~CheckTable();
-
- Check* getRandomCheck();
- Check* getCheck(const Address& address);
-
- // bool isPresent(const Address& address) const;
- // void removeCheckFromTable(const Address& address);
- // bool isTableFull() const;
- // Need a method to select a check or retrieve a check
-
- void print(std::ostream& out) const;
-
- private:
- void addCheck(const Address& address);
-
- // Private copy constructor and assignment operator
- CheckTable(const CheckTable& obj);
- CheckTable& operator=(const CheckTable& obj);
-
- std::vector<Check*> m_check_vector;
- m5::hash_map<Address, Check*> m_lookup_map;
-
- int m_num_cpu_sequencers;
- RubyTester* m_tester_ptr;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const CheckTable& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif // __CPU_RUBYTEST_CHECKTABLE_HH__
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#include "cpu/rubytest/Check.hh"
-#include "cpu/rubytest/RubyTester.hh"
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/system/System.hh"
-#include "sim/sim_exit.hh"
-
-RubyTester::RubyTester(const Params *p)
- : MemObject(p), checkStartEvent(this),
- m_checks_to_complete(p->checks_to_complete),
- m_deadlock_threshold(p->deadlock_threshold),
- m_wakeup_frequency(p->wakeup_frequency)
-{
- m_checks_completed = 0;
-
- // add the check start event to the event queue
- schedule(checkStartEvent, 1);
-}
-
-RubyTester::~RubyTester()
-{
- delete m_checkTable_ptr;
- for (int i = 0; i < ports.size(); i++)
- delete ports[i];
-}
-
-void
-RubyTester::init()
-{
- assert(ports.size() > 0);
-
- m_last_progress_vector.resize(ports.size());
- for (int i = 0; i < m_last_progress_vector.size(); i++) {
- m_last_progress_vector[i] = 0;
- }
-
- m_num_cpu_sequencers = ports.size();
-
- m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this);
-}
-
-Port *
-RubyTester::getPort(const std::string &if_name, int idx)
-{
- if (if_name != "cpuPort") {
- panic("RubyTester::getPort: unknown port %s requested", if_name);
- }
-
- if (idx >= (int)ports.size()) {
- ports.resize(idx + 1);
- }
-
- if (ports[idx] != NULL) {
- panic("RubyTester::getPort: port %d already assigned", idx);
- }
-
- CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
-
- ports[idx] = port;
- return port;
-}
-
-Tick
-RubyTester::CpuPort::recvAtomic(PacketPtr pkt)
-{
- panic("RubyTester::CpuPort::recvAtomic() not implemented!\n");
- return 0;
-}
-
-bool
-RubyTester::CpuPort::recvTiming(PacketPtr pkt)
-{
- // retrieve the subblock and call hitCallback
- RubyTester::SenderState* senderState =
- safe_cast<RubyTester::SenderState*>(pkt->senderState);
- SubBlock* subblock = senderState->subBlock;
- assert(subblock != NULL);
-
- // pop the sender state from the packet
- pkt->senderState = senderState->saved;
-
- tester->hitCallback(idx, subblock);
-
- // Now that the tester has completed, delete the senderState
- // (includes sublock) and the packet, then return
- delete senderState;
- delete pkt->req;
- delete pkt;
- return true;
-}
-
-Port*
-RubyTester::getCpuPort(int idx)
-{
- assert(idx >= 0 && idx < ports.size());
-
- return ports[idx];
-}
-
-void
-RubyTester::hitCallback(NodeID proc, SubBlock* data)
-{
- // Mark that we made progress
- m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
-
- DPRINTF(RubyTest, "completed request for proc: %d\n", proc);
- DPRINTF(RubyTest, "addr: 0x%x, size: %d, data: ",
- data->getAddress(), data->getSize());
- for (int byte = 0; byte < data->getSize(); byte++) {
- DPRINTF(RubyTest, "%d", data->getByte(byte));
- }
- DPRINTF(RubyTest, "\n");
-
- // This tells us our store has 'completed' or for a load gives us
- // back the data to make the check
- Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
- assert(check_ptr != NULL);
- check_ptr->performCallback(proc, data);
-}
-
-void
-RubyTester::wakeup()
-{
- if (m_checks_completed < m_checks_to_complete) {
- // Try to perform an action or check
- Check* check_ptr = m_checkTable_ptr->getRandomCheck();
- assert(check_ptr != NULL);
- check_ptr->initiate();
-
- checkForDeadlock();
-
- schedule(checkStartEvent, curTick + m_wakeup_frequency);
- } else {
- exitSimLoop("Ruby Tester completed");
- }
-}
-
-void
-RubyTester::checkForDeadlock()
-{
- int size = m_last_progress_vector.size();
- Time current_time = g_eventQueue_ptr->getTime();
- for (int processor = 0; processor < size; processor++) {
- if ((current_time - m_last_progress_vector[processor]) >
- m_deadlock_threshold) {
- WARN_EXPR(current_time);
- WARN_EXPR(m_last_progress_vector[processor]);
- WARN_EXPR(current_time - m_last_progress_vector[processor]);
- WARN_EXPR(processor);
- ERROR_MSG("Deadlock detected.");
- }
- }
-}
-
-void
-RubyTester::print(std::ostream& out) const
-{
- out << "[RubyTester]" << std::endl;
-}
-
-RubyTester *
-RubyTesterParams::create()
-{
- return new RubyTester(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
- * 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.
- */
-
-#ifndef __CPU_RUBYTEST_RUBYTESTER_HH__
-#define __CPU_RUBYTEST_RUBYTESTER_HH__
-
-#include <iostream>
-#include <vector>
-#include <string>
-
-#include "cpu/rubytest/CheckTable.hh"
-#include "mem/mem_object.hh"
-#include "mem/packet.hh"
-#include "mem/ruby/common/DataBlock.hh"
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/system/RubyPort.hh"
-#include "params/RubyTester.hh"
-
-class RubyTester : public MemObject
-{
- public:
- class CpuPort : public SimpleTimingPort
- {
- private:
- RubyTester *tester;
-
- public:
- CpuPort(const std::string &_name, RubyTester *_tester, int _idx)
- : SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx)
- {}
-
- int idx;
-
- protected:
- virtual bool recvTiming(PacketPtr pkt);
- virtual Tick recvAtomic(PacketPtr pkt);
- };
-
- struct SenderState : public Packet::SenderState
- {
- SubBlock* subBlock;
- Packet::SenderState *saved;
-
- SenderState(Address addr, int size,
- Packet::SenderState *sender_state = NULL)
- : saved(sender_state)
- {
- subBlock = new SubBlock(addr, size);
- }
-
- ~SenderState()
- {
- delete subBlock;
- }
- };
-
- typedef RubyTesterParams Params;
- RubyTester(const Params *p);
- ~RubyTester();
-
- virtual Port *getPort(const std::string &if_name, int idx = -1);
-
- Port* getCpuPort(int idx);
-
- virtual void init();
-
- void wakeup();
-
- void incrementCheckCompletions() { m_checks_completed++; }
-
- void printStats(std::ostream& out) const {}
- void clearStats() {}
- void printConfig(std::ostream& out) const {}
-
- void print(std::ostream& out) const;
-
- protected:
- class CheckStartEvent : public Event
- {
- private:
- RubyTester *tester;
-
- public:
- CheckStartEvent(RubyTester *_tester)
- : Event(CPU_Tick_Pri), tester(_tester)
- {}
- void process() { tester->wakeup(); }
- virtual const char *description() const { return "RubyTester tick"; }
- };
-
- CheckStartEvent checkStartEvent;
-
- private:
- void hitCallback(NodeID proc, SubBlock* data);
-
- void checkForDeadlock();
-
- // Private copy constructor and assignment operator
- RubyTester(const RubyTester& obj);
- RubyTester& operator=(const RubyTester& obj);
-
- CheckTable* m_checkTable_ptr;
- std::vector<Time> m_last_progress_vector;
-
- uint64 m_checks_completed;
- std::vector<CpuPort*> ports;
- uint64 m_checks_to_complete;
- int m_deadlock_threshold;
- int m_num_cpu_sequencers;
- int m_wakeup_frequency;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const RubyTester& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif // __CPU_RUBYTEST_RUBYTESTER_HH__
+++ /dev/null
-# Copyright (c) 2005-2007 The Regents of The University of Michigan
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# 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.
-#
-
-from MemObject import MemObject
-from m5.params import *
-from m5.proxy import *
-
-class RubyTester(MemObject):
- type = 'RubyTester'
- cpuPort = VectorPort("the cpu ports")
- checks_to_complete = Param.Int(100, "checks to complete")
- deadlock_threshold = Param.Int(50000, "how often to check for deadlock")
- wakeup_frequency = Param.Int(10, "number of cycles between wakeups")
+++ /dev/null
-# -*- mode:python -*-
-
-# Copyright (c) 2006 The Regents of The University of Michigan
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# 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.
-#
-
-Import('*')
-
-#
-# Currently the ruby testser relies on Ruby specific objects (SubBlock, etc.)
-# When this dependency is removed, the ruby tester should be compiled
-# independently from Ruby
-#
-if not env['RUBY']:
- Return()
-
-SimObject('RubyTester.py')
-
-Source('RubyTester.cc')
-Source('Check.cc')
-Source('CheckTable.cc')
-
-TraceFlag('RubyTest')
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+
+DirectedGenerator::DirectedGenerator(const Params *p)
+ : SimObject(p)
+{
+ m_num_cpus = p->num_cpus;
+ m_directed_tester = NULL;
+}
+
+void
+DirectedGenerator::setDirectedTester(RubyDirectedTester* directed_tester)
+{
+ assert(m_directed_tester == NULL);
+ m_directed_tester = directed_tester;
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * 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.
+ */
+
+#ifndef __CPU_DIRECTEDTEST_DIRECTEDGENERATOR_HH__
+#define __CPU_DIRECTEDTEST_DIRECTEDGENERATOR_HH__
+
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "cpu/testers/directedtest/RubyDirectedTester.hh"
+#include "params/DirectedGenerator.hh"
+#include "sim/sim_object.hh"
+
+class DirectedGenerator : public SimObject
+{
+ public:
+ typedef DirectedGeneratorParams Params;
+ DirectedGenerator(const Params *p);
+
+ virtual ~DirectedGenerator() {}
+
+ virtual bool initiate() = 0;
+ virtual void performCallback(uint proc, Addr address) = 0;
+
+ void setDirectedTester(RubyDirectedTester* directed_tester);
+
+ protected:
+ int m_num_cpus;
+ RubyDirectedTester* m_directed_tester;
+};
+
+#endif //__CPU_DIRECTEDTEST_DIRECTEDGENERATOR_HH__
+
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "cpu/testers/directedtest/RubyDirectedTester.hh"
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "cpu/testers/directedtest/InvalidateGenerator.hh"
+
+InvalidateGenerator::InvalidateGenerator(const Params *p)
+ : DirectedGenerator(p)
+{
+ //
+ // First, issue loads to bring the block into S state
+ //
+ m_status = InvalidateGeneratorStatus_Load_Waiting;
+ m_active_read_node = 0;
+ m_active_inv_node = 0;
+ m_address = 0x0;
+ m_addr_increment_size = p->addr_increment_size;
+}
+
+InvalidateGenerator::~InvalidateGenerator()
+{
+}
+
+bool
+InvalidateGenerator::initiate()
+{
+ RubyDirectedTester::CpuPort* port;
+ Request::Flags flags;
+ PacketPtr pkt;
+ Packet::Command cmd;
+
+ // For simplicity, requests are assumed to be 1 byte-sized
+ Request *req = new Request(m_address, 1, flags);
+
+ //
+ // Based on the current state, issue a load or a store
+ //
+ if (m_status == InvalidateGeneratorStatus_Load_Waiting) {
+ DPRINTF(DirectedTest, "initiating read\n");
+ cmd = MemCmd::ReadReq;
+ port = safe_cast<RubyDirectedTester::CpuPort*>(m_directed_tester->
+ getCpuPort(m_active_read_node));
+ pkt = new Packet(req, cmd, m_active_read_node);
+ } else if (m_status == InvalidateGeneratorStatus_Inv_Waiting) {
+ DPRINTF(DirectedTest, "initiating invalidating write\n");
+ cmd = MemCmd::WriteReq;
+ port = safe_cast<RubyDirectedTester::CpuPort*>(m_directed_tester->
+ getCpuPort(m_active_inv_node));
+ pkt = new Packet(req, cmd, m_active_inv_node);
+ } else {
+ panic("initiate was unexpectedly called\n");
+ }
+ uint8_t* dummyData = new uint8_t;
+ *dummyData = 0;
+ pkt->dataDynamic(dummyData);
+
+ if (port->sendTiming(pkt)) {
+ DPRINTF(DirectedTest, "initiating request - successful\n");
+ if (m_status == InvalidateGeneratorStatus_Load_Waiting) {
+ m_status = InvalidateGeneratorStatus_Load_Pending;
+ } else {
+ m_status = InvalidateGeneratorStatus_Inv_Pending;
+ }
+ return true;
+ } else {
+ // If the packet did not issue, must delete
+ // Note: No need to delete the data, the packet destructor
+ // will delete it
+ delete pkt->req;
+ delete pkt;
+
+ DPRINTF(DirectedTest, "failed to issue request - sequencer not ready\n");
+ return false;
+ }
+}
+
+void
+InvalidateGenerator::performCallback(uint proc, Addr address)
+{
+ assert(m_address == address);
+
+ if (m_status == InvalidateGeneratorStatus_Load_Pending) {
+ assert(m_active_read_node == proc);
+ m_active_read_node++;
+ //
+ // Once all cpus have the block in S state, issue the invalidate
+ //
+ if (m_active_read_node == m_num_cpus) {
+ m_status = InvalidateGeneratorStatus_Inv_Waiting;
+ m_active_read_node = 0;
+ } else {
+ m_status = InvalidateGeneratorStatus_Load_Waiting;
+ }
+ } else if (m_status == InvalidateGeneratorStatus_Inv_Pending) {
+ assert(m_active_inv_node == proc);
+ m_active_inv_node++;
+ if (m_active_inv_node == m_num_cpus) {
+ m_address += m_addr_increment_size;
+ m_active_inv_node = 0;
+ }
+ //
+ // Invalidate completed, send that info to the tester and restart
+ // the cycle
+ //
+ m_directed_tester->incrementCycleCompletions();
+ m_status = InvalidateGeneratorStatus_Load_Waiting;
+ }
+
+}
+
+InvalidateGenerator *
+InvalidateGeneratorParams::create()
+{
+ return new InvalidateGenerator(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * 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.
+ */
+
+//
+// This Directed Generator generates GETX requests for all nodes in the
+// system. The GETX requests are generated one at a time in round-robin fashion
+// 0...1...2...etc.
+//
+
+#ifndef __CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__
+#define __CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__
+
+#include "cpu/testers/directedtest/RubyDirectedTester.hh"
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "mem/protocol/InvalidateGeneratorStatus.hh"
+#include "params/InvalidateGenerator.hh"
+
+class InvalidateGenerator : public DirectedGenerator
+{
+ public:
+ typedef InvalidateGeneratorParams Params;
+ InvalidateGenerator(const Params *p);
+
+ ~InvalidateGenerator();
+
+ bool initiate();
+ void performCallback(uint proc, Addr address);
+
+ private:
+ InvalidateGeneratorStatus m_status;
+ Addr m_address;
+ uint m_active_read_node;
+ uint m_active_inv_node;
+ uint m_addr_increment_size;
+};
+
+#endif //__CPU_DIRECTEDTEST_INVALIDATEGENERATOR_HH__
+
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "cpu/testers/directedtest/RubyDirectedTester.hh"
+#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include "sim/sim_exit.hh"
+
+RubyDirectedTester::RubyDirectedTester(const Params *p)
+ : MemObject(p), directedStartEvent(this),
+ m_requests_to_complete(p->requests_to_complete),
+ generator(p->generator)
+{
+ m_requests_completed = 0;
+
+ // add the check start event to the event queue
+ schedule(directedStartEvent, 1);
+}
+
+RubyDirectedTester::~RubyDirectedTester()
+{
+ for (int i = 0; i < ports.size(); i++)
+ delete ports[i];
+}
+
+void
+RubyDirectedTester::init()
+{
+ assert(ports.size() > 0);
+ generator->setDirectedTester(this);
+}
+
+Port *
+RubyDirectedTester::getPort(const std::string &if_name, int idx)
+{
+ if (if_name != "cpuPort") {
+ panic("RubyDirectedTester::getPort: unknown port %s requested", if_name);
+ }
+
+ if (idx >= (int)ports.size()) {
+ ports.resize(idx + 1);
+ }
+
+ if (ports[idx] != NULL) {
+ panic("RubyDirectedTester::getPort: port %d already assigned", idx);
+ }
+
+ CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
+
+ ports[idx] = port;
+ return port;
+}
+
+Tick
+RubyDirectedTester::CpuPort::recvAtomic(PacketPtr pkt)
+{
+ panic("RubyDirectedTester::CpuPort::recvAtomic() not implemented!\n");
+ return 0;
+}
+
+bool
+RubyDirectedTester::CpuPort::recvTiming(PacketPtr pkt)
+{
+ tester->hitCallback(idx, pkt->getAddr());
+
+ //
+ // Now that the tester has completed, delete the packet, then return
+ //
+ delete pkt->req;
+ delete pkt;
+ return true;
+}
+
+Port*
+RubyDirectedTester::getCpuPort(int idx)
+{
+ assert(idx >= 0 && idx < ports.size());
+
+ return ports[idx];
+}
+
+void
+RubyDirectedTester::hitCallback(NodeID proc, Addr addr)
+{
+ DPRINTF(DirectedTest,
+ "completed request for proc: %d addr: 0x%x\n",
+ proc,
+ addr);
+
+ generator->performCallback(proc, addr);
+ schedule(directedStartEvent, curTick);
+}
+
+void
+RubyDirectedTester::wakeup()
+{
+ if (m_requests_completed < m_requests_to_complete) {
+ if (!generator->initiate()) {
+ schedule(directedStartEvent, curTick + 1);
+ }
+ } else {
+ exitSimLoop("Ruby DirectedTester completed");
+ }
+}
+
+RubyDirectedTester *
+RubyDirectedTesterParams::create()
+{
+ return new RubyDirectedTester(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#ifndef __CPU_DIRECTEDTEST_RUBYDIRECTEDTESTER_HH__
+#define __CPU_DIRECTEDTEST_RUBYDIRECTEDTESTER_HH__
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/ruby/common/DataBlock.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/common/SubBlock.hh"
+#include "mem/ruby/system/RubyPort.hh"
+#include "params/RubyDirectedTester.hh"
+
+class DirectedGenerator;
+
+class RubyDirectedTester : public MemObject
+{
+ public:
+ class CpuPort : public SimpleTimingPort
+ {
+ private:
+ RubyDirectedTester *tester;
+
+ public:
+ CpuPort(const std::string &_name, RubyDirectedTester *_tester, uint _idx)
+ : SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx)
+ {}
+
+ uint idx;
+
+ protected:
+ virtual bool recvTiming(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
+ };
+
+ typedef RubyDirectedTesterParams Params;
+ RubyDirectedTester(const Params *p);
+ ~RubyDirectedTester();
+
+ virtual Port *getPort(const std::string &if_name, int idx = -1);
+
+ Port* getCpuPort(int idx);
+
+ virtual void init();
+
+ void wakeup();
+
+ void incrementCycleCompletions() { m_requests_completed++; }
+
+ void printStats(std::ostream& out) const {}
+ void clearStats() {}
+ void printConfig(std::ostream& out) const {}
+
+ void print(std::ostream& out) const;
+
+ protected:
+ class DirectedStartEvent : public Event
+ {
+ private:
+ RubyDirectedTester *tester;
+
+ public:
+ DirectedStartEvent(RubyDirectedTester *_tester)
+ : Event(CPU_Tick_Pri), tester(_tester)
+ {}
+ void process() { tester->wakeup(); }
+ virtual const char *description() const { return "Directed tick"; }
+ };
+
+ DirectedStartEvent directedStartEvent;
+
+ private:
+ void hitCallback(NodeID proc, Addr addr);
+
+ void checkForDeadlock();
+
+ // Private copy constructor and assignment operator
+ RubyDirectedTester(const RubyDirectedTester& obj);
+ RubyDirectedTester& operator=(const RubyDirectedTester& obj);
+
+ uint64 m_requests_completed;
+ std::vector<CpuPort*> ports;
+ uint64 m_requests_to_complete;
+ DirectedGenerator* generator;
+};
+
+#endif // __CPU_DIRECTEDTEST_RUBYDIRECTEDTESTER_HH__
--- /dev/null
+# Copyright (c) 2010 Advanced Micro Devices, Inc.
+# 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: Brad Beckmann
+
+from m5.SimObject import SimObject
+from MemObject import MemObject
+from m5.params import *
+from m5.proxy import *
+
+class DirectedGenerator(SimObject):
+ type = 'DirectedGenerator'
+ abstract = True
+ num_cpus = Param.Int("num of cpus")
+
+class SeriesRequestGenerator(DirectedGenerator):
+ type = 'SeriesRequestGenerator'
+ addr_increment_size = Param.Int(64, "address increment size")
+ issue_writes = Param.Bool(True, "issue writes if true, otherwise reads")
+
+class InvalidateGenerator(DirectedGenerator):
+ type = 'InvalidateGenerator'
+ addr_increment_size = Param.Int(64, "address increment size")
+
+class RubyDirectedTester(MemObject):
+ type = 'RubyDirectedTester'
+ cpuPort = VectorPort("the cpu ports")
+ requests_to_complete = Param.Int("checks to complete")
+ generator = Param.DirectedGenerator("the request generator")
--- /dev/null
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
+# 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.
+#
+
+Import('*')
+
+#
+# Currently the ruby testser relies on Ruby specific objects (SubBlock, etc.)
+# When this dependency is removed, the ruby tester should be compiled
+# independently from Ruby
+#
+if not env['RUBY']:
+ Return()
+
+SimObject('RubyDirectedTester.py')
+
+Source('RubyDirectedTester.cc')
+Source('DirectedGenerator.cc')
+Source('SeriesRequestGenerator.cc')
+Source('InvalidateGenerator.cc')
+
+TraceFlag('DirectedTest')
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "cpu/testers/directedtest/RubyDirectedTester.hh"
+#include "cpu/testers/directedtest/SeriesRequestGenerator.hh"
+
+SeriesRequestGenerator::SeriesRequestGenerator(const Params *p)
+ : DirectedGenerator(p)
+{
+ m_status = SeriesRequestGeneratorStatus_Thinking;
+ m_active_node = 0;
+ m_address = 0x0;
+ m_addr_increment_size = p->addr_increment_size;
+ m_issue_writes = p->issue_writes;
+}
+
+SeriesRequestGenerator::~SeriesRequestGenerator()
+{
+}
+
+bool
+SeriesRequestGenerator::initiate()
+{
+ DPRINTF(DirectedTest, "initiating request\n");
+ assert(m_status == SeriesRequestGeneratorStatus_Thinking);
+
+ RubyDirectedTester::CpuPort* port =
+ safe_cast<RubyDirectedTester::CpuPort*>(m_directed_tester->
+ getCpuPort(m_active_node));
+
+ Request::Flags flags;
+
+ // For simplicity, requests are assumed to be 1 byte-sized
+ Request *req = new Request(m_address, 1, flags);
+
+ Packet::Command cmd;
+ if (m_issue_writes) {
+ cmd = MemCmd::WriteReq;
+ } else {
+ cmd = MemCmd::ReadReq;
+ }
+ PacketPtr pkt = new Packet(req, cmd, m_active_node);
+ uint8_t* dummyData = new uint8_t;
+ *dummyData = 0;
+ pkt->dataDynamic(dummyData);
+
+ if (port->sendTiming(pkt)) {
+ DPRINTF(DirectedTest, "initiating request - successful\n");
+ m_status = SeriesRequestGeneratorStatus_Request_Pending;
+ return true;
+ } else {
+ // If the packet did not issue, must delete
+ // Note: No need to delete the data, the packet destructor
+ // will delete it
+ delete pkt->req;
+ delete pkt;
+
+ DPRINTF(DirectedTest, "failed to initiate request - sequencer not ready\n");
+ return false;
+ }
+}
+
+void
+SeriesRequestGenerator::performCallback(uint proc, Addr address)
+{
+ assert(m_active_node == proc);
+ assert(m_address == address);
+ assert(m_status == SeriesRequestGeneratorStatus_Request_Pending);
+
+ m_status = SeriesRequestGeneratorStatus_Thinking;
+ m_active_node++;
+ if (m_active_node == m_num_cpus) {
+ //
+ // Cycle of requests completed, increment cycle completions and restart
+ // at cpu zero
+ //
+ m_directed_tester->incrementCycleCompletions();
+ m_address += m_addr_increment_size;
+ m_active_node = 0;
+ }
+}
+
+SeriesRequestGenerator *
+SeriesRequestGeneratorParams::create()
+{
+ return new SeriesRequestGenerator(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * 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.
+ */
+
+//
+// This Deterministic Generator generates GETX requests for all nodes in the
+// system. The GETX requests are generated one at a time in round-robin fashion
+// 0...1...2...etc.
+//
+
+#ifndef __CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__
+#define __CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__
+
+#include "cpu/testers/directedtest/DirectedGenerator.hh"
+#include "cpu/testers/directedtest/RubyDirectedTester.hh"
+#include "mem/protocol/SeriesRequestGeneratorStatus.hh"
+#include "params/SeriesRequestGenerator.hh"
+
+class SeriesRequestGenerator : public DirectedGenerator
+{
+ public:
+ typedef SeriesRequestGeneratorParams Params;
+ SeriesRequestGenerator(const Params *p);
+
+ ~SeriesRequestGenerator();
+
+ bool initiate();
+ void performCallback(uint proc, Addr address);
+
+ private:
+ SeriesRequestGeneratorStatus m_status;
+ Addr m_address;
+ uint m_active_node;
+ uint m_addr_increment_size;
+ bool m_issue_writes;
+};
+
+#endif //__CPU_DIRECTEDTEST_SERIESREQUESTGENERATOR_HH__
+
--- /dev/null
+# 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")
--- /dev/null
+# -*- 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')
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "cpu/testers/rubytest/Check.hh"
+#include "mem/ruby/common/SubBlock.hh"
+#include "mem/ruby/system/Sequencer.hh"
+#include "mem/ruby/system/System.hh"
+
+typedef RubyTester::SenderState SenderState;
+
+Check::Check(const Address& address, const Address& pc,
+ int _num_cpu_sequencers, RubyTester* _tester)
+ : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
+{
+ m_status = TesterStatus_Idle;
+
+ pickValue();
+ pickInitiatingNode();
+ changeAddress(address);
+ m_pc = pc;
+ m_access_mode = AccessModeType(random() % AccessModeType_NUM);
+ m_store_count = 0;
+}
+
+void
+Check::initiate()
+{
+ DPRINTF(RubyTest, "initiating\n");
+ debugPrint();
+
+ // currently no protocols support prefetches
+ if (false && (random() & 0xf) == 0) {
+ initiatePrefetch(); // Prefetch from random processor
+ }
+
+ if (m_status == TesterStatus_Idle) {
+ initiateAction();
+ } else if (m_status == TesterStatus_Ready) {
+ initiateCheck();
+ } else {
+ // Pending - do nothing
+ DPRINTF(RubyTest,
+ "initiating action/check - failed: action/check is pending\n");
+ }
+}
+
+void
+Check::initiatePrefetch()
+{
+ DPRINTF(RubyTest, "initiating prefetch\n");
+
+ int index = random() % m_num_cpu_sequencers;
+ RubyTester::CpuPort* port =
+ safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
+
+ Request::Flags flags;
+ flags.set(Request::PREFETCH);
+
+ Packet::Command cmd;
+
+ // 1 in 8 chance this will be an exclusive prefetch
+ if ((random() & 0x7) != 0) {
+ cmd = MemCmd::ReadReq;
+
+ // 50% chance that the request will be an instruction fetch
+ if ((random() & 0x1) == 0) {
+ flags.set(Request::INST_FETCH);
+ }
+ } else {
+ cmd = MemCmd::WriteReq;
+ flags.set(Request::PF_EXCLUSIVE);
+ }
+
+ // Prefetches are assumed to be 0 sized
+ Request *req = new Request(m_address.getAddress(), 0, flags, curTick,
+ m_pc.getAddress());
+
+ PacketPtr pkt = new Packet(req, cmd, port->idx);
+
+ // push the subblock onto the sender state. The sequencer will
+ // update the subblock on the return
+ pkt->senderState =
+ new SenderState(m_address, req->getSize(), pkt->senderState);
+
+ if (port->sendTiming(pkt)) {
+ DPRINTF(RubyTest, "successfully initiated prefetch.\n");
+ } else {
+ // If the packet did not issue, must delete
+ SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
+ pkt->senderState = senderState->saved;
+ delete senderState;
+ delete pkt->req;
+ delete pkt;
+
+ DPRINTF(RubyTest,
+ "prefetch initiation failed because Port was busy.\n");
+ }
+}
+
+void
+Check::initiateAction()
+{
+ DPRINTF(RubyTest, "initiating Action\n");
+ assert(m_status == TesterStatus_Idle);
+
+ int index = random() % m_num_cpu_sequencers;
+ RubyTester::CpuPort* port =
+ safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
+
+ Request::Flags flags;
+
+ // Create the particular address for the next byte to be written
+ Address writeAddr(m_address.getAddress() + m_store_count);
+
+ // Stores are assumed to be 1 byte-sized
+ Request *req = new Request(writeAddr.getAddress(), 1, flags, curTick,
+ m_pc.getAddress());
+
+ Packet::Command cmd;
+
+ // 1 out of 8 chance, issue an atomic rather than a write
+ // if ((random() & 0x7) == 0) {
+ // cmd = MemCmd::SwapReq;
+ // } else {
+ cmd = MemCmd::WriteReq;
+ // }
+
+ PacketPtr pkt = new Packet(req, cmd, port->idx);
+ uint8_t* writeData = new uint8_t;
+ *writeData = m_value + m_store_count;
+ pkt->dataDynamic(writeData);
+
+ DPRINTF(RubyTest, "data 0x%x check 0x%x\n",
+ *(pkt->getPtr<uint8_t>()), *writeData);
+
+ // push the subblock onto the sender state. The sequencer will
+ // update the subblock on the return
+ pkt->senderState =
+ new SenderState(writeAddr, req->getSize(), pkt->senderState);
+
+ if (port->sendTiming(pkt)) {
+ DPRINTF(RubyTest, "initiating action - successful\n");
+ DPRINTF(RubyTest, "status before action update: %s\n",
+ (TesterStatus_to_string(m_status)).c_str());
+ m_status = TesterStatus_Action_Pending;
+ } else {
+ // If the packet did not issue, must delete
+ // Note: No need to delete the data, the packet destructor
+ // will delete it
+ SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
+ pkt->senderState = senderState->saved;
+ delete senderState;
+ delete pkt->req;
+ delete pkt;
+
+ DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n");
+ }
+
+ DPRINTF(RubyTest, "status after action update: %s\n",
+ (TesterStatus_to_string(m_status)).c_str());
+}
+
+void
+Check::initiateCheck()
+{
+ DPRINTF(RubyTest, "Initiating Check\n");
+ assert(m_status == TesterStatus_Ready);
+
+ int index = random() % m_num_cpu_sequencers;
+ RubyTester::CpuPort* port =
+ safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
+
+ Request::Flags flags;
+
+ // 50% chance that the request will be an instruction fetch
+ if ((random() & 0x1) == 0) {
+ flags.set(Request::INST_FETCH);
+ }
+
+ // Checks are sized depending on the number of bytes written
+ Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags,
+ curTick, m_pc.getAddress());
+
+ PacketPtr pkt = new Packet(req, MemCmd::ReadReq, port->idx);
+ uint8_t* dataArray = new uint8_t[CHECK_SIZE];
+ pkt->dataDynamicArray(dataArray);
+
+ // push the subblock onto the sender state. The sequencer will
+ // update the subblock on the return
+ pkt->senderState =
+ new SenderState(m_address, req->getSize(), pkt->senderState);
+
+ if (port->sendTiming(pkt)) {
+ DPRINTF(RubyTest, "initiating check - successful\n");
+ DPRINTF(RubyTest, "status before check update: %s\n",
+ TesterStatus_to_string(m_status).c_str());
+ m_status = TesterStatus_Check_Pending;
+ } else {
+ // If the packet did not issue, must delete
+ // Note: No need to delete the data, the packet destructor
+ // will delete it
+ SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
+ pkt->senderState = senderState->saved;
+ delete senderState;
+ delete pkt->req;
+ delete pkt;
+
+ DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n");
+ }
+
+ DPRINTF(RubyTest, "status after check update: %s\n",
+ TesterStatus_to_string(m_status).c_str());
+}
+
+void
+Check::performCallback(NodeID proc, SubBlock* data)
+{
+ Address address = data->getAddress();
+
+ // This isn't exactly right since we now have multi-byte checks
+ // assert(getAddress() == address);
+
+ assert(getAddress().getLineAddress() == address.getLineAddress());
+ assert(data != NULL);
+
+ DPRINTF(RubyTest, "RubyTester Callback\n");
+ debugPrint();
+
+ if (m_status == TesterStatus_Action_Pending) {
+ DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n",
+ (m_value + m_store_count), data->getByte(0));
+ // Perform store one byte at a time
+ data->setByte(0, (m_value + m_store_count));
+ m_store_count++;
+ if (m_store_count == CHECK_SIZE) {
+ m_status = TesterStatus_Ready;
+ } else {
+ m_status = TesterStatus_Idle;
+ }
+ DPRINTF(RubyTest, "Action callback return data now %d\n",
+ data->getByte(0));
+ } else if (m_status == TesterStatus_Check_Pending) {
+ DPRINTF(RubyTest, "Check callback\n");
+ // Perform load/check
+ for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
+ if (uint8(m_value + byte_number) != data->getByte(byte_number)) {
+ WARN_EXPR(proc);
+ WARN_EXPR(address);
+ WARN_EXPR(data);
+ WARN_EXPR(byte_number);
+ WARN_EXPR((int)m_value + byte_number);
+ WARN_EXPR((int)data->getByte(byte_number));
+ WARN_EXPR(*this);
+ WARN_EXPR(g_eventQueue_ptr->getTime());
+ ERROR_MSG("Action/check failure");
+ }
+ }
+ DPRINTF(RubyTest, "Action/check success\n");
+ debugPrint();
+
+ // successful check complete, increment complete
+ m_tester_ptr->incrementCheckCompletions();
+
+ m_status = TesterStatus_Idle;
+ pickValue();
+
+ } else {
+ WARN_EXPR(*this);
+ WARN_EXPR(proc);
+ WARN_EXPR(data);
+ WARN_EXPR(m_status);
+ WARN_EXPR(g_eventQueue_ptr->getTime());
+ ERROR_MSG("Unexpected TesterStatus");
+ }
+
+ DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc,
+ getAddress().getLineAddress());
+ DPRINTF(RubyTest, "Callback done\n");
+ debugPrint();
+}
+
+void
+Check::changeAddress(const Address& address)
+{
+ assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
+ m_status = TesterStatus_Idle;
+ m_address = address;
+ m_store_count = 0;
+}
+
+void
+Check::pickValue()
+{
+ assert(m_status == TesterStatus_Idle);
+ m_status = TesterStatus_Idle;
+ m_value = random() & 0xff; // One byte
+ m_store_count = 0;
+}
+
+void
+Check::pickInitiatingNode()
+{
+ assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
+ m_status = TesterStatus_Idle;
+ m_initiatingNode = (random() % m_num_cpu_sequencers);
+ DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode);
+ m_store_count = 0;
+}
+
+void
+Check::print(std::ostream& out) const
+{
+ out << "["
+ << m_address << ", value: "
+ << (int)m_value << ", status: "
+ << m_status << ", initiating node: "
+ << m_initiatingNode << ", store_count: "
+ << m_store_count
+ << "]" << std::flush;
+}
+
+void
+Check::debugPrint()
+{
+ DPRINTF(RubyTest,
+ "[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n",
+ m_address.getAddress(), (int)m_value,
+ TesterStatus_to_string(m_status).c_str(),
+ m_initiatingNode, m_store_count);
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#ifndef __CPU_RUBYTEST_CHECK_HH__
+#define __CPU_RUBYTEST_CHECK_HH__
+
+#include <iostream>
+
+#include "cpu/testers/rubytest/RubyTester.hh"
+#include "mem/protocol/AccessModeType.hh"
+#include "mem/protocol/TesterStatus.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/system/NodeID.hh"
+
+class SubBlock;
+
+const int CHECK_SIZE_BITS = 2;
+const int CHECK_SIZE = (1 << CHECK_SIZE_BITS);
+
+class Check
+{
+ public:
+ Check(const Address& address, const Address& pc, int _num_cpu_sequencer,
+ RubyTester* _tester);
+
+ void initiate(); // Does Action or Check or nether
+ void performCallback(NodeID proc, SubBlock* data);
+ const Address& getAddress() { return m_address; }
+ void changeAddress(const Address& address);
+
+ void print(std::ostream& out) const;
+
+ private:
+ void initiatePrefetch();
+ void initiateAction();
+ void initiateCheck();
+
+ void pickValue();
+ void pickInitiatingNode();
+
+ void debugPrint();
+
+ TesterStatus m_status;
+ uint8 m_value;
+ int m_store_count;
+ NodeID m_initiatingNode;
+ Address m_address;
+ Address m_pc;
+ AccessModeType m_access_mode;
+ int m_num_cpu_sequencers;
+ RubyTester* m_tester_ptr;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const Check& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif // __CPU_RUBYTEST_CHECK_HH__
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "base/intmath.hh"
+#include "cpu/testers/rubytest/Check.hh"
+#include "cpu/testers/rubytest/CheckTable.hh"
+#include "cpu/testers/rubytest/CheckTable.hh"
+
+CheckTable::CheckTable(int _num_cpu_sequencers, RubyTester* _tester)
+ : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
+{
+ physical_address_t physical = 0;
+ Address address;
+
+ const int size1 = 32;
+ const int size2 = 100;
+
+ // The first set is to get some false sharing
+ physical = 1000;
+ for (int i = 0; i < size1; i++) {
+ // Setup linear addresses
+ address.setAddress(physical);
+ addCheck(address);
+ physical += CHECK_SIZE;
+ }
+
+ // The next two sets are to get some limited false sharing and
+ // cache conflicts
+ physical = 1000;
+ for (int i = 0; i < size2; i++) {
+ // Setup linear addresses
+ address.setAddress(physical);
+ addCheck(address);
+ physical += 256;
+ }
+
+ physical = 1000 + CHECK_SIZE;
+ for (int i = 0; i < size2; i++) {
+ // Setup linear addresses
+ address.setAddress(physical);
+ addCheck(address);
+ physical += 256;
+ }
+}
+
+CheckTable::~CheckTable()
+{
+ int size = m_check_vector.size();
+ for (int i = 0; i < size; i++)
+ delete m_check_vector[i];
+}
+
+void
+CheckTable::addCheck(const Address& address)
+{
+ if (floorLog2(CHECK_SIZE) != 0) {
+ if (address.bitSelect(0, CHECK_SIZE_BITS - 1) != 0) {
+ ERROR_MSG("Check not aligned");
+ }
+ }
+
+ for (int i = 0; i < CHECK_SIZE; i++) {
+ if (m_lookup_map.count(Address(address.getAddress()+i))) {
+ // A mapping for this byte already existed, discard the
+ // entire check
+ return;
+ }
+ }
+
+ Check* check_ptr = new Check(address, Address(100 + m_check_vector.size()),
+ m_num_cpu_sequencers, m_tester_ptr);
+ for (int i = 0; i < CHECK_SIZE; i++) {
+ // Insert it once per byte
+ m_lookup_map[Address(address.getAddress() + i)] = check_ptr;
+ }
+ m_check_vector.push_back(check_ptr);
+}
+
+Check*
+CheckTable::getRandomCheck()
+{
+ return m_check_vector[random() % m_check_vector.size()];
+}
+
+Check*
+CheckTable::getCheck(const Address& address)
+{
+ DEBUG_MSG(TESTER_COMP, MedPrio, "Looking for check by address");
+ DEBUG_EXPR(TESTER_COMP, MedPrio, address);
+
+ m5::hash_map<Address, Check*>::iterator i = m_lookup_map.find(address);
+
+ if (i == m_lookup_map.end())
+ return NULL;
+
+ Check* check = i->second;
+ assert(check != NULL);
+ return check;
+}
+
+void
+CheckTable::print(std::ostream& out) const
+{
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#ifndef __CPU_RUBYTEST_CHECKTABLE_HH__
+#define __CPU_RUBYTEST_CHECKTABLE_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "base/hashmap.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/common/Global.hh"
+
+class Check;
+class RubyTester;
+
+class CheckTable
+{
+ public:
+ CheckTable(int _num_cpu_sequencers, RubyTester* _tester);
+ ~CheckTable();
+
+ Check* getRandomCheck();
+ Check* getCheck(const Address& address);
+
+ // bool isPresent(const Address& address) const;
+ // void removeCheckFromTable(const Address& address);
+ // bool isTableFull() const;
+ // Need a method to select a check or retrieve a check
+
+ void print(std::ostream& out) const;
+
+ private:
+ void addCheck(const Address& address);
+
+ // Private copy constructor and assignment operator
+ CheckTable(const CheckTable& obj);
+ CheckTable& operator=(const CheckTable& obj);
+
+ std::vector<Check*> m_check_vector;
+ m5::hash_map<Address, Check*> m_lookup_map;
+
+ int m_num_cpu_sequencers;
+ RubyTester* m_tester_ptr;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const CheckTable& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif // __CPU_RUBYTEST_CHECKTABLE_HH__
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#include "cpu/testers/rubytest/Check.hh"
+#include "cpu/testers/rubytest/RubyTester.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/common/SubBlock.hh"
+#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include "mem/ruby/system/System.hh"
+#include "sim/sim_exit.hh"
+
+RubyTester::RubyTester(const Params *p)
+ : MemObject(p), checkStartEvent(this),
+ m_checks_to_complete(p->checks_to_complete),
+ m_deadlock_threshold(p->deadlock_threshold),
+ m_wakeup_frequency(p->wakeup_frequency)
+{
+ m_checks_completed = 0;
+
+ // add the check start event to the event queue
+ schedule(checkStartEvent, 1);
+}
+
+RubyTester::~RubyTester()
+{
+ delete m_checkTable_ptr;
+ for (int i = 0; i < ports.size(); i++)
+ delete ports[i];
+}
+
+void
+RubyTester::init()
+{
+ assert(ports.size() > 0);
+
+ m_last_progress_vector.resize(ports.size());
+ for (int i = 0; i < m_last_progress_vector.size(); i++) {
+ m_last_progress_vector[i] = 0;
+ }
+
+ m_num_cpu_sequencers = ports.size();
+
+ m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this);
+}
+
+Port *
+RubyTester::getPort(const std::string &if_name, int idx)
+{
+ if (if_name != "cpuPort") {
+ panic("RubyTester::getPort: unknown port %s requested", if_name);
+ }
+
+ if (idx >= (int)ports.size()) {
+ ports.resize(idx + 1);
+ }
+
+ if (ports[idx] != NULL) {
+ panic("RubyTester::getPort: port %d already assigned", idx);
+ }
+
+ CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
+
+ ports[idx] = port;
+ return port;
+}
+
+Tick
+RubyTester::CpuPort::recvAtomic(PacketPtr pkt)
+{
+ panic("RubyTester::CpuPort::recvAtomic() not implemented!\n");
+ return 0;
+}
+
+bool
+RubyTester::CpuPort::recvTiming(PacketPtr pkt)
+{
+ // retrieve the subblock and call hitCallback
+ RubyTester::SenderState* senderState =
+ safe_cast<RubyTester::SenderState*>(pkt->senderState);
+ SubBlock* subblock = senderState->subBlock;
+ assert(subblock != NULL);
+
+ // pop the sender state from the packet
+ pkt->senderState = senderState->saved;
+
+ tester->hitCallback(idx, subblock);
+
+ // Now that the tester has completed, delete the senderState
+ // (includes sublock) and the packet, then return
+ delete senderState;
+ delete pkt->req;
+ delete pkt;
+ return true;
+}
+
+Port*
+RubyTester::getCpuPort(int idx)
+{
+ assert(idx >= 0 && idx < ports.size());
+
+ return ports[idx];
+}
+
+void
+RubyTester::hitCallback(NodeID proc, SubBlock* data)
+{
+ // Mark that we made progress
+ m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
+
+ DPRINTF(RubyTest, "completed request for proc: %d\n", proc);
+ DPRINTF(RubyTest, "addr: 0x%x, size: %d, data: ",
+ data->getAddress(), data->getSize());
+ for (int byte = 0; byte < data->getSize(); byte++) {
+ DPRINTF(RubyTest, "%d", data->getByte(byte));
+ }
+ DPRINTF(RubyTest, "\n");
+
+ // This tells us our store has 'completed' or for a load gives us
+ // back the data to make the check
+ Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
+ assert(check_ptr != NULL);
+ check_ptr->performCallback(proc, data);
+}
+
+void
+RubyTester::wakeup()
+{
+ if (m_checks_completed < m_checks_to_complete) {
+ // Try to perform an action or check
+ Check* check_ptr = m_checkTable_ptr->getRandomCheck();
+ assert(check_ptr != NULL);
+ check_ptr->initiate();
+
+ checkForDeadlock();
+
+ schedule(checkStartEvent, curTick + m_wakeup_frequency);
+ } else {
+ exitSimLoop("Ruby Tester completed");
+ }
+}
+
+void
+RubyTester::checkForDeadlock()
+{
+ int size = m_last_progress_vector.size();
+ Time current_time = g_eventQueue_ptr->getTime();
+ for (int processor = 0; processor < size; processor++) {
+ if ((current_time - m_last_progress_vector[processor]) >
+ m_deadlock_threshold) {
+ WARN_EXPR(current_time);
+ WARN_EXPR(m_last_progress_vector[processor]);
+ WARN_EXPR(current_time - m_last_progress_vector[processor]);
+ WARN_EXPR(processor);
+ ERROR_MSG("Deadlock detected.");
+ }
+ }
+}
+
+void
+RubyTester::print(std::ostream& out) const
+{
+ out << "[RubyTester]" << std::endl;
+}
+
+RubyTester *
+RubyTesterParams::create()
+{
+ return new RubyTester(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * 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.
+ */
+
+#ifndef __CPU_RUBYTEST_RUBYTESTER_HH__
+#define __CPU_RUBYTEST_RUBYTESTER_HH__
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "cpu/testers/rubytest/CheckTable.hh"
+#include "mem/mem_object.hh"
+#include "mem/packet.hh"
+#include "mem/ruby/common/DataBlock.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/common/SubBlock.hh"
+#include "mem/ruby/system/RubyPort.hh"
+#include "params/RubyTester.hh"
+
+class RubyTester : public MemObject
+{
+ public:
+ class CpuPort : public SimpleTimingPort
+ {
+ private:
+ RubyTester *tester;
+
+ public:
+ CpuPort(const std::string &_name, RubyTester *_tester, int _idx)
+ : SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx)
+ {}
+
+ int idx;
+
+ protected:
+ virtual bool recvTiming(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
+ };
+
+ struct SenderState : public Packet::SenderState
+ {
+ SubBlock* subBlock;
+ Packet::SenderState *saved;
+
+ SenderState(Address addr, int size,
+ Packet::SenderState *sender_state = NULL)
+ : saved(sender_state)
+ {
+ subBlock = new SubBlock(addr, size);
+ }
+
+ ~SenderState()
+ {
+ delete subBlock;
+ }
+ };
+
+ typedef RubyTesterParams Params;
+ RubyTester(const Params *p);
+ ~RubyTester();
+
+ virtual Port *getPort(const std::string &if_name, int idx = -1);
+
+ Port* getCpuPort(int idx);
+
+ virtual void init();
+
+ void wakeup();
+
+ void incrementCheckCompletions() { m_checks_completed++; }
+
+ void printStats(std::ostream& out) const {}
+ void clearStats() {}
+ void printConfig(std::ostream& out) const {}
+
+ void print(std::ostream& out) const;
+
+ protected:
+ class CheckStartEvent : public Event
+ {
+ private:
+ RubyTester *tester;
+
+ public:
+ CheckStartEvent(RubyTester *_tester)
+ : Event(CPU_Tick_Pri), tester(_tester)
+ {}
+ void process() { tester->wakeup(); }
+ virtual const char *description() const { return "RubyTester tick"; }
+ };
+
+ CheckStartEvent checkStartEvent;
+
+ private:
+ void hitCallback(NodeID proc, SubBlock* data);
+
+ void checkForDeadlock();
+
+ // Private copy constructor and assignment operator
+ RubyTester(const RubyTester& obj);
+ RubyTester& operator=(const RubyTester& obj);
+
+ CheckTable* m_checkTable_ptr;
+ std::vector<Time> m_last_progress_vector;
+
+ uint64 m_checks_completed;
+ std::vector<CpuPort*> ports;
+ uint64 m_checks_to_complete;
+ int m_deadlock_threshold;
+ int m_num_cpu_sequencers;
+ int m_wakeup_frequency;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const RubyTester& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif // __CPU_RUBYTEST_RUBYTESTER_HH__
--- /dev/null
+# Copyright (c) 2005-2007 The Regents of The University of Michigan
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# 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.
+#
+
+from MemObject import MemObject
+from m5.params import *
+from m5.proxy import *
+
+class RubyTester(MemObject):
+ type = 'RubyTester'
+ cpuPort = VectorPort("the cpu ports")
+ checks_to_complete = Param.Int(100, "checks to complete")
+ deadlock_threshold = Param.Int(50000, "how often to check for deadlock")
+ wakeup_frequency = Param.Int(10, "number of cycles between wakeups")
--- /dev/null
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# 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.
+#
+
+Import('*')
+
+#
+# Currently the ruby testser relies on Ruby specific objects (SubBlock, etc.)
+# When this dependency is removed, the ruby tester should be compiled
+# independently from Ruby
+#
+if not env['RUBY']:
+ Return()
+
+SimObject('RubyTester.py')
+
+Source('RubyTester.cc')
+Source('Check.cc')
+Source('CheckTable.cc')
+
+TraceFlag('RubyTest')
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "cpu/rubytest/RubyTester.hh"
+#include "cpu/testers/rubytest/RubyTester.hh"
#include "mem/physical.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/RubyPort.hh"
*/
#include "base/str.hh"
-#include "cpu/rubytest/RubyTester.hh"
+#include "cpu/testers/rubytest/RubyTester.hh"
#include "mem/protocol/CacheMsg.hh"
#include "mem/protocol/Protocol.hh"
#include "mem/protocol/Protocol.hh"