This patch adds the network tester for simple and garnet networks.
authorTushar Krishna <tushar@csail.mit.edu>
Tue, 22 Mar 2011 02:51:58 +0000 (22:51 -0400)
committerTushar Krishna <tushar@csail.mit.edu>
Tue, 22 Mar 2011 02:51:58 +0000 (22:51 -0400)
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.

21 files changed:
build_opts/ALPHA_SE_Network_test [new file with mode: 0644]
configs/example/ruby_network_test.py [new file with mode: 0644]
configs/ruby/Network_test.py [new file with mode: 0644]
src/cpu/testers/networktest/NetworkTest.py [new file with mode: 0644]
src/cpu/testers/networktest/SConscript [new file with mode: 0644]
src/cpu/testers/networktest/networktest.cc [new file with mode: 0644]
src/cpu/testers/networktest/networktest.hh [new file with mode: 0644]
src/mem/protocol/Network_test-cache.sm [new file with mode: 0644]
src/mem/protocol/Network_test-dir.sm [new file with mode: 0644]
src/mem/protocol/Network_test-msg.sm [new file with mode: 0644]
src/mem/protocol/Network_test.slicc [new file with mode: 0644]
src/mem/protocol/SConsopts
src/mem/ruby/network/garnet/BaseGarnetNetwork.cc
src/mem/ruby/network/garnet/BaseGarnetNetwork.hh
src/mem/ruby/network/garnet/BaseGarnetNetwork.py
src/mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.cc
src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc
src/mem/ruby/system/Sequencer.cc
src/mem/ruby/system/Sequencer.hh
src/mem/ruby/system/Sequencer.py

diff --git a/build_opts/ALPHA_SE_Network_test b/build_opts/ALPHA_SE_Network_test
new file mode 100644 (file)
index 0000000..a092a94
--- /dev/null
@@ -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 (file)
index 0000000..6abf505
--- /dev/null
@@ -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 (file)
index 0000000..fe1559f
--- /dev/null
@@ -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 (file)
index 0000000..d4eef09
--- /dev/null
@@ -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 (file)
index 0000000..b658ac0
--- /dev/null
@@ -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 (file)
index 0000000..4f4c309
--- /dev/null
@@ -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 (file)
index 0000000..923f47d
--- /dev/null
@@ -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 (file)
index 0000000..603c1f5
--- /dev/null
@@ -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 (file)
index 0000000..6d2bbf3
--- /dev/null
@@ -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 (file)
index 0000000..7de35f1
--- /dev/null
@@ -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 (file)
index 0000000..9629a38
--- /dev/null
@@ -0,0 +1,4 @@
+Network_test-msg.sm
+Network_test-cache.sm
+Network_test-dir.sm
+standard_1level_CMP-protocol.sm
index 0e794d5f05c1479485fcb4d9825e52119fee9899..dac52d742c74fe6131a2a5b82fc9807b695f87d0 100644 (file)
@@ -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',
index 3e5e1cbe81ba26fdd2914f1e0de8b6045c6c074e..19b4c3d04d8030772e81ce18b2f62f2d3981b74a 100644 (file)
@@ -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
index 4a1856e432bf41359bd8ce8b42f07503423b1359..d012252327cc06ee4196565264a04543eaac941e 100644 (file)
@@ -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__
index 44b6bd149561652a1c32c6be7e5239495157de24..3594e93b6d2e9fb72a139ef15bdf9a0b1535ada9 100644 (file)
@@ -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");
index dbfabc8f1267c59e5360ba113310270949b7b662..f0b8ccce7cb8ed124992fef036f7da530488b8a8 100644 (file)
@@ -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;
index 8299a294ffc32f6d4d0c4821d41f042b2f6dee8b..14105a38cc9611666a852563df45846100585678 100644 (file)
@@ -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
index afc841a1b9decb51e5e0eaf32213f18d5d0980f5..60ec09e588dbeac83b7c790fbd9792a8af295370 100644 (file)
@@ -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(),
index 6b0f6e49f8f11bbe5a08592a4f4369139172e481..a5f1a06fab1a15fa1d012105f703065048e0554a 100644 (file)
@@ -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);
index 14b6997e8ed2437445ee992d4e3d3b7e4bf7bb54..ff3a0d5b1bcaeb6beef7fd5a2c5fe6c69a485196 100644 (file)
@@ -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:
index f6d847e10544d0a0e7a176bfcb8700ed7ec573c2..16fb795f889a784e277f9fa989562e6d31dda9eb 100644 (file)
@@ -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")