summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTushar Krishna <tushar@csail.mit.edu>2011-03-21 22:51:58 -0400
committerTushar Krishna <tushar@csail.mit.edu>2011-03-21 22:51:58 -0400
commit09c3a97a4c9aace6e2c52823679b31323cab42f6 (patch)
treed0340677be5f6cd4c10456fb70a46c1374f28e99
parentd7aa794155a46a403825f82c1ea62cd38b9de788 (diff)
downloadgem5-09c3a97a4c9aace6e2c52823679b31323cab42f6.tar.xz
This patch adds the network tester for simple and garnet networks.
The tester code is in testers/networktest. The tester can be invoked by configs/example/ruby_network_test.py. A dummy coherence protocol called Network_test is also addded for network-only simulations and testing. The protocol takes in messages from the tester and just pushes them into the network in the appropriate vnet, without storing any state.
-rw-r--r--build_opts/ALPHA_SE_Network_test5
-rw-r--r--configs/example/ruby_network_test.py131
-rw-r--r--configs/ruby/Network_test.py129
-rw-r--r--src/cpu/testers/networktest/NetworkTest.py42
-rw-r--r--src/cpu/testers/networktest/SConscript37
-rw-r--r--src/cpu/testers/networktest/networktest.cc333
-rw-r--r--src/cpu/testers/networktest/networktest.hh158
-rw-r--r--src/mem/protocol/Network_test-cache.sm218
-rw-r--r--src/mem/protocol/Network_test-dir.sm136
-rw-r--r--src/mem/protocol/Network_test-msg.sm77
-rw-r--r--src/mem/protocol/Network_test.slicc4
-rw-r--r--src/mem/protocol/SConsopts1
-rw-r--r--src/mem/ruby/network/garnet/BaseGarnetNetwork.cc1
-rw-r--r--src/mem/ruby/network/garnet/BaseGarnetNetwork.hh3
-rw-r--r--src/mem/ruby/network/garnet/BaseGarnetNetwork.py1
-rw-r--r--src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc14
-rw-r--r--src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc9
-rw-r--r--src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc8
-rw-r--r--src/mem/ruby/system/Sequencer.cc8
-rw-r--r--src/mem/ruby/system/Sequencer.hh2
-rw-r--r--src/mem/ruby/system/Sequencer.py1
21 files changed, 1294 insertions, 24 deletions
diff --git a/build_opts/ALPHA_SE_Network_test b/build_opts/ALPHA_SE_Network_test
new file mode 100644
index 000000000..a092a94fd
--- /dev/null
+++ b/build_opts/ALPHA_SE_Network_test
@@ -0,0 +1,5 @@
+FULL_SYSTEM = 0
+SS_COMPATIBLE_FP = 1
+CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU'
+PROTOCOL = 'Network_test'
+RUBY = True
diff --git a/configs/example/ruby_network_test.py b/configs/example/ruby_network_test.py
new file mode 100644
index 000000000..6abf50561
--- /dev/null
+++ b/configs/example/ruby_network_test.py
@@ -0,0 +1,131 @@
+# Copyright (c) 2006-2007 The Regents of The University of Michigan
+# 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: Ron Dreslinski
+# Tushar Krishna
+
+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("--synthetic", type="int", default=0,
+ help="Synthetic Traffic type. 0 = Uniform Random,\
+ 1 = Tornado, 2 = Bit Complement")
+
+parser.add_option("-i", "--injectionrate", type="float", default=0.1,
+ metavar="I",
+ help="Injection rate in packets per cycle per node. \
+ Takes decimal value between 0 to 1 (eg. 0.225). \
+ Number of digits after 0 depends upon --precision.")
+
+parser.add_option("--precision", type="int", default=3,
+ help="Number of digits of precision after decimal point\
+ for injection rate")
+
+parser.add_option("--fixed-pkts", action="store_true",
+ help="Network_test: send only -p number of packets")
+
+parser.add_option("-p", "--maxpackets", type="int", default=1,
+ metavar="P",
+ help="Stop after Packets (works only with --fixed-pkts")
+
+#
+# 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)
+
+block_size = 64
+
+if options.num_cpus > block_size:
+ print "Error: Number of cores %d limited to %d because of false sharing" \
+ % (options.num_cpus, block_size)
+ sys.exit(1)
+
+cpus = [ NetworkTest(fixed_pkts=options.fixed_pkts, \
+ max_packets=options.maxpackets, \
+ traffic_type=options.synthetic, \
+ inj_rate=options.injectionrate, \
+ precision=options.precision, \
+ num_memories=options.num_dirs) \
+ for i in xrange(options.num_cpus) ]
+
+# create the desired simulated system
+system = System(cpu = cpus,
+ physmem = PhysicalMemory())
+
+system.ruby = Ruby.create_system(options, system)
+
+i = 0
+for ruby_port in system.ruby.cpu_ruby_ports:
+ #
+ # Tie the cpu test ports to the ruby cpu port
+ #
+ cpus[i].test = ruby_port.port
+ ruby_port.access_phys_mem = False
+
+ i += 1
+
+# -----------------------
+# 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()
diff --git a/configs/ruby/Network_test.py b/configs/ruby/Network_test.py
new file mode 100644
index 000000000..fe1559f53
--- /dev/null
+++ b/configs/ruby/Network_test.py
@@ -0,0 +1,129 @@
+# 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: Brad Beckmann
+
+import m5
+from m5.objects import *
+from m5.defines import buildEnv
+from m5.util import addToPath
+
+#
+# Note: the cache latency is only used by the sequencer on fast path hits
+#
+class Cache(RubyCache):
+ latency = 3
+
+def define_options(parser):
+ return
+
+def create_system(options, system, piobus, dma_devices):
+
+ if buildEnv['PROTOCOL'] != 'Network_test':
+ panic("This script requires the Network_test protocol to be built.")
+
+ cpu_sequencers = []
+
+ #
+ # The Garnet tester protocol does not support fs nor dma
+ #
+ if buildEnv['FULL_SYSTEM']:
+ panic("This script requires system-emulation mode (*_SE).")
+ assert(piobus == None)
+ assert(dma_devices == [])
+
+ #
+ # The ruby network creation expects the list of nodes in the system to be
+ # consistent with the NetDest list. Therefore the l1 controller nodes must be
+ # listed before the directory nodes and directory nodes before dma nodes, etc.
+ #
+ l1_cntrl_nodes = []
+ dir_cntrl_nodes = []
+
+ #
+ # Must create the individual controllers before the network to ensure the
+ # controller constructors are called before the network constructor
+ #
+
+ for i in xrange(options.num_cpus):
+ #
+ # First create the Ruby objects associated with this cpu
+ # Only one cache exists for this protocol, so by default use the L1D
+ # config parameters.
+ #
+ cache = Cache(size = options.l1d_size,
+ assoc = options.l1d_assoc)
+
+ #
+ # Only one unified L1 cache exists. Can cache instructions and data.
+ #
+ cpu_seq = RubySequencer(icache = cache,
+ dcache = cache,
+ physMemPort = system.physmem.port,
+ physmem = system.physmem,
+ using_network_tester = True)
+
+ if piobus != None:
+ cpu_seq.pio_port = piobus.port
+
+ l1_cntrl = L1Cache_Controller(version = i,
+ sequencer = cpu_seq,
+ cacheMemory = cache)
+
+ exec("system.l1_cntrl%d = l1_cntrl" % i)
+ #
+ # Add controllers and sequencers to the appropriate lists
+ #
+ cpu_sequencers.append(cpu_seq)
+ l1_cntrl_nodes.append(l1_cntrl)
+
+ phys_mem_size = long(system.physmem.range.second) - \
+ long(system.physmem.range.first) + 1
+ mem_module_size = phys_mem_size / options.num_dirs
+
+ for i in xrange(options.num_dirs):
+ #
+ # Create the Ruby objects associated with the directory controller
+ #
+
+ mem_cntrl = RubyMemoryControl(version = i)
+
+ dir_size = MemorySize('0B')
+ dir_size.value = mem_module_size
+
+ dir_cntrl = Directory_Controller(version = i,
+ directory = \
+ RubyDirectoryMemory(version = i,
+ size = dir_size),
+ memBuffer = mem_cntrl)
+
+ exec("system.dir_cntrl%d = dir_cntrl" % i)
+ dir_cntrl_nodes.append(dir_cntrl)
+
+ all_cntrls = l1_cntrl_nodes + dir_cntrl_nodes
+
+ return (cpu_sequencers, dir_cntrl_nodes, all_cntrls)
diff --git a/src/cpu/testers/networktest/NetworkTest.py b/src/cpu/testers/networktest/NetworkTest.py
new file mode 100644
index 000000000..d4eef09c5
--- /dev/null
+++ b/src/cpu/testers/networktest/NetworkTest.py
@@ -0,0 +1,42 @@
+# 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: Tushar Krishna
+
+from MemObject import MemObject
+from m5.params import *
+
+class NetworkTest(MemObject):
+ type = 'NetworkTest'
+ block_offset = Param.Int(6, "block offset in bits")
+ num_memories = Param.Int(1, "Num Memories")
+ memory_size = Param.Int(65536, "memory size")
+ fixed_pkts = Param.Bool(False, "Send fixed number of packets")
+ max_packets = Param.Counter(0, "Number of packets to send when in fixed_pkts mode")
+ traffic_type = Param.Counter(0, "Traffic type: uniform random, tornado, bit complement")
+ inj_rate = Param.Float(0.1, "Packet injection rate")
+ precision = Param.Int(3, "Number of digits of precision after decimal point")
+ test = Port("Port to the memory system to test")
diff --git a/src/cpu/testers/networktest/SConscript b/src/cpu/testers/networktest/SConscript
new file mode 100644
index 000000000..b658ac079
--- /dev/null
+++ b/src/cpu/testers/networktest/SConscript
@@ -0,0 +1,37 @@
+# -*- mode:python -*-
+
+# 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: Tushar Krishna
+
+Import('*')
+
+SimObject('NetworkTest.py')
+
+Source('networktest.cc', Werror=False)
+
+TraceFlag('NetworkTest')
diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc
new file mode 100644
index 000000000..4f4c30931
--- /dev/null
+++ b/src/cpu/testers/networktest/networktest.cc
@@ -0,0 +1,333 @@
+/*
+ * 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: Tushar Krishna
+ */
+
+#include <iomanip>
+#include <set>
+#include <string>
+#include <vector>
+#include <cmath>
+
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "cpu/testers/networktest/networktest.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_NETWORK=0;
+
+bool
+NetworkTest::CpuPort::recvTiming(PacketPtr pkt)
+{
+ if (pkt->isResponse()) {
+ networktest->completeRequest(pkt);
+ } else {
+ // must be snoop upcall
+ assert(pkt->isRequest());
+ assert(pkt->getDest() == Packet::Broadcast);
+ }
+ return true;
+}
+
+Tick
+NetworkTest::CpuPort::recvAtomic(PacketPtr pkt)
+{
+ panic("NetworkTest doesn't expect recvAtomic call!");
+ // Will not be used
+ assert(pkt->isRequest());
+ assert(pkt->getDest() == Packet::Broadcast);
+ return curTick();
+}
+
+void
+NetworkTest::CpuPort::recvFunctional(PacketPtr pkt)
+{
+ panic("NetworkTest doesn't expect recvFunctional call!");
+ // Will not be used
+ return;
+}
+
+void
+NetworkTest::CpuPort::recvStatusChange(Status status)
+{
+ if (status == RangeChange) {
+ if (!snoopRangeSent) {
+ snoopRangeSent = true;
+ sendStatusChange(Port::RangeChange);
+ }
+ return;
+ }
+
+ panic("NetworkTest doesn't expect recvStatusChange callback!");
+}
+
+void
+NetworkTest::CpuPort::recvRetry()
+{
+ networktest->doRetry();
+}
+
+void
+NetworkTest::sendPkt(PacketPtr pkt)
+{
+ if (cachePort.sendTiming(pkt)) {
+ numPacketsSent++;
+ accessRetry = false;
+ } else {
+ accessRetry = true;
+ retryPkt = pkt;
+ }
+}
+
+NetworkTest::NetworkTest(const Params *p)
+ : MemObject(p),
+ tickEvent(this),
+ cachePort("network-test", this),
+ retryPkt(NULL),
+ size(p->memory_size),
+ blockSizeBits(p->block_offset),
+ numMemories(p->num_memories),
+ fixedPkts(p->fixed_pkts),
+ maxPackets(p->max_packets),
+ trafficType(p->traffic_type),
+ injRate(p->inj_rate),
+ precision(p->precision)
+{
+ cachePort.snoopRangeSent = false;
+
+ // set up counters
+ noResponseCycles = 0;
+ schedule(tickEvent, 0);
+
+ id = TESTER_NETWORK++;
+ DPRINTF(NetworkTest,"Config Created: Name = %s , and id = %d\n",
+ name(), id);
+
+ accessRetry = false;
+}
+
+Port *
+NetworkTest::getPort(const std::string &if_name, int idx)
+{
+ if (if_name == "test")
+ return &cachePort;
+ else
+ panic("No Such Port\n");
+}
+
+void
+NetworkTest::init()
+{
+ numPacketsSent = 0;
+}
+
+
+void
+NetworkTest::completeRequest(PacketPtr pkt)
+{
+ Request *req = pkt->req;
+
+ DPRINTF(NetworkTest, "Completed injection of %s packet for address %x\n",
+ pkt->isWrite() ? "write" : "read\n",
+ req->getPaddr());
+
+ assert(pkt->isResponse());
+ noResponseCycles = 0;
+ delete pkt->req;
+ delete pkt;
+}
+
+
+void
+NetworkTest::tick()
+{
+ if (!tickEvent.scheduled())
+ schedule(tickEvent, curTick() + ticks(1));
+
+ if (++noResponseCycles >= 500000) {
+ cerr << name() << ": deadlocked at cycle " << curTick() << endl;
+ fatal("");
+ }
+
+ if (accessRetry) {
+ sendPkt(retryPkt);
+ return;
+ }
+
+ // make new request based on injection rate
+ // (injection rate's range depends on precision)
+ // - generate a random number between 0 and 10^precision
+ // - send pkt if this number is < injRate*(10^precision)
+ bool send_this_cycle;
+ int injRange = pow(10, precision);
+ unsigned trySending = random() % injRange;
+ if (trySending < injRate*injRange)
+ send_this_cycle = true;
+ else
+ send_this_cycle = false;
+
+ // always generatePkt unless fixedPkts is enabled
+ if (send_this_cycle) {
+ if (fixedPkts) {
+ if (numPacketsSent < maxPackets) {
+ generatePkt();
+ }
+ } else {
+ generatePkt();
+ }
+ }
+}
+
+void
+NetworkTest::generatePkt()
+{
+ unsigned destination = id;
+ if (trafficType == 0) { // Uniform Random
+ while (destination == id)
+ destination = random() % numMemories;
+ } else if (trafficType == 1) { // Tornado
+ int networkDimension = (int) sqrt(numMemories);
+ int my_x = id%networkDimension;
+ int my_y = id/networkDimension;
+
+ int dest_x = my_x + (int) ceil(networkDimension/2) - 1;
+ dest_x = dest_x%networkDimension;
+ int dest_y = my_y;
+
+ destination = dest_y*networkDimension + dest_x;
+ } else if (trafficType == 2) { // Bit Complement
+ int networkDimension = (int) sqrt(numMemories);
+ int my_x = id%networkDimension;
+ int my_y = id/networkDimension;
+
+ int dest_x = networkDimension - my_x - 1;
+ int dest_y = networkDimension - my_y - 1;
+
+ destination = dest_y*networkDimension + dest_x;
+ }
+
+ Request *req = new Request();
+ Request::Flags flags;
+
+ // The source of the packets is a cache.
+ // The destination of the packets is a directory.
+ // The destination bits are embedded in the address after byte-offset.
+ Addr paddr = destination;
+ paddr <<= blockSizeBits;
+ unsigned access_size = 1; // Does not affect Ruby simulation
+
+ // Modeling different coherence msg types over different msg classes.
+ //
+ // networktest assumes the Network_test coherence protocol
+ // which models three message classes/virtual networks.
+ // These are: request, forward, response.
+ // requests and forwards are "control" packets (typically 8 bytes),
+ // while responses are "data" packets (typically 72 bytes).
+ //
+ // Life of a packet from the tester into the network:
+ // (1) This function generatePkt() generates packets of one of the
+ // following 3 types (randomly) : ReadReq, INST_FETCH, WriteReq
+ // (2) mem/ruby/system/RubyPort.cc converts these to RubyRequestType_LD,
+ // RubyRequestType_IFETCH, RubyRequestType_ST respectively
+ // (3) mem/ruby/system/Sequencer.cc sends these to the cache controllers
+ // in the coherence protocol.
+ // (4) Network_test-cache.sm tags RubyRequestType:LD,
+ // RubyRequestType:IFETCH and RubyRequestType:ST as
+ // Request, Forward, and Response events respectively;
+ // and injects them into virtual networks 0, 1 and 2 respectively.
+ // It immediately calls back the sequencer.
+ // (5) The packet traverses the network (simple/garnet) and reaches its
+ // destination (Directory), and network stats are updated.
+ // (6) Network_test-dir.sm simply drops the packet.
+ //
+ MemCmd::Command requestType;
+
+ unsigned randomReqType = random() % 3;
+ if (randomReqType == 0) {
+ // generate packet for virtual network 0
+ requestType = MemCmd::ReadReq;
+ req->setPhys(paddr, access_size, flags);
+ } else if (randomReqType == 1) {
+ // generate packet for virtual network 1
+ requestType = MemCmd::ReadReq;
+ flags.set(Request::INST_FETCH);
+ req->setVirt(0, 0x0, access_size, flags, 0x0);
+ req->setPaddr(paddr);
+ } else { // if (randomReqType == 2)
+ // generate packet for virtual network 2
+ requestType = MemCmd::WriteReq;
+ req->setPhys(paddr, access_size, flags);
+ }
+
+ req->setThreadContext(id,0);
+ uint8_t *result = new uint8_t[8];
+
+ //No need to do functional simulation
+ //We just do timing simulation of the network
+
+ DPRINTF(NetworkTest,
+ "Generated packet with destination %d, embedded in address %x\n",
+ destination, req->getPaddr());
+
+ PacketPtr pkt = new Packet(req, requestType, 0);
+ pkt->setSrc(0); //Not used
+ pkt->dataDynamicArray(new uint8_t[req->getSize()]);
+ NetworkTestSenderState *state = new NetworkTestSenderState(result);
+ pkt->senderState = state;
+
+ sendPkt(pkt);
+}
+
+void
+NetworkTest::doRetry()
+{
+ if (cachePort.sendTiming(retryPkt)) {
+ accessRetry = false;
+ retryPkt = NULL;
+ }
+}
+
+void
+NetworkTest::printAddr(Addr a)
+{
+ cachePort.printAddr(a);
+}
+
+
+NetworkTest *
+NetworkTestParams::create()
+{
+ return new NetworkTest(this);
+}
diff --git a/src/cpu/testers/networktest/networktest.hh b/src/cpu/testers/networktest/networktest.hh
new file mode 100644
index 000000000..923f47df2
--- /dev/null
+++ b/src/cpu/testers/networktest/networktest.hh
@@ -0,0 +1,158 @@
+/*
+ * 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: Tushar Krishna
+ */
+
+#ifndef __CPU_NETWORKTEST_NETWORKTEST_HH__
+#define __CPU_NETWORKTEST_NETWORKTEST_HH__
+
+#include <set>
+
+#include "base/statistics.hh"
+#include "base/fast_alloc.hh"
+#include "params/NetworkTest.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 NetworkTest : public MemObject
+{
+ public:
+ typedef NetworkTestParams Params;
+ NetworkTest(const Params *p);
+
+ virtual void init();
+
+ 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:
+ NetworkTest *cpu;
+
+ public:
+ TickEvent(NetworkTest *c) : Event(CPU_Tick_Pri), cpu(c) {}
+ void process() { cpu->tick(); }
+ virtual const char *description() const { return "NetworkTest tick"; }
+ };
+
+ TickEvent tickEvent;
+
+ class CpuPort : public Port
+ {
+ NetworkTest *networktest;
+
+ public:
+
+ CpuPort(const std::string &_name, NetworkTest *_networktest)
+ : Port(_name, _networktest), networktest(_networktest)
+ { }
+
+ 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;
+
+ bool snoopRangeSent;
+
+ class NetworkTestSenderState : public Packet::SenderState, public FastAlloc
+ {
+ public:
+ /** Constructor. */
+ NetworkTestSenderState(uint8_t *_data)
+ : data(_data)
+ { }
+
+ // Hold onto data pointer
+ uint8_t *data;
+ };
+
+ PacketPtr retryPkt;
+ bool accessRetry;
+ unsigned size;
+ int id;
+
+ unsigned blockSizeBits;
+
+ Tick noResponseCycles;
+
+ int numMemories;
+ bool fixedPkts;
+ int maxPackets;
+ int numPacketsSent;
+
+ int trafficType;
+ double injRate;
+ int precision;
+
+ void completeRequest(PacketPtr pkt);
+
+ void generatePkt();
+ void sendPkt(PacketPtr pkt);
+
+ void doRetry();
+
+ friend class MemCompleteEvent;
+};
+
+#endif // __CPU_NETWORKTEST_NETWORKTEST_HH__
+
+
+
diff --git a/src/mem/protocol/Network_test-cache.sm b/src/mem/protocol/Network_test-cache.sm
new file mode 100644
index 000000000..603c1f5f9
--- /dev/null
+++ b/src/mem/protocol/Network_test-cache.sm
@@ -0,0 +1,218 @@
+/*
+ * 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: Brad Beckmann
+ * Tushar Krishna
+ */
+
+
+machine(L1Cache, "Network_test L1 Cache")
+: Sequencer * sequencer,
+ int issue_latency = 2
+{
+
+ // NETWORK BUFFERS
+ MessageBuffer requestFromCache, network="To", virtual_network="0", ordered="false";
+ MessageBuffer forwardFromCache, network="To", virtual_network="1", ordered="false";
+ MessageBuffer responseFromCache, network="To", virtual_network="2", ordered="false";
+
+ // STATES
+ state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
+ I, AccessPermission:Invalid, desc="Not Present/Invalid";
+ }
+
+ // EVENTS
+ enumeration(Event, desc="Cache events") {
+ // From processor
+ Request, desc="Request from Network_test";
+ Forward, desc="Forward from Network_test";
+ Response, desc="Response from Network_test";
+ }
+
+ // STRUCTURE DEFINITIONS
+
+ MessageBuffer mandatoryQueue, ordered="false";
+ DataBlock dummyData;
+
+
+ // CacheEntry
+ structure(Entry, desc="...", interface="AbstractCacheEntry") {
+ State CacheState, desc="cache state";
+ DataBlock DataBlk, desc="Data in the block";
+ }
+
+ // TBE fields
+ structure(TBE, desc="...") {
+ State TBEState, desc="Transient state";
+ DataBlock DataBlk, desc="data for the block, required for concurrent writebacks";
+ }
+
+ structure(TBETable, external="yes") {
+ TBE lookup(Address);
+ void allocate(Address);
+ void deallocate(Address);
+ bool isPresent(Address);
+ }
+
+
+ // STRUCTURES
+
+ TBETable TBEs, template_hack="<L1Cache_TBE>";
+
+
+ // FUNCTIONS
+
+ // cpu/testers/networktest/networktest.cc generates packets of the type
+ // ReadReq, INST_FETCH, and WriteReq.
+ // These are converted to LD, IFETCH and ST by mem/ruby/system/RubyPort.cc.
+ // These are then sent to the sequencer, which sends them here.
+ // Network_test-cache.sm tags LD, IFETCH and ST as Request, Forward,
+ // and Response Events respectively, which are then injected into
+ // virtual networks 0, 1 and 2 respectively.
+ // This models traffic of different types within the network.
+ //
+ // Note that requests and forwards are MessageSizeType:Control,
+ // while responses are MessageSizeType:Data.
+ //
+ Event mandatory_request_type_to_event(RubyRequestType type) {
+ if (type == RubyRequestType:LD) {
+ return Event:Request;
+ } else if (type == RubyRequestType:IFETCH) {
+ return Event:Forward;
+ } else if (type == RubyRequestType:ST) {
+ return Event:Response;
+ } else {
+ error("Invalid RubyRequestType");
+ }
+ }
+
+
+ State getState(TBE tbe, Entry cache_entry, Address addr) {
+ return State:I;
+ }
+
+ void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
+
+ }
+
+ Entry getCacheEntry(Address address), return_by_pointer="yes" {
+ return OOD;
+ }
+
+
+ // NETWORK PORTS
+
+ out_port(requestNetwork_out, RequestMsg, requestFromCache);
+ out_port(forwardNetwork_out, RequestMsg, forwardFromCache);
+ out_port(responseNetwork_out, RequestMsg, responseFromCache);
+
+ // Mandatory Queue
+ in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
+ if (mandatoryQueue_in.isReady()) {
+ peek(mandatoryQueue_in, CacheMsg) {
+ trigger(mandatory_request_type_to_event(in_msg.Type),
+ in_msg.LineAddress,
+ getCacheEntry(in_msg.LineAddress),
+ TBEs[in_msg.LineAddress]);
+ }
+ }
+ }
+
+ // ACTIONS
+
+ // The destination directory of the packets is embedded in the address
+ // map_Address_to_Directory is used to retrieve it.
+
+ action(a_issueRequest, "a", desc="Issue a request") {
+ enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:MSG;
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
+ //out_msg.Destination := broadcast(MachineType:Directory);
+ out_msg.MessageSize := MessageSizeType:Control;
+ }
+ }
+
+ action(b_issueForward, "b", desc="Issue a forward") {
+ enqueue(forwardNetwork_out, RequestMsg, latency=issue_latency) {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:MSG;
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.MessageSize := MessageSizeType:Control;
+ }
+ }
+
+ action(c_issueResponse, "c", desc="Issue a response") {
+ enqueue(responseNetwork_out, RequestMsg, latency=issue_latency) {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:MSG;
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.MessageSize := MessageSizeType:Data;
+ }
+ }
+
+ action(m_popMandatoryQueue, "m", desc="Pop the mandatory request queue") {
+ mandatoryQueue_in.dequeue();
+ }
+
+ action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
+ sequencer.readCallback(address, dummyData);
+ }
+
+ action(s_store_hit, "s", desc="Notify sequencer that store completed.") {
+ sequencer.writeCallback(address, dummyData);
+ }
+
+
+ // TRANSITIONS
+
+ // sequencer hit call back is performed after injecting the packets.
+ // The goal of the Network_test protocol is only to inject packets into
+ // the network, not to keep track of them via TBEs.
+
+ transition(I, Response) {
+ s_store_hit;
+ c_issueResponse;
+ m_popMandatoryQueue;
+ }
+
+ transition(I, Request) {
+ r_load_hit;
+ a_issueRequest;
+ m_popMandatoryQueue;
+ }
+ transition(I, Forward) {
+ r_load_hit;
+ b_issueForward;
+ m_popMandatoryQueue;
+ }
+
+}
diff --git a/src/mem/protocol/Network_test-dir.sm b/src/mem/protocol/Network_test-dir.sm
new file mode 100644
index 000000000..6d2bbf359
--- /dev/null
+++ b/src/mem/protocol/Network_test-dir.sm
@@ -0,0 +1,136 @@
+/*
+ * 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: Brad Beckmann
+ * Tushar Krishna
+ */
+
+
+machine(Directory, "Network_test Directory")
+:
+{
+
+ MessageBuffer requestToDir, network="From", virtual_network="0", ordered="false";
+ MessageBuffer forwardToDir, network="From", virtual_network="1", ordered="false";
+ MessageBuffer responseToDir, network="From", virtual_network="2", ordered="false";
+
+ // STATES
+ state_declaration(State, desc="Directory states", default="Directory_State_I") {
+ // Base states
+ I, AccessPermission:Invalid, desc="Invalid";
+ }
+
+ // Events
+ enumeration(Event, desc="Directory events") {
+ // processor requests
+ Receive_Request, desc="Receive Message";
+ Receive_Forward, desc="Receive Message";
+ Receive_Response, desc="Receive Message";
+ }
+
+ // TYPES
+ // DirectoryEntry
+ structure(Entry, desc="...") {
+ State DirectoryState, desc="Directory state";
+ DataBlock DataBlk, desc="data for the block";
+ }
+
+ // ** OBJECTS **
+ State getState(Address addr) {
+ return State:I;
+ }
+
+ void setState(Address addr, State state) {
+
+ }
+
+ // ** IN_PORTS **
+
+ in_port(requestQueue_in, RequestMsg, requestToDir) {
+ if (requestQueue_in.isReady()) {
+ peek(requestQueue_in, RequestMsg) {
+ if (in_msg.Type == CoherenceRequestType:MSG) {
+ trigger(Event:Receive_Request, in_msg.Address);
+ } else {
+ error("Invalid message");
+ }
+ }
+ }
+ }
+ in_port(forwardQueue_in, RequestMsg, forwardToDir) {
+ if (forwardQueue_in.isReady()) {
+ peek(forwardQueue_in, RequestMsg) {
+ if (in_msg.Type == CoherenceRequestType:MSG) {
+ trigger(Event:Receive_Forward, in_msg.Address);
+ } else {
+ error("Invalid message");
+ }
+ }
+ }
+ }
+ in_port(responseQueue_in, RequestMsg, responseToDir) {
+ if (responseQueue_in.isReady()) {
+ peek(responseQueue_in, RequestMsg) {
+ if (in_msg.Type == CoherenceRequestType:MSG) {
+ trigger(Event:Receive_Response, in_msg.Address);
+ } else {
+ error("Invalid message");
+ }
+ }
+ }
+ }
+
+ // Actions
+
+ action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
+ requestQueue_in.dequeue();
+ }
+
+ action(f_popIncomingForwardQueue, "f", desc="Pop incoming forward queue") {
+ forwardQueue_in.dequeue();
+ }
+
+ action(r_popIncomingResponseQueue, "r", desc="Pop incoming response queue") {
+ responseQueue_in.dequeue();
+ }
+
+ // TRANSITIONS
+
+ // The directory simply drops the received packets.
+ // The goal of Network_test is only to track network stats.
+
+ transition(I, Receive_Request) {
+ i_popIncomingRequestQueue;
+ }
+ transition(I, Receive_Forward) {
+ f_popIncomingForwardQueue;
+ }
+ transition(I, Receive_Response) {
+ r_popIncomingResponseQueue;
+ }
+}
diff --git a/src/mem/protocol/Network_test-msg.sm b/src/mem/protocol/Network_test-msg.sm
new file mode 100644
index 000000000..7de35f176
--- /dev/null
+++ b/src/mem/protocol/Network_test-msg.sm
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+
+// CoherenceRequestType
+enumeration(CoherenceRequestType, desc="...") {
+ MSG, desc="Message";
+}
+
+// RequestMsg (and also forwarded requests)
+structure(RequestMsg, desc="...", interface="NetworkMessage") {
+ Address Address, desc="Physical address for this request";
+ CoherenceRequestType Type, desc="Type of request (GetS, GetX, PutX, etc)";
+ MachineID Requestor, desc="Node who initiated the request";
+ NetDest Destination, desc="Multicast destination mask";
+ DataBlock DataBlk, desc="data for the cache line";
+ MessageSizeType MessageSize, desc="size category of the message";
+}
+
+
+enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
+ READ, desc="Memory Read";
+ WRITE, desc="Memory Write";
+ NULL, desc="Invalid";
+}
+
+enumeration(DMAResponseType, desc="...", default="DMAResponseType_NULL") {
+ DATA, desc="DATA read";
+ ACK, desc="ACK write";
+ NULL, desc="Invalid";
+}
+
+structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
+ DMARequestType Type, desc="Request type (read/write)";
+ Address PhysicalAddress, desc="Physical address for this request";
+ Address LineAddress, desc="Line address for this request";
+ NetDest Destination, desc="Destination";
+ DataBlock DataBlk, desc="DataBlk attached to this request";
+ int Len, desc="The length of the request";
+ MessageSizeType MessageSize, desc="size category of the message";
+}
+
+structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
+ DMAResponseType Type, desc="Response type (DATA/ACK)";
+ Address PhysicalAddress, desc="Physical address for this request";
+ Address LineAddress, desc="Line address for this request";
+ NetDest Destination, desc="Destination";
+ DataBlock DataBlk, desc="DataBlk attached to this request";
+ MessageSizeType MessageSize, desc="size category of the message";
+}
+
+
diff --git a/src/mem/protocol/Network_test.slicc b/src/mem/protocol/Network_test.slicc
new file mode 100644
index 000000000..9629a385c
--- /dev/null
+++ b/src/mem/protocol/Network_test.slicc
@@ -0,0 +1,4 @@
+Network_test-msg.sm
+Network_test-cache.sm
+Network_test-dir.sm
+standard_1level_CMP-protocol.sm
diff --git a/src/mem/protocol/SConsopts b/src/mem/protocol/SConsopts
index 0e794d5f0..dac52d742 100644
--- a/src/mem/protocol/SConsopts
+++ b/src/mem/protocol/SConsopts
@@ -48,6 +48,7 @@ all_protocols = [
'MOSI_SMP_directory_1level',
'MSI_MOSI_CMP_directory',
'MOESI_hammer',
+ 'Network_test',
]
opt = EnumVariable('PROTOCOL', 'Coherence protocol for Ruby', 'MI_example',
diff --git a/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc b/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc
index 3e5e1cbe8..19b4c3d04 100644
--- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc
+++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.cc
@@ -38,7 +38,6 @@ BaseGarnetNetwork::BaseGarnetNetwork(const Params *p)
m_vcs_per_class = p->vcs_per_class;
m_buffers_per_data_vc = p->buffers_per_data_vc;
m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
- m_using_network_testing = p->using_network_testing;
}
void
diff --git a/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh b/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh
index 4a1856e43..d01225232 100644
--- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh
+++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh
@@ -36,6 +36,7 @@
#ifndef __MEM_RUBY_NETWORK_GARNET_BASEGARNETNETWORK_HH__
#define __MEM_RUBY_NETWORK_GARNET_BASEGARNETNETWORK_HH__
+#include "math.h"
#include "mem/ruby/network/garnet/NetworkHeader.hh"
#include "mem/ruby/network/Network.hh"
#include "params/BaseGarnetNetwork.hh"
@@ -47,7 +48,6 @@ class BaseGarnetNetwork : public Network
BaseGarnetNetwork(const Params *p);
void init();
- bool isNetworkTesting() {return m_using_network_testing; }
int getFlitSize() {return m_flit_size; }
int getNumPipeStages() {return m_number_of_pipe_stages; }
int getVCsPerClass() {return m_vcs_per_class; }
@@ -60,7 +60,6 @@ class BaseGarnetNetwork : public Network
int m_vcs_per_class;
int m_buffers_per_data_vc;
int m_buffers_per_ctrl_vc;
- bool m_using_network_testing;
};
#endif // __MEM_RUBY_NETWORK_GARNET_BASEGARNETNETWORK_HH__
diff --git a/src/mem/ruby/network/garnet/BaseGarnetNetwork.py b/src/mem/ruby/network/garnet/BaseGarnetNetwork.py
index 44b6bd149..3594e93b6 100644
--- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.py
+++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.py
@@ -39,4 +39,3 @@ class BaseGarnetNetwork(RubyNetwork):
vcs_per_class = Param.Int(4, "virtual channels per message class");
buffers_per_data_vc = Param.Int(4, "buffers per data virtual channel");
buffers_per_ctrl_vc = Param.Int(1, "buffers per ctrl virtual channel");
- using_network_testing = Param.Bool(False, "network testing enable");
diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
index dbfabc8f1..f0b8ccce7 100644
--- a/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
+++ b/src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
@@ -307,15 +307,15 @@ GarnetNetwork_d::printStats(ostream& out) const
}
out << "-------------" << endl;
- // out << "Total flits injected = " << m_flits_injected << endl;
- // out << "Total flits received = " << m_flits_received << endl;
+ out << "Total flits injected = " << m_flits_injected << endl;
+ out << "Total flits received = " << m_flits_received << endl;
out << "Average network latency = "
<< ((double) m_network_latency/ (double) m_flits_received)<< endl;
- // out << "Average queueing latency = "
- // << ((double) m_queueing_latency/ (double) m_flits_received)<< endl;
- // out << "Average latency = "
- // << ((double) (m_queueing_latency + m_network_latency) /
- // (double) m_flits_received)<< endl;
+ out << "Average queueing (at source NI) latency = "
+ << ((double) m_queueing_latency/ (double) m_flits_received)<< endl;
+ out << "Average latency = "
+ << ((double) (m_queueing_latency + m_network_latency) /
+ (double) m_flits_received)<< endl;
out << "-------------" << endl;
double m_total_link_power = 0.0;
diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
index 8299a294f..14105a38c 100644
--- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
+++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
@@ -241,12 +241,9 @@ NetworkInterface_d::wakeup()
bool free_signal = false;
if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
free_signal = true;
- // When we are doing network only testing, the messages do not
- // have to be buffered into the protocol buffers
- if (!m_net_ptr->isNetworkTesting()) {
- outNode_ptr[t_flit->get_vnet()]->
- enqueue(t_flit->get_msg_ptr(), 1);
- }
+
+ outNode_ptr[t_flit->get_vnet()]->enqueue(
+ t_flit->get_msg_ptr(), 1);
}
// Simply send a credit back since we are not buffering
// this flit in the NI
diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc
index afc841a1b..60ec09e58 100644
--- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc
+++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc
@@ -262,12 +262,8 @@ NetworkInterface::wakeup()
DPRINTF(RubyNetwork, "m_id: %d, Message delivered at time: %lld\n",
m_id, g_eventQueue_ptr->getTime());
- // When we are doing network only testing, the messages do not
- // have to be buffered into the message buffers of the protocol
- if (!m_net_ptr->isNetworkTesting()) {
- outNode_ptr[t_flit->get_vnet()]->enqueue(
- t_flit->get_msg_ptr(), 1);
- }
+ outNode_ptr[t_flit->get_vnet()]->enqueue(
+ t_flit->get_msg_ptr(), 1);
// signal the upstream router that this vc can be freed now
inNetLink->release_vc_link(t_flit->get_vc(),
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index 6b0f6e49f..a5f1a06fa 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -77,6 +77,8 @@ Sequencer::Sequencer(const Params *p)
assert(m_deadlock_threshold > 0);
assert(m_instCache_ptr != NULL);
assert(m_dataCache_ptr != NULL);
+
+ m_usingNetworkTester = p->using_network_tester;
}
Sequencer::~Sequencer()
@@ -390,7 +392,11 @@ Sequencer::writeCallback(const Address& address,
// For Alpha, properly handle LL, SC, and write requests with respect to
// locked cache blocks.
//
- bool success = handleLlsc(address, request);
+ // Not valid for Network_test protocl
+ //
+ bool success = true;
+ if(!m_usingNetworkTester)
+ success = handleLlsc(address, request);
if (request->ruby_request.type == RubyRequestType_Locked_RMW_Read) {
m_controller->blockOnQueue(address, m_mandatory_q_ptr);
diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh
index 14b6997e8..ff3a0d5b1 100644
--- a/src/mem/ruby/system/Sequencer.hh
+++ b/src/mem/ruby/system/Sequencer.hh
@@ -152,6 +152,8 @@ class Sequencer : public RubyPort, public Consumer
int m_load_waiting_on_store_cycles;
int m_load_waiting_on_load_cycles;
+ bool m_usingNetworkTester;
+
class SequencerWakeupEvent : public Event
{
private:
diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py
index f6d847e10..16fb795f8 100644
--- a/src/mem/ruby/system/Sequencer.py
+++ b/src/mem/ruby/system/Sequencer.py
@@ -40,6 +40,7 @@ class RubyPort(MemObject):
physmem = Param.PhysicalMemory("")
physMemPort = Port("port to physical memory")
using_ruby_tester = Param.Bool(False, "")
+ using_network_tester = Param.Bool(False, "")
access_phys_mem = Param.Bool(True,
"should the rubyport atomically update phys_mem")