mem-garnet: Upgrade garnet version to 3.0
authorSrikant Bharadwaj <srikant.bharadwaj@amd.com>
Thu, 10 Sep 2020 07:39:45 +0000 (03:39 -0400)
committerBobby R. Bruce <bbruce@ucdavis.edu>
Fri, 11 Sep 2020 05:38:09 +0000 (05:38 +0000)
This version of garnet includes HeteroGarnet which
supports heterogenous interconnect systems, flexible
router and link configurations, and better debugging
resources.
This patch changes the garnet directory structure
to not include the version number. The user will be
informed about the garnet version being used.

Change-Id: Id4763421528305193ae0cd10c159b385a9513553
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/34259
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
77 files changed:
configs/network/Network.py
src/mem/ruby/network/garnet/CommonTypes.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/Credit.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/Credit.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/CreditLink.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/CrossbarSwitch.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/CrossbarSwitch.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/GarnetLink.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/GarnetLink.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/GarnetLink.py [new file with mode: 0644]
src/mem/ruby/network/garnet/GarnetNetwork.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/GarnetNetwork.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/GarnetNetwork.py [new file with mode: 0644]
src/mem/ruby/network/garnet/InputUnit.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/InputUnit.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/NetworkBridge.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/NetworkBridge.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/NetworkInterface.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/NetworkInterface.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/NetworkLink.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/NetworkLink.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/OutVcState.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/OutVcState.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/OutputUnit.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/OutputUnit.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/README.txt [new file with mode: 0644]
src/mem/ruby/network/garnet/Router.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/Router.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/RoutingUnit.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/RoutingUnit.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/SConscript [new file with mode: 0644]
src/mem/ruby/network/garnet/SwitchAllocator.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/SwitchAllocator.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/VirtualChannel.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/VirtualChannel.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/flit.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/flit.hh [new file with mode: 0644]
src/mem/ruby/network/garnet/flitBuffer.cc [new file with mode: 0644]
src/mem/ruby/network/garnet/flitBuffer.hh [new file with mode: 0644]
src/mem/ruby/network/garnet2.0/CommonTypes.hh [deleted file]
src/mem/ruby/network/garnet2.0/Credit.cc [deleted file]
src/mem/ruby/network/garnet2.0/Credit.hh [deleted file]
src/mem/ruby/network/garnet2.0/CreditLink.hh [deleted file]
src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc [deleted file]
src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh [deleted file]
src/mem/ruby/network/garnet2.0/GarnetLink.cc [deleted file]
src/mem/ruby/network/garnet2.0/GarnetLink.hh [deleted file]
src/mem/ruby/network/garnet2.0/GarnetLink.py [deleted file]
src/mem/ruby/network/garnet2.0/GarnetNetwork.cc [deleted file]
src/mem/ruby/network/garnet2.0/GarnetNetwork.hh [deleted file]
src/mem/ruby/network/garnet2.0/GarnetNetwork.py [deleted file]
src/mem/ruby/network/garnet2.0/InputUnit.cc [deleted file]
src/mem/ruby/network/garnet2.0/InputUnit.hh [deleted file]
src/mem/ruby/network/garnet2.0/NetworkBridge.cc [deleted file]
src/mem/ruby/network/garnet2.0/NetworkBridge.hh [deleted file]
src/mem/ruby/network/garnet2.0/NetworkInterface.cc [deleted file]
src/mem/ruby/network/garnet2.0/NetworkInterface.hh [deleted file]
src/mem/ruby/network/garnet2.0/NetworkLink.cc [deleted file]
src/mem/ruby/network/garnet2.0/NetworkLink.hh [deleted file]
src/mem/ruby/network/garnet2.0/OutVcState.cc [deleted file]
src/mem/ruby/network/garnet2.0/OutVcState.hh [deleted file]
src/mem/ruby/network/garnet2.0/OutputUnit.cc [deleted file]
src/mem/ruby/network/garnet2.0/OutputUnit.hh [deleted file]
src/mem/ruby/network/garnet2.0/README.txt [deleted file]
src/mem/ruby/network/garnet2.0/Router.cc [deleted file]
src/mem/ruby/network/garnet2.0/Router.hh [deleted file]
src/mem/ruby/network/garnet2.0/RoutingUnit.cc [deleted file]
src/mem/ruby/network/garnet2.0/RoutingUnit.hh [deleted file]
src/mem/ruby/network/garnet2.0/SConscript [deleted file]
src/mem/ruby/network/garnet2.0/SwitchAllocator.cc [deleted file]
src/mem/ruby/network/garnet2.0/SwitchAllocator.hh [deleted file]
src/mem/ruby/network/garnet2.0/VirtualChannel.cc [deleted file]
src/mem/ruby/network/garnet2.0/VirtualChannel.hh [deleted file]
src/mem/ruby/network/garnet2.0/flit.cc [deleted file]
src/mem/ruby/network/garnet2.0/flit.hh [deleted file]
src/mem/ruby/network/garnet2.0/flitBuffer.cc [deleted file]
src/mem/ruby/network/garnet2.0/flitBuffer.hh [deleted file]

index 20d68c0ae9b549e69556d98b05ecedd6e3bb767c..a907d9ac492830ef38149f3957418b61ea0bee7b 100644 (file)
@@ -31,7 +31,7 @@ import math
 import m5
 from m5.objects import *
 from m5.defines import buildEnv
-from m5.util import addToPath, fatal
+from m5.util import addToPath, fatal, warn
 
 def define_options(parser):
     # By default, ruby uses the simple timing cpu
@@ -42,8 +42,9 @@ def define_options(parser):
     parser.add_option("--mesh-rows", type="int", default=0,
                       help="the number of rows in the mesh topology")
     parser.add_option("--network", type="choice", default="simple",
-                      choices=['simple', 'garnet2.0'],
-                      help="'simple'|'garnet2.0'")
+                      choices=['simple', 'garnet'],
+                      help="""'simple'|'garnet' (garnet2.0 will be
+                      deprecated.)""")
     parser.add_option("--router-latency", action="store", type="int",
                       default=1,
                       help="""number of pipeline stages in the garnet router.
@@ -65,8 +66,8 @@ def define_options(parser):
                       default=0,
                       help="""routing algorithm in network.
                             0: weight-based table
-                            1: XY (for Mesh. see garnet2.0/RoutingUnit.cc)
-                            2: Custom (see garnet2.0/RoutingUnit.cc""")
+                            1: XY (for Mesh. see garnet/RoutingUnit.cc)
+                            2: Custom (see garnet/RoutingUnit.cc""")
     parser.add_option("--network-fault-model", action="store_true",
                       default=False,
                       help="""enable network fault model:
@@ -77,8 +78,16 @@ def define_options(parser):
 
 def create_network(options, ruby):
 
-    # Set the network classes based on the command line options
+    # Allow legacy users to use garnet through garnet2.0 option
+    # until next gem5 release.
     if options.network == "garnet2.0":
+        warn("Usage of option 'garnet2.0' will be depracated. " \
+            "Please use 'garnet' for using the latest garnet " \
+            "version. Current version: 3.0")
+        options.network = "garnet"
+
+    # Set the network classes based on the command line options
+    if options.network == "garnet":
         NetworkClass = GarnetNetwork
         IntLinkClass = GarnetIntLink
         ExtLinkClass = GarnetExtLink
@@ -101,7 +110,7 @@ def create_network(options, ruby):
 
 def init_network(options, network, InterfaceClass):
 
-    if options.network == "garnet2.0":
+    if options.network == "garnet":
         network.num_rows = options.mesh_rows
         network.vcs_per_vnet = options.vcs_per_vnet
         network.ni_flit_size = options.link_width_bits / 8
@@ -181,6 +190,6 @@ def init_network(options, network, InterfaceClass):
         network.netifs = netifs
 
     if options.network_fault_model:
-        assert(options.network == "garnet2.0")
+        assert(options.network == "garnet")
         network.enable_fault_model = True
         network.fault_model = FaultModel()
diff --git a/src/mem/ruby/network/garnet/CommonTypes.hh b/src/mem/ruby/network/garnet/CommonTypes.hh
new file mode 100644 (file)
index 0000000..affbccc
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_COMMONTYPES_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_COMMONTYPES_HH__
+
+#include "mem/ruby/common/NetDest.hh"
+
+// All common enums and typedefs go here
+
+enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_,
+                CREDIT_, NUM_FLIT_TYPE_};
+enum VC_state_type {IDLE_, VC_AB_, ACTIVE_, NUM_VC_STATE_TYPE_};
+enum VNET_type {CTRL_VNET_, DATA_VNET_, NULL_VNET_, NUM_VNET_TYPE_};
+enum flit_stage {I_, VA_, SA_, ST_, LT_, NUM_FLIT_STAGE_};
+enum link_type { EXT_IN_, EXT_OUT_, INT_, NUM_LINK_TYPES_ };
+enum RoutingAlgorithm { TABLE_ = 0, XY_ = 1, CUSTOM_ = 2,
+                        NUM_ROUTING_ALGORITHM_};
+
+struct RouteInfo
+{
+    RouteInfo()
+        : vnet(0), src_ni(0), src_router(0), dest_ni(0), dest_router(0),
+          hops_traversed(0)
+    {}
+
+    // destination format for table-based routing
+    int vnet;
+    NetDest net_dest;
+
+    // src and dest format for topology-specific routing
+    int src_ni;
+    int src_router;
+    int dest_ni;
+    int dest_router;
+    int hops_traversed;
+};
+
+#define INFINITE_ 10000
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_COMMONTYPES_HH__
diff --git a/src/mem/ruby/network/garnet/Credit.cc b/src/mem/ruby/network/garnet/Credit.cc
new file mode 100644 (file)
index 0000000..b24003f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "mem/ruby/network/garnet/Credit.hh"
+
+#include "base/trace.hh"
+#include "debug/RubyNetwork.hh"
+
+// Credit Signal for buffers inside VC
+// Carries m_vc (inherits from flit.hh)
+// and m_is_free_signal (whether VC is free or not)
+
+Credit::Credit(int vc, bool is_free_signal, Tick curTime)
+    : flit(0, vc, 0, RouteInfo(), 0, nullptr, 0, 0, curTime)
+{
+    m_is_free_signal = is_free_signal;
+    m_type = CREDIT_;
+}
+
+flit *
+Credit::serialize(int ser_id, int parts, uint32_t bWidth)
+{
+    DPRINTF(RubyNetwork, "Serializing a credit\n");
+    bool new_free = false;
+    if ((ser_id+1 == parts) && m_is_free_signal) {
+        new_free = true;
+    }
+    Credit *new_credit_flit = new Credit(m_vc, new_free, m_time);
+    return new_credit_flit;
+}
+
+flit *
+Credit::deserialize(int des_id, int num_flits, uint32_t bWidth)
+{
+    DPRINTF(RubyNetwork, "DeSerializing a credit vc:%d free:%d\n",
+    m_vc, m_is_free_signal);
+    if (m_is_free_signal) {
+        // We are not going to get anymore credits for this vc
+        // So send a credit in any case
+        return new Credit(m_vc, true, m_time);
+    }
+
+    return new Credit(m_vc, false, m_time);
+}
+
+void
+Credit::print(std::ostream& out) const
+{
+    out << "[Credit:: ";
+    out << "Type=" << m_type << " ";
+    out << "VC=" << m_vc << " ";
+    out << "FreeVC=" << m_is_free_signal << " ";
+    out << "Set Time=" << m_time << " ";
+    out << "]";
+}
+
+
+
diff --git a/src/mem/ruby/network/garnet/Credit.hh b/src/mem/ruby/network/garnet/Credit.hh
new file mode 100644 (file)
index 0000000..db5823c
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_CREDIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_CREDIT_HH__
+
+#include <cassert>
+#include <iostream>
+
+#include "base/types.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+
+// Credit Signal for buffers inside VC
+// Carries m_vc (inherits from flit.hh)
+// and m_is_free_signal (whether VC is free or not)
+
+class Credit : public flit
+{
+  public:
+    Credit() {};
+    Credit(int vc, bool is_free_signal, Tick curTime);
+
+    // Functions used by SerDes
+    flit* serialize(int ser_id, int parts, uint32_t bWidth);
+    flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
+    void print(std::ostream& out) const;
+
+    ~Credit() {};
+
+    bool is_free_signal() { return m_is_free_signal; }
+
+  private:
+    bool m_is_free_signal;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_CREDIT_HH__
diff --git a/src/mem/ruby/network/garnet/CreditLink.hh b/src/mem/ruby/network/garnet/CreditLink.hh
new file mode 100644 (file)
index 0000000..8735824
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_CREDITLINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_CREDITLINK_HH__
+
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "params/CreditLink.hh"
+
+class CreditLink : public NetworkLink
+{
+  public:
+    typedef CreditLinkParams Params;
+    CreditLink(const Params *p) : NetworkLink(p) {}
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_CREDITLINK_HH__
diff --git a/src/mem/ruby/network/garnet/CrossbarSwitch.cc b/src/mem/ruby/network/garnet/CrossbarSwitch.cc
new file mode 100644 (file)
index 0000000..6b158df
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/CrossbarSwitch.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+
+CrossbarSwitch::CrossbarSwitch(Router *router)
+  : Consumer(router), m_router(router), m_num_vcs(m_router->get_num_vcs()),
+    m_crossbar_activity(0), switchBuffers(0)
+{
+}
+
+void
+CrossbarSwitch::init()
+{
+    switchBuffers.resize(m_router->get_num_inports());
+}
+
+/*
+ * The wakeup function of the CrossbarSwitch loops through all input ports,
+ * and sends the winning flit (from SA) out of its output port on to the
+ * output link. The output link is scheduled for wakeup in the next cycle.
+ */
+
+void
+CrossbarSwitch::wakeup()
+{
+    DPRINTF(RubyNetwork, "CrossbarSwitch at Router %d woke up "
+            "at time: %lld\n",
+            m_router->get_id(), m_router->curCycle());
+
+    for (auto& switch_buffer : switchBuffers) {
+        if (!switch_buffer.isReady(curTick())) {
+            continue;
+        }
+
+        flit *t_flit = switch_buffer.peekTopFlit();
+        if (t_flit->is_stage(ST_, curTick())) {
+            int outport = t_flit->get_outport();
+
+            // flit performs LT_ in the next cycle
+            t_flit->advance_stage(LT_, m_router->clockEdge(Cycles(1)));
+            t_flit->set_time(m_router->clockEdge(Cycles(1)));
+
+            // This will take care of waking up the Network Link
+            // in the next cycle
+            m_router->getOutputUnit(outport)->insert_flit(t_flit);
+            switch_buffer.getTopFlit();
+            m_crossbar_activity++;
+        }
+    }
+}
+
+uint32_t
+CrossbarSwitch::functionalWrite(Packet *pkt)
+{
+   uint32_t num_functional_writes = 0;
+
+   for (auto& switch_buffer : switchBuffers) {
+       num_functional_writes += switch_buffer.functionalWrite(pkt);
+   }
+
+   return num_functional_writes;
+}
+
+void
+CrossbarSwitch::resetStats()
+{
+    m_crossbar_activity = 0;
+}
diff --git a/src/mem/ruby/network/garnet/CrossbarSwitch.hh b/src/mem/ruby/network/garnet/CrossbarSwitch.hh
new file mode 100644 (file)
index 0000000..ee3a5ec
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_CROSSBARSWITCH_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_CROSSBARSWITCH_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+class Router;
+
+class CrossbarSwitch : public Consumer
+{
+  public:
+    CrossbarSwitch(Router *router);
+    ~CrossbarSwitch() = default;
+    void wakeup();
+    void init();
+    void print(std::ostream& out) const {};
+
+    inline void
+    update_sw_winner(int inport, flit *t_flit)
+    {
+        switchBuffers[inport].insert(t_flit);
+    }
+
+    inline double get_crossbar_activity() { return m_crossbar_activity; }
+
+    uint32_t functionalWrite(Packet *pkt);
+    void resetStats();
+
+  private:
+    Router *m_router;
+    int m_num_vcs;
+    double m_crossbar_activity;
+    std::vector<flitBuffer> switchBuffers;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_CROSSBARSWITCH_HH__
diff --git a/src/mem/ruby/network/garnet/GarnetLink.cc b/src/mem/ruby/network/garnet/GarnetLink.cc
new file mode 100644 (file)
index 0000000..ae96933
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/GarnetLink.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/NetworkBridge.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+
+GarnetIntLink::GarnetIntLink(const Params *p)
+    : BasicIntLink(p)
+{
+    // Uni-directional
+
+    m_network_link = p->network_link;
+    m_credit_link = p->credit_link;
+
+    srcCdcEn = p->src_cdc;
+    dstCdcEn = p->dst_cdc;
+
+    srcSerdesEn = p->src_serdes;
+    dstSerdesEn = p->dst_serdes;
+
+    srcBridgeEn = false;
+    dstBridgeEn = false;
+
+    if (srcCdcEn || srcSerdesEn) {
+        srcBridgeEn = true;
+        srcNetBridge = p->src_net_bridge;
+        srcCredBridge = p->src_cred_bridge;
+    }
+    if (dstCdcEn || dstSerdesEn) {
+        dstBridgeEn = true;
+        dstNetBridge = p->dst_net_bridge;
+        dstCredBridge = p->dst_cred_bridge;
+    }
+
+}
+
+void
+GarnetIntLink::init()
+{
+    if (srcBridgeEn) {
+        assert(srcNetBridge && srcCredBridge);
+        srcNetBridge->initBridge(srcCredBridge, srcCdcEn, srcSerdesEn);
+        srcCredBridge->initBridge(srcNetBridge, srcCdcEn, srcSerdesEn);
+    }
+
+    if (dstBridgeEn) {
+        assert(dstNetBridge && dstCredBridge);
+        dstNetBridge->initBridge(dstCredBridge, dstCdcEn, dstSerdesEn);
+        dstCredBridge->initBridge(dstNetBridge, dstCdcEn, dstSerdesEn);
+    }
+}
+
+void
+GarnetIntLink::print(std::ostream& out) const
+{
+    out << name();
+}
+
+GarnetIntLink *
+GarnetIntLinkParams::create()
+{
+    return new GarnetIntLink(this);
+}
+
+GarnetExtLink::GarnetExtLink(const Params *p)
+    : BasicExtLink(p)
+{
+    // Bi-directional
+
+    // In
+    m_network_links[0] = p->network_links[0];
+    m_credit_links[0] = p->credit_links[0];
+
+    // Out
+    m_network_links[1] = p->network_links[1];
+    m_credit_links[1] = p->credit_links[1];
+
+
+    extCdcEn = p->ext_cdc;
+    intCdcEn = p->int_cdc;
+
+    extSerdesEn = p->ext_serdes;
+    intSerdesEn = p->int_serdes;
+
+    extBridgeEn = false;
+    intBridgeEn = false;
+
+    if (extCdcEn || extSerdesEn) {
+        extBridgeEn = true;
+        extNetBridge[0] = p->ext_net_bridge[0];
+        extCredBridge[0] = p->ext_cred_bridge[0];
+        extNetBridge[1] = p->ext_net_bridge[1];
+        extCredBridge[1] = p->ext_cred_bridge[1];
+    }
+
+    if (intCdcEn || intSerdesEn) {
+        intBridgeEn = true;
+        intNetBridge[0] = p->int_net_bridge[0];
+        intNetBridge[1] = p->int_net_bridge[1];
+        intCredBridge[0] = p->int_cred_bridge[0];
+        intCredBridge[1] = p->int_cred_bridge[1];
+    }
+
+}
+
+void
+GarnetExtLink::init()
+{
+    if (extBridgeEn) {
+        assert(extNetBridge[0] && extCredBridge[0] &&
+           extNetBridge[1] && extCredBridge[1]);
+        extNetBridge[0]->initBridge(extCredBridge[0], extCdcEn, extSerdesEn);
+        extCredBridge[0]->initBridge(extNetBridge[0], extCdcEn, extSerdesEn);
+        extNetBridge[1]->initBridge(extCredBridge[1], extCdcEn, extSerdesEn);
+        extCredBridge[1]->initBridge(extNetBridge[1], extCdcEn, extSerdesEn);
+    }
+
+    if (intBridgeEn) {
+        assert(intNetBridge[0] && intCredBridge[0] &&
+           intNetBridge[1] && intCredBridge[1]);
+        intNetBridge[0]->initBridge(intCredBridge[0], intCdcEn, intSerdesEn);
+        intCredBridge[0]->initBridge(intNetBridge[0], intCdcEn, intSerdesEn);
+        intNetBridge[1]->initBridge(intCredBridge[1], intCdcEn, intSerdesEn);
+        intCredBridge[1]->initBridge(intNetBridge[1], intCdcEn, intSerdesEn);
+    }
+}
+
+void
+GarnetExtLink::print(std::ostream& out) const
+{
+    out << name();
+}
+
+GarnetExtLink *
+GarnetExtLinkParams::create()
+{
+    return new GarnetExtLink(this);
+}
diff --git a/src/mem/ruby/network/garnet/GarnetLink.hh b/src/mem/ruby/network/garnet/GarnetLink.hh
new file mode 100644 (file)
index 0000000..554a0da
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_GARNETLINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_GARNETLINK_HH__
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "mem/ruby/network/BasicLink.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/NetworkBridge.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "params/GarnetExtLink.hh"
+#include "params/GarnetIntLink.hh"
+
+class GarnetIntLink : public BasicIntLink
+{
+  public:
+    typedef GarnetIntLinkParams Params;
+    GarnetIntLink(const Params *p);
+
+    void init();
+
+    void print(std::ostream& out) const;
+
+    friend class GarnetNetwork;
+
+  protected:
+    NetworkLink* m_network_link;
+    CreditLink* m_credit_link;
+
+    bool srcBridgeEn;
+    bool dstBridgeEn;
+
+    bool srcSerdesEn;
+    bool dstSerdesEn;
+
+    bool srcCdcEn;
+    bool dstCdcEn;
+
+    NetworkBridge* srcNetBridge;
+    NetworkBridge* dstNetBridge;
+
+    NetworkBridge* srcCredBridge;
+    NetworkBridge* dstCredBridge;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetIntLink& obj)
+{
+    obj.print(out);
+    out << std::flush;
+    return out;
+}
+
+class GarnetExtLink : public BasicExtLink
+{
+  public:
+    typedef GarnetExtLinkParams Params;
+    GarnetExtLink(const Params *p);
+
+    void init();
+
+    void print(std::ostream& out) const;
+
+    friend class GarnetNetwork;
+
+  protected:
+    bool extBridgeEn;
+    bool intBridgeEn;
+
+    bool extSerdesEn;
+    bool intSerdesEn;
+
+    bool extCdcEn;
+    bool intCdcEn;
+
+    NetworkLink* m_network_links[2];
+    CreditLink* m_credit_links[2];
+
+    NetworkBridge* extNetBridge[2];
+    NetworkBridge* intNetBridge[2];
+
+    NetworkBridge* extCredBridge[2];
+    NetworkBridge* intCredBridge[2];
+
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetExtLink& obj)
+{
+    obj.print(out);
+    out << std::flush;
+    return out;
+}
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_GARNETLINK_HH__
diff --git a/src/mem/ruby/network/garnet/GarnetLink.py b/src/mem/ruby/network/garnet/GarnetLink.py
new file mode 100644 (file)
index 0000000..45350b5
--- /dev/null
@@ -0,0 +1,154 @@
+# Copyright (c) 2008 Princeton University
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from m5.params import *
+from m5.proxy import *
+from m5.objects.ClockedObject import ClockedObject
+from m5.objects.BasicLink import BasicIntLink, BasicExtLink
+
+class CDCType(Enum): vals = [
+    'LINK_OBJECT',
+    'OBJECT_LINK',
+    ]
+
+class NetworkLink(ClockedObject):
+    type = 'NetworkLink'
+    cxx_header = "mem/ruby/network/garnet/NetworkLink.hh"
+    link_id = Param.Int(Parent.link_id, "link id")
+    link_latency = Param.Cycles(Parent.latency, "link latency")
+    vcs_per_vnet = Param.Int(Parent.vcs_per_vnet,
+                              "virtual channels per virtual network")
+    virt_nets = Param.Int(Parent.number_of_virtual_networks,
+                          "number of virtual networks")
+    supported_vnets = VectorParam.Int(Parent.supported_vnets,
+                                      "Vnets supported")
+    width = Param.UInt32(Parent.width, "bit-width of the link")
+
+class CreditLink(NetworkLink):
+    type = 'CreditLink'
+    cxx_header = "mem/ruby/network/garnet/CreditLink.hh"
+
+class NetworkBridge(CreditLink):
+    type = 'NetworkBridge'
+    cxx_header = "mem/ruby/network/garnet/NetworkBridge.hh"
+    link = Param.NetworkLink("Associated Network Link")
+    vtype = Param.CDCType('LINK_OBJECT',
+              "Direction of CDC LINK->OBJECT or OBJECT->LINK")
+    serdes_latency = Param.Cycles(1, "Latency of SerDes Unit")
+    cdc_latency = Param.Cycles(1, "Latency of CDC Unit")
+
+# Interior fixed pipeline links between routers
+class GarnetIntLink(BasicIntLink):
+    type = 'GarnetIntLink'
+    cxx_header = "mem/ruby/network/garnet/GarnetLink.hh"
+    # The internal link includes one forward link (for flit)
+    # and one backward flow-control link (for credit)
+    network_link = Param.NetworkLink(NetworkLink(), "forward link")
+    credit_link  = Param.CreditLink(CreditLink(), "backward flow-control link")
+
+    # The src_cdc and dst_cdc flags are used to enable the
+    # clock domain crossing(CDC) at the source and destination
+    # end of the link respectively. This is required when the
+    # link and the objected connected to the link are operating
+    # at different clock domains. These flags should be set
+    # in the network topology files.
+    src_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+    dst_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+
+    # The src_serdes and dst_serdes flags are used to enable
+    # the Serializer-Deserializer units at the source and
+    # destination end of the link respectively. Enabling
+    # these flags is necessary when the connecting object
+    # supports a different flit width.
+    src_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+    dst_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+
+    # The network bridge encapsulates both the CDC and Ser-Des
+    # units in HeteroGarnet. This is automatically enabled when
+    # either CDC or Ser-Des is enabled.
+    src_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at source")
+    dst_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at dest")
+    src_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at source")
+    dst_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at dest")
+
+    width = Param.UInt32(Parent.ni_flit_size,
+                          "bit width supported by the router")
+
+# Exterior fixed pipeline links between a router and a controller
+class GarnetExtLink(BasicExtLink):
+    type = 'GarnetExtLink'
+    cxx_header = "mem/ruby/network/garnet/GarnetLink.hh"
+    # The external link is bi-directional.
+    # It includes two forward links (for flits)
+    # and two backward flow-control links (for credits),
+    # one per direction
+    _nls = []
+    # In uni-directional link
+    _nls.append(NetworkLink());
+    # Out uni-directional link
+    _nls.append(NetworkLink());
+    network_links = VectorParam.NetworkLink(_nls, "forward links")
+
+    _cls = []
+    # In uni-directional link
+    _cls.append(CreditLink());
+    # Out uni-directional link
+    _cls.append(CreditLink());
+    credit_links = VectorParam.CreditLink(_cls, "backward flow-control links")
+
+    # The ext_cdc and intt_cdc flags are used to enable the
+    # clock domain crossing(CDC) at the external and internal
+    # end of the link respectively. This is required when the
+    # link and the objected connected to the link are operating
+    # at different clock domains. These flags should be set
+    # in the network topology files.
+    ext_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+    int_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+
+    # The ext_serdes and int_serdes flags are used to enable
+    # the Serializer-Deserializer units at the external and
+    # internal end of the link respectively. Enabling
+    # these flags is necessary when the connecting object
+    # supports a different flit width.
+    ext_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+    int_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+
+    # The network bridge encapsulates both the CDC and Ser-Des
+    # units in HeteroGarnet. This is automatically enabled when
+    # either CDC or Ser-Des is enabled.
+    ext_net_bridge = VectorParam.NetworkBridge([],
+        "Network Bridge at external end")
+    ext_cred_bridge = VectorParam.NetworkBridge([],
+        "Credit Bridge at external end")
+    int_net_bridge = VectorParam.NetworkBridge([],
+        "Network Bridge at internal end")
+    int_cred_bridge = VectorParam.NetworkBridge([],
+        "Credit Bridge at internal end")
+
+
+    width = Param.UInt32(Parent.ni_flit_size,
+                          "bit width supported by the router")
diff --git a/src/mem/ruby/network/garnet/GarnetNetwork.cc b/src/mem/ruby/network/garnet/GarnetNetwork.cc
new file mode 100644 (file)
index 0000000..8334107
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+
+#include <cassert>
+
+#include "base/cast.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/common/NetDest.hh"
+#include "mem/ruby/network/MessageBuffer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetLink.hh"
+#include "mem/ruby/network/garnet/NetworkInterface.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/system/RubySystem.hh"
+
+using namespace std;
+
+/*
+ * GarnetNetwork sets up the routers and links and collects stats.
+ * Default parameters (GarnetNetwork.py) can be overwritten from command line
+ * (see configs/network/Network.py)
+ */
+
+GarnetNetwork::GarnetNetwork(const Params *p)
+    : Network(p)
+{
+    m_num_rows = p->num_rows;
+    m_ni_flit_size = p->ni_flit_size;
+    m_max_vcs_per_vnet = 0;
+    m_buffers_per_data_vc = p->buffers_per_data_vc;
+    m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
+    m_routing_algorithm = p->routing_algorithm;
+
+    m_enable_fault_model = p->enable_fault_model;
+    if (m_enable_fault_model)
+        fault_model = p->fault_model;
+
+    m_vnet_type.resize(m_virtual_networks);
+
+    for (int i = 0 ; i < m_virtual_networks ; i++) {
+        if (m_vnet_type_names[i] == "response")
+            m_vnet_type[i] = DATA_VNET_; // carries data (and ctrl) packets
+        else
+            m_vnet_type[i] = CTRL_VNET_; // carries only ctrl packets
+    }
+
+    // record the routers
+    for (vector<BasicRouter*>::const_iterator i =  p->routers.begin();
+         i != p->routers.end(); ++i) {
+        Router* router = safe_cast<Router*>(*i);
+        m_routers.push_back(router);
+
+        // initialize the router's network pointers
+        router->init_net_ptr(this);
+    }
+
+    // record the network interfaces
+    for (vector<ClockedObject*>::const_iterator i = p->netifs.begin();
+         i != p->netifs.end(); ++i) {
+        NetworkInterface *ni = safe_cast<NetworkInterface *>(*i);
+        m_nis.push_back(ni);
+        ni->init_net_ptr(this);
+    }
+
+    // Print Garnet version
+    inform("Garnet version %s\n", garnetVersion);
+}
+
+void
+GarnetNetwork::init()
+{
+    Network::init();
+
+    for (int i=0; i < m_nodes; i++) {
+        m_nis[i]->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
+    }
+
+    // The topology pointer should have already been initialized in the
+    // parent network constructor
+    assert(m_topology_ptr != NULL);
+    m_topology_ptr->createLinks(this);
+
+    // Initialize topology specific parameters
+    if (getNumRows() > 0) {
+        // Only for Mesh topology
+        // m_num_rows and m_num_cols are only used for
+        // implementing XY or custom routing in RoutingUnit.cc
+        m_num_rows = getNumRows();
+        m_num_cols = m_routers.size() / m_num_rows;
+        assert(m_num_rows * m_num_cols == m_routers.size());
+    } else {
+        m_num_rows = -1;
+        m_num_cols = -1;
+    }
+
+    // FaultModel: declare each router to the fault model
+    if (isFaultModelEnabled()) {
+        for (vector<Router*>::const_iterator i= m_routers.begin();
+             i != m_routers.end(); ++i) {
+            Router* router = safe_cast<Router*>(*i);
+            int router_id M5_VAR_USED =
+                fault_model->declare_router(router->get_num_inports(),
+                                            router->get_num_outports(),
+                                            router->get_vc_per_vnet(),
+                                            getBuffersPerDataVC(),
+                                            getBuffersPerCtrlVC());
+            assert(router_id == router->get_id());
+            router->printAggregateFaultProbability(cout);
+            router->printFaultVector(cout);
+        }
+    }
+}
+
+/*
+ * This function creates a link from the Network Interface (NI)
+ * into the Network.
+ * It creates a Network Link from the NI to a Router and a Credit Link from
+ * the Router to the NI
+*/
+
+void
+GarnetNetwork::makeExtInLink(NodeID global_src, SwitchID dest, BasicLink* link,
+                             std::vector<NetDest>& routing_table_entry)
+{
+    NodeID local_src = getLocalNodeID(global_src);
+    assert(local_src < m_nodes);
+
+    GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
+
+    // GarnetExtLink is bi-directional
+    NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_In];
+    net_link->setType(EXT_IN_);
+    CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_In];
+
+    m_networklinks.push_back(net_link);
+    m_creditlinks.push_back(credit_link);
+
+    PortDirection dst_inport_dirn = "Local";
+
+    m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
+                             m_routers[dest]->get_vc_per_vnet());
+
+    /*
+     * We check if a bridge was enabled at any end of the link.
+     * The bridge is enabled if either of clock domain
+     * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
+     * enabled for the link at each end. The bridge encapsulates
+     * the functionality for both CDC and SerDes and is a Consumer
+     * object similiar to a NetworkLink.
+     *
+     * If a bridge was enabled we connect the NI and Routers to
+     * bridge before connecting the link. Example, if an external
+     * bridge is enabled, we would connect:
+     * NI--->NetworkBridge--->GarnetExtLink---->Router
+     */
+    if (garnet_link->extBridgeEn) {
+        DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
+            garnet_link->name());
+        m_nis[local_src]->
+        addOutPort(garnet_link->extNetBridge[LinkDirection_In],
+                   garnet_link->extCredBridge[LinkDirection_In],
+                   dest, m_routers[dest]->get_vc_per_vnet());
+    } else {
+        m_nis[local_src]->addOutPort(net_link, credit_link, dest,
+            m_routers[dest]->get_vc_per_vnet());
+    }
+
+    if (garnet_link->intBridgeEn) {
+        DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
+            garnet_link->name());
+        m_routers[dest]->
+            addInPort(dst_inport_dirn,
+                      garnet_link->intNetBridge[LinkDirection_In],
+                      garnet_link->intCredBridge[LinkDirection_In]);
+    } else {
+        m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
+    }
+
+}
+
+/*
+ * This function creates a link from the Network to a NI.
+ * It creates a Network Link from a Router to the NI and
+ * a Credit Link from NI to the Router
+*/
+
+void
+GarnetNetwork::makeExtOutLink(SwitchID src, NodeID global_dest,
+                              BasicLink* link,
+                              std::vector<NetDest>& routing_table_entry)
+{
+    NodeID local_dest = getLocalNodeID(global_dest);
+    assert(local_dest < m_nodes);
+    assert(src < m_routers.size());
+    assert(m_routers[src] != NULL);
+
+    GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
+
+    // GarnetExtLink is bi-directional
+    NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_Out];
+    net_link->setType(EXT_OUT_);
+    CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_Out];
+
+    m_networklinks.push_back(net_link);
+    m_creditlinks.push_back(credit_link);
+
+    PortDirection src_outport_dirn = "Local";
+
+    m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
+                             m_routers[src]->get_vc_per_vnet());
+
+    /*
+     * We check if a bridge was enabled at any end of the link.
+     * The bridge is enabled if either of clock domain
+     * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
+     * enabled for the link at each end. The bridge encapsulates
+     * the functionality for both CDC and SerDes and is a Consumer
+     * object similiar to a NetworkLink.
+     *
+     * If a bridge was enabled we connect the NI and Routers to
+     * bridge before connecting the link. Example, if an external
+     * bridge is enabled, we would connect:
+     * NI<---NetworkBridge<---GarnetExtLink<----Router
+     */
+    if (garnet_link->extBridgeEn) {
+        DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
+            garnet_link->name());
+        m_nis[local_dest]->
+            addInPort(garnet_link->extNetBridge[LinkDirection_Out],
+                      garnet_link->extCredBridge[LinkDirection_Out]);
+    } else {
+        m_nis[local_dest]->addInPort(net_link, credit_link);
+    }
+
+    if (garnet_link->intBridgeEn) {
+        DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
+            garnet_link->name());
+        m_routers[src]->
+            addOutPort(src_outport_dirn,
+                       garnet_link->intNetBridge[LinkDirection_Out],
+                       routing_table_entry, link->m_weight,
+                       garnet_link->intCredBridge[LinkDirection_Out],
+                       m_routers[src]->get_vc_per_vnet());
+    } else {
+        m_routers[src]->
+            addOutPort(src_outport_dirn, net_link,
+                       routing_table_entry,
+                       link->m_weight, credit_link,
+                       m_routers[src]->get_vc_per_vnet());
+    }
+}
+
+/*
+ * This function creates an internal network link between two routers.
+ * It adds both the network link and an opposite credit link.
+*/
+
+void
+GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
+                                std::vector<NetDest>& routing_table_entry,
+                                PortDirection src_outport_dirn,
+                                PortDirection dst_inport_dirn)
+{
+    GarnetIntLink* garnet_link = safe_cast<GarnetIntLink*>(link);
+
+    // GarnetIntLink is unidirectional
+    NetworkLink* net_link = garnet_link->m_network_link;
+    net_link->setType(INT_);
+    CreditLink* credit_link = garnet_link->m_credit_link;
+
+    m_networklinks.push_back(net_link);
+    m_creditlinks.push_back(credit_link);
+
+    m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
+                             std::max(m_routers[dest]->get_vc_per_vnet(),
+                             m_routers[src]->get_vc_per_vnet()));
+
+    /*
+     * We check if a bridge was enabled at any end of the link.
+     * The bridge is enabled if either of clock domain
+     * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
+     * enabled for the link at each end. The bridge encapsulates
+     * the functionality for both CDC and SerDes and is a Consumer
+     * object similiar to a NetworkLink.
+     *
+     * If a bridge was enabled we connect the NI and Routers to
+     * bridge before connecting the link. Example, if a source
+     * bridge is enabled, we would connect:
+     * Router--->NetworkBridge--->GarnetIntLink---->Router
+     */
+    if (garnet_link->dstBridgeEn) {
+        DPRINTF(RubyNetwork, "Enable destination bridge for %s\n",
+            garnet_link->name());
+        m_routers[dest]->addInPort(dst_inport_dirn,
+            garnet_link->dstNetBridge, garnet_link->dstCredBridge);
+    } else {
+        m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
+    }
+
+    if (garnet_link->srcBridgeEn) {
+        DPRINTF(RubyNetwork, "Enable source bridge for %s\n",
+            garnet_link->name());
+        m_routers[src]->
+            addOutPort(src_outport_dirn, garnet_link->srcNetBridge,
+                       routing_table_entry,
+                       link->m_weight, garnet_link->srcCredBridge,
+                       m_routers[dest]->get_vc_per_vnet());
+    } else {
+        m_routers[src]->addOutPort(src_outport_dirn, net_link,
+                        routing_table_entry,
+                        link->m_weight, credit_link,
+                        m_routers[dest]->get_vc_per_vnet());
+    }
+}
+
+// Total routers in the network
+int
+GarnetNetwork::getNumRouters()
+{
+    return m_routers.size();
+}
+
+// Get ID of router connected to a NI.
+int
+GarnetNetwork::get_router_id(int global_ni, int vnet)
+{
+    NodeID local_ni = getLocalNodeID(global_ni);
+
+    return m_nis[local_ni]->get_router_id(vnet);
+}
+
+void
+GarnetNetwork::regStats()
+{
+    Network::regStats();
+
+    // Packets
+    m_packets_received
+        .init(m_virtual_networks)
+        .name(name() + ".packets_received")
+        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+        ;
+
+    m_packets_injected
+        .init(m_virtual_networks)
+        .name(name() + ".packets_injected")
+        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+        ;
+
+    m_packet_network_latency
+        .init(m_virtual_networks)
+        .name(name() + ".packet_network_latency")
+        .flags(Stats::oneline)
+        ;
+
+    m_packet_queueing_latency
+        .init(m_virtual_networks)
+        .name(name() + ".packet_queueing_latency")
+        .flags(Stats::oneline)
+        ;
+
+    for (int i = 0; i < m_virtual_networks; i++) {
+        m_packets_received.subname(i, csprintf("vnet-%i", i));
+        m_packets_injected.subname(i, csprintf("vnet-%i", i));
+        m_packet_network_latency.subname(i, csprintf("vnet-%i", i));
+        m_packet_queueing_latency.subname(i, csprintf("vnet-%i", i));
+    }
+
+    m_avg_packet_vnet_latency
+        .name(name() + ".average_packet_vnet_latency")
+        .flags(Stats::oneline);
+    m_avg_packet_vnet_latency =
+        m_packet_network_latency / m_packets_received;
+
+    m_avg_packet_vqueue_latency
+        .name(name() + ".average_packet_vqueue_latency")
+        .flags(Stats::oneline);
+    m_avg_packet_vqueue_latency =
+        m_packet_queueing_latency / m_packets_received;
+
+    m_avg_packet_network_latency
+        .name(name() + ".average_packet_network_latency");
+    m_avg_packet_network_latency =
+        sum(m_packet_network_latency) / sum(m_packets_received);
+
+    m_avg_packet_queueing_latency
+        .name(name() + ".average_packet_queueing_latency");
+    m_avg_packet_queueing_latency
+        = sum(m_packet_queueing_latency) / sum(m_packets_received);
+
+    m_avg_packet_latency
+        .name(name() + ".average_packet_latency");
+    m_avg_packet_latency
+        = m_avg_packet_network_latency + m_avg_packet_queueing_latency;
+
+    // Flits
+    m_flits_received
+        .init(m_virtual_networks)
+        .name(name() + ".flits_received")
+        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+        ;
+
+    m_flits_injected
+        .init(m_virtual_networks)
+        .name(name() + ".flits_injected")
+        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+        ;
+
+    m_flit_network_latency
+        .init(m_virtual_networks)
+        .name(name() + ".flit_network_latency")
+        .flags(Stats::oneline)
+        ;
+
+    m_flit_queueing_latency
+        .init(m_virtual_networks)
+        .name(name() + ".flit_queueing_latency")
+        .flags(Stats::oneline)
+        ;
+
+    for (int i = 0; i < m_virtual_networks; i++) {
+        m_flits_received.subname(i, csprintf("vnet-%i", i));
+        m_flits_injected.subname(i, csprintf("vnet-%i", i));
+        m_flit_network_latency.subname(i, csprintf("vnet-%i", i));
+        m_flit_queueing_latency.subname(i, csprintf("vnet-%i", i));
+    }
+
+    m_avg_flit_vnet_latency
+        .name(name() + ".average_flit_vnet_latency")
+        .flags(Stats::oneline);
+    m_avg_flit_vnet_latency = m_flit_network_latency / m_flits_received;
+
+    m_avg_flit_vqueue_latency
+        .name(name() + ".average_flit_vqueue_latency")
+        .flags(Stats::oneline);
+    m_avg_flit_vqueue_latency =
+        m_flit_queueing_latency / m_flits_received;
+
+    m_avg_flit_network_latency
+        .name(name() + ".average_flit_network_latency");
+    m_avg_flit_network_latency =
+        sum(m_flit_network_latency) / sum(m_flits_received);
+
+    m_avg_flit_queueing_latency
+        .name(name() + ".average_flit_queueing_latency");
+    m_avg_flit_queueing_latency =
+        sum(m_flit_queueing_latency) / sum(m_flits_received);
+
+    m_avg_flit_latency
+        .name(name() + ".average_flit_latency");
+    m_avg_flit_latency =
+        m_avg_flit_network_latency + m_avg_flit_queueing_latency;
+
+
+    // Hops
+    m_avg_hops.name(name() + ".average_hops");
+    m_avg_hops = m_total_hops / sum(m_flits_received);
+
+    // Links
+    m_total_ext_in_link_utilization
+        .name(name() + ".ext_in_link_utilization");
+    m_total_ext_out_link_utilization
+        .name(name() + ".ext_out_link_utilization");
+    m_total_int_link_utilization
+        .name(name() + ".int_link_utilization");
+    m_average_link_utilization
+        .name(name() + ".avg_link_utilization");
+    m_average_vc_load
+        .init(m_virtual_networks * m_max_vcs_per_vnet)
+        .name(name() + ".avg_vc_load")
+        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+        ;
+}
+
+void
+GarnetNetwork::collateStats()
+{
+    RubySystem *rs = params()->ruby_system;
+    double time_delta = double(curCycle() - rs->getStartCycle());
+
+    for (int i = 0; i < m_networklinks.size(); i++) {
+        link_type type = m_networklinks[i]->getType();
+        int activity = m_networklinks[i]->getLinkUtilization();
+
+        if (type == EXT_IN_)
+            m_total_ext_in_link_utilization += activity;
+        else if (type == EXT_OUT_)
+            m_total_ext_out_link_utilization += activity;
+        else if (type == INT_)
+            m_total_int_link_utilization += activity;
+
+        m_average_link_utilization +=
+            (double(activity) / time_delta);
+
+        vector<unsigned int> vc_load = m_networklinks[i]->getVcLoad();
+        for (int j = 0; j < vc_load.size(); j++) {
+            m_average_vc_load[j] += ((double)vc_load[j] / time_delta);
+        }
+    }
+
+    // Ask the routers to collate their statistics
+    for (int i = 0; i < m_routers.size(); i++) {
+        m_routers[i]->collateStats();
+    }
+}
+
+void
+GarnetNetwork::resetStats()
+{
+    for (int i = 0; i < m_routers.size(); i++) {
+        m_routers[i]->resetStats();
+    }
+    for (int i = 0; i < m_networklinks.size(); i++) {
+        m_networklinks[i]->resetStats();
+    }
+    for (int i = 0; i < m_creditlinks.size(); i++) {
+        m_creditlinks[i]->resetStats();
+    }
+}
+
+void
+GarnetNetwork::print(ostream& out) const
+{
+    out << "[GarnetNetwork]";
+}
+
+GarnetNetwork *
+GarnetNetworkParams::create()
+{
+    return new GarnetNetwork(this);
+}
+
+uint32_t
+GarnetNetwork::functionalWrite(Packet *pkt)
+{
+    uint32_t num_functional_writes = 0;
+
+    for (unsigned int i = 0; i < m_routers.size(); i++) {
+        num_functional_writes += m_routers[i]->functionalWrite(pkt);
+    }
+
+    for (unsigned int i = 0; i < m_nis.size(); ++i) {
+        num_functional_writes += m_nis[i]->functionalWrite(pkt);
+    }
+
+    for (unsigned int i = 0; i < m_networklinks.size(); ++i) {
+        num_functional_writes += m_networklinks[i]->functionalWrite(pkt);
+    }
+
+    return num_functional_writes;
+}
diff --git a/src/mem/ruby/network/garnet/GarnetNetwork.hh b/src/mem/ruby/network/garnet/GarnetNetwork.hh
new file mode 100644 (file)
index 0000000..2f9f543
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_GARNETNETWORK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_GARNETNETWORK_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/network/Network.hh"
+#include "mem/ruby/network/fault_model/FaultModel.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "params/GarnetNetwork.hh"
+
+class FaultModel;
+class NetworkInterface;
+class Router;
+class NetDest;
+class NetworkLink;
+class CreditLink;
+
+class GarnetNetwork : public Network
+{
+  public:
+    typedef GarnetNetworkParams Params;
+    GarnetNetwork(const Params *p);
+    ~GarnetNetwork() = default;
+
+    void init();
+
+    const char *garnetVersion = "3.0";
+
+    // Configuration (set externally)
+
+    // for 2D topology
+    int getNumRows() const { return m_num_rows; }
+    int getNumCols() { return m_num_cols; }
+
+    // for network
+    uint32_t getNiFlitSize() const { return m_ni_flit_size; }
+    uint32_t getBuffersPerDataVC() { return m_buffers_per_data_vc; }
+    uint32_t getBuffersPerCtrlVC() { return m_buffers_per_ctrl_vc; }
+    int getRoutingAlgorithm() const { return m_routing_algorithm; }
+
+    bool isFaultModelEnabled() const { return m_enable_fault_model; }
+    FaultModel* fault_model;
+
+
+    // Internal configuration
+    bool isVNetOrdered(int vnet) const { return m_ordered[vnet]; }
+    VNET_type
+    get_vnet_type(int vnet)
+    {
+        return m_vnet_type[vnet];
+    }
+    int getNumRouters();
+    int get_router_id(int ni, int vnet);
+
+
+    // Methods used by Topology to setup the network
+    void makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
+                     std::vector<NetDest>& routing_table_entry);
+    void makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
+                    std::vector<NetDest>& routing_table_entry);
+    void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
+                          std::vector<NetDest>& routing_table_entry,
+                          PortDirection src_outport_dirn,
+                          PortDirection dest_inport_dirn);
+
+    //! Function for performing a functional write. The return value
+    //! indicates the number of messages that were written.
+    uint32_t functionalWrite(Packet *pkt);
+
+    // Stats
+    void collateStats();
+    void regStats();
+    void resetStats();
+    void print(std::ostream& out) const;
+
+    // increment counters
+    void increment_injected_packets(int vnet) { m_packets_injected[vnet]++; }
+    void increment_received_packets(int vnet) { m_packets_received[vnet]++; }
+
+    void
+    increment_packet_network_latency(Tick latency, int vnet)
+    {
+        m_packet_network_latency[vnet] += latency;
+    }
+
+    void
+    increment_packet_queueing_latency(Tick latency, int vnet)
+    {
+        m_packet_queueing_latency[vnet] += latency;
+    }
+
+    void increment_injected_flits(int vnet) { m_flits_injected[vnet]++; }
+    void increment_received_flits(int vnet) { m_flits_received[vnet]++; }
+
+    void
+    increment_flit_network_latency(Tick latency, int vnet)
+    {
+        m_flit_network_latency[vnet] += latency;
+    }
+
+    void
+    increment_flit_queueing_latency(Tick latency, int vnet)
+    {
+        m_flit_queueing_latency[vnet] += latency;
+    }
+
+    void
+    increment_total_hops(int hops)
+    {
+        m_total_hops += hops;
+    }
+
+  protected:
+    // Configuration
+    int m_num_rows;
+    int m_num_cols;
+    uint32_t m_ni_flit_size;
+    uint32_t m_max_vcs_per_vnet;
+    uint32_t m_buffers_per_ctrl_vc;
+    uint32_t m_buffers_per_data_vc;
+    int m_routing_algorithm;
+    bool m_enable_fault_model;
+
+    // Statistical variables
+    Stats::Vector m_packets_received;
+    Stats::Vector m_packets_injected;
+    Stats::Vector m_packet_network_latency;
+    Stats::Vector m_packet_queueing_latency;
+
+    Stats::Formula m_avg_packet_vnet_latency;
+    Stats::Formula m_avg_packet_vqueue_latency;
+    Stats::Formula m_avg_packet_network_latency;
+    Stats::Formula m_avg_packet_queueing_latency;
+    Stats::Formula m_avg_packet_latency;
+
+    Stats::Vector m_flits_received;
+    Stats::Vector m_flits_injected;
+    Stats::Vector m_flit_network_latency;
+    Stats::Vector m_flit_queueing_latency;
+
+    Stats::Formula m_avg_flit_vnet_latency;
+    Stats::Formula m_avg_flit_vqueue_latency;
+    Stats::Formula m_avg_flit_network_latency;
+    Stats::Formula m_avg_flit_queueing_latency;
+    Stats::Formula m_avg_flit_latency;
+
+    Stats::Scalar m_total_ext_in_link_utilization;
+    Stats::Scalar m_total_ext_out_link_utilization;
+    Stats::Scalar m_total_int_link_utilization;
+    Stats::Scalar m_average_link_utilization;
+    Stats::Vector m_average_vc_load;
+
+    Stats::Scalar  m_total_hops;
+    Stats::Formula m_avg_hops;
+
+  private:
+    GarnetNetwork(const GarnetNetwork& obj);
+    GarnetNetwork& operator=(const GarnetNetwork& obj);
+
+    std::vector<VNET_type > m_vnet_type;
+    std::vector<Router *> m_routers;   // All Routers in Network
+    std::vector<NetworkLink *> m_networklinks; // All flit links in the network
+    std::vector<CreditLink *> m_creditlinks; // All credit links in the network
+    std::vector<NetworkInterface *> m_nis;   // All NI's in Network
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetNetwork& obj)
+{
+    obj.print(out);
+    out << std::flush;
+    return out;
+}
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_GARNETNETWORK_HH__
diff --git a/src/mem/ruby/network/garnet/GarnetNetwork.py b/src/mem/ruby/network/garnet/GarnetNetwork.py
new file mode 100644 (file)
index 0000000..d7a3f0d
--- /dev/null
@@ -0,0 +1,74 @@
+# Copyright (c) 2008 Princeton University
+# 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.
+#
+# Author: Tushar Krishna
+#
+
+from m5.params import *
+from m5.proxy import *
+from m5.objects.Network import RubyNetwork
+from m5.objects.BasicRouter import BasicRouter
+from m5.objects.ClockedObject import ClockedObject
+
+class GarnetNetwork(RubyNetwork):
+    type = 'GarnetNetwork'
+    cxx_header = "mem/ruby/network/garnet/GarnetNetwork.hh"
+    num_rows = Param.Int(0, "number of rows if 2D (mesh/torus/..) topology");
+    ni_flit_size = Param.UInt32(16, "network interface flit size in bytes")
+    vcs_per_vnet = Param.UInt32(4, "virtual channels per virtual network");
+    buffers_per_data_vc = Param.UInt32(4, "buffers per data virtual channel");
+    buffers_per_ctrl_vc = Param.UInt32(1, "buffers per ctrl virtual channel");
+    routing_algorithm = Param.Int(0,
+        "0: Weight-based Table, 1: XY, 2: Custom");
+    enable_fault_model = Param.Bool(False, "enable network fault model");
+    fault_model = Param.FaultModel(NULL, "network fault model");
+    garnet_deadlock_threshold = Param.UInt32(50000,
+                              "network-level deadlock threshold")
+
+class GarnetNetworkInterface(ClockedObject):
+    type = 'GarnetNetworkInterface'
+    cxx_class = 'NetworkInterface'
+    cxx_header = "mem/ruby/network/garnet/NetworkInterface.hh"
+
+    id = Param.UInt32("ID in relation to other network interfaces")
+    vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
+                             "virtual channels per virtual network")
+    virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
+                          "number of virtual networks")
+    garnet_deadlock_threshold = Param.UInt32(Parent.garnet_deadlock_threshold,
+                                      "network-level deadlock threshold")
+
+class GarnetRouter(BasicRouter):
+    type = 'GarnetRouter'
+    cxx_class = 'Router'
+    cxx_header = "mem/ruby/network/garnet/Router.hh"
+    vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
+                              "virtual channels per virtual network")
+    virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
+                          "number of virtual networks")
+    width = Param.UInt32(Parent.ni_flit_size,
+                          "bit width supported by the router")
diff --git a/src/mem/ruby/network/garnet/InputUnit.cc b/src/mem/ruby/network/garnet/InputUnit.cc
new file mode 100644 (file)
index 0000000..72c1b5c
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/InputUnit.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+
+using namespace std;
+
+InputUnit::InputUnit(int id, PortDirection direction, Router *router)
+  : Consumer(router), m_router(router), m_id(id), m_direction(direction),
+    m_vc_per_vnet(m_router->get_vc_per_vnet())
+{
+    const int m_num_vcs = m_router->get_num_vcs();
+    m_num_buffer_reads.resize(m_num_vcs/m_vc_per_vnet);
+    m_num_buffer_writes.resize(m_num_vcs/m_vc_per_vnet);
+    for (int i = 0; i < m_num_buffer_reads.size(); i++) {
+        m_num_buffer_reads[i] = 0;
+        m_num_buffer_writes[i] = 0;
+    }
+
+    // Instantiating the virtual channels
+    virtualChannels.reserve(m_num_vcs);
+    for (int i=0; i < m_num_vcs; i++) {
+        virtualChannels.emplace_back();
+    }
+}
+
+/*
+ * The InputUnit wakeup function reads the input flit from its input link.
+ * Each flit arrives with an input VC.
+ * For HEAD/HEAD_TAIL flits, performs route computation,
+ * and updates route in the input VC.
+ * The flit is buffered for (m_latency - 1) cycles in the input VC
+ * and marked as valid for SwitchAllocation starting that cycle.
+ *
+ */
+
+void
+InputUnit::wakeup()
+{
+    flit *t_flit;
+    if (m_in_link->isReady(curTick())) {
+
+        t_flit = m_in_link->consumeLink();
+        DPRINTF(RubyNetwork, "Router[%d] Consuming:%s Width: %d Flit:%s\n",
+        m_router->get_id(), m_in_link->name(),
+        m_router->getBitWidth(), *t_flit);
+        assert(t_flit->m_width == m_router->getBitWidth());
+        int vc = t_flit->get_vc();
+        t_flit->increment_hops(); // for stats
+
+        if ((t_flit->get_type() == HEAD_) ||
+            (t_flit->get_type() == HEAD_TAIL_)) {
+
+            assert(virtualChannels[vc].get_state() == IDLE_);
+            set_vc_active(vc, curTick());
+
+            // Route computation for this vc
+            int outport = m_router->route_compute(t_flit->get_route(),
+                m_id, m_direction);
+
+            // Update output port in VC
+            // All flits in this packet will use this output port
+            // The output port field in the flit is updated after it wins SA
+            grant_outport(vc, outport);
+
+        } else {
+            assert(virtualChannels[vc].get_state() == ACTIVE_);
+        }
+
+
+        // Buffer the flit
+        virtualChannels[vc].insertFlit(t_flit);
+
+        int vnet = vc/m_vc_per_vnet;
+        // number of writes same as reads
+        // any flit that is written will be read only once
+        m_num_buffer_writes[vnet]++;
+        m_num_buffer_reads[vnet]++;
+
+        Cycles pipe_stages = m_router->get_pipe_stages();
+        if (pipe_stages == 1) {
+            // 1-cycle router
+            // Flit goes for SA directly
+            t_flit->advance_stage(SA_, curTick());
+        } else {
+            assert(pipe_stages > 1);
+            // Router delay is modeled by making flit wait in buffer for
+            // (pipe_stages cycles - 1) cycles before going for SA
+
+            Cycles wait_time = pipe_stages - Cycles(1);
+            t_flit->advance_stage(SA_, m_router->clockEdge(wait_time));
+
+            // Wakeup the router in that cycle to perform SA
+            m_router->schedule_wakeup(Cycles(wait_time));
+        }
+
+        if (m_in_link->isReady(curTick())) {
+            m_router->schedule_wakeup(Cycles(1));
+        }
+    }
+}
+
+// Send a credit back to upstream router for this VC.
+// Called by SwitchAllocator when the flit in this VC wins the Switch.
+void
+InputUnit::increment_credit(int in_vc, bool free_signal, Tick curTime)
+{
+    DPRINTF(RubyNetwork, "Router[%d]: Sending a credit vc:%d free:%d to %s\n",
+    m_router->get_id(), in_vc, free_signal, m_credit_link->name());
+    Credit *t_credit = new Credit(in_vc, free_signal, curTime);
+    creditQueue.insert(t_credit);
+    m_credit_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
+}
+
+
+uint32_t
+InputUnit::functionalWrite(Packet *pkt)
+{
+    uint32_t num_functional_writes = 0;
+    for (auto& virtual_channel : virtualChannels) {
+        num_functional_writes += virtual_channel.functionalWrite(pkt);
+    }
+
+    return num_functional_writes;
+}
+
+void
+InputUnit::resetStats()
+{
+    for (int j = 0; j < m_num_buffer_reads.size(); j++) {
+        m_num_buffer_reads[j] = 0;
+        m_num_buffer_writes[j] = 0;
+    }
+}
diff --git a/src/mem/ruby/network/garnet/InputUnit.hh b/src/mem/ruby/network/garnet/InputUnit.hh
new file mode 100644 (file)
index 0000000..e57f0be
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_INPUTUNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_INPUTUNIT_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/network/garnet/VirtualChannel.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+class InputUnit : public Consumer
+{
+  public:
+    InputUnit(int id, PortDirection direction, Router *router);
+    ~InputUnit() = default;
+
+    void wakeup();
+    void print(std::ostream& out) const {};
+
+    inline PortDirection get_direction() { return m_direction; }
+
+    inline void
+    set_vc_idle(int vc, Tick curTime)
+    {
+        virtualChannels[vc].set_idle(curTime);
+    }
+
+    inline void
+    set_vc_active(int vc, Tick curTime)
+    {
+        virtualChannels[vc].set_active(curTime);
+    }
+
+    inline void
+    grant_outport(int vc, int outport)
+    {
+        virtualChannels[vc].set_outport(outport);
+    }
+
+    inline void
+    grant_outvc(int vc, int outvc)
+    {
+        virtualChannels[vc].set_outvc(outvc);
+    }
+
+    inline int
+    get_outport(int invc)
+    {
+        return virtualChannels[invc].get_outport();
+    }
+
+    inline int
+    get_outvc(int invc)
+    {
+        return virtualChannels[invc].get_outvc();
+    }
+
+    inline Tick
+    get_enqueue_time(int invc)
+    {
+        return virtualChannels[invc].get_enqueue_time();
+    }
+
+    void increment_credit(int in_vc, bool free_signal, Tick curTime);
+
+    inline flit*
+    peekTopFlit(int vc)
+    {
+        return virtualChannels[vc].peekTopFlit();
+    }
+
+    inline flit*
+    getTopFlit(int vc)
+    {
+        return virtualChannels[vc].getTopFlit();
+    }
+
+    inline bool
+    need_stage(int vc, flit_stage stage, Tick time)
+    {
+        return virtualChannels[vc].need_stage(stage, time);
+    }
+
+    inline bool
+    isReady(int invc, Tick curTime)
+    {
+        return virtualChannels[invc].isReady(curTime);
+    }
+
+    flitBuffer* getCreditQueue() { return &creditQueue; }
+
+    inline void
+    set_in_link(NetworkLink *link)
+    {
+        m_in_link = link;
+    }
+
+    inline int get_inlink_id() { return m_in_link->get_id(); }
+
+    inline void
+    set_credit_link(CreditLink *credit_link)
+    {
+        m_credit_link = credit_link;
+    }
+
+    double get_buf_read_activity(unsigned int vnet) const
+    { return m_num_buffer_reads[vnet]; }
+    double get_buf_write_activity(unsigned int vnet) const
+    { return m_num_buffer_writes[vnet]; }
+
+    uint32_t functionalWrite(Packet *pkt);
+    void resetStats();
+
+  private:
+    Router *m_router;
+    int m_id;
+    PortDirection m_direction;
+    int m_vc_per_vnet;
+    NetworkLink *m_in_link;
+    CreditLink *m_credit_link;
+    flitBuffer creditQueue;
+
+    // Input Virtual channels
+    std::vector<VirtualChannel> virtualChannels;
+
+    // Statistical variables
+    std::vector<double> m_num_buffer_writes;
+    std::vector<double> m_num_buffer_reads;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_INPUTUNIT_HH__
diff --git a/src/mem/ruby/network/garnet/NetworkBridge.cc b/src/mem/ruby/network/garnet/NetworkBridge.cc
new file mode 100644 (file)
index 0000000..9a1490c
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER 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: Srikant Bharadwaj
+ */
+
+
+#include "mem/ruby/network/garnet/NetworkBridge.hh"
+
+#include <cmath>
+
+#include "debug/RubyNetwork.hh"
+#include "params/GarnetIntLink.hh"
+
+NetworkBridge::NetworkBridge(const Params *p)
+    :CreditLink(p)
+{
+    enCdc = true;
+    enSerDes = true;
+    mType = p->vtype;
+
+    cdcLatency = p->cdc_latency;
+    serDesLatency = p->serdes_latency;
+    lastScheduledAt = 0;
+
+    nLink = p->link;
+    if (mType == Enums::LINK_OBJECT) {
+        nLink->setLinkConsumer(this);
+        setSourceQueue(nLink->getBuffer(), nLink);
+    } else if (mType == Enums::OBJECT_LINK) {
+        nLink->setSourceQueue(&linkBuffer, this);
+        setLinkConsumer(nLink);
+    } else {
+        // CDC type must be set
+        panic("CDC type must be set");
+    }
+}
+
+void
+NetworkBridge::setVcsPerVnet(uint32_t consumerVcs)
+{
+    DPRINTF(RubyNetwork, "VcsPerVnet VC: %d\n", consumerVcs);
+    NetworkLink::setVcsPerVnet(consumerVcs);
+    lenBuffer.resize(consumerVcs * m_virt_nets);
+    sizeSent.resize(consumerVcs * m_virt_nets);
+    flitsSent.resize(consumerVcs * m_virt_nets);
+    extraCredit.resize(consumerVcs * m_virt_nets);
+
+    nLink->setVcsPerVnet(consumerVcs);
+}
+
+void
+NetworkBridge::initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en)
+{
+    coBridge = coBrid;
+    enCdc = cdc_en;
+    enSerDes = serdes_en;
+}
+
+NetworkBridge::~NetworkBridge()
+{
+}
+
+void
+NetworkBridge::scheduleFlit(flit *t_flit, Cycles latency)
+{
+    Cycles totLatency = latency;
+
+    if (enCdc) {
+        // Add the CDC latency
+        totLatency = latency + cdcLatency;
+    }
+
+    Tick sendTime = link_consumer->getObject()->clockEdge(totLatency);
+    Tick nextAvailTick = lastScheduledAt + link_consumer->getObject()->\
+            cyclesToTicks(Cycles(1));
+    sendTime = std::max(nextAvailTick, sendTime);
+    t_flit->set_time(sendTime);
+    lastScheduledAt = sendTime;
+    linkBuffer.insert(t_flit);
+    link_consumer->scheduleEventAbsolute(sendTime);
+}
+
+void
+NetworkBridge::neutralize(int vc, int eCredit)
+{
+    extraCredit[vc].push(eCredit);
+}
+
+void
+NetworkBridge::flitisizeAndSend(flit *t_flit)
+{
+    // Serialize-Deserialize only if it is enabled
+    if (enSerDes) {
+        // Calculate the target-width
+        int target_width = bitWidth;
+        int cur_width = nLink->bitWidth;
+        if (mType == Enums::OBJECT_LINK) {
+            target_width = nLink->bitWidth;
+            cur_width = bitWidth;
+        }
+
+        DPRINTF(RubyNetwork, "Target width: %d Current: %d\n",
+            target_width, cur_width);
+        assert(target_width != cur_width);
+
+        int vc = t_flit->get_vc();
+
+        if (target_width > cur_width) {
+            // Deserialize
+            // This deserializer combines flits from the
+            // same message together
+            int num_flits = 0;
+            int flitPossible = 0;
+            if (t_flit->get_type() == CREDIT_) {
+                lenBuffer[vc]++;
+                assert(extraCredit[vc].front());
+                if (lenBuffer[vc] == extraCredit[vc].front()) {
+                    flitPossible = 1;
+                    extraCredit[vc].pop();
+                    lenBuffer[vc] = 0;
+                }
+            } else if (t_flit->get_type() == TAIL_ ||
+                       t_flit->get_type() == HEAD_TAIL_) {
+                // If its the end of packet, then send whatever
+                // is available.
+                int sizeAvail = (t_flit->msgSize - sizeSent[vc]);
+                flitPossible = ceil((float)sizeAvail/(float)target_width);
+                assert (flitPossible < 2);
+                num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
+                // Stop tracking the packet.
+                flitsSent[vc] = 0;
+                sizeSent[vc] = 0;
+            } else {
+                // If we are yet to receive the complete packet
+                // track the size recieved and flits deserialized.
+                int sizeAvail =
+                    ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
+                flitPossible = floor((float)sizeAvail/(float)target_width);
+                assert (flitPossible < 2);
+                num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
+                if (flitPossible) {
+                    sizeSent[vc] += target_width;
+                    flitsSent[vc] = t_flit->get_id() + 1;
+                }
+            }
+
+            DPRINTF(RubyNetwork, "Deserialize :%dB -----> %dB "
+                " vc:%d\n", cur_width, target_width, vc);
+
+            flit *fl = NULL;
+            if (flitPossible) {
+                fl = t_flit->deserialize(lenBuffer[vc], num_flits,
+                    target_width);
+            }
+
+            // Inform the credit serializer about the number
+            // of flits that were generated.
+            if (t_flit->get_type() != CREDIT_ && fl) {
+                coBridge->neutralize(vc, num_flits);
+            }
+
+            // Schedule only if we are done deserializing
+            if (fl) {
+                DPRINTF(RubyNetwork, "Scheduling a flit\n");
+                lenBuffer[vc] = 0;
+                scheduleFlit(fl, serDesLatency);
+            }
+            // Delete this flit, new flit is sent in any case
+            delete t_flit;
+        } else {
+            // Serialize
+            DPRINTF(RubyNetwork, "Serializing flit :%d -----> %d "
+            "(vc:%d, Original Message Size: %d)\n",
+                cur_width, target_width, vc, t_flit->msgSize);
+
+            int flitPossible = 0;
+            if (t_flit->get_type() == CREDIT_) {
+                // We store the deserialization ratio and then
+                // access it when serializing credits in the
+                // oppposite direction.
+                assert(extraCredit[vc].front());
+                flitPossible = extraCredit[vc].front();
+                extraCredit[vc].pop();
+            } else if (t_flit->get_type() == HEAD_ ||
+                    t_flit->get_type() == BODY_) {
+                int sizeAvail =
+                    ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
+                flitPossible = floor((float)sizeAvail/(float)target_width);
+                if (flitPossible) {
+                    sizeSent[vc] += flitPossible*target_width;
+                    flitsSent[vc] += flitPossible;
+                }
+            } else {
+                int sizeAvail = t_flit->msgSize - sizeSent[vc];
+                flitPossible = ceil((float)sizeAvail/(float)target_width);
+                sizeSent[vc] = 0;
+                flitsSent[vc] = 0;
+            }
+            assert(flitPossible > 0);
+
+            // Schedule all the flits
+            // num_flits could be zero for credits
+            for (int i = 0; i < flitPossible; i++) {
+                // Ignore neutralized credits
+                flit *fl = t_flit->serialize(i, flitPossible, target_width);
+                scheduleFlit(fl, serDesLatency);
+                DPRINTF(RubyNetwork, "Serialized to flit[%d of %d parts]:"
+                " %s\n", i+1, flitPossible, *fl);
+            }
+
+            if (t_flit->get_type() != CREDIT_) {
+                coBridge->neutralize(vc, flitPossible);
+            }
+            // Delete this flit, new flit is sent in any case
+            delete t_flit;
+        }
+        return;
+    }
+
+    // If only CDC is enabled schedule it
+    scheduleFlit(t_flit, Cycles(0));
+}
+void
+NetworkBridge::wakeup()
+{
+    flit *t_flit;
+
+    if (link_srcQueue->isReady(curTick())) {
+        t_flit = link_srcQueue->getTopFlit();
+        DPRINTF(RubyNetwork, "Recieved flit %s\n", *t_flit);
+        flitisizeAndSend(t_flit);
+        return;
+    }
+    assert(!link_srcQueue->getSize());
+}
+
+NetworkBridge *
+NetworkBridgeParams::create()
+{
+    return new NetworkBridge(this);
+}
diff --git a/src/mem/ruby/network/garnet/NetworkBridge.hh b/src/mem/ruby/network/garnet/NetworkBridge.hh
new file mode 100644 (file)
index 0000000..c6c37cb
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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 HOLDER 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: Srikant Bharadwaj
+ */
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_NETWORK_BRIDGE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_NETWORK_BRIDGE_HH__
+
+#include <iostream>
+#include <queue>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetLink.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+#include "params/NetworkBridge.hh"
+
+class GarnetNetwork;
+
+class NetworkBridge: public CreditLink
+{
+  public:
+    typedef NetworkBridgeParams Params;
+    NetworkBridge(const Params *p);
+    ~NetworkBridge();
+
+    void initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en);
+
+    void wakeup();
+    void neutralize(int vc, int eCredit);
+
+    void scheduleFlit(flit *t_flit, Cycles latency);
+    void flitisizeAndSend(flit *t_flit);
+    void setVcsPerVnet(uint32_t consumerVcs);
+
+  protected:
+    // Pointer to co-existing bridge
+    // CreditBridge for Network Bridge and vice versa
+    NetworkBridge *coBridge;
+
+    // Link connected toBridge
+    // could be a source or destination
+    // depending on mType
+    NetworkLink *nLink;
+
+    // CDC enable/disable
+    bool enCdc;
+    // SerDes enable/disable
+    bool enSerDes;
+
+    // Type of Bridge
+    int mType;
+
+    Cycles cdcLatency;
+    Cycles serDesLatency;
+
+    Tick lastScheduledAt;
+
+    // Used by Credit Deserializer
+    std::vector<int> lenBuffer;
+    std::vector<int> sizeSent;
+    std::vector<int> flitsSent;
+    std::vector<std::queue<int>> extraCredit;
+
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_NETWORK_BRIDGE_HH__
diff --git a/src/mem/ruby/network/garnet/NetworkInterface.cc b/src/mem/ruby/network/garnet/NetworkInterface.cc
new file mode 100644 (file)
index 0000000..6dbe0d9
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/NetworkInterface.hh"
+
+#include <cassert>
+#include <cmath>
+
+#include "base/cast.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/MessageBuffer.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+
+using namespace std;
+
+NetworkInterface::NetworkInterface(const Params *p)
+  : ClockedObject(p), Consumer(this), m_id(p->id),
+    m_virtual_networks(p->virt_nets), m_vc_per_vnet(0),
+    m_vc_allocator(m_virtual_networks, 0),
+    m_deadlock_threshold(p->garnet_deadlock_threshold),
+    vc_busy_counter(m_virtual_networks, 0)
+{
+    m_stall_count.resize(m_virtual_networks);
+    niOutVcs.resize(0);
+}
+
+void
+NetworkInterface::addInPort(NetworkLink *in_link,
+                              CreditLink *credit_link)
+{
+    InputPort *newInPort = new InputPort(in_link, credit_link);
+    inPorts.push_back(newInPort);
+    DPRINTF(RubyNetwork, "Adding input port:%s with vnets %s\n",
+    in_link->name(), newInPort->printVnets());
+
+    in_link->setLinkConsumer(this);
+    credit_link->setSourceQueue(newInPort->outCreditQueue(), this);
+    if (m_vc_per_vnet != 0) {
+        in_link->setVcsPerVnet(m_vc_per_vnet);
+        credit_link->setVcsPerVnet(m_vc_per_vnet);
+    }
+
+}
+
+void
+NetworkInterface::addOutPort(NetworkLink *out_link,
+                             CreditLink *credit_link,
+                             SwitchID router_id, uint32_t consumerVcs)
+{
+    OutputPort *newOutPort = new OutputPort(out_link, credit_link, router_id);
+    outPorts.push_back(newOutPort);
+
+    assert(consumerVcs > 0);
+    // We are not allowing different physical links to have different vcs
+    // If it is required that the Network Interface support different VCs
+    // for every physical link connected to it. Then they need to change
+    // the logic within outport and inport.
+    if (niOutVcs.size() == 0) {
+        m_vc_per_vnet = consumerVcs;
+        int m_num_vcs = consumerVcs * m_virtual_networks;
+        niOutVcs.resize(m_num_vcs);
+        outVcState.reserve(m_num_vcs);
+        m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
+        // instantiating the NI flit buffers
+        for (int i = 0; i < m_num_vcs; i++) {
+            m_ni_out_vcs_enqueue_time[i] = Tick(INFINITE_);
+            outVcState.emplace_back(i, m_net_ptr, consumerVcs);
+        }
+
+        // Reset VC Per VNET for input links already instantiated
+        for (auto &iPort: inPorts) {
+            NetworkLink *inNetLink = iPort->inNetLink();
+            inNetLink->setVcsPerVnet(m_vc_per_vnet);
+            credit_link->setVcsPerVnet(m_vc_per_vnet);
+        }
+    } else {
+        fatal_if(consumerVcs != m_vc_per_vnet,
+        "%s: Connected Physical links have different vc requests: %d and %d\n",
+        name(), consumerVcs, m_vc_per_vnet);
+    }
+
+    DPRINTF(RubyNetwork, "OutputPort:%s Vnet: %s\n",
+    out_link->name(), newOutPort->printVnets());
+
+    out_link->setSourceQueue(newOutPort->outFlitQueue(), this);
+    out_link->setVcsPerVnet(m_vc_per_vnet);
+    credit_link->setLinkConsumer(this);
+    credit_link->setVcsPerVnet(m_vc_per_vnet);
+}
+
+void
+NetworkInterface::addNode(vector<MessageBuffer *>& in,
+                            vector<MessageBuffer *>& out)
+{
+    inNode_ptr = in;
+    outNode_ptr = out;
+
+    for (auto& it : in) {
+        if (it != nullptr) {
+            it->setConsumer(this);
+        }
+    }
+}
+
+void
+NetworkInterface::dequeueCallback()
+{
+    // An output MessageBuffer has dequeued something this cycle and there
+    // is now space to enqueue a stalled message. However, we cannot wake
+    // on the same cycle as the dequeue. Schedule a wake at the soonest
+    // possible time (next cycle).
+    scheduleEventAbsolute(clockEdge(Cycles(1)));
+}
+
+void
+NetworkInterface::incrementStats(flit *t_flit)
+{
+    int vnet = t_flit->get_vnet();
+
+    // Latency
+    m_net_ptr->increment_received_flits(vnet);
+    Tick network_delay =
+        t_flit->get_dequeue_time() -
+        t_flit->get_enqueue_time() - cyclesToTicks(Cycles(1));
+    Tick src_queueing_delay = t_flit->get_src_delay();
+    Tick dest_queueing_delay = (curTick() - t_flit->get_dequeue_time());
+    Tick queueing_delay = src_queueing_delay + dest_queueing_delay;
+
+    m_net_ptr->increment_flit_network_latency(network_delay, vnet);
+    m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
+
+    if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
+        m_net_ptr->increment_received_packets(vnet);
+        m_net_ptr->increment_packet_network_latency(network_delay, vnet);
+        m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
+    }
+
+    // Hops
+    m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
+}
+
+/*
+ * The NI wakeup checks whether there are any ready messages in the protocol
+ * buffer. If yes, it picks that up, flitisizes it into a number of flits and
+ * puts it into an output buffer and schedules the output link. On a wakeup
+ * it also checks whether there are flits in the input link. If yes, it picks
+ * them up and if the flit is a tail, the NI inserts the corresponding message
+ * into the protocol buffer. It also checks for credits being sent by the
+ * downstream router.
+ */
+
+void
+NetworkInterface::wakeup()
+{
+    std::ostringstream oss;
+    for (auto &oPort: outPorts) {
+        oss << oPort->routerID() << "[" << oPort->printVnets() << "] ";
+    }
+    DPRINTF(RubyNetwork, "Network Interface %d connected to router:%s "
+            "woke up. Period: %ld\n", m_id, oss.str(), clockPeriod());
+
+    assert(curTick() == clockEdge());
+    MsgPtr msg_ptr;
+    Tick curTime = clockEdge();
+
+    // Checking for messages coming from the protocol
+    // can pick up a message/cycle for each virtual net
+    for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
+        MessageBuffer *b = inNode_ptr[vnet];
+        if (b == nullptr) {
+            continue;
+        }
+
+        if (b->isReady(curTime)) { // Is there a message waiting
+            msg_ptr = b->peekMsgPtr();
+            if (flitisizeMessage(msg_ptr, vnet)) {
+                b->dequeue(curTime);
+            }
+        }
+    }
+
+    scheduleOutputLink();
+
+    // Check if there are flits stalling a virtual channel. Track if a
+    // message is enqueued to restrict ejection to one message per cycle.
+    checkStallQueue();
+
+    /*********** Check the incoming flit link **********/
+    DPRINTF(RubyNetwork, "Number of input ports: %d\n", inPorts.size());
+    for (auto &iPort: inPorts) {
+        NetworkLink *inNetLink = iPort->inNetLink();
+        if (inNetLink->isReady(curTick())) {
+            flit *t_flit = inNetLink->consumeLink();
+            DPRINTF(RubyNetwork, "Recieved flit:%s\n", *t_flit);
+            assert(t_flit->m_width == iPort->bitWidth());
+
+            int vnet = t_flit->get_vnet();
+            t_flit->set_dequeue_time(curTick());
+
+            // If a tail flit is received, enqueue into the protocol buffers
+            // if space is available. Otherwise, exchange non-tail flits for
+            // credits.
+            if (t_flit->get_type() == TAIL_ ||
+                t_flit->get_type() == HEAD_TAIL_) {
+                if (!iPort->messageEnqueuedThisCycle &&
+                    outNode_ptr[vnet]->areNSlotsAvailable(1, curTime)) {
+                    // Space is available. Enqueue to protocol buffer.
+                    outNode_ptr[vnet]->enqueue(t_flit->get_msg_ptr(), curTime,
+                                               cyclesToTicks(Cycles(1)));
+
+                    // Simply send a credit back since we are not buffering
+                    // this flit in the NI
+                    Credit *cFlit = new Credit(t_flit->get_vc(),
+                                               true, curTick());
+                    iPort->sendCredit(cFlit);
+                    // Update stats and delete flit pointer
+                    incrementStats(t_flit);
+                    delete t_flit;
+                } else {
+                    // No space available- Place tail flit in stall queue and
+                    // set up a callback for when protocol buffer is dequeued.
+                    // Stat update and flit pointer deletion will occur upon
+                    // unstall.
+                    iPort->m_stall_queue.push_back(t_flit);
+                    m_stall_count[vnet]++;
+
+                    outNode_ptr[vnet]->registerDequeueCallback([this]() {
+                        dequeueCallback(); });
+                }
+            } else {
+                // Non-tail flit. Send back a credit but not VC free signal.
+                Credit *cFlit = new Credit(t_flit->get_vc(), false,
+                                               curTick());
+                // Simply send a credit back since we are not buffering
+                // this flit in the NI
+                iPort->sendCredit(cFlit);
+
+                // Update stats and delete flit pointer.
+                incrementStats(t_flit);
+                delete t_flit;
+            }
+        }
+    }
+
+    /****************** Check the incoming credit link *******/
+
+    for (auto &oPort: outPorts) {
+        CreditLink *inCreditLink = oPort->inCreditLink();
+        if (inCreditLink->isReady(curTick())) {
+            Credit *t_credit = (Credit*) inCreditLink->consumeLink();
+            outVcState[t_credit->get_vc()].increment_credit();
+            if (t_credit->is_free_signal()) {
+                outVcState[t_credit->get_vc()].setState(IDLE_,
+                    curTick());
+            }
+            delete t_credit;
+        }
+    }
+
+
+    // It is possible to enqueue multiple outgoing credit flits if a message
+    // was unstalled in the same cycle as a new message arrives. In this
+    // case, we should schedule another wakeup to ensure the credit is sent
+    // back.
+    for (auto &iPort: inPorts) {
+        if (iPort->outCreditQueue()->getSize() > 0) {
+            DPRINTF(RubyNetwork, "Sending a credit %s via %s at %ld\n",
+            *(iPort->outCreditQueue()->peekTopFlit()),
+            iPort->outCreditLink()->name(), clockEdge(Cycles(1)));
+            iPort->outCreditLink()->
+                scheduleEventAbsolute(clockEdge(Cycles(1)));
+        }
+    }
+    checkReschedule();
+}
+
+void
+NetworkInterface::checkStallQueue()
+{
+    // Check all stall queues.
+    // There is one stall queue for each input link
+    for (auto &iPort: inPorts) {
+        iPort->messageEnqueuedThisCycle = false;
+        Tick curTime = clockEdge();
+
+        if (!iPort->m_stall_queue.empty()) {
+            for (auto stallIter = iPort->m_stall_queue.begin();
+                 stallIter != iPort->m_stall_queue.end(); ) {
+                flit *stallFlit = *stallIter;
+                int vnet = stallFlit->get_vnet();
+
+                // If we can now eject to the protocol buffer,
+                // send back credits
+                if (outNode_ptr[vnet]->areNSlotsAvailable(1,
+                    curTime)) {
+                    outNode_ptr[vnet]->enqueue(stallFlit->get_msg_ptr(),
+                        curTime, cyclesToTicks(Cycles(1)));
+
+                    // Send back a credit with free signal now that the
+                    // VC is no longer stalled.
+                    Credit *cFlit = new Credit(stallFlit->get_vc(), true,
+                                                   curTick());
+                    iPort->sendCredit(cFlit);
+
+                    // Update Stats
+                    incrementStats(stallFlit);
+
+                    // Flit can now safely be deleted and removed from stall
+                    // queue
+                    delete stallFlit;
+                    iPort->m_stall_queue.erase(stallIter);
+                    m_stall_count[vnet]--;
+
+                    // If there are no more stalled messages for this vnet, the
+                    // callback on it's MessageBuffer is not needed.
+                    if (m_stall_count[vnet] == 0)
+                        outNode_ptr[vnet]->unregisterDequeueCallback();
+
+                    iPort->messageEnqueuedThisCycle = true;
+                    break;
+                } else {
+                    ++stallIter;
+                }
+            }
+        }
+    }
+}
+
+// Embed the protocol message into flits
+bool
+NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
+{
+    Message *net_msg_ptr = msg_ptr.get();
+    NetDest net_msg_dest = net_msg_ptr->getDestination();
+
+    // gets all the destinations associated with this message.
+    vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
+
+    // Number of flits is dependent on the link bandwidth available.
+    // This is expressed in terms of bytes/cycle or the flit size
+    OutputPort *oPort = getOutportForVnet(vnet);
+    assert(oPort);
+    int num_flits = (int)divCeil((float) m_net_ptr->MessageSizeType_to_int(
+        net_msg_ptr->getMessageSize()), (float)oPort->bitWidth());
+
+    DPRINTF(RubyNetwork, "Message Size:%d vnet:%d bitWidth:%d\n",
+        m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize()),
+        vnet, oPort->bitWidth());
+
+    // loop to convert all multicast messages into unicast messages
+    for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
+
+        // this will return a free output virtual channel
+        int vc = calculateVC(vnet);
+
+        if (vc == -1) {
+            return false ;
+        }
+        MsgPtr new_msg_ptr = msg_ptr->clone();
+        NodeID destID = dest_nodes[ctr];
+
+        Message *new_net_msg_ptr = new_msg_ptr.get();
+        if (dest_nodes.size() > 1) {
+            NetDest personal_dest;
+            for (int m = 0; m < (int) MachineType_NUM; m++) {
+                if ((destID >= MachineType_base_number((MachineType) m)) &&
+                    destID < MachineType_base_number((MachineType) (m+1))) {
+                    // calculating the NetDest associated with this destID
+                    personal_dest.clear();
+                    personal_dest.add((MachineID) {(MachineType) m, (destID -
+                        MachineType_base_number((MachineType) m))});
+                    new_net_msg_ptr->getDestination() = personal_dest;
+                    break;
+                }
+            }
+            net_msg_dest.removeNetDest(personal_dest);
+            // removing the destination from the original message to reflect
+            // that a message with this particular destination has been
+            // flitisized and an output vc is acquired
+            net_msg_ptr->getDestination().removeNetDest(personal_dest);
+        }
+
+        // Embed Route into the flits
+        // NetDest format is used by the routing table
+        // Custom routing algorithms just need destID
+
+        RouteInfo route;
+        route.vnet = vnet;
+        route.net_dest = new_net_msg_ptr->getDestination();
+        route.src_ni = m_id;
+        route.src_router = oPort->routerID();
+        route.dest_ni = destID;
+        route.dest_router = m_net_ptr->get_router_id(destID, vnet);
+
+        // initialize hops_traversed to -1
+        // so that the first router increments it to 0
+        route.hops_traversed = -1;
+
+        m_net_ptr->increment_injected_packets(vnet);
+        for (int i = 0; i < num_flits; i++) {
+            m_net_ptr->increment_injected_flits(vnet);
+            flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
+                m_net_ptr->MessageSizeType_to_int(
+                net_msg_ptr->getMessageSize()),
+                oPort->bitWidth(), curTick());
+
+            fl->set_src_delay(curTick() - ticksToCycles(msg_ptr->getTime()));
+            niOutVcs[vc].insert(fl);
+        }
+
+        m_ni_out_vcs_enqueue_time[vc] = curTick();
+        outVcState[vc].setState(ACTIVE_, curTick());
+    }
+    return true ;
+}
+
+// Looking for a free output vc
+int
+NetworkInterface::calculateVC(int vnet)
+{
+    for (int i = 0; i < m_vc_per_vnet; i++) {
+        int delta = m_vc_allocator[vnet];
+        m_vc_allocator[vnet]++;
+        if (m_vc_allocator[vnet] == m_vc_per_vnet)
+            m_vc_allocator[vnet] = 0;
+
+        if (outVcState[(vnet*m_vc_per_vnet) + delta].isInState(
+                    IDLE_, curTick())) {
+            vc_busy_counter[vnet] = 0;
+            return ((vnet*m_vc_per_vnet) + delta);
+        }
+    }
+
+    vc_busy_counter[vnet] += 1;
+    panic_if(vc_busy_counter[vnet] > m_deadlock_threshold,
+        "%s: Possible network deadlock in vnet: %d at time: %llu \n",
+        name(), vnet, curTick());
+
+    return -1;
+}
+
+void
+NetworkInterface::scheduleOutputPort(OutputPort *oPort)
+{
+   int vc = oPort->vcRoundRobin();
+
+   for (int i = 0; i < niOutVcs.size(); i++) {
+       vc++;
+       if (vc == niOutVcs.size())
+           vc = 0;
+
+       int t_vnet = get_vnet(vc);
+       if (oPort->isVnetSupported(t_vnet)) {
+           // model buffer backpressure
+           if (niOutVcs[vc].isReady(curTick()) &&
+               outVcState[vc].has_credit()) {
+
+               bool is_candidate_vc = true;
+               int vc_base = t_vnet * m_vc_per_vnet;
+
+               if (m_net_ptr->isVNetOrdered(t_vnet)) {
+                   for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
+                        vc_offset++) {
+                       int t_vc = vc_base + vc_offset;
+                       if (niOutVcs[t_vc].isReady(curTick())) {
+                           if (m_ni_out_vcs_enqueue_time[t_vc] <
+                               m_ni_out_vcs_enqueue_time[vc]) {
+                               is_candidate_vc = false;
+                               break;
+                           }
+                       }
+                   }
+               }
+               if (!is_candidate_vc)
+                   continue;
+
+               // Update the round robin arbiter
+               oPort->vcRoundRobin(vc);
+
+               outVcState[vc].decrement_credit();
+
+               // Just removing the top flit
+               flit *t_flit = niOutVcs[vc].getTopFlit();
+               t_flit->set_time(clockEdge(Cycles(1)));
+
+               // Scheduling the flit
+               scheduleFlit(t_flit);
+
+               if (t_flit->get_type() == TAIL_ ||
+                  t_flit->get_type() == HEAD_TAIL_) {
+                   m_ni_out_vcs_enqueue_time[vc] = Tick(INFINITE_);
+               }
+
+               // Done with this port, continue to schedule
+               // other ports
+               return;
+           }
+       }
+   }
+}
+
+
+
+/** This function looks at the NI buffers
+ *  if some buffer has flits which are ready to traverse the link in the next
+ *  cycle, and the downstream output vc associated with this flit has buffers
+ *  left, the link is scheduled for the next cycle
+ */
+
+void
+NetworkInterface::scheduleOutputLink()
+{
+    // Schedule each output link
+    for (auto &oPort: outPorts) {
+        scheduleOutputPort(oPort);
+    }
+}
+
+NetworkInterface::InputPort *
+NetworkInterface::getInportForVnet(int vnet)
+{
+    for (auto &iPort : inPorts) {
+        if (iPort->isVnetSupported(vnet)) {
+            return iPort;
+        }
+    }
+
+    return nullptr;
+}
+
+/*
+ * This function returns the outport which supports the given vnet.
+ * Currently, HeteroGarnet does not support multiple outports to
+ * support same vnet. Thus, this function returns the first-and
+ * only outport which supports the vnet.
+ */
+NetworkInterface::OutputPort *
+NetworkInterface::getOutportForVnet(int vnet)
+{
+    for (auto &oPort : outPorts) {
+        if (oPort->isVnetSupported(vnet)) {
+            return oPort;
+        }
+    }
+
+    return nullptr;
+}
+void
+NetworkInterface::scheduleFlit(flit *t_flit)
+{
+    OutputPort *oPort = getOutportForVnet(t_flit->get_vnet());
+
+    if (oPort) {
+        DPRINTF(RubyNetwork, "Scheduling at %s time:%ld flit:%s Message:%s\n",
+        oPort->outNetLink()->name(), clockEdge(Cycles(1)),
+        *t_flit, *(t_flit->get_msg_ptr()));
+        oPort->outFlitQueue()->insert(t_flit);
+        oPort->outNetLink()->scheduleEventAbsolute(clockEdge(Cycles(1)));
+        return;
+    }
+
+    panic("No output port found for vnet:%d\n", t_flit->get_vnet());
+    return;
+}
+
+int
+NetworkInterface::get_vnet(int vc)
+{
+    for (int i = 0; i < m_virtual_networks; i++) {
+        if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
+            return i;
+        }
+    }
+    fatal("Could not determine vc");
+}
+
+
+// Wakeup the NI in the next cycle if there are waiting
+// messages in the protocol buffer, or waiting flits in the
+// output VC buffer.
+// Also check if we have to reschedule because of a clock period
+// difference.
+void
+NetworkInterface::checkReschedule()
+{
+    for (const auto& it : inNode_ptr) {
+        if (it == nullptr) {
+            continue;
+        }
+
+        while (it->isReady(clockEdge())) { // Is there a message waiting
+            scheduleEvent(Cycles(1));
+            return;
+        }
+    }
+
+    for (auto& ni_out_vc : niOutVcs) {
+        if (ni_out_vc.isReady(clockEdge(Cycles(1)))) {
+            scheduleEvent(Cycles(1));
+            return;
+        }
+    }
+
+    // Check if any input links have flits to be popped.
+    // This can happen if the links are operating at
+    // a higher frequency.
+    for (auto &iPort : inPorts) {
+        NetworkLink *inNetLink = iPort->inNetLink();
+        if (inNetLink->isReady(curTick())) {
+            scheduleEvent(Cycles(1));
+            return;
+        }
+    }
+
+    for (auto &oPort : outPorts) {
+        CreditLink *inCreditLink = oPort->inCreditLink();
+        if (inCreditLink->isReady(curTick())) {
+            scheduleEvent(Cycles(1));
+            return;
+        }
+    }
+}
+
+void
+NetworkInterface::print(std::ostream& out) const
+{
+    out << "[Network Interface]";
+}
+
+uint32_t
+NetworkInterface::functionalWrite(Packet *pkt)
+{
+    uint32_t num_functional_writes = 0;
+    for (auto& ni_out_vc : niOutVcs) {
+        num_functional_writes += ni_out_vc.functionalWrite(pkt);
+    }
+
+    for (auto &oPort: outPorts) {
+        num_functional_writes += oPort->outFlitQueue()->functionalWrite(pkt);
+    }
+    return num_functional_writes;
+}
+
+NetworkInterface *
+GarnetNetworkInterfaceParams::create()
+{
+    return new NetworkInterface(this);
+}
diff --git a/src/mem/ruby/network/garnet/NetworkInterface.hh b/src/mem/ruby/network/garnet/NetworkInterface.hh
new file mode 100644 (file)
index 0000000..2f90772
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_NETWORKINTERFACE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_NETWORKINTERFACE_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/OutVcState.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+#include "params/GarnetNetworkInterface.hh"
+
+class MessageBuffer;
+class flitBuffer;
+
+class NetworkInterface : public ClockedObject, public Consumer
+{
+  public:
+    typedef GarnetNetworkInterfaceParams Params;
+    NetworkInterface(const Params *p);
+    ~NetworkInterface() = default;
+
+    void addInPort(NetworkLink *in_link, CreditLink *credit_link);
+    void addOutPort(NetworkLink *out_link, CreditLink *credit_link,
+        SwitchID router_id, uint32_t consumerVcs);
+
+    void dequeueCallback();
+    void wakeup();
+    void addNode(std::vector<MessageBuffer *> &inNode,
+                 std::vector<MessageBuffer *> &outNode);
+
+    void print(std::ostream& out) const;
+    int get_vnet(int vc);
+    void init_net_ptr(GarnetNetwork *net_ptr) { m_net_ptr = net_ptr; }
+
+    uint32_t functionalWrite(Packet *);
+
+    void scheduleFlit(flit *t_flit);
+
+    int get_router_id(int vnet)
+    {
+        OutputPort *oPort = getOutportForVnet(vnet);
+        assert(oPort);
+        return oPort->routerID();
+    }
+
+    class OutputPort
+    {
+      public:
+          OutputPort(NetworkLink *outLink, CreditLink *creditLink,
+              int routerID)
+          {
+              _vnets = outLink->mVnets;
+              _outFlitQueue = new flitBuffer();
+
+              _outNetLink = outLink;
+              _inCreditLink = creditLink;
+
+              _routerID = routerID;
+              _bitWidth = outLink->bitWidth;
+              _vcRoundRobin = 0;
+
+          }
+
+          flitBuffer *
+          outFlitQueue()
+          {
+              return _outFlitQueue;
+          }
+
+          NetworkLink *
+          outNetLink()
+          {
+              return _outNetLink;
+          }
+
+          CreditLink *
+          inCreditLink()
+          {
+              return _inCreditLink;
+          }
+
+          int
+          routerID()
+          {
+              return _routerID;
+          }
+
+          uint32_t bitWidth()
+          {
+              return _bitWidth;
+          }
+
+          bool isVnetSupported(int pVnet)
+          {
+              if (!_vnets.size()) {
+                  return true;
+              }
+
+              for (auto &it : _vnets) {
+                  if (it == pVnet) {
+                      return true;
+                  }
+              }
+              return false;
+
+          }
+
+          std::string
+          printVnets()
+          {
+              std::stringstream ss;
+              for (auto &it : _vnets) {
+                  ss << it;
+                  ss << " ";
+              }
+              return ss.str();
+          }
+
+          int vcRoundRobin()
+          {
+              return _vcRoundRobin;
+          }
+
+          void vcRoundRobin(int vc)
+          {
+              _vcRoundRobin = vc;
+          }
+
+
+      private:
+          std::vector<int> _vnets;
+          flitBuffer *_outFlitQueue;
+
+          NetworkLink *_outNetLink;
+          CreditLink *_inCreditLink;
+
+          int _vcRoundRobin; // For round robin scheduling
+
+          int _routerID;
+          uint32_t _bitWidth;
+    };
+
+    class InputPort
+    {
+      public:
+          InputPort(NetworkLink *inLink, CreditLink *creditLink)
+          {
+              _vnets = inLink->mVnets;
+              _outCreditQueue = new flitBuffer();
+
+              _inNetLink = inLink;
+              _outCreditLink = creditLink;
+              _bitWidth = inLink->bitWidth;
+          }
+
+          flitBuffer *
+          outCreditQueue()
+          {
+              return _outCreditQueue;
+          }
+
+          NetworkLink *
+          inNetLink()
+          {
+              return _inNetLink;
+          }
+
+          CreditLink *
+          outCreditLink()
+          {
+              return _outCreditLink;
+          }
+
+          bool isVnetSupported(int pVnet)
+          {
+              if (!_vnets.size()) {
+                  return true;
+              }
+
+              for (auto &it : _vnets) {
+                  if (it == pVnet) {
+                      return true;
+                  }
+              }
+              return false;
+
+          }
+
+          void sendCredit(Credit *cFlit)
+          {
+              _outCreditQueue->insert(cFlit);
+          }
+
+          uint32_t bitWidth()
+          {
+              return _bitWidth;
+          }
+
+          std::string
+          printVnets()
+          {
+              std::stringstream ss;
+              for (auto &it : _vnets) {
+                  ss << it;
+                  ss << " ";
+              }
+              return ss.str();
+          }
+
+          // Queue for stalled flits
+          std::deque<flit *> m_stall_queue;
+          bool messageEnqueuedThisCycle;
+      private:
+          std::vector<int> _vnets;
+          flitBuffer *_outCreditQueue;
+
+          NetworkLink *_inNetLink;
+          CreditLink *_outCreditLink;
+          uint32_t _bitWidth;
+    };
+
+
+  private:
+    GarnetNetwork *m_net_ptr;
+    const NodeID m_id;
+    const int m_virtual_networks;
+    int m_vc_per_vnet;
+    std::vector<int> m_vc_allocator;
+    std::vector<OutputPort *> outPorts;
+    std::vector<InputPort *> inPorts;
+    int m_deadlock_threshold;
+    std::vector<OutVcState> outVcState;
+
+    std::vector<int> m_stall_count;
+
+    // Input Flit Buffers
+    // The flit buffers which will serve the Consumer
+    std::vector<flitBuffer>  niOutVcs;
+    std::vector<Tick> m_ni_out_vcs_enqueue_time;
+
+    // The Message buffers that takes messages from the protocol
+    std::vector<MessageBuffer *> inNode_ptr;
+    // The Message buffers that provides messages to the protocol
+    std::vector<MessageBuffer *> outNode_ptr;
+    // When a vc stays busy for a long time, it indicates a deadlock
+    std::vector<int> vc_busy_counter;
+
+    void checkStallQueue();
+    bool flitisizeMessage(MsgPtr msg_ptr, int vnet);
+    int calculateVC(int vnet);
+
+
+    void scheduleOutputPort(OutputPort *oPort);
+    void scheduleOutputLink();
+    void checkReschedule();
+
+    void incrementStats(flit *t_flit);
+
+    InputPort *getInportForVnet(int vnet);
+    OutputPort *getOutportForVnet(int vnet);
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_NETWORKINTERFACE_HH__
diff --git a/src/mem/ruby/network/garnet/NetworkLink.cc b/src/mem/ruby/network/garnet/NetworkLink.cc
new file mode 100644 (file)
index 0000000..872159d
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+
+#include "base/trace.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+
+NetworkLink::NetworkLink(const Params *p)
+    : ClockedObject(p), Consumer(this), m_id(p->link_id),
+      m_type(NUM_LINK_TYPES_),
+      m_latency(p->link_latency), m_link_utilized(0),
+      m_virt_nets(p->virt_nets), linkBuffer(),
+      link_consumer(nullptr), link_srcQueue(nullptr)
+{
+    int num_vnets = (p->supported_vnets).size();
+    mVnets.resize(num_vnets);
+    bitWidth = p->width;
+    for (int i = 0; i < num_vnets; i++) {
+        mVnets[i] = p->supported_vnets[i];
+    }
+}
+
+void
+NetworkLink::setLinkConsumer(Consumer *consumer)
+{
+    link_consumer = consumer;
+}
+
+void
+NetworkLink::setVcsPerVnet(uint32_t consumerVcs)
+{
+    m_vc_load.resize(m_virt_nets * consumerVcs);
+}
+
+void
+NetworkLink::setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObj)
+{
+    link_srcQueue = src_queue;
+    src_object = srcClockObj;
+}
+
+void
+NetworkLink::wakeup()
+{
+    DPRINTF(RubyNetwork, "Woke up to transfer flits from %s\n",
+        src_object->name());
+    assert(link_srcQueue != nullptr);
+    assert(curTick() == clockEdge());
+    if (link_srcQueue->isReady(curTick())) {
+        flit *t_flit = link_srcQueue->getTopFlit();
+        DPRINTF(RubyNetwork, "Transmission will finish at %ld :%s\n",
+                clockEdge(m_latency), *t_flit);
+        if (m_type != NUM_LINK_TYPES_) {
+            // Only for assertions and debug messages
+            assert(t_flit->m_width == bitWidth);
+            assert((std::find(mVnets.begin(), mVnets.end(),
+                t_flit->get_vnet()) != mVnets.end()) ||
+                (mVnets.size() == 0));
+        }
+        t_flit->set_time(clockEdge(m_latency));
+        linkBuffer.insert(t_flit);
+        link_consumer->scheduleEventAbsolute(clockEdge(m_latency));
+        m_link_utilized++;
+        m_vc_load[t_flit->get_vc()]++;
+    }
+
+    if (!link_srcQueue->isEmpty()) {
+        scheduleEvent(Cycles(1));
+    }
+}
+
+void
+NetworkLink::resetStats()
+{
+    for (int i = 0; i < m_vc_load.size(); i++) {
+        m_vc_load[i] = 0;
+    }
+
+    m_link_utilized = 0;
+}
+
+NetworkLink *
+NetworkLinkParams::create()
+{
+    return new NetworkLink(this);
+}
+
+CreditLink *
+CreditLinkParams::create()
+{
+    return new CreditLink(this);
+}
+
+uint32_t
+NetworkLink::functionalWrite(Packet *pkt)
+{
+    return linkBuffer.functionalWrite(pkt);
+}
diff --git a/src/mem/ruby/network/garnet/NetworkLink.hh b/src/mem/ruby/network/garnet/NetworkLink.hh
new file mode 100644 (file)
index 0000000..22b1a7c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_NETWORKLINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_NETWORKLINK_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+#include "params/NetworkLink.hh"
+#include "sim/clocked_object.hh"
+
+class GarnetNetwork;
+
+class NetworkLink : public ClockedObject, public Consumer
+{
+  public:
+    typedef NetworkLinkParams Params;
+    NetworkLink(const Params *p);
+    ~NetworkLink() = default;
+
+    void setLinkConsumer(Consumer *consumer);
+    void setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObject);
+    virtual void setVcsPerVnet(uint32_t consumerVcs);
+    void setType(link_type type) { m_type = type; }
+    link_type getType() { return m_type; }
+    void print(std::ostream& out) const {}
+    int get_id() const { return m_id; }
+    flitBuffer *getBuffer() { return &linkBuffer;}
+    virtual void wakeup();
+
+    unsigned int getLinkUtilization() const { return m_link_utilized; }
+    const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; }
+
+    inline bool isReady(Tick curTime)
+    {
+        return linkBuffer.isReady(curTime);
+    }
+
+    inline flit* peekLink() { return linkBuffer.peekTopFlit(); }
+    inline flit* consumeLink() { return linkBuffer.getTopFlit(); }
+
+    uint32_t functionalWrite(Packet *);
+    void resetStats();
+
+    std::vector<int> mVnets;
+    uint32_t bitWidth;
+
+  private:
+    const int m_id;
+    link_type m_type;
+    const Cycles m_latency;
+
+    ClockedObject *src_object;
+
+    // Statistical variables
+    unsigned int m_link_utilized;
+    std::vector<unsigned int> m_vc_load;
+
+  protected:
+    uint32_t m_virt_nets;
+    flitBuffer linkBuffer;
+    Consumer *link_consumer;
+    flitBuffer *link_srcQueue;
+
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_NETWORKLINK_HH__
diff --git a/src/mem/ruby/network/garnet/OutVcState.cc b/src/mem/ruby/network/garnet/OutVcState.cc
new file mode 100644 (file)
index 0000000..1bb8698
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/OutVcState.hh"
+
+#include "mem/ruby/system/RubySystem.hh"
+
+OutVcState::OutVcState(int id, GarnetNetwork *network_ptr,
+    uint32_t consumerVcs)
+    : m_time(0)
+{
+    m_id = id;
+    m_vc_state = IDLE_;
+    /*
+     * We find the virtual network using the number of
+     * vcs per vnet. This assumes that the same vcs per
+     * vnet is used throughout the given object.
+     */
+    int vnet = floor(id/consumerVcs);
+
+    if (network_ptr->get_vnet_type(vnet) == DATA_VNET_)
+        m_max_credit_count = network_ptr->getBuffersPerDataVC();
+    else
+        m_max_credit_count = network_ptr->getBuffersPerCtrlVC();
+
+    m_credit_count = m_max_credit_count;
+    assert(m_credit_count >= 1);
+}
+
+void
+OutVcState::increment_credit()
+{
+    m_credit_count++;
+    assert(m_credit_count <= m_max_credit_count);
+}
+
+void
+OutVcState::decrement_credit()
+{
+    m_credit_count--;
+    assert(m_credit_count >= 0);
+}
diff --git a/src/mem/ruby/network/garnet/OutVcState.hh b/src/mem/ruby/network/garnet/OutVcState.hh
new file mode 100644 (file)
index 0000000..c78af08
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_OUTVCSTATE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_OUTVCSTATE_HH__
+
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+
+class OutVcState
+{
+  public:
+    OutVcState(int id, GarnetNetwork *network_ptr, uint32_t consumerVcs);
+
+    int get_credit_count()          { return m_credit_count; }
+    inline bool has_credit()       { return (m_credit_count > 0); }
+    void increment_credit();
+    void decrement_credit();
+
+    inline bool
+    isInState(VC_state_type state, Tick request_time)
+    {
+        return ((m_vc_state == state) && (request_time >= m_time) );
+    }
+    inline void
+    setState(VC_state_type state, Tick time)
+    {
+        m_vc_state = state;
+        m_time = time;
+    }
+
+  private:
+    int m_id ;
+    Tick m_time;
+    VC_state_type m_vc_state;
+    int m_credit_count;
+    int m_max_credit_count;
+};
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_OUTVCSTATE_HH__
diff --git a/src/mem/ruby/network/garnet/OutputUnit.cc b/src/mem/ruby/network/garnet/OutputUnit.cc
new file mode 100644 (file)
index 0000000..ac9673c
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+OutputUnit::OutputUnit(int id, PortDirection direction, Router *router,
+  uint32_t consumerVcs)
+  : Consumer(router), m_router(router), m_id(id), m_direction(direction),
+    m_vc_per_vnet(consumerVcs)
+{
+    const int m_num_vcs = consumerVcs * m_router->get_num_vnets();
+    outVcState.reserve(m_num_vcs);
+    for (int i = 0; i < m_num_vcs; i++) {
+        outVcState.emplace_back(i, m_router->get_net_ptr(), consumerVcs);
+    }
+}
+
+void
+OutputUnit::decrement_credit(int out_vc)
+{
+    DPRINTF(RubyNetwork, "Router %d OutputUnit %s decrementing credit:%d for "
+            "outvc %d at time: %lld for %s\n", m_router->get_id(),
+            m_router->getPortDirectionName(get_direction()),
+            outVcState[out_vc].get_credit_count(),
+            out_vc, m_router->curCycle(), m_credit_link->name());
+
+    outVcState[out_vc].decrement_credit();
+}
+
+void
+OutputUnit::increment_credit(int out_vc)
+{
+    DPRINTF(RubyNetwork, "Router %d OutputUnit %s incrementing credit:%d for "
+            "outvc %d at time: %lld from:%s\n", m_router->get_id(),
+            m_router->getPortDirectionName(get_direction()),
+            outVcState[out_vc].get_credit_count(),
+            out_vc, m_router->curCycle(), m_credit_link->name());
+
+    outVcState[out_vc].increment_credit();
+}
+
+// Check if the output VC (i.e., input VC at next router)
+// has free credits (i..e, buffer slots).
+// This is tracked by OutVcState
+bool
+OutputUnit::has_credit(int out_vc)
+{
+    assert(outVcState[out_vc].isInState(ACTIVE_, curTick()));
+    return outVcState[out_vc].has_credit();
+}
+
+
+// Check if the output port (i.e., input port at next router) has free VCs.
+bool
+OutputUnit::has_free_vc(int vnet)
+{
+    int vc_base = vnet*m_vc_per_vnet;
+    for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
+        if (is_vc_idle(vc, curTick()))
+            return true;
+    }
+
+    return false;
+}
+
+// Assign a free output VC to the winner of Switch Allocation
+int
+OutputUnit::select_free_vc(int vnet)
+{
+    int vc_base = vnet*m_vc_per_vnet;
+    for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
+        if (is_vc_idle(vc, curTick())) {
+            outVcState[vc].setState(ACTIVE_, curTick());
+            return vc;
+        }
+    }
+
+    return -1;
+}
+
+/*
+ * The wakeup function of the OutputUnit reads the credit signal from the
+ * downstream router for the output VC (i.e., input VC at downstream router).
+ * It increments the credit count in the appropriate output VC state.
+ * If the credit carries is_free_signal as true,
+ * the output VC is marked IDLE.
+ */
+
+void
+OutputUnit::wakeup()
+{
+    if (m_credit_link->isReady(curTick())) {
+        Credit *t_credit = (Credit*) m_credit_link->consumeLink();
+        increment_credit(t_credit->get_vc());
+
+        if (t_credit->is_free_signal())
+            set_vc_state(IDLE_, t_credit->get_vc(), curTick());
+
+        delete t_credit;
+
+        if (m_credit_link->isReady(curTick())) {
+            scheduleEvent(Cycles(1));
+        }
+    }
+}
+
+flitBuffer*
+OutputUnit::getOutQueue()
+{
+    return &outBuffer;
+}
+
+void
+OutputUnit::set_out_link(NetworkLink *link)
+{
+    m_out_link = link;
+}
+
+void
+OutputUnit::set_credit_link(CreditLink *credit_link)
+{
+    m_credit_link = credit_link;
+}
+
+void
+OutputUnit::insert_flit(flit *t_flit)
+{
+    outBuffer.insert(t_flit);
+    m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
+}
+
+uint32_t
+OutputUnit::functionalWrite(Packet *pkt)
+{
+    return outBuffer.functionalWrite(pkt);
+}
diff --git a/src/mem/ruby/network/garnet/OutputUnit.hh b/src/mem/ruby/network/garnet/OutputUnit.hh
new file mode 100644 (file)
index 0000000..3cb924d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_OUTPUTUNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_OUTPUTUNIT_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "base/compiler.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/OutVcState.hh"
+
+class CreditLink;
+class Router;
+
+class OutputUnit : public Consumer
+{
+  public:
+    OutputUnit(int id, PortDirection direction, Router *router,
+               uint32_t consumerVcs);
+    ~OutputUnit() = default;
+    void set_out_link(NetworkLink *link);
+    void set_credit_link(CreditLink *credit_link);
+    void wakeup();
+    flitBuffer* getOutQueue();
+    void print(std::ostream& out) const {};
+    void decrement_credit(int out_vc);
+    void increment_credit(int out_vc);
+    bool has_credit(int out_vc);
+    bool has_free_vc(int vnet);
+    int select_free_vc(int vnet);
+
+    inline PortDirection get_direction() { return m_direction; }
+
+    int
+    get_credit_count(int vc)
+    {
+        return outVcState[vc].get_credit_count();
+    }
+
+    inline int
+    get_outlink_id()
+    {
+        return m_out_link->get_id();
+    }
+
+    inline void
+    set_vc_state(VC_state_type state, int vc, Tick curTime)
+    {
+      outVcState[vc].setState(state, curTime);
+    }
+
+    inline bool
+    is_vc_idle(int vc, Tick curTime)
+    {
+        return (outVcState[vc].isInState(IDLE_, curTime));
+    }
+
+    void insert_flit(flit *t_flit);
+
+    inline int
+    getVcsPerVnet()
+    {
+        return m_vc_per_vnet;
+    }
+
+    uint32_t functionalWrite(Packet *pkt);
+
+  private:
+    Router *m_router;
+    int M5_CLASS_VAR_USED m_id;
+    PortDirection m_direction;
+    int m_vc_per_vnet;
+    NetworkLink *m_out_link;
+    CreditLink *m_credit_link;
+
+    // This is for the network link to consume
+    flitBuffer outBuffer;
+    // vc state of downstream router
+    std::vector<OutVcState> outVcState;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_OUTPUTUNIT_HH__
diff --git a/src/mem/ruby/network/garnet/README.txt b/src/mem/ruby/network/garnet/README.txt
new file mode 100644 (file)
index 0000000..573ab60
--- /dev/null
@@ -0,0 +1,79 @@
+README for Garnet3.0
+Written By: Tushar Krishna (tushar@ece.gatech.edu)
+Last Updated: Sep 9, 2020
+-------------------------------------------------------
+
+Garnet Network Parameters and Setup:
+- GarnetNetwork.py
+    * defaults can be overwritten from command line (see configs/network/Network.py)
+- GarnetNetwork.hh/cc
+    * sets up the routers and links
+    * collects stats
+
+
+CODE FLOW
+- NetworkInterface.cc::wakeup()
+    * Every NI connected to one coherence protocol controller on one end, and one router on the other.
+    * receives messages from coherence protocol buffer in appropriate vnet and converts them into network packets and sends them into the network.
+        * garnet adds the ability to capture a network trace at this point.
+    * receives flits from the network, extracts the protocol message and sends it to the coherence protocol buffer in appropriate vnet.
+    * manages flow-control (i.e., credits) with its attached router.
+    * The consuming flit/credit output link of the NI is put in the global event queue with a timestamp set to next cycle.
+      The eventqueue calls the wakeup function in the consumer.
+
+- NetworkLink.cc::wakeup()
+    * receives flits from NI/router and sends it to NI/router after m_latency cycles delay
+        * Default latency value for every link can be set from command line (see configs/network/Network.py)
+        * Per link latency can be overwritten in the topology file
+    * The consumer of the link (NI/router) is put in the global event queue with a timestamp set after m_latency cycles.
+      The eventqueue calls the wakeup function in the consumer.
+
+- Router.cc::wakeup()
+    * Loop through all InputUnits and call their wakeup()
+    * Loop through all OutputUnits and call their wakeup()
+    * Call SwitchAllocator's wakeup()
+    * Call CrossbarSwitch's wakeup()
+    * The router's wakeup function is called whenever any of its modules (InputUnit, OutputUnit, SwitchAllocator, CrossbarSwitch) have
+      a ready flit/credit to act upon this cycle.
+
+- InputUnit.cc::wakeup()
+    * Read input flit from upstream router if it is ready for this cycle
+    * For HEAD/HEAD_TAIL flits, perform route computation, and update route in the VC.
+    * Buffer the flit for (m_latency - 1) cycles and mark it valid for SwitchAllocation starting that cycle.
+        * Default latency for every router can be set from command line (see configs/network/Network.py)
+        * Per router latency (i.e., num pipeline stages) can be set in the topology file
+
+- OutputUnit.cc::wakeup()
+    * Read input credit from downstream router if it is ready for this cycle
+    * Increment the credit in the appropriate output VC state.
+    * Mark output VC as free if the credit carries is_free_signal as true
+
+- SwitchAllocator.cc::wakeup()
+    * Note: SwitchAllocator performs VC arbitration and selection within it.
+    * SA-I (or SA-i): Loop through all input VCs at every input port, and select one in a round robin manner.
+        * For HEAD/HEAD_TAIL flits only select an input VC whose output port has at least one free output VC.
+        * For BODY/TAIL flits, only select an input VC that has credits in its output VC.
+    * Place a request for the output port from this VC.
+    * SA-II (or SA-o): Loop through all output ports, and select one input VC (that placed a request during SA-I) as the winner for this output port in a round robin manner.
+        * For HEAD/HEAD_TAIL flits, perform outvc allocation (i.e., select a free VC from the output port).
+        * For BODY/TAIL flits, decrement a credit in the output vc.
+    * Read the flit out from the input VC, and send it to the CrossbarSwitch
+    * Send a increment_credit signal to the upstream router for this input VC.
+        * for HEAD_TAIL/TAIL flits, mark is_free_signal as true in the credit.
+        * The input unit sends the credit out on the credit link to the upstream router.
+    * Reschedule the Router to wakeup next cycle for any flits ready for SA next cycle.
+
+- CrossbarSwitch.cc::wakeup()
+    * Loop through all input ports, and send the winning flit out of its output port onto the output link.
+    * The consuming flit output link of the router is put in the global event queue with a timestamp set to next cycle.
+      The eventqueue calls the wakeup function in the consumer.
+
+
+If a clock domain crossing(CDC) or Serializer-Deserializer unit is
+instantiated, then the Network Brisge takes over the flit in HeteroGarnet.
+- NetworkBridge::wakeup()
+    * Check if SerDes is enabled and do appropriate calculations for
+    serializing or deserializing the flits
+    * Check if CDC is enabled and schedule all the flits according
+    to the consumers clock domain.
+
diff --git a/src/mem/ruby/network/garnet/Router.cc b/src/mem/ruby/network/garnet/Router.cc
new file mode 100644 (file)
index 0000000..47cb9be
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/Router.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/InputUnit.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+
+using namespace std;
+
+Router::Router(const Params *p)
+  : BasicRouter(p), Consumer(this), m_latency(p->latency),
+    m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
+    m_num_vcs(m_virtual_networks * m_vc_per_vnet), m_bit_width(p->width),
+    m_network_ptr(nullptr), routingUnit(this), switchAllocator(this),
+    crossbarSwitch(this)
+{
+    m_input_unit.clear();
+    m_output_unit.clear();
+}
+
+void
+Router::init()
+{
+    BasicRouter::init();
+
+    switchAllocator.init();
+    crossbarSwitch.init();
+}
+
+void
+Router::wakeup()
+{
+    DPRINTF(RubyNetwork, "Router %d woke up\n", m_id);
+    assert(clockEdge() == curTick());
+
+    // check for incoming flits
+    for (int inport = 0; inport < m_input_unit.size(); inport++) {
+        m_input_unit[inport]->wakeup();
+    }
+
+    // check for incoming credits
+    // Note: the credit update is happening before SA
+    // buffer turnaround time =
+    //     credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
+    // if we want the credit update to take place after SA, this loop should
+    // be moved after the SA request
+    for (int outport = 0; outport < m_output_unit.size(); outport++) {
+        m_output_unit[outport]->wakeup();
+    }
+
+    // Switch Allocation
+    switchAllocator.wakeup();
+
+    // Switch Traversal
+    crossbarSwitch.wakeup();
+}
+
+void
+Router::addInPort(PortDirection inport_dirn,
+                  NetworkLink *in_link, CreditLink *credit_link)
+{
+    fatal_if(in_link->bitWidth != m_bit_width, "Widths of link %s(%d)does"
+            " not match that of Router%d(%d). Consider inserting SerDes "
+            "Units.", in_link->name(), in_link->bitWidth, m_id, m_bit_width);
+
+    int port_num = m_input_unit.size();
+    InputUnit *input_unit = new InputUnit(port_num, inport_dirn, this);
+
+    input_unit->set_in_link(in_link);
+    input_unit->set_credit_link(credit_link);
+    in_link->setLinkConsumer(this);
+    in_link->setVcsPerVnet(get_vc_per_vnet());
+    credit_link->setSourceQueue(input_unit->getCreditQueue(), this);
+    credit_link->setVcsPerVnet(get_vc_per_vnet());
+
+    m_input_unit.push_back(std::shared_ptr<InputUnit>(input_unit));
+
+    routingUnit.addInDirection(inport_dirn, port_num);
+}
+
+void
+Router::addOutPort(PortDirection outport_dirn,
+                   NetworkLink *out_link,
+                   std::vector<NetDest>& routing_table_entry, int link_weight,
+                   CreditLink *credit_link, uint32_t consumerVcs)
+{
+    fatal_if(out_link->bitWidth != m_bit_width, "Widths of units do not match."
+            " Consider inserting SerDes Units");
+
+    int port_num = m_output_unit.size();
+    OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this,
+                                             consumerVcs);
+
+    output_unit->set_out_link(out_link);
+    output_unit->set_credit_link(credit_link);
+    credit_link->setLinkConsumer(this);
+    credit_link->setVcsPerVnet(consumerVcs);
+    out_link->setSourceQueue(output_unit->getOutQueue(), this);
+    out_link->setVcsPerVnet(consumerVcs);
+
+    m_output_unit.push_back(std::shared_ptr<OutputUnit>(output_unit));
+
+    routingUnit.addRoute(routing_table_entry);
+    routingUnit.addWeight(link_weight);
+    routingUnit.addOutDirection(outport_dirn, port_num);
+}
+
+PortDirection
+Router::getOutportDirection(int outport)
+{
+    return m_output_unit[outport]->get_direction();
+}
+
+PortDirection
+Router::getInportDirection(int inport)
+{
+    return m_input_unit[inport]->get_direction();
+}
+
+int
+Router::route_compute(RouteInfo route, int inport, PortDirection inport_dirn)
+{
+    return routingUnit.outportCompute(route, inport, inport_dirn);
+}
+
+void
+Router::grant_switch(int inport, flit *t_flit)
+{
+    crossbarSwitch.update_sw_winner(inport, t_flit);
+}
+
+void
+Router::schedule_wakeup(Cycles time)
+{
+    // wake up after time cycles
+    scheduleEvent(time);
+}
+
+std::string
+Router::getPortDirectionName(PortDirection direction)
+{
+    // PortDirection is actually a string
+    // If not, then this function should add a switch
+    // statement to convert direction to a string
+    // that can be printed out
+    return direction;
+}
+
+void
+Router::regStats()
+{
+    BasicRouter::regStats();
+
+    m_buffer_reads
+        .name(name() + ".buffer_reads")
+        .flags(Stats::nozero)
+    ;
+
+    m_buffer_writes
+        .name(name() + ".buffer_writes")
+        .flags(Stats::nozero)
+    ;
+
+    m_crossbar_activity
+        .name(name() + ".crossbar_activity")
+        .flags(Stats::nozero)
+    ;
+
+    m_sw_input_arbiter_activity
+        .name(name() + ".sw_input_arbiter_activity")
+        .flags(Stats::nozero)
+    ;
+
+    m_sw_output_arbiter_activity
+        .name(name() + ".sw_output_arbiter_activity")
+        .flags(Stats::nozero)
+    ;
+}
+
+void
+Router::collateStats()
+{
+    for (int j = 0; j < m_virtual_networks; j++) {
+        for (int i = 0; i < m_input_unit.size(); i++) {
+            m_buffer_reads += m_input_unit[i]->get_buf_read_activity(j);
+            m_buffer_writes += m_input_unit[i]->get_buf_write_activity(j);
+        }
+    }
+
+    m_sw_input_arbiter_activity = switchAllocator.get_input_arbiter_activity();
+    m_sw_output_arbiter_activity =
+        switchAllocator.get_output_arbiter_activity();
+    m_crossbar_activity = crossbarSwitch.get_crossbar_activity();
+}
+
+void
+Router::resetStats()
+{
+    for (int i = 0; i < m_input_unit.size(); i++) {
+            m_input_unit[i]->resetStats();
+    }
+
+    crossbarSwitch.resetStats();
+    switchAllocator.resetStats();
+}
+
+void
+Router::printFaultVector(ostream& out)
+{
+    int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
+    int num_fault_types = m_network_ptr->fault_model->number_of_fault_types;
+    float fault_vector[num_fault_types];
+    get_fault_vector(temperature_celcius, fault_vector);
+    out << "Router-" << m_id << " fault vector: " << endl;
+    for (int fault_type_index = 0; fault_type_index < num_fault_types;
+         fault_type_index++) {
+        out << " - probability of (";
+        out <<
+        m_network_ptr->fault_model->fault_type_to_string(fault_type_index);
+        out << ") = ";
+        out << fault_vector[fault_type_index] << endl;
+    }
+}
+
+void
+Router::printAggregateFaultProbability(std::ostream& out)
+{
+    int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
+    float aggregate_fault_prob;
+    get_aggregate_fault_probability(temperature_celcius,
+                                    &aggregate_fault_prob);
+    out << "Router-" << m_id << " fault probability: ";
+    out << aggregate_fault_prob << endl;
+}
+
+uint32_t
+Router::functionalWrite(Packet *pkt)
+{
+    uint32_t num_functional_writes = 0;
+    num_functional_writes += crossbarSwitch.functionalWrite(pkt);
+
+    for (uint32_t i = 0; i < m_input_unit.size(); i++) {
+        num_functional_writes += m_input_unit[i]->functionalWrite(pkt);
+    }
+
+    for (uint32_t i = 0; i < m_output_unit.size(); i++) {
+        num_functional_writes += m_output_unit[i]->functionalWrite(pkt);
+    }
+
+    return num_functional_writes;
+}
+
+Router *
+GarnetRouterParams::create()
+{
+    return new Router(this);
+}
diff --git a/src/mem/ruby/network/garnet/Router.hh b/src/mem/ruby/network/garnet/Router.hh
new file mode 100644 (file)
index 0000000..59d16bd
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_ROUTER_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_ROUTER_HH__
+
+#include <iostream>
+#include <memory>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/NetDest.hh"
+#include "mem/ruby/network/BasicRouter.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CrossbarSwitch.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/RoutingUnit.hh"
+#include "mem/ruby/network/garnet/SwitchAllocator.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+#include "params/GarnetRouter.hh"
+
+class NetworkLink;
+class CreditLink;
+class InputUnit;
+class OutputUnit;
+class FaultModel;
+
+class Router : public BasicRouter, public Consumer
+{
+  public:
+    typedef GarnetRouterParams Params;
+    Router(const Params *p);
+
+    ~Router() = default;
+
+    void wakeup();
+    void print(std::ostream& out) const {};
+
+    void init();
+    void addInPort(PortDirection inport_dirn, NetworkLink *link,
+                   CreditLink *credit_link);
+    void addOutPort(PortDirection outport_dirn, NetworkLink *link,
+                    std::vector<NetDest>& routing_table_entry,
+                    int link_weight, CreditLink *credit_link,
+                    uint32_t consumerVcs);
+
+    Cycles get_pipe_stages(){ return m_latency; }
+    uint32_t get_num_vcs()       { return m_num_vcs; }
+    uint32_t get_num_vnets()     { return m_virtual_networks; }
+    uint32_t get_vc_per_vnet()   { return m_vc_per_vnet; }
+    int get_num_inports()   { return m_input_unit.size(); }
+    int get_num_outports()  { return m_output_unit.size(); }
+    int get_id()            { return m_id; }
+
+    void init_net_ptr(GarnetNetwork* net_ptr)
+    {
+        m_network_ptr = net_ptr;
+    }
+
+    GarnetNetwork* get_net_ptr()                    { return m_network_ptr; }
+
+    InputUnit*
+    getInputUnit(unsigned port)
+    {
+        assert(port < m_input_unit.size());
+        return m_input_unit[port].get();
+    }
+
+    OutputUnit*
+    getOutputUnit(unsigned port)
+    {
+        assert(port < m_output_unit.size());
+        return m_output_unit[port].get();
+    }
+
+    int getBitWidth() { return m_bit_width; }
+
+    PortDirection getOutportDirection(int outport);
+    PortDirection getInportDirection(int inport);
+
+    int route_compute(RouteInfo route, int inport, PortDirection direction);
+    void grant_switch(int inport, flit *t_flit);
+    void schedule_wakeup(Cycles time);
+
+    std::string getPortDirectionName(PortDirection direction);
+    void printFaultVector(std::ostream& out);
+    void printAggregateFaultProbability(std::ostream& out);
+
+    void regStats();
+    void collateStats();
+    void resetStats();
+
+    // For Fault Model:
+    bool get_fault_vector(int temperature, float fault_vector[]) {
+        return m_network_ptr->fault_model->fault_vector(m_id, temperature,
+                                                        fault_vector);
+    }
+    bool get_aggregate_fault_probability(int temperature,
+                                         float *aggregate_fault_prob) {
+        return m_network_ptr->fault_model->fault_prob(m_id, temperature,
+                                                      aggregate_fault_prob);
+    }
+
+    uint32_t functionalWrite(Packet *);
+
+  private:
+    Cycles m_latency;
+    uint32_t m_virtual_networks, m_vc_per_vnet, m_num_vcs;
+    uint32_t m_bit_width;
+    GarnetNetwork *m_network_ptr;
+
+    RoutingUnit routingUnit;
+    SwitchAllocator switchAllocator;
+    CrossbarSwitch crossbarSwitch;
+
+    std::vector<std::shared_ptr<InputUnit>> m_input_unit;
+    std::vector<std::shared_ptr<OutputUnit>> m_output_unit;
+
+    // Statistical variables required for power computations
+    Stats::Scalar m_buffer_reads;
+    Stats::Scalar m_buffer_writes;
+
+    Stats::Scalar m_sw_input_arbiter_activity;
+    Stats::Scalar m_sw_output_arbiter_activity;
+
+    Stats::Scalar m_crossbar_activity;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_ROUTER_HH__
diff --git a/src/mem/ruby/network/garnet/RoutingUnit.cc b/src/mem/ruby/network/garnet/RoutingUnit.cc
new file mode 100644 (file)
index 0000000..835f052
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/RoutingUnit.hh"
+
+#include "base/cast.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/InputUnit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+
+RoutingUnit::RoutingUnit(Router *router)
+{
+    m_router = router;
+    m_routing_table.clear();
+    m_weight_table.clear();
+}
+
+void
+RoutingUnit::addRoute(std::vector<NetDest>& routing_table_entry)
+{
+    if (routing_table_entry.size() > m_routing_table.size()) {
+        m_routing_table.resize(routing_table_entry.size());
+    }
+    for (int v = 0; v < routing_table_entry.size(); v++) {
+        m_routing_table[v].push_back(routing_table_entry[v]);
+    }
+}
+
+void
+RoutingUnit::addWeight(int link_weight)
+{
+    m_weight_table.push_back(link_weight);
+}
+
+bool
+RoutingUnit::supportsVnet(int vnet, std::vector<int> sVnets)
+{
+    // If all vnets are supported, return true
+    if (sVnets.size() == 0) {
+        return true;
+    }
+
+    // Find the vnet in the vector, return true
+    if (std::find(sVnets.begin(), sVnets.end(), vnet) != sVnets.end()) {
+        return true;
+    }
+
+    // Not supported vnet
+    return false;
+}
+
+/*
+ * This is the default routing algorithm in garnet.
+ * The routing table is populated during topology creation.
+ * Routes can be biased via weight assignments in the topology file.
+ * Correct weight assignments are critical to provide deadlock avoidance.
+ */
+int
+RoutingUnit::lookupRoutingTable(int vnet, NetDest msg_destination)
+{
+    // First find all possible output link candidates
+    // For ordered vnet, just choose the first
+    // (to make sure different packets don't choose different routes)
+    // For unordered vnet, randomly choose any of the links
+    // To have a strict ordering between links, they should be given
+    // different weights in the topology file
+
+    int output_link = -1;
+    int min_weight = INFINITE_;
+    std::vector<int> output_link_candidates;
+    int num_candidates = 0;
+
+    // Identify the minimum weight among the candidate output links
+    for (int link = 0; link < m_routing_table[vnet].size(); link++) {
+        if (msg_destination.intersectionIsNotEmpty(
+            m_routing_table[vnet][link])) {
+
+        if (m_weight_table[link] <= min_weight)
+            min_weight = m_weight_table[link];
+        }
+    }
+
+    // Collect all candidate output links with this minimum weight
+    for (int link = 0; link < m_routing_table[vnet].size(); link++) {
+        if (msg_destination.intersectionIsNotEmpty(
+            m_routing_table[vnet][link])) {
+
+            if (m_weight_table[link] == min_weight) {
+                num_candidates++;
+                output_link_candidates.push_back(link);
+            }
+        }
+    }
+
+    if (output_link_candidates.size() == 0) {
+        fatal("Fatal Error:: No Route exists from this Router.");
+        exit(0);
+    }
+
+    // Randomly select any candidate output link
+    int candidate = 0;
+    if (!(m_router->get_net_ptr())->isVNetOrdered(vnet))
+        candidate = rand() % num_candidates;
+
+    output_link = output_link_candidates.at(candidate);
+    return output_link;
+}
+
+
+void
+RoutingUnit::addInDirection(PortDirection inport_dirn, int inport_idx)
+{
+    m_inports_dirn2idx[inport_dirn] = inport_idx;
+    m_inports_idx2dirn[inport_idx]  = inport_dirn;
+}
+
+void
+RoutingUnit::addOutDirection(PortDirection outport_dirn, int outport_idx)
+{
+    m_outports_dirn2idx[outport_dirn] = outport_idx;
+    m_outports_idx2dirn[outport_idx]  = outport_dirn;
+}
+
+// outportCompute() is called by the InputUnit
+// It calls the routing table by default.
+// A template for adaptive topology-specific routing algorithm
+// implementations using port directions rather than a static routing
+// table is provided here.
+
+int
+RoutingUnit::outportCompute(RouteInfo route, int inport,
+                            PortDirection inport_dirn)
+{
+    int outport = -1;
+
+    if (route.dest_router == m_router->get_id()) {
+
+        // Multiple NIs may be connected to this router,
+        // all with output port direction = "Local"
+        // Get exact outport id from table
+        outport = lookupRoutingTable(route.vnet, route.net_dest);
+        return outport;
+    }
+
+    // Routing Algorithm set in GarnetNetwork.py
+    // Can be over-ridden from command line using --routing-algorithm = 1
+    RoutingAlgorithm routing_algorithm =
+        (RoutingAlgorithm) m_router->get_net_ptr()->getRoutingAlgorithm();
+
+    switch (routing_algorithm) {
+        case TABLE_:  outport =
+            lookupRoutingTable(route.vnet, route.net_dest); break;
+        case XY_:     outport =
+            outportComputeXY(route, inport, inport_dirn); break;
+        // any custom algorithm
+        case CUSTOM_: outport =
+            outportComputeCustom(route, inport, inport_dirn); break;
+        default: outport =
+            lookupRoutingTable(route.vnet, route.net_dest); break;
+    }
+
+    assert(outport != -1);
+    return outport;
+}
+
+// XY routing implemented using port directions
+// Only for reference purpose in a Mesh
+// By default Garnet uses the routing table
+int
+RoutingUnit::outportComputeXY(RouteInfo route,
+                              int inport,
+                              PortDirection inport_dirn)
+{
+    PortDirection outport_dirn = "Unknown";
+
+    int M5_VAR_USED num_rows = m_router->get_net_ptr()->getNumRows();
+    int num_cols = m_router->get_net_ptr()->getNumCols();
+    assert(num_rows > 0 && num_cols > 0);
+
+    int my_id = m_router->get_id();
+    int my_x = my_id % num_cols;
+    int my_y = my_id / num_cols;
+
+    int dest_id = route.dest_router;
+    int dest_x = dest_id % num_cols;
+    int dest_y = dest_id / num_cols;
+
+    int x_hops = abs(dest_x - my_x);
+    int y_hops = abs(dest_y - my_y);
+
+    bool x_dirn = (dest_x >= my_x);
+    bool y_dirn = (dest_y >= my_y);
+
+    // already checked that in outportCompute() function
+    assert(!(x_hops == 0 && y_hops == 0));
+
+    if (x_hops > 0) {
+        if (x_dirn) {
+            assert(inport_dirn == "Local" || inport_dirn == "West");
+            outport_dirn = "East";
+        } else {
+            assert(inport_dirn == "Local" || inport_dirn == "East");
+            outport_dirn = "West";
+        }
+    } else if (y_hops > 0) {
+        if (y_dirn) {
+            // "Local" or "South" or "West" or "East"
+            assert(inport_dirn != "North");
+            outport_dirn = "North";
+        } else {
+            // "Local" or "North" or "West" or "East"
+            assert(inport_dirn != "South");
+            outport_dirn = "South";
+        }
+    } else {
+        // x_hops == 0 and y_hops == 0
+        // this is not possible
+        // already checked that in outportCompute() function
+        panic("x_hops == y_hops == 0");
+    }
+
+    return m_outports_dirn2idx[outport_dirn];
+}
+
+// Template for implementing custom routing algorithm
+// using port directions. (Example adaptive)
+int
+RoutingUnit::outportComputeCustom(RouteInfo route,
+                                 int inport,
+                                 PortDirection inport_dirn)
+{
+    panic("%s placeholder executed", __FUNCTION__);
+}
diff --git a/src/mem/ruby/network/garnet/RoutingUnit.hh b/src/mem/ruby/network/garnet/RoutingUnit.hh
new file mode 100644 (file)
index 0000000..8881ea4
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_ROUTINGUNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_ROUTINGUNIT_HH__
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/NetDest.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+
+class InputUnit;
+class Router;
+
+class RoutingUnit
+{
+  public:
+    RoutingUnit(Router *router);
+    int outportCompute(RouteInfo route,
+                      int inport,
+                      PortDirection inport_dirn);
+
+    // Topology-agnostic Routing Table based routing (default)
+    void addRoute(std::vector<NetDest>& routing_table_entry);
+    void addWeight(int link_weight);
+
+    // get output port from routing table
+    int  lookupRoutingTable(int vnet, NetDest net_dest);
+
+    // Topology-specific direction based routing
+    void addInDirection(PortDirection inport_dirn, int inport);
+    void addOutDirection(PortDirection outport_dirn, int outport);
+
+    // Routing for Mesh
+    int outportComputeXY(RouteInfo route,
+                         int inport,
+                         PortDirection inport_dirn);
+
+    // Custom Routing Algorithm using Port Directions
+    int outportComputeCustom(RouteInfo route,
+                             int inport,
+                             PortDirection inport_dirn);
+
+    // Returns true if vnet is present in the vector
+    // of vnets or if the vector supports all vnets.
+    bool supportsVnet(int vnet, std::vector<int> sVnets);
+
+
+  private:
+    Router *m_router;
+
+    // Routing Table
+    std::vector<std::vector<NetDest>> m_routing_table;
+    std::vector<int> m_weight_table;
+
+    // Inport and Outport direction to idx maps
+    std::map<PortDirection, int> m_inports_dirn2idx;
+    std::map<int, PortDirection> m_inports_idx2dirn;
+    std::map<int, PortDirection> m_outports_idx2dirn;
+    std::map<PortDirection, int> m_outports_dirn2idx;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_ROUTINGUNIT_HH__
diff --git a/src/mem/ruby/network/garnet/SConscript b/src/mem/ruby/network/garnet/SConscript
new file mode 100644 (file)
index 0000000..e3bc110
--- /dev/null
@@ -0,0 +1,52 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2016 Georgia Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('*')
+
+if env['PROTOCOL'] == 'None':
+    Return()
+
+SimObject('GarnetLink.py')
+SimObject('GarnetNetwork.py')
+
+Source('GarnetLink.cc')
+Source('GarnetNetwork.cc')
+Source('InputUnit.cc')
+Source('NetworkInterface.cc')
+Source('NetworkLink.cc')
+Source('OutVcState.cc')
+Source('OutputUnit.cc')
+Source('Router.cc')
+Source('RoutingUnit.cc')
+Source('SwitchAllocator.cc')
+Source('CrossbarSwitch.cc')
+Source('VirtualChannel.cc')
+Source('flitBuffer.cc')
+Source('flit.cc')
+Source('Credit.cc')
+Source('NetworkBridge.cc')
diff --git a/src/mem/ruby/network/garnet/SwitchAllocator.cc b/src/mem/ruby/network/garnet/SwitchAllocator.cc
new file mode 100644 (file)
index 0000000..0b3141e
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/SwitchAllocator.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/InputUnit.hh"
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+
+SwitchAllocator::SwitchAllocator(Router *router)
+    : Consumer(router)
+{
+    m_router = router;
+    m_num_vcs = m_router->get_num_vcs();
+    m_vc_per_vnet = m_router->get_vc_per_vnet();
+
+    m_input_arbiter_activity = 0;
+    m_output_arbiter_activity = 0;
+}
+
+void
+SwitchAllocator::init()
+{
+    m_num_inports = m_router->get_num_inports();
+    m_num_outports = m_router->get_num_outports();
+    m_round_robin_inport.resize(m_num_outports);
+    m_round_robin_invc.resize(m_num_inports);
+    m_port_requests.resize(m_num_outports);
+    m_vc_winners.resize(m_num_outports);
+
+    for (int i = 0; i < m_num_inports; i++) {
+        m_round_robin_invc[i] = 0;
+    }
+
+    for (int i = 0; i < m_num_outports; i++) {
+        m_port_requests[i].resize(m_num_inports);
+        m_vc_winners[i].resize(m_num_inports);
+
+        m_round_robin_inport[i] = 0;
+
+        for (int j = 0; j < m_num_inports; j++) {
+            m_port_requests[i][j] = false; // [outport][inport]
+        }
+    }
+}
+
+/*
+ * The wakeup function of the SwitchAllocator performs a 2-stage
+ * seperable switch allocation. At the end of the 2nd stage, a free
+ * output VC is assigned to the winning flits of each output port.
+ * There is no separate VCAllocator stage like the one in garnet1.0.
+ * At the end of this function, the router is rescheduled to wakeup
+ * next cycle for peforming SA for any flits ready next cycle.
+ */
+
+void
+SwitchAllocator::wakeup()
+{
+    arbitrate_inports(); // First stage of allocation
+    arbitrate_outports(); // Second stage of allocation
+
+    clear_request_vector();
+    check_for_wakeup();
+}
+
+/*
+ * SA-I (or SA-i) loops through all input VCs at every input port,
+ * and selects one in a round robin manner.
+ *    - For HEAD/HEAD_TAIL flits only selects an input VC whose output port
+ *     has at least one free output VC.
+ *    - For BODY/TAIL flits, only selects an input VC that has credits
+ *      in its output VC.
+ * Places a request for the output port from this input VC.
+ */
+
+void
+SwitchAllocator::arbitrate_inports()
+{
+    // Select a VC from each input in a round robin manner
+    // Independent arbiter at each input port
+    for (int inport = 0; inport < m_num_inports; inport++) {
+        int invc = m_round_robin_invc[inport];
+
+        for (int invc_iter = 0; invc_iter < m_num_vcs; invc_iter++) {
+            auto input_unit = m_router->getInputUnit(inport);
+
+            if (input_unit->need_stage(invc, SA_, curTick())) {
+                // This flit is in SA stage
+
+                int outport = input_unit->get_outport(invc);
+                int outvc = input_unit->get_outvc(invc);
+
+                // check if the flit in this InputVC is allowed to be sent
+                // send_allowed conditions described in that function.
+                bool make_request =
+                    send_allowed(inport, invc, outport, outvc);
+
+                if (make_request) {
+                    m_input_arbiter_activity++;
+                    m_port_requests[outport][inport] = true;
+                    m_vc_winners[outport][inport]= invc;
+
+                    break; // got one vc winner for this port
+                }
+            }
+
+            invc++;
+            if (invc >= m_num_vcs)
+                invc = 0;
+        }
+    }
+}
+
+/*
+ * SA-II (or SA-o) loops through all output ports,
+ * and selects one input VC (that placed a request during SA-I)
+ * as the winner for this output port in a round robin manner.
+ *      - For HEAD/HEAD_TAIL flits, performs simplified outvc allocation.
+ *        (i.e., select a free VC from the output port).
+ *      - For BODY/TAIL flits, decrement a credit in the output vc.
+ * The winning flit is read out from the input VC and sent to the
+ * CrossbarSwitch.
+ * An increment_credit signal is sent from the InputUnit
+ * to the upstream router. For HEAD_TAIL/TAIL flits, is_free_signal in the
+ * credit is set to true.
+ */
+
+void
+SwitchAllocator::arbitrate_outports()
+{
+    // Now there are a set of input vc requests for output vcs.
+    // Again do round robin arbitration on these requests
+    // Independent arbiter at each output port
+    for (int outport = 0; outport < m_num_outports; outport++) {
+        int inport = m_round_robin_inport[outport];
+
+        for (int inport_iter = 0; inport_iter < m_num_inports;
+                 inport_iter++) {
+
+            // inport has a request this cycle for outport
+            if (m_port_requests[outport][inport]) {
+                auto output_unit = m_router->getOutputUnit(outport);
+                auto input_unit = m_router->getInputUnit(inport);
+
+                // grant this outport to this inport
+                int invc = m_vc_winners[outport][inport];
+
+                int outvc = input_unit->get_outvc(invc);
+                if (outvc == -1) {
+                    // VC Allocation - select any free VC from outport
+                    outvc = vc_allocate(outport, inport, invc);
+                }
+
+                // remove flit from Input VC
+                flit *t_flit = input_unit->getTopFlit(invc);
+
+                DPRINTF(RubyNetwork, "SwitchAllocator at Router %d "
+                                     "granted outvc %d at outport %d "
+                                     "to invc %d at inport %d to flit %s at "
+                                     "cycle: %lld\n",
+                        m_router->get_id(), outvc,
+                        m_router->getPortDirectionName(
+                            output_unit->get_direction()),
+                        invc,
+                        m_router->getPortDirectionName(
+                            input_unit->get_direction()),
+                            *t_flit,
+                        m_router->curCycle());
+
+
+                // Update outport field in the flit since this is
+                // used by CrossbarSwitch code to send it out of
+                // correct outport.
+                // Note: post route compute in InputUnit,
+                // outport is updated in VC, but not in flit
+                t_flit->set_outport(outport);
+
+                // set outvc (i.e., invc for next hop) in flit
+                // (This was updated in VC by vc_allocate, but not in flit)
+                t_flit->set_vc(outvc);
+
+                // decrement credit in outvc
+                output_unit->decrement_credit(outvc);
+
+                // flit ready for Switch Traversal
+                t_flit->advance_stage(ST_, curTick());
+                m_router->grant_switch(inport, t_flit);
+                m_output_arbiter_activity++;
+
+                if ((t_flit->get_type() == TAIL_) ||
+                    t_flit->get_type() == HEAD_TAIL_) {
+
+                    // This Input VC should now be empty
+                    assert(!(input_unit->isReady(invc, curTick())));
+
+                    // Free this VC
+                    input_unit->set_vc_idle(invc, curTick());
+
+                    // Send a credit back
+                    // along with the information that this VC is now idle
+                    input_unit->increment_credit(invc, true, curTick());
+                } else {
+                    // Send a credit back
+                    // but do not indicate that the VC is idle
+                    input_unit->increment_credit(invc, false, curTick());
+                }
+
+                // remove this request
+                m_port_requests[outport][inport] = false;
+
+                // Update Round Robin pointer
+                m_round_robin_inport[outport] = inport + 1;
+                if (m_round_robin_inport[outport] >= m_num_inports)
+                    m_round_robin_inport[outport] = 0;
+
+                // Update Round Robin pointer to the next VC
+                // We do it here to keep it fair.
+                // Only the VC which got switch traversal
+                // is updated.
+                m_round_robin_invc[inport] = invc + 1;
+                if (m_round_robin_invc[inport] >= m_num_vcs)
+                    m_round_robin_invc[inport] = 0;
+
+
+                break; // got a input winner for this outport
+            }
+
+            inport++;
+            if (inport >= m_num_inports)
+                inport = 0;
+        }
+    }
+}
+
+/*
+ * A flit can be sent only if
+ * (1) there is at least one free output VC at the
+ *     output port (for HEAD/HEAD_TAIL),
+ *  or
+ * (2) if there is at least one credit (i.e., buffer slot)
+ *     within the VC for BODY/TAIL flits of multi-flit packets.
+ * and
+ * (3) pt-to-pt ordering is not violated in ordered vnets, i.e.,
+ *     there should be no other flit in this input port
+ *     within an ordered vnet
+ *     that arrived before this flit and is requesting the same output port.
+ */
+
+bool
+SwitchAllocator::send_allowed(int inport, int invc, int outport, int outvc)
+{
+    // Check if outvc needed
+    // Check if credit needed (for multi-flit packet)
+    // Check if ordering violated (in ordered vnet)
+
+    int vnet = get_vnet(invc);
+    bool has_outvc = (outvc != -1);
+    bool has_credit = false;
+
+    auto output_unit = m_router->getOutputUnit(outport);
+    if (!has_outvc) {
+
+        // needs outvc
+        // this is only true for HEAD and HEAD_TAIL flits.
+
+        if (output_unit->has_free_vc(vnet)) {
+
+            has_outvc = true;
+
+            // each VC has at least one buffer,
+            // so no need for additional credit check
+            has_credit = true;
+        }
+    } else {
+        has_credit = output_unit->has_credit(outvc);
+    }
+
+    // cannot send if no outvc or no credit.
+    if (!has_outvc || !has_credit)
+        return false;
+
+
+    // protocol ordering check
+    if ((m_router->get_net_ptr())->isVNetOrdered(vnet)) {
+        auto input_unit = m_router->getInputUnit(inport);
+
+        // enqueue time of this flit
+        Tick t_enqueue_time = input_unit->get_enqueue_time(invc);
+
+        // check if any other flit is ready for SA and for same output port
+        // and was enqueued before this flit
+        int vc_base = vnet*m_vc_per_vnet;
+        for (int vc_offset = 0; vc_offset < m_vc_per_vnet; vc_offset++) {
+            int temp_vc = vc_base + vc_offset;
+            if (input_unit->need_stage(temp_vc, SA_, curTick()) &&
+               (input_unit->get_outport(temp_vc) == outport) &&
+               (input_unit->get_enqueue_time(temp_vc) < t_enqueue_time)) {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+// Assign a free VC to the winner of the output port.
+int
+SwitchAllocator::vc_allocate(int outport, int inport, int invc)
+{
+    // Select a free VC from the output port
+    int outvc =
+        m_router->getOutputUnit(outport)->select_free_vc(get_vnet(invc));
+
+    // has to get a valid VC since it checked before performing SA
+    assert(outvc != -1);
+    m_router->getInputUnit(inport)->grant_outvc(invc, outvc);
+    return outvc;
+}
+
+// Wakeup the router next cycle to perform SA again
+// if there are flits ready.
+void
+SwitchAllocator::check_for_wakeup()
+{
+    Tick nextCycle = m_router->clockEdge(Cycles(1));
+
+    if (m_router->alreadyScheduled(nextCycle)) {
+        return;
+    }
+
+    for (int i = 0; i < m_num_inports; i++) {
+        for (int j = 0; j < m_num_vcs; j++) {
+            if (m_router->getInputUnit(i)->need_stage(j, SA_, nextCycle)) {
+                m_router->schedule_wakeup(Cycles(1));
+                return;
+            }
+        }
+    }
+}
+
+int
+SwitchAllocator::get_vnet(int invc)
+{
+    int vnet = invc/m_vc_per_vnet;
+    assert(vnet < m_router->get_num_vnets());
+    return vnet;
+}
+
+
+// Clear the request vector within the allocator at end of SA-II.
+// Was populated by SA-I.
+void
+SwitchAllocator::clear_request_vector()
+{
+    for (int i = 0; i < m_num_outports; i++) {
+        for (int j = 0; j < m_num_inports; j++) {
+            m_port_requests[i][j] = false;
+        }
+    }
+}
+
+void
+SwitchAllocator::resetStats()
+{
+    m_input_arbiter_activity = 0;
+    m_output_arbiter_activity = 0;
+}
diff --git a/src/mem/ruby/network/garnet/SwitchAllocator.hh b/src/mem/ruby/network/garnet/SwitchAllocator.hh
new file mode 100644 (file)
index 0000000..82ee67e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_SWITCHALLOCATOR_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_SWITCHALLOCATOR_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+
+class Router;
+class InputUnit;
+class OutputUnit;
+
+class SwitchAllocator : public Consumer
+{
+  public:
+    SwitchAllocator(Router *router);
+    void wakeup();
+    void init();
+    void clear_request_vector();
+    void check_for_wakeup();
+    int get_vnet (int invc);
+    void print(std::ostream& out) const {};
+    void arbitrate_inports();
+    void arbitrate_outports();
+    bool send_allowed(int inport, int invc, int outport, int outvc);
+    int vc_allocate(int outport, int inport, int invc);
+
+    inline double
+    get_input_arbiter_activity()
+    {
+        return m_input_arbiter_activity;
+    }
+    inline double
+    get_output_arbiter_activity()
+    {
+        return m_output_arbiter_activity;
+    }
+
+    void resetStats();
+
+  private:
+    int m_num_inports, m_num_outports;
+    int m_num_vcs, m_vc_per_vnet;
+
+    double m_input_arbiter_activity, m_output_arbiter_activity;
+
+    Router *m_router;
+    std::vector<int> m_round_robin_invc;
+    std::vector<int> m_round_robin_inport;
+    std::vector<std::vector<bool>> m_port_requests;
+    std::vector<std::vector<int>> m_vc_winners; // a list for each outport
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_SWITCHALLOCATOR_HH__
diff --git a/src/mem/ruby/network/garnet/VirtualChannel.cc b/src/mem/ruby/network/garnet/VirtualChannel.cc
new file mode 100644 (file)
index 0000000..1035660
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/VirtualChannel.hh"
+
+VirtualChannel::VirtualChannel()
+  : inputBuffer(), m_vc_state(IDLE_, Tick(0)), m_output_port(-1),
+    m_enqueue_time(INFINITE_), m_output_vc(-1)
+{
+}
+
+void
+VirtualChannel::set_idle(Tick curTime)
+{
+    m_vc_state.first = IDLE_;
+    m_vc_state.second = curTime;
+    m_enqueue_time = Tick(INFINITE_);
+    m_output_port = -1;
+    m_output_vc = -1;
+}
+
+void
+VirtualChannel::set_active(Tick curTime)
+{
+    m_vc_state.first = ACTIVE_;
+    m_vc_state.second = curTime;
+    m_enqueue_time = curTime;
+}
+
+bool
+VirtualChannel::need_stage(flit_stage stage, Tick time)
+{
+    if (inputBuffer.isReady(time)) {
+        assert(m_vc_state.first == ACTIVE_ && m_vc_state.second <= time);
+        flit *t_flit = inputBuffer.peekTopFlit();
+        return(t_flit->is_stage(stage, time));
+    }
+    return false;
+}
+
+uint32_t
+VirtualChannel::functionalWrite(Packet *pkt)
+{
+    return inputBuffer.functionalWrite(pkt);
+}
diff --git a/src/mem/ruby/network/garnet/VirtualChannel.hh b/src/mem/ruby/network/garnet/VirtualChannel.hh
new file mode 100644 (file)
index 0000000..c538451
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_VIRTUALCHANNEL_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_VIRTUALCHANNEL_HH__
+
+#include <utility>
+
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+class VirtualChannel
+{
+  public:
+    VirtualChannel();
+    ~VirtualChannel() = default;
+
+    bool need_stage(flit_stage stage, Tick time);
+    void set_idle(Tick curTime);
+    void set_active(Tick curTime);
+    void set_outvc(int outvc)               { m_output_vc = outvc; }
+    inline int get_outvc()                  { return m_output_vc; }
+    void set_outport(int outport)           { m_output_port = outport; };
+    inline int get_outport()                  { return m_output_port; }
+
+    inline Tick get_enqueue_time()          { return m_enqueue_time; }
+    inline void set_enqueue_time(Tick time) { m_enqueue_time = time; }
+    inline VC_state_type get_state()        { return m_vc_state.first; }
+
+    inline bool
+    isReady(Tick curTime)
+    {
+        return inputBuffer.isReady(curTime);
+    }
+
+    inline void
+    insertFlit(flit *t_flit)
+    {
+        inputBuffer.insert(t_flit);
+    }
+
+    inline void
+    set_state(VC_state_type m_state, Tick curTime)
+    {
+        m_vc_state.first = m_state;
+        m_vc_state.second = curTime;
+    }
+
+    inline flit*
+    peekTopFlit()
+    {
+        return inputBuffer.peekTopFlit();
+    }
+
+    inline flit*
+    getTopFlit()
+    {
+        return inputBuffer.getTopFlit();
+    }
+
+    uint32_t functionalWrite(Packet *pkt);
+
+  private:
+    flitBuffer inputBuffer;
+    std::pair<VC_state_type, Tick> m_vc_state;
+    int m_output_port;
+    Tick m_enqueue_time;
+    int m_output_vc;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_VIRTUALCHANNEL_HH__
diff --git a/src/mem/ruby/network/garnet/flit.cc b/src/mem/ruby/network/garnet/flit.cc
new file mode 100644 (file)
index 0000000..50a8911
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/flit.hh"
+
+#include "base/intmath.hh"
+#include "debug/RubyNetwork.hh"
+
+// Constructor for the flit
+flit::flit(int id, int  vc, int vnet, RouteInfo route, int size,
+    MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime)
+{
+    m_size = size;
+    m_msg_ptr = msg_ptr;
+    m_enqueue_time = curTime;
+    m_dequeue_time = curTime;
+    m_time = curTime;
+    m_id = id;
+    m_vnet = vnet;
+    m_vc = vc;
+    m_route = route;
+    m_stage.first = I_;
+    m_stage.second = curTime;
+    m_width = bWidth;
+    msgSize = MsgSize;
+
+    if (size == 1) {
+        m_type = HEAD_TAIL_;
+        return;
+    }
+    if (id == 0)
+        m_type = HEAD_;
+    else if (id == (size - 1))
+        m_type = TAIL_;
+    else
+        m_type = BODY_;
+}
+
+flit *
+flit::serialize(int ser_id, int parts, uint32_t bWidth)
+{
+    assert(m_width > bWidth);
+
+    int ratio = (int)divCeil(m_width, bWidth);
+    int new_id = (m_id*ratio) + ser_id;
+    int new_size = (int)divCeil((float)msgSize, (float)bWidth);
+    assert(new_id < new_size);
+
+    flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
+                    new_size, m_msg_ptr, msgSize, bWidth, m_time);
+    fl->set_enqueue_time(m_enqueue_time);
+    fl->set_src_delay(src_delay);
+    return fl;
+}
+
+flit *
+flit::deserialize(int des_id, int num_flits, uint32_t bWidth)
+{
+    int ratio = (int)divCeil((float)bWidth, (float)m_width);
+    int new_id = ((int)divCeil((float)(m_id+1), (float)ratio)) - 1;
+    int new_size = (int)divCeil((float)msgSize, (float)bWidth);
+    assert(new_id < new_size);
+
+    flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
+                    new_size, m_msg_ptr, msgSize, bWidth, m_time);
+    fl->set_enqueue_time(m_enqueue_time);
+    fl->set_src_delay(src_delay);
+    return fl;
+}
+
+// Flit can be printed out for debugging purposes
+void
+flit::print(std::ostream& out) const
+{
+    out << "[flit:: ";
+    out << "Id=" << m_id << " ";
+    out << "Type=" << m_type << " ";
+    out << "Size=" << m_size << " ";
+    out << "Vnet=" << m_vnet << " ";
+    out << "VC=" << m_vc << " ";
+    out << "Src NI=" << m_route.src_ni << " ";
+    out << "Src Router=" << m_route.src_router << " ";
+    out << "Dest NI=" << m_route.dest_ni << " ";
+    out << "Dest Router=" << m_route.dest_router << " ";
+    out << "Set Time=" << m_time << " ";
+    out << "Width=" << m_width<< " ";
+    out << "]";
+}
+
+bool
+flit::functionalWrite(Packet *pkt)
+{
+    Message *msg = m_msg_ptr.get();
+    return msg->functionalWrite(pkt);
+}
diff --git a/src/mem/ruby/network/garnet/flit.hh b/src/mem/ruby/network/garnet/flit.hh
new file mode 100644 (file)
index 0000000..0396c97
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_FLIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_FLIT_HH__
+
+#include <cassert>
+#include <iostream>
+
+#include "base/types.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+
+class flit
+{
+  public:
+    flit() {}
+    flit(int id, int vc, int vnet, RouteInfo route, int size,
+         MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime);
+
+    virtual ~flit(){};
+
+    int get_outport() {return m_outport; }
+    int get_size() { return m_size; }
+    Tick get_enqueue_time() { return m_enqueue_time; }
+    Tick get_dequeue_time() { return m_dequeue_time; }
+    int get_id() { return m_id; }
+    Tick get_time() { return m_time; }
+    int get_vnet() { return m_vnet; }
+    int get_vc() { return m_vc; }
+    RouteInfo get_route() { return m_route; }
+    MsgPtr& get_msg_ptr() { return m_msg_ptr; }
+    flit_type get_type() { return m_type; }
+    std::pair<flit_stage, Tick> get_stage() { return m_stage; }
+    Tick get_src_delay() { return src_delay; }
+
+    void set_outport(int port) { m_outport = port; }
+    void set_time(Tick time) { m_time = time; }
+    void set_vc(int vc) { m_vc = vc; }
+    void set_route(RouteInfo route) { m_route = route; }
+    void set_src_delay(Tick delay) { src_delay = delay; }
+    void set_dequeue_time(Tick time) { m_dequeue_time = time; }
+    void set_enqueue_time(Tick time) { m_enqueue_time = time; }
+
+    void increment_hops() { m_route.hops_traversed++; }
+    virtual void print(std::ostream& out) const;
+
+    bool
+    is_stage(flit_stage stage, Tick time)
+    {
+        return (stage == m_stage.first &&
+                time >= m_stage.second);
+    }
+
+    void
+    advance_stage(flit_stage t_stage, Tick newTime)
+    {
+        m_stage.first = t_stage;
+        m_stage.second = newTime;
+    }
+
+    static bool
+    greater(flit* n1, flit* n2)
+    {
+        if (n1->get_time() == n2->get_time()) {
+            //assert(n1->flit_id != n2->flit_id);
+            return (n1->get_id() > n2->get_id());
+        } else {
+            return (n1->get_time() > n2->get_time());
+        }
+    }
+
+    bool functionalWrite(Packet *pkt);
+
+    virtual flit* serialize(int ser_id, int parts, uint32_t bWidth);
+    virtual flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
+
+    uint32_t m_width;
+    int msgSize;
+  protected:
+    int m_id;
+    int m_vnet;
+    int m_vc;
+    RouteInfo m_route;
+    int m_size;
+    Tick m_enqueue_time, m_dequeue_time;
+    Tick m_time;
+    flit_type m_type;
+    MsgPtr m_msg_ptr;
+    int m_outport;
+    Tick src_delay;
+    std::pair<flit_stage, Tick> m_stage;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const flit& obj)
+{
+    obj.print(out);
+    out << std::flush;
+    return out;
+}
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_FLIT_HH__
diff --git a/src/mem/ruby/network/garnet/flitBuffer.cc b/src/mem/ruby/network/garnet/flitBuffer.cc
new file mode 100644 (file)
index 0000000..6c0c1ad
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+flitBuffer::flitBuffer()
+{
+    max_size = INFINITE_;
+}
+
+flitBuffer::flitBuffer(int maximum_size)
+{
+    max_size = maximum_size;
+}
+
+bool
+flitBuffer::isEmpty()
+{
+    return (m_buffer.size() == 0);
+}
+
+bool
+flitBuffer::isReady(Tick curTime)
+{
+    if (m_buffer.size() != 0 ) {
+        flit *t_flit = peekTopFlit();
+        if (t_flit->get_time() <= curTime)
+            return true;
+    }
+    return false;
+}
+
+void
+flitBuffer::print(std::ostream& out) const
+{
+    out << "[flitBuffer: " << m_buffer.size() << "] " << std::endl;
+}
+
+bool
+flitBuffer::isFull()
+{
+    return (m_buffer.size() >= max_size);
+}
+
+void
+flitBuffer::setMaxSize(int maximum)
+{
+    max_size = maximum;
+}
+
+uint32_t
+flitBuffer::functionalWrite(Packet *pkt)
+{
+    uint32_t num_functional_writes = 0;
+
+    for (unsigned int i = 0; i < m_buffer.size(); ++i) {
+        if (m_buffer[i]->functionalWrite(pkt)) {
+            num_functional_writes++;
+        }
+    }
+
+    return num_functional_writes;
+}
diff --git a/src/mem/ruby/network/garnet/flitBuffer.hh b/src/mem/ruby/network/garnet/flitBuffer.hh
new file mode 100644 (file)
index 0000000..40af826
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_FLITBUFFER_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_FLITBUFFER_HH__
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+
+class flitBuffer
+{
+  public:
+    flitBuffer();
+    flitBuffer(int maximum_size);
+
+    bool isReady(Tick curTime);
+    bool isEmpty();
+    void print(std::ostream& out) const;
+    bool isFull();
+    void setMaxSize(int maximum);
+    int getSize() const { return m_buffer.size(); }
+
+    flit *
+    getTopFlit()
+    {
+        flit *f = m_buffer.front();
+        std::pop_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
+        m_buffer.pop_back();
+        return f;
+    }
+
+    flit *
+    peekTopFlit()
+    {
+        return m_buffer.front();
+    }
+
+    void
+    insert(flit *flt)
+    {
+        m_buffer.push_back(flt);
+        std::push_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
+    }
+
+    uint32_t functionalWrite(Packet *pkt);
+
+  private:
+    std::vector<flit *> m_buffer;
+    int max_size;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const flitBuffer& obj)
+{
+    obj.print(out);
+    out << std::flush;
+    return out;
+}
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_FLITBUFFER_HH__
diff --git a/src/mem/ruby/network/garnet2.0/CommonTypes.hh b/src/mem/ruby/network/garnet2.0/CommonTypes.hh
deleted file mode 100644 (file)
index 643ce8c..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_COMMONTYPES_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_COMMONTYPES_HH__
-
-#include "mem/ruby/common/NetDest.hh"
-
-// All common enums and typedefs go here
-
-enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_,
-                CREDIT_, NUM_FLIT_TYPE_};
-enum VC_state_type {IDLE_, VC_AB_, ACTIVE_, NUM_VC_STATE_TYPE_};
-enum VNET_type {CTRL_VNET_, DATA_VNET_, NULL_VNET_, NUM_VNET_TYPE_};
-enum flit_stage {I_, VA_, SA_, ST_, LT_, NUM_FLIT_STAGE_};
-enum link_type { EXT_IN_, EXT_OUT_, INT_, NUM_LINK_TYPES_ };
-enum RoutingAlgorithm { TABLE_ = 0, XY_ = 1, CUSTOM_ = 2,
-                        NUM_ROUTING_ALGORITHM_};
-
-struct RouteInfo
-{
-    RouteInfo()
-        : vnet(0), src_ni(0), src_router(0), dest_ni(0), dest_router(0),
-          hops_traversed(0)
-    {}
-
-    // destination format for table-based routing
-    int vnet;
-    NetDest net_dest;
-
-    // src and dest format for topology-specific routing
-    int src_ni;
-    int src_router;
-    int dest_ni;
-    int dest_router;
-    int hops_traversed;
-};
-
-#define INFINITE_ 10000
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_COMMONTYPES_HH__
diff --git a/src/mem/ruby/network/garnet2.0/Credit.cc b/src/mem/ruby/network/garnet2.0/Credit.cc
deleted file mode 100644 (file)
index bde9484..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-
-#include "base/trace.hh"
-#include "debug/RubyNetwork.hh"
-
-// Credit Signal for buffers inside VC
-// Carries m_vc (inherits from flit.hh)
-// and m_is_free_signal (whether VC is free or not)
-
-Credit::Credit(int vc, bool is_free_signal, Tick curTime)
-    : flit(0, vc, 0, RouteInfo(), 0, nullptr, 0, 0, curTime)
-{
-    m_is_free_signal = is_free_signal;
-    m_type = CREDIT_;
-}
-
-flit *
-Credit::serialize(int ser_id, int parts, uint32_t bWidth)
-{
-    DPRINTF(RubyNetwork, "Serializing a credit\n");
-    bool new_free = false;
-    if ((ser_id+1 == parts) && m_is_free_signal) {
-        new_free = true;
-    }
-    Credit *new_credit_flit = new Credit(m_vc, new_free, m_time);
-    return new_credit_flit;
-}
-
-flit *
-Credit::deserialize(int des_id, int num_flits, uint32_t bWidth)
-{
-    DPRINTF(RubyNetwork, "DeSerializing a credit vc:%d free:%d\n",
-    m_vc, m_is_free_signal);
-    if (m_is_free_signal) {
-        // We are not going to get anymore credits for this vc
-        // So send a credit in any case
-        return new Credit(m_vc, true, m_time);
-    }
-
-    return new Credit(m_vc, false, m_time);
-}
-
-void
-Credit::print(std::ostream& out) const
-{
-    out << "[Credit:: ";
-    out << "Type=" << m_type << " ";
-    out << "VC=" << m_vc << " ";
-    out << "FreeVC=" << m_is_free_signal << " ";
-    out << "Set Time=" << m_time << " ";
-    out << "]";
-}
-
-
-
diff --git a/src/mem/ruby/network/garnet2.0/Credit.hh b/src/mem/ruby/network/garnet2.0/Credit.hh
deleted file mode 100644 (file)
index bcfd76f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_CREDIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_CREDIT_HH__
-
-#include <cassert>
-#include <iostream>
-
-#include "base/types.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-// Credit Signal for buffers inside VC
-// Carries m_vc (inherits from flit.hh)
-// and m_is_free_signal (whether VC is free or not)
-
-class Credit : public flit
-{
-  public:
-    Credit() {};
-    Credit(int vc, bool is_free_signal, Tick curTime);
-
-    // Functions used by SerDes
-    flit* serialize(int ser_id, int parts, uint32_t bWidth);
-    flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
-    void print(std::ostream& out) const;
-
-    ~Credit() {};
-
-    bool is_free_signal() { return m_is_free_signal; }
-
-  private:
-    bool m_is_free_signal;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_CREDIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/CreditLink.hh b/src/mem/ruby/network/garnet2.0/CreditLink.hh
deleted file mode 100644 (file)
index 13e670d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_CREDITLINK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_CREDITLINK_HH__
-
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "params/CreditLink.hh"
-
-class CreditLink : public NetworkLink
-{
-  public:
-    typedef CreditLinkParams Params;
-    CreditLink(const Params *p) : NetworkLink(p) {}
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_CREDITLINK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc b/src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc
deleted file mode 100644 (file)
index 3148446..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-CrossbarSwitch::CrossbarSwitch(Router *router)
-  : Consumer(router), m_router(router), m_num_vcs(m_router->get_num_vcs()),
-    m_crossbar_activity(0), switchBuffers(0)
-{
-}
-
-void
-CrossbarSwitch::init()
-{
-    switchBuffers.resize(m_router->get_num_inports());
-}
-
-/*
- * The wakeup function of the CrossbarSwitch loops through all input ports,
- * and sends the winning flit (from SA) out of its output port on to the
- * output link. The output link is scheduled for wakeup in the next cycle.
- */
-
-void
-CrossbarSwitch::wakeup()
-{
-    DPRINTF(RubyNetwork, "CrossbarSwitch at Router %d woke up "
-            "at time: %lld\n",
-            m_router->get_id(), m_router->curCycle());
-
-    for (auto& switch_buffer : switchBuffers) {
-        if (!switch_buffer.isReady(curTick())) {
-            continue;
-        }
-
-        flit *t_flit = switch_buffer.peekTopFlit();
-        if (t_flit->is_stage(ST_, curTick())) {
-            int outport = t_flit->get_outport();
-
-            // flit performs LT_ in the next cycle
-            t_flit->advance_stage(LT_, m_router->clockEdge(Cycles(1)));
-            t_flit->set_time(m_router->clockEdge(Cycles(1)));
-
-            // This will take care of waking up the Network Link
-            // in the next cycle
-            m_router->getOutputUnit(outport)->insert_flit(t_flit);
-            switch_buffer.getTopFlit();
-            m_crossbar_activity++;
-        }
-    }
-}
-
-uint32_t
-CrossbarSwitch::functionalWrite(Packet *pkt)
-{
-   uint32_t num_functional_writes = 0;
-
-   for (auto& switch_buffer : switchBuffers) {
-       num_functional_writes += switch_buffer.functionalWrite(pkt);
-   }
-
-   return num_functional_writes;
-}
-
-void
-CrossbarSwitch::resetStats()
-{
-    m_crossbar_activity = 0;
-}
diff --git a/src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh b/src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh
deleted file mode 100644 (file)
index 7dee784..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_CROSSBARSWITCH_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_CROSSBARSWITCH_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-class Router;
-
-class CrossbarSwitch : public Consumer
-{
-  public:
-    CrossbarSwitch(Router *router);
-    ~CrossbarSwitch() = default;
-    void wakeup();
-    void init();
-    void print(std::ostream& out) const {};
-
-    inline void
-    update_sw_winner(int inport, flit *t_flit)
-    {
-        switchBuffers[inport].insert(t_flit);
-    }
-
-    inline double get_crossbar_activity() { return m_crossbar_activity; }
-
-    uint32_t functionalWrite(Packet *pkt);
-    void resetStats();
-
-  private:
-    Router *m_router;
-    int m_num_vcs;
-    double m_crossbar_activity;
-    std::vector<flitBuffer> switchBuffers;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_CROSSBARSWITCH_HH__
diff --git a/src/mem/ruby/network/garnet2.0/GarnetLink.cc b/src/mem/ruby/network/garnet2.0/GarnetLink.cc
deleted file mode 100644 (file)
index 99d891f..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-
-GarnetIntLink::GarnetIntLink(const Params *p)
-    : BasicIntLink(p)
-{
-    // Uni-directional
-
-    m_network_link = p->network_link;
-    m_credit_link = p->credit_link;
-
-    srcCdcEn = p->src_cdc;
-    dstCdcEn = p->dst_cdc;
-
-    srcSerdesEn = p->src_serdes;
-    dstSerdesEn = p->dst_serdes;
-
-    srcBridgeEn = false;
-    dstBridgeEn = false;
-
-    if (srcCdcEn || srcSerdesEn) {
-        srcBridgeEn = true;
-        srcNetBridge = p->src_net_bridge;
-        srcCredBridge = p->src_cred_bridge;
-    }
-    if (dstCdcEn || dstSerdesEn) {
-        dstBridgeEn = true;
-        dstNetBridge = p->dst_net_bridge;
-        dstCredBridge = p->dst_cred_bridge;
-    }
-
-}
-
-void
-GarnetIntLink::init()
-{
-    if (srcBridgeEn) {
-        assert(srcNetBridge && srcCredBridge);
-        srcNetBridge->initBridge(srcCredBridge, srcCdcEn, srcSerdesEn);
-        srcCredBridge->initBridge(srcNetBridge, srcCdcEn, srcSerdesEn);
-    }
-
-    if (dstBridgeEn) {
-        assert(dstNetBridge && dstCredBridge);
-        dstNetBridge->initBridge(dstCredBridge, dstCdcEn, dstSerdesEn);
-        dstCredBridge->initBridge(dstNetBridge, dstCdcEn, dstSerdesEn);
-    }
-}
-
-void
-GarnetIntLink::print(std::ostream& out) const
-{
-    out << name();
-}
-
-GarnetIntLink *
-GarnetIntLinkParams::create()
-{
-    return new GarnetIntLink(this);
-}
-
-GarnetExtLink::GarnetExtLink(const Params *p)
-    : BasicExtLink(p)
-{
-    // Bi-directional
-
-    // In
-    m_network_links[0] = p->network_links[0];
-    m_credit_links[0] = p->credit_links[0];
-
-    // Out
-    m_network_links[1] = p->network_links[1];
-    m_credit_links[1] = p->credit_links[1];
-
-
-    extCdcEn = p->ext_cdc;
-    intCdcEn = p->int_cdc;
-
-    extSerdesEn = p->ext_serdes;
-    intSerdesEn = p->int_serdes;
-
-    extBridgeEn = false;
-    intBridgeEn = false;
-
-    if (extCdcEn || extSerdesEn) {
-        extBridgeEn = true;
-        extNetBridge[0] = p->ext_net_bridge[0];
-        extCredBridge[0] = p->ext_cred_bridge[0];
-        extNetBridge[1] = p->ext_net_bridge[1];
-        extCredBridge[1] = p->ext_cred_bridge[1];
-    }
-
-    if (intCdcEn || intSerdesEn) {
-        intBridgeEn = true;
-        intNetBridge[0] = p->int_net_bridge[0];
-        intNetBridge[1] = p->int_net_bridge[1];
-        intCredBridge[0] = p->int_cred_bridge[0];
-        intCredBridge[1] = p->int_cred_bridge[1];
-    }
-
-}
-
-void
-GarnetExtLink::init()
-{
-    if (extBridgeEn) {
-        assert(extNetBridge[0] && extCredBridge[0] &&
-           extNetBridge[1] && extCredBridge[1]);
-        extNetBridge[0]->initBridge(extCredBridge[0], extCdcEn, extSerdesEn);
-        extCredBridge[0]->initBridge(extNetBridge[0], extCdcEn, extSerdesEn);
-        extNetBridge[1]->initBridge(extCredBridge[1], extCdcEn, extSerdesEn);
-        extCredBridge[1]->initBridge(extNetBridge[1], extCdcEn, extSerdesEn);
-    }
-
-    if (intBridgeEn) {
-        assert(intNetBridge[0] && intCredBridge[0] &&
-           intNetBridge[1] && intCredBridge[1]);
-        intNetBridge[0]->initBridge(intCredBridge[0], intCdcEn, intSerdesEn);
-        intCredBridge[0]->initBridge(intNetBridge[0], intCdcEn, intSerdesEn);
-        intNetBridge[1]->initBridge(intCredBridge[1], intCdcEn, intSerdesEn);
-        intCredBridge[1]->initBridge(intNetBridge[1], intCdcEn, intSerdesEn);
-    }
-}
-
-void
-GarnetExtLink::print(std::ostream& out) const
-{
-    out << name();
-}
-
-GarnetExtLink *
-GarnetExtLinkParams::create()
-{
-    return new GarnetExtLink(this);
-}
diff --git a/src/mem/ruby/network/garnet2.0/GarnetLink.hh b/src/mem/ruby/network/garnet2.0/GarnetLink.hh
deleted file mode 100644 (file)
index 089bcce..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_GARNETLINK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_GARNETLINK_HH__
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "mem/ruby/network/BasicLink.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "params/GarnetExtLink.hh"
-#include "params/GarnetIntLink.hh"
-
-class GarnetIntLink : public BasicIntLink
-{
-  public:
-    typedef GarnetIntLinkParams Params;
-    GarnetIntLink(const Params *p);
-
-    void init();
-
-    void print(std::ostream& out) const;
-
-    friend class GarnetNetwork;
-
-  protected:
-    NetworkLink* m_network_link;
-    CreditLink* m_credit_link;
-
-    bool srcBridgeEn;
-    bool dstBridgeEn;
-
-    bool srcSerdesEn;
-    bool dstSerdesEn;
-
-    bool srcCdcEn;
-    bool dstCdcEn;
-
-    NetworkBridge* srcNetBridge;
-    NetworkBridge* dstNetBridge;
-
-    NetworkBridge* srcCredBridge;
-    NetworkBridge* dstCredBridge;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const GarnetIntLink& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-class GarnetExtLink : public BasicExtLink
-{
-  public:
-    typedef GarnetExtLinkParams Params;
-    GarnetExtLink(const Params *p);
-
-    void init();
-
-    void print(std::ostream& out) const;
-
-    friend class GarnetNetwork;
-
-  protected:
-    bool extBridgeEn;
-    bool intBridgeEn;
-
-    bool extSerdesEn;
-    bool intSerdesEn;
-
-    bool extCdcEn;
-    bool intCdcEn;
-
-    NetworkLink* m_network_links[2];
-    CreditLink* m_credit_links[2];
-
-    NetworkBridge* extNetBridge[2];
-    NetworkBridge* intNetBridge[2];
-
-    NetworkBridge* extCredBridge[2];
-    NetworkBridge* intCredBridge[2];
-
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const GarnetExtLink& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_GARNETLINK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/GarnetLink.py b/src/mem/ruby/network/garnet2.0/GarnetLink.py
deleted file mode 100644 (file)
index 9f7fe8b..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-# Copyright (c) 2008 Princeton University
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from m5.params import *
-from m5.proxy import *
-from m5.objects.ClockedObject import ClockedObject
-from m5.objects.BasicLink import BasicIntLink, BasicExtLink
-
-class CDCType(Enum): vals = [
-    'LINK_OBJECT',
-    'OBJECT_LINK',
-    ]
-
-class NetworkLink(ClockedObject):
-    type = 'NetworkLink'
-    cxx_header = "mem/ruby/network/garnet2.0/NetworkLink.hh"
-    link_id = Param.Int(Parent.link_id, "link id")
-    link_latency = Param.Cycles(Parent.latency, "link latency")
-    vcs_per_vnet = Param.Int(Parent.vcs_per_vnet,
-                              "virtual channels per virtual network")
-    virt_nets = Param.Int(Parent.number_of_virtual_networks,
-                          "number of virtual networks")
-    supported_vnets = VectorParam.Int(Parent.supported_vnets,
-                                      "Vnets supported")
-    width = Param.UInt32(Parent.width, "bit-width of the link")
-
-class CreditLink(NetworkLink):
-    type = 'CreditLink'
-    cxx_header = "mem/ruby/network/garnet2.0/CreditLink.hh"
-
-class NetworkBridge(CreditLink):
-    type = 'NetworkBridge'
-    cxx_header = "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-    link = Param.NetworkLink("Associated Network Link")
-    vtype = Param.CDCType('LINK_OBJECT',
-              "Direction of CDC LINK->OBJECT or OBJECT->LINK")
-    serdes_latency = Param.Cycles(1, "Latency of SerDes Unit")
-    cdc_latency = Param.Cycles(1, "Latency of CDC Unit")
-
-# Interior fixed pipeline links between routers
-class GarnetIntLink(BasicIntLink):
-    type = 'GarnetIntLink'
-    cxx_header = "mem/ruby/network/garnet2.0/GarnetLink.hh"
-    # The internal link includes one forward link (for flit)
-    # and one backward flow-control link (for credit)
-    network_link = Param.NetworkLink(NetworkLink(), "forward link")
-    credit_link  = Param.CreditLink(CreditLink(), "backward flow-control link")
-
-    # The src_cdc and dst_cdc flags are used to enable the
-    # clock domain crossing(CDC) at the source and destination
-    # end of the link respectively. This is required when the
-    # link and the objected connected to the link are operating
-    # at different clock domains. These flags should be set
-    # in the network topology files.
-    src_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
-    dst_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
-
-    # The src_serdes and dst_serdes flags are used to enable
-    # the Serializer-Deserializer units at the source and
-    # destination end of the link respectively. Enabling
-    # these flags is necessary when the connecting object
-    # supports a different flit width.
-    src_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
-    dst_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
-
-    # The network bridge encapsulates both the CDC and Ser-Des
-    # units in HeteroGarnet. This is automatically enabled when
-    # either CDC or Ser-Des is enabled.
-    src_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at source")
-    dst_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at dest")
-    src_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at source")
-    dst_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at dest")
-
-    width = Param.UInt32(Parent.ni_flit_size,
-                          "bit width supported by the router")
-
-# Exterior fixed pipeline links between a router and a controller
-class GarnetExtLink(BasicExtLink):
-    type = 'GarnetExtLink'
-    cxx_header = "mem/ruby/network/garnet2.0/GarnetLink.hh"
-    # The external link is bi-directional.
-    # It includes two forward links (for flits)
-    # and two backward flow-control links (for credits),
-    # one per direction
-    _nls = []
-    # In uni-directional link
-    _nls.append(NetworkLink());
-    # Out uni-directional link
-    _nls.append(NetworkLink());
-    network_links = VectorParam.NetworkLink(_nls, "forward links")
-
-    _cls = []
-    # In uni-directional link
-    _cls.append(CreditLink());
-    # Out uni-directional link
-    _cls.append(CreditLink());
-    credit_links = VectorParam.CreditLink(_cls, "backward flow-control links")
-
-    # The ext_cdc and intt_cdc flags are used to enable the
-    # clock domain crossing(CDC) at the external and internal
-    # end of the link respectively. This is required when the
-    # link and the objected connected to the link are operating
-    # at different clock domains. These flags should be set
-    # in the network topology files.
-    ext_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
-    int_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
-
-    # The ext_serdes and int_serdes flags are used to enable
-    # the Serializer-Deserializer units at the external and
-    # internal end of the link respectively. Enabling
-    # these flags is necessary when the connecting object
-    # supports a different flit width.
-    ext_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
-    int_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
-
-    # The network bridge encapsulates both the CDC and Ser-Des
-    # units in HeteroGarnet. This is automatically enabled when
-    # either CDC or Ser-Des is enabled.
-    ext_net_bridge = VectorParam.NetworkBridge([],
-        "Network Bridge at external end")
-    ext_cred_bridge = VectorParam.NetworkBridge([],
-        "Credit Bridge at external end")
-    int_net_bridge = VectorParam.NetworkBridge([],
-        "Network Bridge at internal end")
-    int_cred_bridge = VectorParam.NetworkBridge([],
-        "Credit Bridge at internal end")
-
-
-    width = Param.UInt32(Parent.ni_flit_size,
-                          "bit width supported by the router")
diff --git a/src/mem/ruby/network/garnet2.0/GarnetNetwork.cc b/src/mem/ruby/network/garnet2.0/GarnetNetwork.cc
deleted file mode 100644 (file)
index bcc476f..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-
-#include <cassert>
-
-#include "base/cast.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/ruby/network/MessageBuffer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/system/RubySystem.hh"
-
-using namespace std;
-
-/*
- * GarnetNetwork sets up the routers and links and collects stats.
- * Default parameters (GarnetNetwork.py) can be overwritten from command line
- * (see configs/network/Network.py)
- */
-
-GarnetNetwork::GarnetNetwork(const Params *p)
-    : Network(p)
-{
-    m_num_rows = p->num_rows;
-    m_ni_flit_size = p->ni_flit_size;
-    m_max_vcs_per_vnet = 0;
-    m_buffers_per_data_vc = p->buffers_per_data_vc;
-    m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
-    m_routing_algorithm = p->routing_algorithm;
-
-    m_enable_fault_model = p->enable_fault_model;
-    if (m_enable_fault_model)
-        fault_model = p->fault_model;
-
-    m_vnet_type.resize(m_virtual_networks);
-
-    for (int i = 0 ; i < m_virtual_networks ; i++) {
-        if (m_vnet_type_names[i] == "response")
-            m_vnet_type[i] = DATA_VNET_; // carries data (and ctrl) packets
-        else
-            m_vnet_type[i] = CTRL_VNET_; // carries only ctrl packets
-    }
-
-    // record the routers
-    for (vector<BasicRouter*>::const_iterator i =  p->routers.begin();
-         i != p->routers.end(); ++i) {
-        Router* router = safe_cast<Router*>(*i);
-        m_routers.push_back(router);
-
-        // initialize the router's network pointers
-        router->init_net_ptr(this);
-    }
-
-    // record the network interfaces
-    for (vector<ClockedObject*>::const_iterator i = p->netifs.begin();
-         i != p->netifs.end(); ++i) {
-        NetworkInterface *ni = safe_cast<NetworkInterface *>(*i);
-        m_nis.push_back(ni);
-        ni->init_net_ptr(this);
-    }
-}
-
-void
-GarnetNetwork::init()
-{
-    Network::init();
-
-    for (int i=0; i < m_nodes; i++) {
-        m_nis[i]->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
-    }
-
-    // The topology pointer should have already been initialized in the
-    // parent network constructor
-    assert(m_topology_ptr != NULL);
-    m_topology_ptr->createLinks(this);
-
-    // Initialize topology specific parameters
-    if (getNumRows() > 0) {
-        // Only for Mesh topology
-        // m_num_rows and m_num_cols are only used for
-        // implementing XY or custom routing in RoutingUnit.cc
-        m_num_rows = getNumRows();
-        m_num_cols = m_routers.size() / m_num_rows;
-        assert(m_num_rows * m_num_cols == m_routers.size());
-    } else {
-        m_num_rows = -1;
-        m_num_cols = -1;
-    }
-
-    // FaultModel: declare each router to the fault model
-    if (isFaultModelEnabled()) {
-        for (vector<Router*>::const_iterator i= m_routers.begin();
-             i != m_routers.end(); ++i) {
-            Router* router = safe_cast<Router*>(*i);
-            int router_id M5_VAR_USED =
-                fault_model->declare_router(router->get_num_inports(),
-                                            router->get_num_outports(),
-                                            router->get_vc_per_vnet(),
-                                            getBuffersPerDataVC(),
-                                            getBuffersPerCtrlVC());
-            assert(router_id == router->get_id());
-            router->printAggregateFaultProbability(cout);
-            router->printFaultVector(cout);
-        }
-    }
-}
-
-/*
- * This function creates a link from the Network Interface (NI)
- * into the Network.
- * It creates a Network Link from the NI to a Router and a Credit Link from
- * the Router to the NI
-*/
-
-void
-GarnetNetwork::makeExtInLink(NodeID global_src, SwitchID dest, BasicLink* link,
-                             std::vector<NetDest>& routing_table_entry)
-{
-    NodeID local_src = getLocalNodeID(global_src);
-    assert(local_src < m_nodes);
-
-    GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
-
-    // GarnetExtLink is bi-directional
-    NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_In];
-    net_link->setType(EXT_IN_);
-    CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_In];
-
-    m_networklinks.push_back(net_link);
-    m_creditlinks.push_back(credit_link);
-
-    PortDirection dst_inport_dirn = "Local";
-
-    m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
-                             m_routers[dest]->get_vc_per_vnet());
-
-    /*
-     * We check if a bridge was enabled at any end of the link.
-     * The bridge is enabled if either of clock domain
-     * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
-     * enabled for the link at each end. The bridge encapsulates
-     * the functionality for both CDC and SerDes and is a Consumer
-     * object similiar to a NetworkLink.
-     *
-     * If a bridge was enabled we connect the NI and Routers to
-     * bridge before connecting the link. Example, if an external
-     * bridge is enabled, we would connect:
-     * NI--->NetworkBridge--->GarnetExtLink---->Router
-     */
-    if (garnet_link->extBridgeEn) {
-        DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
-            garnet_link->name());
-        m_nis[local_src]->
-        addOutPort(garnet_link->extNetBridge[LinkDirection_In],
-                   garnet_link->extCredBridge[LinkDirection_In],
-                   dest, m_routers[dest]->get_vc_per_vnet());
-    } else {
-        m_nis[local_src]->addOutPort(net_link, credit_link, dest,
-            m_routers[dest]->get_vc_per_vnet());
-    }
-
-    if (garnet_link->intBridgeEn) {
-        DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
-            garnet_link->name());
-        m_routers[dest]->
-            addInPort(dst_inport_dirn,
-                      garnet_link->intNetBridge[LinkDirection_In],
-                      garnet_link->intCredBridge[LinkDirection_In]);
-    } else {
-        m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
-    }
-
-}
-
-/*
- * This function creates a link from the Network to a NI.
- * It creates a Network Link from a Router to the NI and
- * a Credit Link from NI to the Router
-*/
-
-void
-GarnetNetwork::makeExtOutLink(SwitchID src, NodeID global_dest,
-                              BasicLink* link,
-                              std::vector<NetDest>& routing_table_entry)
-{
-    NodeID local_dest = getLocalNodeID(global_dest);
-    assert(local_dest < m_nodes);
-    assert(src < m_routers.size());
-    assert(m_routers[src] != NULL);
-
-    GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
-
-    // GarnetExtLink is bi-directional
-    NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_Out];
-    net_link->setType(EXT_OUT_);
-    CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_Out];
-
-    m_networklinks.push_back(net_link);
-    m_creditlinks.push_back(credit_link);
-
-    PortDirection src_outport_dirn = "Local";
-
-    m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
-                             m_routers[src]->get_vc_per_vnet());
-
-    /*
-     * We check if a bridge was enabled at any end of the link.
-     * The bridge is enabled if either of clock domain
-     * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
-     * enabled for the link at each end. The bridge encapsulates
-     * the functionality for both CDC and SerDes and is a Consumer
-     * object similiar to a NetworkLink.
-     *
-     * If a bridge was enabled we connect the NI and Routers to
-     * bridge before connecting the link. Example, if an external
-     * bridge is enabled, we would connect:
-     * NI<---NetworkBridge<---GarnetExtLink<----Router
-     */
-    if (garnet_link->extBridgeEn) {
-        DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
-            garnet_link->name());
-        m_nis[local_dest]->
-            addInPort(garnet_link->extNetBridge[LinkDirection_Out],
-                      garnet_link->extCredBridge[LinkDirection_Out]);
-    } else {
-        m_nis[local_dest]->addInPort(net_link, credit_link);
-    }
-
-    if (garnet_link->intBridgeEn) {
-        DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
-            garnet_link->name());
-        m_routers[src]->
-            addOutPort(src_outport_dirn,
-                       garnet_link->intNetBridge[LinkDirection_Out],
-                       routing_table_entry, link->m_weight,
-                       garnet_link->intCredBridge[LinkDirection_Out],
-                       m_routers[src]->get_vc_per_vnet());
-    } else {
-        m_routers[src]->
-            addOutPort(src_outport_dirn, net_link,
-                       routing_table_entry,
-                       link->m_weight, credit_link,
-                       m_routers[src]->get_vc_per_vnet());
-    }
-}
-
-/*
- * This function creates an internal network link between two routers.
- * It adds both the network link and an opposite credit link.
-*/
-
-void
-GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
-                                std::vector<NetDest>& routing_table_entry,
-                                PortDirection src_outport_dirn,
-                                PortDirection dst_inport_dirn)
-{
-    GarnetIntLink* garnet_link = safe_cast<GarnetIntLink*>(link);
-
-    // GarnetIntLink is unidirectional
-    NetworkLink* net_link = garnet_link->m_network_link;
-    net_link->setType(INT_);
-    CreditLink* credit_link = garnet_link->m_credit_link;
-
-    m_networklinks.push_back(net_link);
-    m_creditlinks.push_back(credit_link);
-
-    m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
-                             std::max(m_routers[dest]->get_vc_per_vnet(),
-                             m_routers[src]->get_vc_per_vnet()));
-
-    /*
-     * We check if a bridge was enabled at any end of the link.
-     * The bridge is enabled if either of clock domain
-     * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
-     * enabled for the link at each end. The bridge encapsulates
-     * the functionality for both CDC and SerDes and is a Consumer
-     * object similiar to a NetworkLink.
-     *
-     * If a bridge was enabled we connect the NI and Routers to
-     * bridge before connecting the link. Example, if a source
-     * bridge is enabled, we would connect:
-     * Router--->NetworkBridge--->GarnetIntLink---->Router
-     */
-    if (garnet_link->dstBridgeEn) {
-        DPRINTF(RubyNetwork, "Enable destination bridge for %s\n",
-            garnet_link->name());
-        m_routers[dest]->addInPort(dst_inport_dirn,
-            garnet_link->dstNetBridge, garnet_link->dstCredBridge);
-    } else {
-        m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
-    }
-
-    if (garnet_link->srcBridgeEn) {
-        DPRINTF(RubyNetwork, "Enable source bridge for %s\n",
-            garnet_link->name());
-        m_routers[src]->
-            addOutPort(src_outport_dirn, garnet_link->srcNetBridge,
-                       routing_table_entry,
-                       link->m_weight, garnet_link->srcCredBridge,
-                       m_routers[dest]->get_vc_per_vnet());
-    } else {
-        m_routers[src]->addOutPort(src_outport_dirn, net_link,
-                        routing_table_entry,
-                        link->m_weight, credit_link,
-                        m_routers[dest]->get_vc_per_vnet());
-    }
-}
-
-// Total routers in the network
-int
-GarnetNetwork::getNumRouters()
-{
-    return m_routers.size();
-}
-
-// Get ID of router connected to a NI.
-int
-GarnetNetwork::get_router_id(int global_ni, int vnet)
-{
-    NodeID local_ni = getLocalNodeID(global_ni);
-
-    return m_nis[local_ni]->get_router_id(vnet);
-}
-
-void
-GarnetNetwork::regStats()
-{
-    Network::regStats();
-
-    // Packets
-    m_packets_received
-        .init(m_virtual_networks)
-        .name(name() + ".packets_received")
-        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
-        ;
-
-    m_packets_injected
-        .init(m_virtual_networks)
-        .name(name() + ".packets_injected")
-        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
-        ;
-
-    m_packet_network_latency
-        .init(m_virtual_networks)
-        .name(name() + ".packet_network_latency")
-        .flags(Stats::oneline)
-        ;
-
-    m_packet_queueing_latency
-        .init(m_virtual_networks)
-        .name(name() + ".packet_queueing_latency")
-        .flags(Stats::oneline)
-        ;
-
-    for (int i = 0; i < m_virtual_networks; i++) {
-        m_packets_received.subname(i, csprintf("vnet-%i", i));
-        m_packets_injected.subname(i, csprintf("vnet-%i", i));
-        m_packet_network_latency.subname(i, csprintf("vnet-%i", i));
-        m_packet_queueing_latency.subname(i, csprintf("vnet-%i", i));
-    }
-
-    m_avg_packet_vnet_latency
-        .name(name() + ".average_packet_vnet_latency")
-        .flags(Stats::oneline);
-    m_avg_packet_vnet_latency =
-        m_packet_network_latency / m_packets_received;
-
-    m_avg_packet_vqueue_latency
-        .name(name() + ".average_packet_vqueue_latency")
-        .flags(Stats::oneline);
-    m_avg_packet_vqueue_latency =
-        m_packet_queueing_latency / m_packets_received;
-
-    m_avg_packet_network_latency
-        .name(name() + ".average_packet_network_latency");
-    m_avg_packet_network_latency =
-        sum(m_packet_network_latency) / sum(m_packets_received);
-
-    m_avg_packet_queueing_latency
-        .name(name() + ".average_packet_queueing_latency");
-    m_avg_packet_queueing_latency
-        = sum(m_packet_queueing_latency) / sum(m_packets_received);
-
-    m_avg_packet_latency
-        .name(name() + ".average_packet_latency");
-    m_avg_packet_latency
-        = m_avg_packet_network_latency + m_avg_packet_queueing_latency;
-
-    // Flits
-    m_flits_received
-        .init(m_virtual_networks)
-        .name(name() + ".flits_received")
-        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
-        ;
-
-    m_flits_injected
-        .init(m_virtual_networks)
-        .name(name() + ".flits_injected")
-        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
-        ;
-
-    m_flit_network_latency
-        .init(m_virtual_networks)
-        .name(name() + ".flit_network_latency")
-        .flags(Stats::oneline)
-        ;
-
-    m_flit_queueing_latency
-        .init(m_virtual_networks)
-        .name(name() + ".flit_queueing_latency")
-        .flags(Stats::oneline)
-        ;
-
-    for (int i = 0; i < m_virtual_networks; i++) {
-        m_flits_received.subname(i, csprintf("vnet-%i", i));
-        m_flits_injected.subname(i, csprintf("vnet-%i", i));
-        m_flit_network_latency.subname(i, csprintf("vnet-%i", i));
-        m_flit_queueing_latency.subname(i, csprintf("vnet-%i", i));
-    }
-
-    m_avg_flit_vnet_latency
-        .name(name() + ".average_flit_vnet_latency")
-        .flags(Stats::oneline);
-    m_avg_flit_vnet_latency = m_flit_network_latency / m_flits_received;
-
-    m_avg_flit_vqueue_latency
-        .name(name() + ".average_flit_vqueue_latency")
-        .flags(Stats::oneline);
-    m_avg_flit_vqueue_latency =
-        m_flit_queueing_latency / m_flits_received;
-
-    m_avg_flit_network_latency
-        .name(name() + ".average_flit_network_latency");
-    m_avg_flit_network_latency =
-        sum(m_flit_network_latency) / sum(m_flits_received);
-
-    m_avg_flit_queueing_latency
-        .name(name() + ".average_flit_queueing_latency");
-    m_avg_flit_queueing_latency =
-        sum(m_flit_queueing_latency) / sum(m_flits_received);
-
-    m_avg_flit_latency
-        .name(name() + ".average_flit_latency");
-    m_avg_flit_latency =
-        m_avg_flit_network_latency + m_avg_flit_queueing_latency;
-
-
-    // Hops
-    m_avg_hops.name(name() + ".average_hops");
-    m_avg_hops = m_total_hops / sum(m_flits_received);
-
-    // Links
-    m_total_ext_in_link_utilization
-        .name(name() + ".ext_in_link_utilization");
-    m_total_ext_out_link_utilization
-        .name(name() + ".ext_out_link_utilization");
-    m_total_int_link_utilization
-        .name(name() + ".int_link_utilization");
-    m_average_link_utilization
-        .name(name() + ".avg_link_utilization");
-    m_average_vc_load
-        .init(m_virtual_networks * m_max_vcs_per_vnet)
-        .name(name() + ".avg_vc_load")
-        .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
-        ;
-}
-
-void
-GarnetNetwork::collateStats()
-{
-    RubySystem *rs = params()->ruby_system;
-    double time_delta = double(curCycle() - rs->getStartCycle());
-
-    for (int i = 0; i < m_networklinks.size(); i++) {
-        link_type type = m_networklinks[i]->getType();
-        int activity = m_networklinks[i]->getLinkUtilization();
-
-        if (type == EXT_IN_)
-            m_total_ext_in_link_utilization += activity;
-        else if (type == EXT_OUT_)
-            m_total_ext_out_link_utilization += activity;
-        else if (type == INT_)
-            m_total_int_link_utilization += activity;
-
-        m_average_link_utilization +=
-            (double(activity) / time_delta);
-
-        vector<unsigned int> vc_load = m_networklinks[i]->getVcLoad();
-        for (int j = 0; j < vc_load.size(); j++) {
-            m_average_vc_load[j] += ((double)vc_load[j] / time_delta);
-        }
-    }
-
-    // Ask the routers to collate their statistics
-    for (int i = 0; i < m_routers.size(); i++) {
-        m_routers[i]->collateStats();
-    }
-}
-
-void
-GarnetNetwork::resetStats()
-{
-    for (int i = 0; i < m_routers.size(); i++) {
-        m_routers[i]->resetStats();
-    }
-    for (int i = 0; i < m_networklinks.size(); i++) {
-        m_networklinks[i]->resetStats();
-    }
-    for (int i = 0; i < m_creditlinks.size(); i++) {
-        m_creditlinks[i]->resetStats();
-    }
-}
-
-void
-GarnetNetwork::print(ostream& out) const
-{
-    out << "[GarnetNetwork]";
-}
-
-GarnetNetwork *
-GarnetNetworkParams::create()
-{
-    return new GarnetNetwork(this);
-}
-
-uint32_t
-GarnetNetwork::functionalWrite(Packet *pkt)
-{
-    uint32_t num_functional_writes = 0;
-
-    for (unsigned int i = 0; i < m_routers.size(); i++) {
-        num_functional_writes += m_routers[i]->functionalWrite(pkt);
-    }
-
-    for (unsigned int i = 0; i < m_nis.size(); ++i) {
-        num_functional_writes += m_nis[i]->functionalWrite(pkt);
-    }
-
-    for (unsigned int i = 0; i < m_networklinks.size(); ++i) {
-        num_functional_writes += m_networklinks[i]->functionalWrite(pkt);
-    }
-
-    return num_functional_writes;
-}
diff --git a/src/mem/ruby/network/garnet2.0/GarnetNetwork.hh b/src/mem/ruby/network/garnet2.0/GarnetNetwork.hh
deleted file mode 100644 (file)
index bb4b24a..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_GARNETNETWORK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_GARNETNETWORK_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/network/Network.hh"
-#include "mem/ruby/network/fault_model/FaultModel.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "params/GarnetNetwork.hh"
-
-class FaultModel;
-class NetworkInterface;
-class Router;
-class NetDest;
-class NetworkLink;
-class CreditLink;
-
-class GarnetNetwork : public Network
-{
-  public:
-    typedef GarnetNetworkParams Params;
-    GarnetNetwork(const Params *p);
-    ~GarnetNetwork() = default;
-
-    void init();
-
-    // Configuration (set externally)
-
-    // for 2D topology
-    int getNumRows() const { return m_num_rows; }
-    int getNumCols() { return m_num_cols; }
-
-    // for network
-    uint32_t getNiFlitSize() const { return m_ni_flit_size; }
-    uint32_t getBuffersPerDataVC() { return m_buffers_per_data_vc; }
-    uint32_t getBuffersPerCtrlVC() { return m_buffers_per_ctrl_vc; }
-    int getRoutingAlgorithm() const { return m_routing_algorithm; }
-
-    bool isFaultModelEnabled() const { return m_enable_fault_model; }
-    FaultModel* fault_model;
-
-
-    // Internal configuration
-    bool isVNetOrdered(int vnet) const { return m_ordered[vnet]; }
-    VNET_type
-    get_vnet_type(int vnet)
-    {
-        return m_vnet_type[vnet];
-    }
-    int getNumRouters();
-    int get_router_id(int ni, int vnet);
-
-
-    // Methods used by Topology to setup the network
-    void makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
-                     std::vector<NetDest>& routing_table_entry);
-    void makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
-                    std::vector<NetDest>& routing_table_entry);
-    void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
-                          std::vector<NetDest>& routing_table_entry,
-                          PortDirection src_outport_dirn,
-                          PortDirection dest_inport_dirn);
-
-    //! Function for performing a functional write. The return value
-    //! indicates the number of messages that were written.
-    uint32_t functionalWrite(Packet *pkt);
-
-    // Stats
-    void collateStats();
-    void regStats();
-    void resetStats();
-    void print(std::ostream& out) const;
-
-    // increment counters
-    void increment_injected_packets(int vnet) { m_packets_injected[vnet]++; }
-    void increment_received_packets(int vnet) { m_packets_received[vnet]++; }
-
-    void
-    increment_packet_network_latency(Tick latency, int vnet)
-    {
-        m_packet_network_latency[vnet] += latency;
-    }
-
-    void
-    increment_packet_queueing_latency(Tick latency, int vnet)
-    {
-        m_packet_queueing_latency[vnet] += latency;
-    }
-
-    void increment_injected_flits(int vnet) { m_flits_injected[vnet]++; }
-    void increment_received_flits(int vnet) { m_flits_received[vnet]++; }
-
-    void
-    increment_flit_network_latency(Tick latency, int vnet)
-    {
-        m_flit_network_latency[vnet] += latency;
-    }
-
-    void
-    increment_flit_queueing_latency(Tick latency, int vnet)
-    {
-        m_flit_queueing_latency[vnet] += latency;
-    }
-
-    void
-    increment_total_hops(int hops)
-    {
-        m_total_hops += hops;
-    }
-
-  protected:
-    // Configuration
-    int m_num_rows;
-    int m_num_cols;
-    uint32_t m_ni_flit_size;
-    uint32_t m_max_vcs_per_vnet;
-    uint32_t m_buffers_per_ctrl_vc;
-    uint32_t m_buffers_per_data_vc;
-    int m_routing_algorithm;
-    bool m_enable_fault_model;
-
-    // Statistical variables
-    Stats::Vector m_packets_received;
-    Stats::Vector m_packets_injected;
-    Stats::Vector m_packet_network_latency;
-    Stats::Vector m_packet_queueing_latency;
-
-    Stats::Formula m_avg_packet_vnet_latency;
-    Stats::Formula m_avg_packet_vqueue_latency;
-    Stats::Formula m_avg_packet_network_latency;
-    Stats::Formula m_avg_packet_queueing_latency;
-    Stats::Formula m_avg_packet_latency;
-
-    Stats::Vector m_flits_received;
-    Stats::Vector m_flits_injected;
-    Stats::Vector m_flit_network_latency;
-    Stats::Vector m_flit_queueing_latency;
-
-    Stats::Formula m_avg_flit_vnet_latency;
-    Stats::Formula m_avg_flit_vqueue_latency;
-    Stats::Formula m_avg_flit_network_latency;
-    Stats::Formula m_avg_flit_queueing_latency;
-    Stats::Formula m_avg_flit_latency;
-
-    Stats::Scalar m_total_ext_in_link_utilization;
-    Stats::Scalar m_total_ext_out_link_utilization;
-    Stats::Scalar m_total_int_link_utilization;
-    Stats::Scalar m_average_link_utilization;
-    Stats::Vector m_average_vc_load;
-
-    Stats::Scalar  m_total_hops;
-    Stats::Formula m_avg_hops;
-
-  private:
-    GarnetNetwork(const GarnetNetwork& obj);
-    GarnetNetwork& operator=(const GarnetNetwork& obj);
-
-    std::vector<VNET_type > m_vnet_type;
-    std::vector<Router *> m_routers;   // All Routers in Network
-    std::vector<NetworkLink *> m_networklinks; // All flit links in the network
-    std::vector<CreditLink *> m_creditlinks; // All credit links in the network
-    std::vector<NetworkInterface *> m_nis;   // All NI's in Network
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const GarnetNetwork& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_GARNETNETWORK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/GarnetNetwork.py b/src/mem/ruby/network/garnet2.0/GarnetNetwork.py
deleted file mode 100644 (file)
index 012ab60..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (c) 2008 Princeton University
-# 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.
-#
-# Author: Tushar Krishna
-#
-
-from m5.params import *
-from m5.proxy import *
-from m5.objects.Network import RubyNetwork
-from m5.objects.BasicRouter import BasicRouter
-from m5.objects.ClockedObject import ClockedObject
-
-class GarnetNetwork(RubyNetwork):
-    type = 'GarnetNetwork'
-    cxx_header = "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-    num_rows = Param.Int(0, "number of rows if 2D (mesh/torus/..) topology");
-    ni_flit_size = Param.UInt32(16, "network interface flit size in bytes")
-    vcs_per_vnet = Param.UInt32(4, "virtual channels per virtual network");
-    buffers_per_data_vc = Param.UInt32(4, "buffers per data virtual channel");
-    buffers_per_ctrl_vc = Param.UInt32(1, "buffers per ctrl virtual channel");
-    routing_algorithm = Param.Int(0,
-        "0: Weight-based Table, 1: XY, 2: Custom");
-    enable_fault_model = Param.Bool(False, "enable network fault model");
-    fault_model = Param.FaultModel(NULL, "network fault model");
-    garnet_deadlock_threshold = Param.UInt32(50000,
-                              "network-level deadlock threshold")
-
-class GarnetNetworkInterface(ClockedObject):
-    type = 'GarnetNetworkInterface'
-    cxx_class = 'NetworkInterface'
-    cxx_header = "mem/ruby/network/garnet2.0/NetworkInterface.hh"
-
-    id = Param.UInt32("ID in relation to other network interfaces")
-    vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
-                             "virtual channels per virtual network")
-    virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
-                          "number of virtual networks")
-    garnet_deadlock_threshold = Param.UInt32(Parent.garnet_deadlock_threshold,
-                                      "network-level deadlock threshold")
-
-class GarnetRouter(BasicRouter):
-    type = 'GarnetRouter'
-    cxx_class = 'Router'
-    cxx_header = "mem/ruby/network/garnet2.0/Router.hh"
-    vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
-                              "virtual channels per virtual network")
-    virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
-                          "number of virtual networks")
-    width = Param.UInt32(Parent.ni_flit_size,
-                          "bit width supported by the router")
diff --git a/src/mem/ruby/network/garnet2.0/InputUnit.cc b/src/mem/ruby/network/garnet2.0/InputUnit.cc
deleted file mode 100644 (file)
index db24aef..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-using namespace std;
-
-InputUnit::InputUnit(int id, PortDirection direction, Router *router)
-  : Consumer(router), m_router(router), m_id(id), m_direction(direction),
-    m_vc_per_vnet(m_router->get_vc_per_vnet())
-{
-    const int m_num_vcs = m_router->get_num_vcs();
-    m_num_buffer_reads.resize(m_num_vcs/m_vc_per_vnet);
-    m_num_buffer_writes.resize(m_num_vcs/m_vc_per_vnet);
-    for (int i = 0; i < m_num_buffer_reads.size(); i++) {
-        m_num_buffer_reads[i] = 0;
-        m_num_buffer_writes[i] = 0;
-    }
-
-    // Instantiating the virtual channels
-    virtualChannels.reserve(m_num_vcs);
-    for (int i=0; i < m_num_vcs; i++) {
-        virtualChannels.emplace_back();
-    }
-}
-
-/*
- * The InputUnit wakeup function reads the input flit from its input link.
- * Each flit arrives with an input VC.
- * For HEAD/HEAD_TAIL flits, performs route computation,
- * and updates route in the input VC.
- * The flit is buffered for (m_latency - 1) cycles in the input VC
- * and marked as valid for SwitchAllocation starting that cycle.
- *
- */
-
-void
-InputUnit::wakeup()
-{
-    flit *t_flit;
-    if (m_in_link->isReady(curTick())) {
-
-        t_flit = m_in_link->consumeLink();
-        DPRINTF(RubyNetwork, "Router[%d] Consuming:%s Width: %d Flit:%s\n",
-        m_router->get_id(), m_in_link->name(),
-        m_router->getBitWidth(), *t_flit);
-        assert(t_flit->m_width == m_router->getBitWidth());
-        int vc = t_flit->get_vc();
-        t_flit->increment_hops(); // for stats
-
-        if ((t_flit->get_type() == HEAD_) ||
-            (t_flit->get_type() == HEAD_TAIL_)) {
-
-            assert(virtualChannels[vc].get_state() == IDLE_);
-            set_vc_active(vc, curTick());
-
-            // Route computation for this vc
-            int outport = m_router->route_compute(t_flit->get_route(),
-                m_id, m_direction);
-
-            // Update output port in VC
-            // All flits in this packet will use this output port
-            // The output port field in the flit is updated after it wins SA
-            grant_outport(vc, outport);
-
-        } else {
-            assert(virtualChannels[vc].get_state() == ACTIVE_);
-        }
-
-
-        // Buffer the flit
-        virtualChannels[vc].insertFlit(t_flit);
-
-        int vnet = vc/m_vc_per_vnet;
-        // number of writes same as reads
-        // any flit that is written will be read only once
-        m_num_buffer_writes[vnet]++;
-        m_num_buffer_reads[vnet]++;
-
-        Cycles pipe_stages = m_router->get_pipe_stages();
-        if (pipe_stages == 1) {
-            // 1-cycle router
-            // Flit goes for SA directly
-            t_flit->advance_stage(SA_, curTick());
-        } else {
-            assert(pipe_stages > 1);
-            // Router delay is modeled by making flit wait in buffer for
-            // (pipe_stages cycles - 1) cycles before going for SA
-
-            Cycles wait_time = pipe_stages - Cycles(1);
-            t_flit->advance_stage(SA_, m_router->clockEdge(wait_time));
-
-            // Wakeup the router in that cycle to perform SA
-            m_router->schedule_wakeup(Cycles(wait_time));
-        }
-
-        if (m_in_link->isReady(curTick())) {
-            m_router->schedule_wakeup(Cycles(1));
-        }
-    }
-}
-
-// Send a credit back to upstream router for this VC.
-// Called by SwitchAllocator when the flit in this VC wins the Switch.
-void
-InputUnit::increment_credit(int in_vc, bool free_signal, Tick curTime)
-{
-    DPRINTF(RubyNetwork, "Router[%d]: Sending a credit vc:%d free:%d to %s\n",
-    m_router->get_id(), in_vc, free_signal, m_credit_link->name());
-    Credit *t_credit = new Credit(in_vc, free_signal, curTime);
-    creditQueue.insert(t_credit);
-    m_credit_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
-}
-
-
-uint32_t
-InputUnit::functionalWrite(Packet *pkt)
-{
-    uint32_t num_functional_writes = 0;
-    for (auto& virtual_channel : virtualChannels) {
-        num_functional_writes += virtual_channel.functionalWrite(pkt);
-    }
-
-    return num_functional_writes;
-}
-
-void
-InputUnit::resetStats()
-{
-    for (int j = 0; j < m_num_buffer_reads.size(); j++) {
-        m_num_buffer_reads[j] = 0;
-        m_num_buffer_writes[j] = 0;
-    }
-}
diff --git a/src/mem/ruby/network/garnet2.0/InputUnit.hh b/src/mem/ruby/network/garnet2.0/InputUnit.hh
deleted file mode 100644 (file)
index 40ef251..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_INPUTUNIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_INPUTUNIT_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-class InputUnit : public Consumer
-{
-  public:
-    InputUnit(int id, PortDirection direction, Router *router);
-    ~InputUnit() = default;
-
-    void wakeup();
-    void print(std::ostream& out) const {};
-
-    inline PortDirection get_direction() { return m_direction; }
-
-    inline void
-    set_vc_idle(int vc, Tick curTime)
-    {
-        virtualChannels[vc].set_idle(curTime);
-    }
-
-    inline void
-    set_vc_active(int vc, Tick curTime)
-    {
-        virtualChannels[vc].set_active(curTime);
-    }
-
-    inline void
-    grant_outport(int vc, int outport)
-    {
-        virtualChannels[vc].set_outport(outport);
-    }
-
-    inline void
-    grant_outvc(int vc, int outvc)
-    {
-        virtualChannels[vc].set_outvc(outvc);
-    }
-
-    inline int
-    get_outport(int invc)
-    {
-        return virtualChannels[invc].get_outport();
-    }
-
-    inline int
-    get_outvc(int invc)
-    {
-        return virtualChannels[invc].get_outvc();
-    }
-
-    inline Tick
-    get_enqueue_time(int invc)
-    {
-        return virtualChannels[invc].get_enqueue_time();
-    }
-
-    void increment_credit(int in_vc, bool free_signal, Tick curTime);
-
-    inline flit*
-    peekTopFlit(int vc)
-    {
-        return virtualChannels[vc].peekTopFlit();
-    }
-
-    inline flit*
-    getTopFlit(int vc)
-    {
-        return virtualChannels[vc].getTopFlit();
-    }
-
-    inline bool
-    need_stage(int vc, flit_stage stage, Tick time)
-    {
-        return virtualChannels[vc].need_stage(stage, time);
-    }
-
-    inline bool
-    isReady(int invc, Tick curTime)
-    {
-        return virtualChannels[invc].isReady(curTime);
-    }
-
-    flitBuffer* getCreditQueue() { return &creditQueue; }
-
-    inline void
-    set_in_link(NetworkLink *link)
-    {
-        m_in_link = link;
-    }
-
-    inline int get_inlink_id() { return m_in_link->get_id(); }
-
-    inline void
-    set_credit_link(CreditLink *credit_link)
-    {
-        m_credit_link = credit_link;
-    }
-
-    double get_buf_read_activity(unsigned int vnet) const
-    { return m_num_buffer_reads[vnet]; }
-    double get_buf_write_activity(unsigned int vnet) const
-    { return m_num_buffer_writes[vnet]; }
-
-    uint32_t functionalWrite(Packet *pkt);
-    void resetStats();
-
-  private:
-    Router *m_router;
-    int m_id;
-    PortDirection m_direction;
-    int m_vc_per_vnet;
-    NetworkLink *m_in_link;
-    CreditLink *m_credit_link;
-    flitBuffer creditQueue;
-
-    // Input Virtual channels
-    std::vector<VirtualChannel> virtualChannels;
-
-    // Statistical variables
-    std::vector<double> m_num_buffer_writes;
-    std::vector<double> m_num_buffer_reads;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_INPUTUNIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/NetworkBridge.cc b/src/mem/ruby/network/garnet2.0/NetworkBridge.cc
deleted file mode 100644 (file)
index e7d340a..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * For use for simulation and test purposes only
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 3. Neither the name of the copyright holder 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 HOLDER 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: Srikant Bharadwaj
- */
-
-
-#include "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-
-#include <cmath>
-
-#include "debug/RubyNetwork.hh"
-#include "params/GarnetIntLink.hh"
-
-NetworkBridge::NetworkBridge(const Params *p)
-    :CreditLink(p)
-{
-    enCdc = true;
-    enSerDes = true;
-    mType = p->vtype;
-
-    cdcLatency = p->cdc_latency;
-    serDesLatency = p->serdes_latency;
-    lastScheduledAt = 0;
-
-    nLink = p->link;
-    if (mType == Enums::LINK_OBJECT) {
-        nLink->setLinkConsumer(this);
-        setSourceQueue(nLink->getBuffer(), nLink);
-    } else if (mType == Enums::OBJECT_LINK) {
-        nLink->setSourceQueue(&linkBuffer, this);
-        setLinkConsumer(nLink);
-    } else {
-        // CDC type must be set
-        panic("CDC type must be set");
-    }
-}
-
-void
-NetworkBridge::setVcsPerVnet(uint32_t consumerVcs)
-{
-    DPRINTF(RubyNetwork, "VcsPerVnet VC: %d\n", consumerVcs);
-    NetworkLink::setVcsPerVnet(consumerVcs);
-    lenBuffer.resize(consumerVcs * m_virt_nets);
-    sizeSent.resize(consumerVcs * m_virt_nets);
-    flitsSent.resize(consumerVcs * m_virt_nets);
-    extraCredit.resize(consumerVcs * m_virt_nets);
-
-    nLink->setVcsPerVnet(consumerVcs);
-}
-
-void
-NetworkBridge::initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en)
-{
-    coBridge = coBrid;
-    enCdc = cdc_en;
-    enSerDes = serdes_en;
-}
-
-NetworkBridge::~NetworkBridge()
-{
-}
-
-void
-NetworkBridge::scheduleFlit(flit *t_flit, Cycles latency)
-{
-    Cycles totLatency = latency;
-
-    if (enCdc) {
-        // Add the CDC latency
-        totLatency = latency + cdcLatency;
-    }
-
-    Tick sendTime = link_consumer->getObject()->clockEdge(totLatency);
-    Tick nextAvailTick = lastScheduledAt + link_consumer->getObject()->\
-            cyclesToTicks(Cycles(1));
-    sendTime = std::max(nextAvailTick, sendTime);
-    t_flit->set_time(sendTime);
-    lastScheduledAt = sendTime;
-    linkBuffer.insert(t_flit);
-    link_consumer->scheduleEventAbsolute(sendTime);
-}
-
-void
-NetworkBridge::neutralize(int vc, int eCredit)
-{
-    extraCredit[vc].push(eCredit);
-}
-
-void
-NetworkBridge::flitisizeAndSend(flit *t_flit)
-{
-    // Serialize-Deserialize only if it is enabled
-    if (enSerDes) {
-        // Calculate the target-width
-        int target_width = bitWidth;
-        int cur_width = nLink->bitWidth;
-        if (mType == Enums::OBJECT_LINK) {
-            target_width = nLink->bitWidth;
-            cur_width = bitWidth;
-        }
-
-        DPRINTF(RubyNetwork, "Target width: %d Current: %d\n",
-            target_width, cur_width);
-        assert(target_width != cur_width);
-
-        int vc = t_flit->get_vc();
-
-        if (target_width > cur_width) {
-            // Deserialize
-            // This deserializer combines flits from the
-            // same message together
-            int num_flits = 0;
-            int flitPossible = 0;
-            if (t_flit->get_type() == CREDIT_) {
-                lenBuffer[vc]++;
-                assert(extraCredit[vc].front());
-                if (lenBuffer[vc] == extraCredit[vc].front()) {
-                    flitPossible = 1;
-                    extraCredit[vc].pop();
-                    lenBuffer[vc] = 0;
-                }
-            } else if (t_flit->get_type() == TAIL_ ||
-                       t_flit->get_type() == HEAD_TAIL_) {
-                // If its the end of packet, then send whatever
-                // is available.
-                int sizeAvail = (t_flit->msgSize - sizeSent[vc]);
-                flitPossible = ceil((float)sizeAvail/(float)target_width);
-                assert (flitPossible < 2);
-                num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
-                // Stop tracking the packet.
-                flitsSent[vc] = 0;
-                sizeSent[vc] = 0;
-            } else {
-                // If we are yet to receive the complete packet
-                // track the size recieved and flits deserialized.
-                int sizeAvail =
-                    ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
-                flitPossible = floor((float)sizeAvail/(float)target_width);
-                assert (flitPossible < 2);
-                num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
-                if (flitPossible) {
-                    sizeSent[vc] += target_width;
-                    flitsSent[vc] = t_flit->get_id() + 1;
-                }
-            }
-
-            DPRINTF(RubyNetwork, "Deserialize :%dB -----> %dB "
-                " vc:%d\n", cur_width, target_width, vc);
-
-            flit *fl = NULL;
-            if (flitPossible) {
-                fl = t_flit->deserialize(lenBuffer[vc], num_flits,
-                    target_width);
-            }
-
-            // Inform the credit serializer about the number
-            // of flits that were generated.
-            if (t_flit->get_type() != CREDIT_ && fl) {
-                coBridge->neutralize(vc, num_flits);
-            }
-
-            // Schedule only if we are done deserializing
-            if (fl) {
-                DPRINTF(RubyNetwork, "Scheduling a flit\n");
-                lenBuffer[vc] = 0;
-                scheduleFlit(fl, serDesLatency);
-            }
-            // Delete this flit, new flit is sent in any case
-            delete t_flit;
-        } else {
-            // Serialize
-            DPRINTF(RubyNetwork, "Serializing flit :%d -----> %d "
-            "(vc:%d, Original Message Size: %d)\n",
-                cur_width, target_width, vc, t_flit->msgSize);
-
-            int flitPossible = 0;
-            if (t_flit->get_type() == CREDIT_) {
-                // We store the deserialization ratio and then
-                // access it when serializing credits in the
-                // oppposite direction.
-                assert(extraCredit[vc].front());
-                flitPossible = extraCredit[vc].front();
-                extraCredit[vc].pop();
-            } else if (t_flit->get_type() == HEAD_ ||
-                    t_flit->get_type() == BODY_) {
-                int sizeAvail =
-                    ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
-                flitPossible = floor((float)sizeAvail/(float)target_width);
-                if (flitPossible) {
-                    sizeSent[vc] += flitPossible*target_width;
-                    flitsSent[vc] += flitPossible;
-                }
-            } else {
-                int sizeAvail = t_flit->msgSize - sizeSent[vc];
-                flitPossible = ceil((float)sizeAvail/(float)target_width);
-                sizeSent[vc] = 0;
-                flitsSent[vc] = 0;
-            }
-            assert(flitPossible > 0);
-
-            // Schedule all the flits
-            // num_flits could be zero for credits
-            for (int i = 0; i < flitPossible; i++) {
-                // Ignore neutralized credits
-                flit *fl = t_flit->serialize(i, flitPossible, target_width);
-                scheduleFlit(fl, serDesLatency);
-                DPRINTF(RubyNetwork, "Serialized to flit[%d of %d parts]:"
-                " %s\n", i+1, flitPossible, *fl);
-            }
-
-            if (t_flit->get_type() != CREDIT_) {
-                coBridge->neutralize(vc, flitPossible);
-            }
-            // Delete this flit, new flit is sent in any case
-            delete t_flit;
-        }
-        return;
-    }
-
-    // If only CDC is enabled schedule it
-    scheduleFlit(t_flit, Cycles(0));
-}
-void
-NetworkBridge::wakeup()
-{
-    flit *t_flit;
-
-    if (link_srcQueue->isReady(curTick())) {
-        t_flit = link_srcQueue->getTopFlit();
-        DPRINTF(RubyNetwork, "Recieved flit %s\n", *t_flit);
-        flitisizeAndSend(t_flit);
-        return;
-    }
-    assert(!link_srcQueue->getSize());
-}
-
-NetworkBridge *
-NetworkBridgeParams::create()
-{
-    return new NetworkBridge(this);
-}
diff --git a/src/mem/ruby/network/garnet2.0/NetworkBridge.hh b/src/mem/ruby/network/garnet2.0/NetworkBridge.hh
deleted file mode 100644 (file)
index 0e8ac0c..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * For use for simulation and test purposes only
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. 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.
- *
- * 3. Neither the name of the copyright holder 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 HOLDER 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: Srikant Bharadwaj
- */
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_NETWORK_BRIDGE_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_NETWORK_BRIDGE_HH__
-
-#include <iostream>
-#include <queue>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-#include "params/NetworkBridge.hh"
-
-class GarnetNetwork;
-
-class NetworkBridge: public CreditLink
-{
-  public:
-    typedef NetworkBridgeParams Params;
-    NetworkBridge(const Params *p);
-    ~NetworkBridge();
-
-    void initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en);
-
-    void wakeup();
-    void neutralize(int vc, int eCredit);
-
-    void scheduleFlit(flit *t_flit, Cycles latency);
-    void flitisizeAndSend(flit *t_flit);
-    void setVcsPerVnet(uint32_t consumerVcs);
-
-  protected:
-    // Pointer to co-existing bridge
-    // CreditBridge for Network Bridge and vice versa
-    NetworkBridge *coBridge;
-
-    // Link connected toBridge
-    // could be a source or destination
-    // depending on mType
-    NetworkLink *nLink;
-
-    // CDC enable/disable
-    bool enCdc;
-    // SerDes enable/disable
-    bool enSerDes;
-
-    // Type of Bridge
-    int mType;
-
-    Cycles cdcLatency;
-    Cycles serDesLatency;
-
-    Tick lastScheduledAt;
-
-    // Used by Credit Deserializer
-    std::vector<int> lenBuffer;
-    std::vector<int> sizeSent;
-    std::vector<int> flitsSent;
-    std::vector<std::queue<int>> extraCredit;
-
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_NETWORK_BRIDGE_HH__
diff --git a/src/mem/ruby/network/garnet2.0/NetworkInterface.cc b/src/mem/ruby/network/garnet2.0/NetworkInterface.cc
deleted file mode 100644 (file)
index 1b3c262..0000000
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
-
-#include <cassert>
-#include <cmath>
-
-#include "base/cast.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/MessageBuffer.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-using namespace std;
-
-NetworkInterface::NetworkInterface(const Params *p)
-  : ClockedObject(p), Consumer(this), m_id(p->id),
-    m_virtual_networks(p->virt_nets), m_vc_per_vnet(0),
-    m_vc_allocator(m_virtual_networks, 0),
-    m_deadlock_threshold(p->garnet_deadlock_threshold),
-    vc_busy_counter(m_virtual_networks, 0)
-{
-    m_stall_count.resize(m_virtual_networks);
-    niOutVcs.resize(0);
-}
-
-void
-NetworkInterface::addInPort(NetworkLink *in_link,
-                              CreditLink *credit_link)
-{
-    InputPort *newInPort = new InputPort(in_link, credit_link);
-    inPorts.push_back(newInPort);
-    DPRINTF(RubyNetwork, "Adding input port:%s with vnets %s\n",
-    in_link->name(), newInPort->printVnets());
-
-    in_link->setLinkConsumer(this);
-    credit_link->setSourceQueue(newInPort->outCreditQueue(), this);
-    if (m_vc_per_vnet != 0) {
-        in_link->setVcsPerVnet(m_vc_per_vnet);
-        credit_link->setVcsPerVnet(m_vc_per_vnet);
-    }
-
-}
-
-void
-NetworkInterface::addOutPort(NetworkLink *out_link,
-                             CreditLink *credit_link,
-                             SwitchID router_id, uint32_t consumerVcs)
-{
-    OutputPort *newOutPort = new OutputPort(out_link, credit_link, router_id);
-    outPorts.push_back(newOutPort);
-
-    assert(consumerVcs > 0);
-    // We are not allowing different physical links to have different vcs
-    // If it is required that the Network Interface support different VCs
-    // for every physical link connected to it. Then they need to change
-    // the logic within outport and inport.
-    if (niOutVcs.size() == 0) {
-        m_vc_per_vnet = consumerVcs;
-        int m_num_vcs = consumerVcs * m_virtual_networks;
-        niOutVcs.resize(m_num_vcs);
-        outVcState.reserve(m_num_vcs);
-        m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
-        // instantiating the NI flit buffers
-        for (int i = 0; i < m_num_vcs; i++) {
-            m_ni_out_vcs_enqueue_time[i] = Tick(INFINITE_);
-            outVcState.emplace_back(i, m_net_ptr, consumerVcs);
-        }
-
-        // Reset VC Per VNET for input links already instantiated
-        for (auto &iPort: inPorts) {
-            NetworkLink *inNetLink = iPort->inNetLink();
-            inNetLink->setVcsPerVnet(m_vc_per_vnet);
-            credit_link->setVcsPerVnet(m_vc_per_vnet);
-        }
-    } else {
-        fatal_if(consumerVcs != m_vc_per_vnet,
-        "%s: Connected Physical links have different vc requests: %d and %d\n",
-        name(), consumerVcs, m_vc_per_vnet);
-    }
-
-    DPRINTF(RubyNetwork, "OutputPort:%s Vnet: %s\n",
-    out_link->name(), newOutPort->printVnets());
-
-    out_link->setSourceQueue(newOutPort->outFlitQueue(), this);
-    out_link->setVcsPerVnet(m_vc_per_vnet);
-    credit_link->setLinkConsumer(this);
-    credit_link->setVcsPerVnet(m_vc_per_vnet);
-}
-
-void
-NetworkInterface::addNode(vector<MessageBuffer *>& in,
-                            vector<MessageBuffer *>& out)
-{
-    inNode_ptr = in;
-    outNode_ptr = out;
-
-    for (auto& it : in) {
-        if (it != nullptr) {
-            it->setConsumer(this);
-        }
-    }
-}
-
-void
-NetworkInterface::dequeueCallback()
-{
-    // An output MessageBuffer has dequeued something this cycle and there
-    // is now space to enqueue a stalled message. However, we cannot wake
-    // on the same cycle as the dequeue. Schedule a wake at the soonest
-    // possible time (next cycle).
-    scheduleEventAbsolute(clockEdge(Cycles(1)));
-}
-
-void
-NetworkInterface::incrementStats(flit *t_flit)
-{
-    int vnet = t_flit->get_vnet();
-
-    // Latency
-    m_net_ptr->increment_received_flits(vnet);
-    Tick network_delay =
-        t_flit->get_dequeue_time() -
-        t_flit->get_enqueue_time() - cyclesToTicks(Cycles(1));
-    Tick src_queueing_delay = t_flit->get_src_delay();
-    Tick dest_queueing_delay = (curTick() - t_flit->get_dequeue_time());
-    Tick queueing_delay = src_queueing_delay + dest_queueing_delay;
-
-    m_net_ptr->increment_flit_network_latency(network_delay, vnet);
-    m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
-
-    if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
-        m_net_ptr->increment_received_packets(vnet);
-        m_net_ptr->increment_packet_network_latency(network_delay, vnet);
-        m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
-    }
-
-    // Hops
-    m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
-}
-
-/*
- * The NI wakeup checks whether there are any ready messages in the protocol
- * buffer. If yes, it picks that up, flitisizes it into a number of flits and
- * puts it into an output buffer and schedules the output link. On a wakeup
- * it also checks whether there are flits in the input link. If yes, it picks
- * them up and if the flit is a tail, the NI inserts the corresponding message
- * into the protocol buffer. It also checks for credits being sent by the
- * downstream router.
- */
-
-void
-NetworkInterface::wakeup()
-{
-    std::ostringstream oss;
-    for (auto &oPort: outPorts) {
-        oss << oPort->routerID() << "[" << oPort->printVnets() << "] ";
-    }
-    DPRINTF(RubyNetwork, "Network Interface %d connected to router:%s "
-            "woke up. Period: %ld\n", m_id, oss.str(), clockPeriod());
-
-    assert(curTick() == clockEdge());
-    MsgPtr msg_ptr;
-    Tick curTime = clockEdge();
-
-    // Checking for messages coming from the protocol
-    // can pick up a message/cycle for each virtual net
-    for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
-        MessageBuffer *b = inNode_ptr[vnet];
-        if (b == nullptr) {
-            continue;
-        }
-
-        if (b->isReady(curTime)) { // Is there a message waiting
-            msg_ptr = b->peekMsgPtr();
-            if (flitisizeMessage(msg_ptr, vnet)) {
-                b->dequeue(curTime);
-            }
-        }
-    }
-
-    scheduleOutputLink();
-
-    // Check if there are flits stalling a virtual channel. Track if a
-    // message is enqueued to restrict ejection to one message per cycle.
-    checkStallQueue();
-
-    /*********** Check the incoming flit link **********/
-    DPRINTF(RubyNetwork, "Number of input ports: %d\n", inPorts.size());
-    for (auto &iPort: inPorts) {
-        NetworkLink *inNetLink = iPort->inNetLink();
-        if (inNetLink->isReady(curTick())) {
-            flit *t_flit = inNetLink->consumeLink();
-            DPRINTF(RubyNetwork, "Recieved flit:%s\n", *t_flit);
-            assert(t_flit->m_width == iPort->bitWidth());
-
-            int vnet = t_flit->get_vnet();
-            t_flit->set_dequeue_time(curTick());
-
-            // If a tail flit is received, enqueue into the protocol buffers
-            // if space is available. Otherwise, exchange non-tail flits for
-            // credits.
-            if (t_flit->get_type() == TAIL_ ||
-                t_flit->get_type() == HEAD_TAIL_) {
-                if (!iPort->messageEnqueuedThisCycle &&
-                    outNode_ptr[vnet]->areNSlotsAvailable(1, curTime)) {
-                    // Space is available. Enqueue to protocol buffer.
-                    outNode_ptr[vnet]->enqueue(t_flit->get_msg_ptr(), curTime,
-                                               cyclesToTicks(Cycles(1)));
-
-                    // Simply send a credit back since we are not buffering
-                    // this flit in the NI
-                    Credit *cFlit = new Credit(t_flit->get_vc(),
-                                               true, curTick());
-                    iPort->sendCredit(cFlit);
-                    // Update stats and delete flit pointer
-                    incrementStats(t_flit);
-                    delete t_flit;
-                } else {
-                    // No space available- Place tail flit in stall queue and
-                    // set up a callback for when protocol buffer is dequeued.
-                    // Stat update and flit pointer deletion will occur upon
-                    // unstall.
-                    iPort->m_stall_queue.push_back(t_flit);
-                    m_stall_count[vnet]++;
-
-                    outNode_ptr[vnet]->registerDequeueCallback([this]() {
-                        dequeueCallback(); });
-                }
-            } else {
-                // Non-tail flit. Send back a credit but not VC free signal.
-                Credit *cFlit = new Credit(t_flit->get_vc(), false,
-                                               curTick());
-                // Simply send a credit back since we are not buffering
-                // this flit in the NI
-                iPort->sendCredit(cFlit);
-
-                // Update stats and delete flit pointer.
-                incrementStats(t_flit);
-                delete t_flit;
-            }
-        }
-    }
-
-    /****************** Check the incoming credit link *******/
-
-    for (auto &oPort: outPorts) {
-        CreditLink *inCreditLink = oPort->inCreditLink();
-        if (inCreditLink->isReady(curTick())) {
-            Credit *t_credit = (Credit*) inCreditLink->consumeLink();
-            outVcState[t_credit->get_vc()].increment_credit();
-            if (t_credit->is_free_signal()) {
-                outVcState[t_credit->get_vc()].setState(IDLE_,
-                    curTick());
-            }
-            delete t_credit;
-        }
-    }
-
-
-    // It is possible to enqueue multiple outgoing credit flits if a message
-    // was unstalled in the same cycle as a new message arrives. In this
-    // case, we should schedule another wakeup to ensure the credit is sent
-    // back.
-    for (auto &iPort: inPorts) {
-        if (iPort->outCreditQueue()->getSize() > 0) {
-            DPRINTF(RubyNetwork, "Sending a credit %s via %s at %ld\n",
-            *(iPort->outCreditQueue()->peekTopFlit()),
-            iPort->outCreditLink()->name(), clockEdge(Cycles(1)));
-            iPort->outCreditLink()->
-                scheduleEventAbsolute(clockEdge(Cycles(1)));
-        }
-    }
-    checkReschedule();
-}
-
-void
-NetworkInterface::checkStallQueue()
-{
-    // Check all stall queues.
-    // There is one stall queue for each input link
-    for (auto &iPort: inPorts) {
-        iPort->messageEnqueuedThisCycle = false;
-        Tick curTime = clockEdge();
-
-        if (!iPort->m_stall_queue.empty()) {
-            for (auto stallIter = iPort->m_stall_queue.begin();
-                 stallIter != iPort->m_stall_queue.end(); ) {
-                flit *stallFlit = *stallIter;
-                int vnet = stallFlit->get_vnet();
-
-                // If we can now eject to the protocol buffer,
-                // send back credits
-                if (outNode_ptr[vnet]->areNSlotsAvailable(1,
-                    curTime)) {
-                    outNode_ptr[vnet]->enqueue(stallFlit->get_msg_ptr(),
-                        curTime, cyclesToTicks(Cycles(1)));
-
-                    // Send back a credit with free signal now that the
-                    // VC is no longer stalled.
-                    Credit *cFlit = new Credit(stallFlit->get_vc(), true,
-                                                   curTick());
-                    iPort->sendCredit(cFlit);
-
-                    // Update Stats
-                    incrementStats(stallFlit);
-
-                    // Flit can now safely be deleted and removed from stall
-                    // queue
-                    delete stallFlit;
-                    iPort->m_stall_queue.erase(stallIter);
-                    m_stall_count[vnet]--;
-
-                    // If there are no more stalled messages for this vnet, the
-                    // callback on it's MessageBuffer is not needed.
-                    if (m_stall_count[vnet] == 0)
-                        outNode_ptr[vnet]->unregisterDequeueCallback();
-
-                    iPort->messageEnqueuedThisCycle = true;
-                    break;
-                } else {
-                    ++stallIter;
-                }
-            }
-        }
-    }
-}
-
-// Embed the protocol message into flits
-bool
-NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
-{
-    Message *net_msg_ptr = msg_ptr.get();
-    NetDest net_msg_dest = net_msg_ptr->getDestination();
-
-    // gets all the destinations associated with this message.
-    vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
-
-    // Number of flits is dependent on the link bandwidth available.
-    // This is expressed in terms of bytes/cycle or the flit size
-    OutputPort *oPort = getOutportForVnet(vnet);
-    assert(oPort);
-    int num_flits = (int)divCeil((float) m_net_ptr->MessageSizeType_to_int(
-        net_msg_ptr->getMessageSize()), (float)oPort->bitWidth());
-
-    DPRINTF(RubyNetwork, "Message Size:%d vnet:%d bitWidth:%d\n",
-        m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize()),
-        vnet, oPort->bitWidth());
-
-    // loop to convert all multicast messages into unicast messages
-    for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
-
-        // this will return a free output virtual channel
-        int vc = calculateVC(vnet);
-
-        if (vc == -1) {
-            return false ;
-        }
-        MsgPtr new_msg_ptr = msg_ptr->clone();
-        NodeID destID = dest_nodes[ctr];
-
-        Message *new_net_msg_ptr = new_msg_ptr.get();
-        if (dest_nodes.size() > 1) {
-            NetDest personal_dest;
-            for (int m = 0; m < (int) MachineType_NUM; m++) {
-                if ((destID >= MachineType_base_number((MachineType) m)) &&
-                    destID < MachineType_base_number((MachineType) (m+1))) {
-                    // calculating the NetDest associated with this destID
-                    personal_dest.clear();
-                    personal_dest.add((MachineID) {(MachineType) m, (destID -
-                        MachineType_base_number((MachineType) m))});
-                    new_net_msg_ptr->getDestination() = personal_dest;
-                    break;
-                }
-            }
-            net_msg_dest.removeNetDest(personal_dest);
-            // removing the destination from the original message to reflect
-            // that a message with this particular destination has been
-            // flitisized and an output vc is acquired
-            net_msg_ptr->getDestination().removeNetDest(personal_dest);
-        }
-
-        // Embed Route into the flits
-        // NetDest format is used by the routing table
-        // Custom routing algorithms just need destID
-
-        RouteInfo route;
-        route.vnet = vnet;
-        route.net_dest = new_net_msg_ptr->getDestination();
-        route.src_ni = m_id;
-        route.src_router = oPort->routerID();
-        route.dest_ni = destID;
-        route.dest_router = m_net_ptr->get_router_id(destID, vnet);
-
-        // initialize hops_traversed to -1
-        // so that the first router increments it to 0
-        route.hops_traversed = -1;
-
-        m_net_ptr->increment_injected_packets(vnet);
-        for (int i = 0; i < num_flits; i++) {
-            m_net_ptr->increment_injected_flits(vnet);
-            flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
-                m_net_ptr->MessageSizeType_to_int(
-                net_msg_ptr->getMessageSize()),
-                oPort->bitWidth(), curTick());
-
-            fl->set_src_delay(curTick() - ticksToCycles(msg_ptr->getTime()));
-            niOutVcs[vc].insert(fl);
-        }
-
-        m_ni_out_vcs_enqueue_time[vc] = curTick();
-        outVcState[vc].setState(ACTIVE_, curTick());
-    }
-    return true ;
-}
-
-// Looking for a free output vc
-int
-NetworkInterface::calculateVC(int vnet)
-{
-    for (int i = 0; i < m_vc_per_vnet; i++) {
-        int delta = m_vc_allocator[vnet];
-        m_vc_allocator[vnet]++;
-        if (m_vc_allocator[vnet] == m_vc_per_vnet)
-            m_vc_allocator[vnet] = 0;
-
-        if (outVcState[(vnet*m_vc_per_vnet) + delta].isInState(
-                    IDLE_, curTick())) {
-            vc_busy_counter[vnet] = 0;
-            return ((vnet*m_vc_per_vnet) + delta);
-        }
-    }
-
-    vc_busy_counter[vnet] += 1;
-    panic_if(vc_busy_counter[vnet] > m_deadlock_threshold,
-        "%s: Possible network deadlock in vnet: %d at time: %llu \n",
-        name(), vnet, curTick());
-
-    return -1;
-}
-
-void
-NetworkInterface::scheduleOutputPort(OutputPort *oPort)
-{
-   int vc = oPort->vcRoundRobin();
-
-   for (int i = 0; i < niOutVcs.size(); i++) {
-       vc++;
-       if (vc == niOutVcs.size())
-           vc = 0;
-
-       int t_vnet = get_vnet(vc);
-       if (oPort->isVnetSupported(t_vnet)) {
-           // model buffer backpressure
-           if (niOutVcs[vc].isReady(curTick()) &&
-               outVcState[vc].has_credit()) {
-
-               bool is_candidate_vc = true;
-               int vc_base = t_vnet * m_vc_per_vnet;
-
-               if (m_net_ptr->isVNetOrdered(t_vnet)) {
-                   for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
-                        vc_offset++) {
-                       int t_vc = vc_base + vc_offset;
-                       if (niOutVcs[t_vc].isReady(curTick())) {
-                           if (m_ni_out_vcs_enqueue_time[t_vc] <
-                               m_ni_out_vcs_enqueue_time[vc]) {
-                               is_candidate_vc = false;
-                               break;
-                           }
-                       }
-                   }
-               }
-               if (!is_candidate_vc)
-                   continue;
-
-               // Update the round robin arbiter
-               oPort->vcRoundRobin(vc);
-
-               outVcState[vc].decrement_credit();
-
-               // Just removing the top flit
-               flit *t_flit = niOutVcs[vc].getTopFlit();
-               t_flit->set_time(clockEdge(Cycles(1)));
-
-               // Scheduling the flit
-               scheduleFlit(t_flit);
-
-               if (t_flit->get_type() == TAIL_ ||
-                  t_flit->get_type() == HEAD_TAIL_) {
-                   m_ni_out_vcs_enqueue_time[vc] = Tick(INFINITE_);
-               }
-
-               // Done with this port, continue to schedule
-               // other ports
-               return;
-           }
-       }
-   }
-}
-
-
-
-/** This function looks at the NI buffers
- *  if some buffer has flits which are ready to traverse the link in the next
- *  cycle, and the downstream output vc associated with this flit has buffers
- *  left, the link is scheduled for the next cycle
- */
-
-void
-NetworkInterface::scheduleOutputLink()
-{
-    // Schedule each output link
-    for (auto &oPort: outPorts) {
-        scheduleOutputPort(oPort);
-    }
-}
-
-NetworkInterface::InputPort *
-NetworkInterface::getInportForVnet(int vnet)
-{
-    for (auto &iPort : inPorts) {
-        if (iPort->isVnetSupported(vnet)) {
-            return iPort;
-        }
-    }
-
-    return nullptr;
-}
-
-/*
- * This function returns the outport which supports the given vnet.
- * Currently, HeteroGarnet does not support multiple outports to
- * support same vnet. Thus, this function returns the first-and
- * only outport which supports the vnet.
- */
-NetworkInterface::OutputPort *
-NetworkInterface::getOutportForVnet(int vnet)
-{
-    for (auto &oPort : outPorts) {
-        if (oPort->isVnetSupported(vnet)) {
-            return oPort;
-        }
-    }
-
-    return nullptr;
-}
-void
-NetworkInterface::scheduleFlit(flit *t_flit)
-{
-    OutputPort *oPort = getOutportForVnet(t_flit->get_vnet());
-
-    if (oPort) {
-        DPRINTF(RubyNetwork, "Scheduling at %s time:%ld flit:%s Message:%s\n",
-        oPort->outNetLink()->name(), clockEdge(Cycles(1)),
-        *t_flit, *(t_flit->get_msg_ptr()));
-        oPort->outFlitQueue()->insert(t_flit);
-        oPort->outNetLink()->scheduleEventAbsolute(clockEdge(Cycles(1)));
-        return;
-    }
-
-    panic("No output port found for vnet:%d\n", t_flit->get_vnet());
-    return;
-}
-
-int
-NetworkInterface::get_vnet(int vc)
-{
-    for (int i = 0; i < m_virtual_networks; i++) {
-        if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
-            return i;
-        }
-    }
-    fatal("Could not determine vc");
-}
-
-
-// Wakeup the NI in the next cycle if there are waiting
-// messages in the protocol buffer, or waiting flits in the
-// output VC buffer.
-// Also check if we have to reschedule because of a clock period
-// difference.
-void
-NetworkInterface::checkReschedule()
-{
-    for (const auto& it : inNode_ptr) {
-        if (it == nullptr) {
-            continue;
-        }
-
-        while (it->isReady(clockEdge())) { // Is there a message waiting
-            scheduleEvent(Cycles(1));
-            return;
-        }
-    }
-
-    for (auto& ni_out_vc : niOutVcs) {
-        if (ni_out_vc.isReady(clockEdge(Cycles(1)))) {
-            scheduleEvent(Cycles(1));
-            return;
-        }
-    }
-
-    // Check if any input links have flits to be popped.
-    // This can happen if the links are operating at
-    // a higher frequency.
-    for (auto &iPort : inPorts) {
-        NetworkLink *inNetLink = iPort->inNetLink();
-        if (inNetLink->isReady(curTick())) {
-            scheduleEvent(Cycles(1));
-            return;
-        }
-    }
-
-    for (auto &oPort : outPorts) {
-        CreditLink *inCreditLink = oPort->inCreditLink();
-        if (inCreditLink->isReady(curTick())) {
-            scheduleEvent(Cycles(1));
-            return;
-        }
-    }
-}
-
-void
-NetworkInterface::print(std::ostream& out) const
-{
-    out << "[Network Interface]";
-}
-
-uint32_t
-NetworkInterface::functionalWrite(Packet *pkt)
-{
-    uint32_t num_functional_writes = 0;
-    for (auto& ni_out_vc : niOutVcs) {
-        num_functional_writes += ni_out_vc.functionalWrite(pkt);
-    }
-
-    for (auto &oPort: outPorts) {
-        num_functional_writes += oPort->outFlitQueue()->functionalWrite(pkt);
-    }
-    return num_functional_writes;
-}
-
-NetworkInterface *
-GarnetNetworkInterfaceParams::create()
-{
-    return new NetworkInterface(this);
-}
diff --git a/src/mem/ruby/network/garnet2.0/NetworkInterface.hh b/src/mem/ruby/network/garnet2.0/NetworkInterface.hh
deleted file mode 100644 (file)
index 09a13d9..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_NETWORKINTERFACE_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_NETWORKINTERFACE_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/OutVcState.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-#include "params/GarnetNetworkInterface.hh"
-
-class MessageBuffer;
-class flitBuffer;
-
-class NetworkInterface : public ClockedObject, public Consumer
-{
-  public:
-    typedef GarnetNetworkInterfaceParams Params;
-    NetworkInterface(const Params *p);
-    ~NetworkInterface() = default;
-
-    void addInPort(NetworkLink *in_link, CreditLink *credit_link);
-    void addOutPort(NetworkLink *out_link, CreditLink *credit_link,
-        SwitchID router_id, uint32_t consumerVcs);
-
-    void dequeueCallback();
-    void wakeup();
-    void addNode(std::vector<MessageBuffer *> &inNode,
-                 std::vector<MessageBuffer *> &outNode);
-
-    void print(std::ostream& out) const;
-    int get_vnet(int vc);
-    void init_net_ptr(GarnetNetwork *net_ptr) { m_net_ptr = net_ptr; }
-
-    uint32_t functionalWrite(Packet *);
-
-    void scheduleFlit(flit *t_flit);
-
-    int get_router_id(int vnet)
-    {
-        OutputPort *oPort = getOutportForVnet(vnet);
-        assert(oPort);
-        return oPort->routerID();
-    }
-
-    class OutputPort
-    {
-      public:
-          OutputPort(NetworkLink *outLink, CreditLink *creditLink,
-              int routerID)
-          {
-              _vnets = outLink->mVnets;
-              _outFlitQueue = new flitBuffer();
-
-              _outNetLink = outLink;
-              _inCreditLink = creditLink;
-
-              _routerID = routerID;
-              _bitWidth = outLink->bitWidth;
-              _vcRoundRobin = 0;
-
-          }
-
-          flitBuffer *
-          outFlitQueue()
-          {
-              return _outFlitQueue;
-          }
-
-          NetworkLink *
-          outNetLink()
-          {
-              return _outNetLink;
-          }
-
-          CreditLink *
-          inCreditLink()
-          {
-              return _inCreditLink;
-          }
-
-          int
-          routerID()
-          {
-              return _routerID;
-          }
-
-          uint32_t bitWidth()
-          {
-              return _bitWidth;
-          }
-
-          bool isVnetSupported(int pVnet)
-          {
-              if (!_vnets.size()) {
-                  return true;
-              }
-
-              for (auto &it : _vnets) {
-                  if (it == pVnet) {
-                      return true;
-                  }
-              }
-              return false;
-
-          }
-
-          std::string
-          printVnets()
-          {
-              std::stringstream ss;
-              for (auto &it : _vnets) {
-                  ss << it;
-                  ss << " ";
-              }
-              return ss.str();
-          }
-
-          int vcRoundRobin()
-          {
-              return _vcRoundRobin;
-          }
-
-          void vcRoundRobin(int vc)
-          {
-              _vcRoundRobin = vc;
-          }
-
-
-      private:
-          std::vector<int> _vnets;
-          flitBuffer *_outFlitQueue;
-
-          NetworkLink *_outNetLink;
-          CreditLink *_inCreditLink;
-
-          int _vcRoundRobin; // For round robin scheduling
-
-          int _routerID;
-          uint32_t _bitWidth;
-    };
-
-    class InputPort
-    {
-      public:
-          InputPort(NetworkLink *inLink, CreditLink *creditLink)
-          {
-              _vnets = inLink->mVnets;
-              _outCreditQueue = new flitBuffer();
-
-              _inNetLink = inLink;
-              _outCreditLink = creditLink;
-              _bitWidth = inLink->bitWidth;
-          }
-
-          flitBuffer *
-          outCreditQueue()
-          {
-              return _outCreditQueue;
-          }
-
-          NetworkLink *
-          inNetLink()
-          {
-              return _inNetLink;
-          }
-
-          CreditLink *
-          outCreditLink()
-          {
-              return _outCreditLink;
-          }
-
-          bool isVnetSupported(int pVnet)
-          {
-              if (!_vnets.size()) {
-                  return true;
-              }
-
-              for (auto &it : _vnets) {
-                  if (it == pVnet) {
-                      return true;
-                  }
-              }
-              return false;
-
-          }
-
-          void sendCredit(Credit *cFlit)
-          {
-              _outCreditQueue->insert(cFlit);
-          }
-
-          uint32_t bitWidth()
-          {
-              return _bitWidth;
-          }
-
-          std::string
-          printVnets()
-          {
-              std::stringstream ss;
-              for (auto &it : _vnets) {
-                  ss << it;
-                  ss << " ";
-              }
-              return ss.str();
-          }
-
-          // Queue for stalled flits
-          std::deque<flit *> m_stall_queue;
-          bool messageEnqueuedThisCycle;
-      private:
-          std::vector<int> _vnets;
-          flitBuffer *_outCreditQueue;
-
-          NetworkLink *_inNetLink;
-          CreditLink *_outCreditLink;
-          uint32_t _bitWidth;
-    };
-
-
-  private:
-    GarnetNetwork *m_net_ptr;
-    const NodeID m_id;
-    const int m_virtual_networks;
-    int m_vc_per_vnet;
-    std::vector<int> m_vc_allocator;
-    std::vector<OutputPort *> outPorts;
-    std::vector<InputPort *> inPorts;
-    int m_deadlock_threshold;
-    std::vector<OutVcState> outVcState;
-
-    std::vector<int> m_stall_count;
-
-    // Input Flit Buffers
-    // The flit buffers which will serve the Consumer
-    std::vector<flitBuffer>  niOutVcs;
-    std::vector<Tick> m_ni_out_vcs_enqueue_time;
-
-    // The Message buffers that takes messages from the protocol
-    std::vector<MessageBuffer *> inNode_ptr;
-    // The Message buffers that provides messages to the protocol
-    std::vector<MessageBuffer *> outNode_ptr;
-    // When a vc stays busy for a long time, it indicates a deadlock
-    std::vector<int> vc_busy_counter;
-
-    void checkStallQueue();
-    bool flitisizeMessage(MsgPtr msg_ptr, int vnet);
-    int calculateVC(int vnet);
-
-
-    void scheduleOutputPort(OutputPort *oPort);
-    void scheduleOutputLink();
-    void checkReschedule();
-
-    void incrementStats(flit *t_flit);
-
-    InputPort *getInportForVnet(int vnet);
-    OutputPort *getOutportForVnet(int vnet);
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_NETWORKINTERFACE_HH__
diff --git a/src/mem/ruby/network/garnet2.0/NetworkLink.cc b/src/mem/ruby/network/garnet2.0/NetworkLink.cc
deleted file mode 100644 (file)
index e947781..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-
-#include "base/trace.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-
-NetworkLink::NetworkLink(const Params *p)
-    : ClockedObject(p), Consumer(this), m_id(p->link_id),
-      m_type(NUM_LINK_TYPES_),
-      m_latency(p->link_latency), m_link_utilized(0),
-      m_virt_nets(p->virt_nets), linkBuffer(),
-      link_consumer(nullptr), link_srcQueue(nullptr)
-{
-    int num_vnets = (p->supported_vnets).size();
-    mVnets.resize(num_vnets);
-    bitWidth = p->width;
-    for (int i = 0; i < num_vnets; i++) {
-        mVnets[i] = p->supported_vnets[i];
-    }
-}
-
-void
-NetworkLink::setLinkConsumer(Consumer *consumer)
-{
-    link_consumer = consumer;
-}
-
-void
-NetworkLink::setVcsPerVnet(uint32_t consumerVcs)
-{
-    m_vc_load.resize(m_virt_nets * consumerVcs);
-}
-
-void
-NetworkLink::setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObj)
-{
-    link_srcQueue = src_queue;
-    src_object = srcClockObj;
-}
-
-void
-NetworkLink::wakeup()
-{
-    DPRINTF(RubyNetwork, "Woke up to transfer flits from %s\n",
-        src_object->name());
-    assert(link_srcQueue != nullptr);
-    assert(curTick() == clockEdge());
-    if (link_srcQueue->isReady(curTick())) {
-        flit *t_flit = link_srcQueue->getTopFlit();
-        DPRINTF(RubyNetwork, "Transmission will finish at %ld :%s\n",
-                clockEdge(m_latency), *t_flit);
-        if (m_type != NUM_LINK_TYPES_) {
-            // Only for assertions and debug messages
-            assert(t_flit->m_width == bitWidth);
-            assert((std::find(mVnets.begin(), mVnets.end(),
-                t_flit->get_vnet()) != mVnets.end()) ||
-                (mVnets.size() == 0));
-        }
-        t_flit->set_time(clockEdge(m_latency));
-        linkBuffer.insert(t_flit);
-        link_consumer->scheduleEventAbsolute(clockEdge(m_latency));
-        m_link_utilized++;
-        m_vc_load[t_flit->get_vc()]++;
-    }
-
-    if (!link_srcQueue->isEmpty()) {
-        scheduleEvent(Cycles(1));
-    }
-}
-
-void
-NetworkLink::resetStats()
-{
-    for (int i = 0; i < m_vc_load.size(); i++) {
-        m_vc_load[i] = 0;
-    }
-
-    m_link_utilized = 0;
-}
-
-NetworkLink *
-NetworkLinkParams::create()
-{
-    return new NetworkLink(this);
-}
-
-CreditLink *
-CreditLinkParams::create()
-{
-    return new CreditLink(this);
-}
-
-uint32_t
-NetworkLink::functionalWrite(Packet *pkt)
-{
-    return linkBuffer.functionalWrite(pkt);
-}
diff --git a/src/mem/ruby/network/garnet2.0/NetworkLink.hh b/src/mem/ruby/network/garnet2.0/NetworkLink.hh
deleted file mode 100644 (file)
index 9cf2efb..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_NETWORKLINK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_NETWORKLINK_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-#include "params/NetworkLink.hh"
-#include "sim/clocked_object.hh"
-
-class GarnetNetwork;
-
-class NetworkLink : public ClockedObject, public Consumer
-{
-  public:
-    typedef NetworkLinkParams Params;
-    NetworkLink(const Params *p);
-    ~NetworkLink() = default;
-
-    void setLinkConsumer(Consumer *consumer);
-    void setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObject);
-    virtual void setVcsPerVnet(uint32_t consumerVcs);
-    void setType(link_type type) { m_type = type; }
-    link_type getType() { return m_type; }
-    void print(std::ostream& out) const {}
-    int get_id() const { return m_id; }
-    flitBuffer *getBuffer() { return &linkBuffer;}
-    virtual void wakeup();
-
-    unsigned int getLinkUtilization() const { return m_link_utilized; }
-    const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; }
-
-    inline bool isReady(Tick curTime)
-    {
-        return linkBuffer.isReady(curTime);
-    }
-
-    inline flit* peekLink() { return linkBuffer.peekTopFlit(); }
-    inline flit* consumeLink() { return linkBuffer.getTopFlit(); }
-
-    uint32_t functionalWrite(Packet *);
-    void resetStats();
-
-    std::vector<int> mVnets;
-    uint32_t bitWidth;
-
-  private:
-    const int m_id;
-    link_type m_type;
-    const Cycles m_latency;
-
-    ClockedObject *src_object;
-
-    // Statistical variables
-    unsigned int m_link_utilized;
-    std::vector<unsigned int> m_vc_load;
-
-  protected:
-    uint32_t m_virt_nets;
-    flitBuffer linkBuffer;
-    Consumer *link_consumer;
-    flitBuffer *link_srcQueue;
-
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_NETWORKLINK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/OutVcState.cc b/src/mem/ruby/network/garnet2.0/OutVcState.cc
deleted file mode 100644 (file)
index 812038d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/OutVcState.hh"
-
-#include "mem/ruby/system/RubySystem.hh"
-
-OutVcState::OutVcState(int id, GarnetNetwork *network_ptr,
-    uint32_t consumerVcs)
-    : m_time(0)
-{
-    m_id = id;
-    m_vc_state = IDLE_;
-    /*
-     * We find the virtual network using the number of
-     * vcs per vnet. This assumes that the same vcs per
-     * vnet is used throughout the given object.
-     */
-    int vnet = floor(id/consumerVcs);
-
-    if (network_ptr->get_vnet_type(vnet) == DATA_VNET_)
-        m_max_credit_count = network_ptr->getBuffersPerDataVC();
-    else
-        m_max_credit_count = network_ptr->getBuffersPerCtrlVC();
-
-    m_credit_count = m_max_credit_count;
-    assert(m_credit_count >= 1);
-}
-
-void
-OutVcState::increment_credit()
-{
-    m_credit_count++;
-    assert(m_credit_count <= m_max_credit_count);
-}
-
-void
-OutVcState::decrement_credit()
-{
-    m_credit_count--;
-    assert(m_credit_count >= 0);
-}
diff --git a/src/mem/ruby/network/garnet2.0/OutVcState.hh b/src/mem/ruby/network/garnet2.0/OutVcState.hh
deleted file mode 100644 (file)
index 915c46f..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_OUTVCSTATE_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_OUTVCSTATE_HH__
-
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-
-class OutVcState
-{
-  public:
-    OutVcState(int id, GarnetNetwork *network_ptr, uint32_t consumerVcs);
-
-    int get_credit_count()          { return m_credit_count; }
-    inline bool has_credit()       { return (m_credit_count > 0); }
-    void increment_credit();
-    void decrement_credit();
-
-    inline bool
-    isInState(VC_state_type state, Tick request_time)
-    {
-        return ((m_vc_state == state) && (request_time >= m_time) );
-    }
-    inline void
-    setState(VC_state_type state, Tick time)
-    {
-        m_vc_state = state;
-        m_time = time;
-    }
-
-  private:
-    int m_id ;
-    Tick m_time;
-    VC_state_type m_vc_state;
-    int m_credit_count;
-    int m_max_credit_count;
-};
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_OUTVCSTATE_HH__
diff --git a/src/mem/ruby/network/garnet2.0/OutputUnit.cc b/src/mem/ruby/network/garnet2.0/OutputUnit.cc
deleted file mode 100644 (file)
index dfa63e3..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-OutputUnit::OutputUnit(int id, PortDirection direction, Router *router,
-  uint32_t consumerVcs)
-  : Consumer(router), m_router(router), m_id(id), m_direction(direction),
-    m_vc_per_vnet(consumerVcs)
-{
-    const int m_num_vcs = consumerVcs * m_router->get_num_vnets();
-    outVcState.reserve(m_num_vcs);
-    for (int i = 0; i < m_num_vcs; i++) {
-        outVcState.emplace_back(i, m_router->get_net_ptr(), consumerVcs);
-    }
-}
-
-void
-OutputUnit::decrement_credit(int out_vc)
-{
-    DPRINTF(RubyNetwork, "Router %d OutputUnit %s decrementing credit:%d for "
-            "outvc %d at time: %lld for %s\n", m_router->get_id(),
-            m_router->getPortDirectionName(get_direction()),
-            outVcState[out_vc].get_credit_count(),
-            out_vc, m_router->curCycle(), m_credit_link->name());
-
-    outVcState[out_vc].decrement_credit();
-}
-
-void
-OutputUnit::increment_credit(int out_vc)
-{
-    DPRINTF(RubyNetwork, "Router %d OutputUnit %s incrementing credit:%d for "
-            "outvc %d at time: %lld from:%s\n", m_router->get_id(),
-            m_router->getPortDirectionName(get_direction()),
-            outVcState[out_vc].get_credit_count(),
-            out_vc, m_router->curCycle(), m_credit_link->name());
-
-    outVcState[out_vc].increment_credit();
-}
-
-// Check if the output VC (i.e., input VC at next router)
-// has free credits (i..e, buffer slots).
-// This is tracked by OutVcState
-bool
-OutputUnit::has_credit(int out_vc)
-{
-    assert(outVcState[out_vc].isInState(ACTIVE_, curTick()));
-    return outVcState[out_vc].has_credit();
-}
-
-
-// Check if the output port (i.e., input port at next router) has free VCs.
-bool
-OutputUnit::has_free_vc(int vnet)
-{
-    int vc_base = vnet*m_vc_per_vnet;
-    for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
-        if (is_vc_idle(vc, curTick()))
-            return true;
-    }
-
-    return false;
-}
-
-// Assign a free output VC to the winner of Switch Allocation
-int
-OutputUnit::select_free_vc(int vnet)
-{
-    int vc_base = vnet*m_vc_per_vnet;
-    for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
-        if (is_vc_idle(vc, curTick())) {
-            outVcState[vc].setState(ACTIVE_, curTick());
-            return vc;
-        }
-    }
-
-    return -1;
-}
-
-/*
- * The wakeup function of the OutputUnit reads the credit signal from the
- * downstream router for the output VC (i.e., input VC at downstream router).
- * It increments the credit count in the appropriate output VC state.
- * If the credit carries is_free_signal as true,
- * the output VC is marked IDLE.
- */
-
-void
-OutputUnit::wakeup()
-{
-    if (m_credit_link->isReady(curTick())) {
-        Credit *t_credit = (Credit*) m_credit_link->consumeLink();
-        increment_credit(t_credit->get_vc());
-
-        if (t_credit->is_free_signal())
-            set_vc_state(IDLE_, t_credit->get_vc(), curTick());
-
-        delete t_credit;
-
-        if (m_credit_link->isReady(curTick())) {
-            scheduleEvent(Cycles(1));
-        }
-    }
-}
-
-flitBuffer*
-OutputUnit::getOutQueue()
-{
-    return &outBuffer;
-}
-
-void
-OutputUnit::set_out_link(NetworkLink *link)
-{
-    m_out_link = link;
-}
-
-void
-OutputUnit::set_credit_link(CreditLink *credit_link)
-{
-    m_credit_link = credit_link;
-}
-
-void
-OutputUnit::insert_flit(flit *t_flit)
-{
-    outBuffer.insert(t_flit);
-    m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
-}
-
-uint32_t
-OutputUnit::functionalWrite(Packet *pkt)
-{
-    return outBuffer.functionalWrite(pkt);
-}
diff --git a/src/mem/ruby/network/garnet2.0/OutputUnit.hh b/src/mem/ruby/network/garnet2.0/OutputUnit.hh
deleted file mode 100644 (file)
index 3e80dde..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_OUTPUTUNIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_OUTPUTUNIT_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "base/compiler.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/OutVcState.hh"
-
-class CreditLink;
-class Router;
-
-class OutputUnit : public Consumer
-{
-  public:
-    OutputUnit(int id, PortDirection direction, Router *router,
-               uint32_t consumerVcs);
-    ~OutputUnit() = default;
-    void set_out_link(NetworkLink *link);
-    void set_credit_link(CreditLink *credit_link);
-    void wakeup();
-    flitBuffer* getOutQueue();
-    void print(std::ostream& out) const {};
-    void decrement_credit(int out_vc);
-    void increment_credit(int out_vc);
-    bool has_credit(int out_vc);
-    bool has_free_vc(int vnet);
-    int select_free_vc(int vnet);
-
-    inline PortDirection get_direction() { return m_direction; }
-
-    int
-    get_credit_count(int vc)
-    {
-        return outVcState[vc].get_credit_count();
-    }
-
-    inline int
-    get_outlink_id()
-    {
-        return m_out_link->get_id();
-    }
-
-    inline void
-    set_vc_state(VC_state_type state, int vc, Tick curTime)
-    {
-      outVcState[vc].setState(state, curTime);
-    }
-
-    inline bool
-    is_vc_idle(int vc, Tick curTime)
-    {
-        return (outVcState[vc].isInState(IDLE_, curTime));
-    }
-
-    void insert_flit(flit *t_flit);
-
-    inline int
-    getVcsPerVnet()
-    {
-        return m_vc_per_vnet;
-    }
-
-    uint32_t functionalWrite(Packet *pkt);
-
-  private:
-    Router *m_router;
-    int M5_CLASS_VAR_USED m_id;
-    PortDirection m_direction;
-    int m_vc_per_vnet;
-    NetworkLink *m_out_link;
-    CreditLink *m_credit_link;
-
-    // This is for the network link to consume
-    flitBuffer outBuffer;
-    // vc state of downstream router
-    std::vector<OutVcState> outVcState;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_OUTPUTUNIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/README.txt b/src/mem/ruby/network/garnet2.0/README.txt
deleted file mode 100644 (file)
index 817b1d4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-README for Garnet2.0
-Written By: Tushar Krishna (tushar@ece.gatech.edu)
-Last Updated: Jul 9, 2016
--------------------------------------------------------
-
-Garnet Network Parameters and Setup:
-- GarnetNetwork.py
-    * defaults can be overwritten from command line (see configs/network/Network.py)
-- GarnetNetwork.hh/cc
-    * sets up the routers and links
-    * collects stats
-
-
-CODE FLOW
-- NetworkInterface.cc::wakeup()
-    * Every NI connected to one coherence protocol controller on one end, and one router on the other.
-    * receives messages from coherence protocol buffer in appropriate vnet and converts them into network packets and sends them into the network.
-        * garnet2.0 adds the ability to capture a network trace at this point.
-    * receives flits from the network, extracts the protocol message and sends it to the coherence protocol buffer in appropriate vnet.
-    * manages flow-control (i.e., credits) with its attached router.
-    * The consuming flit/credit output link of the NI is put in the global event queue with a timestamp set to next cycle.
-      The eventqueue calls the wakeup function in the consumer.
-
-- NetworkLink.cc::wakeup()
-    * receives flits from NI/router and sends it to NI/router after m_latency cycles delay
-        * Default latency value for every link can be set from command line (see configs/network/Network.py)
-        * Per link latency can be overwritten in the topology file
-    * The consumer of the link (NI/router) is put in the global event queue with a timestamp set after m_latency cycles.
-      The eventqueue calls the wakeup function in the consumer.
-
-- Router.cc::wakeup()
-    * Loop through all InputUnits and call their wakeup()
-    * Loop through all OutputUnits and call their wakeup()
-    * Call SwitchAllocator's wakeup()
-    * Call CrossbarSwitch's wakeup()
-    * The router's wakeup function is called whenever any of its modules (InputUnit, OutputUnit, SwitchAllocator, CrossbarSwitch) have
-      a ready flit/credit to act upon this cycle.
-
-- InputUnit.cc::wakeup()
-    * Read input flit from upstream router if it is ready for this cycle
-    * For HEAD/HEAD_TAIL flits, perform route computation, and update route in the VC.
-    * Buffer the flit for (m_latency - 1) cycles and mark it valid for SwitchAllocation starting that cycle.
-        * Default latency for every router can be set from command line (see configs/network/Network.py)
-        * Per router latency (i.e., num pipeline stages) can be set in the topology file
-
-- OutputUnit.cc::wakeup()
-    * Read input credit from downstream router if it is ready for this cycle
-    * Increment the credit in the appropriate output VC state.
-    * Mark output VC as free if the credit carries is_free_signal as true
-
-- SwitchAllocator.cc::wakeup()
-    * Note: SwitchAllocator performs VC arbitration and selection within it.
-    * SA-I (or SA-i): Loop through all input VCs at every input port, and select one in a round robin manner.
-        * For HEAD/HEAD_TAIL flits only select an input VC whose output port has at least one free output VC.
-        * For BODY/TAIL flits, only select an input VC that has credits in its output VC.
-    * Place a request for the output port from this VC.
-    * SA-II (or SA-o): Loop through all output ports, and select one input VC (that placed a request during SA-I) as the winner for this output port in a round robin manner.
-        * For HEAD/HEAD_TAIL flits, perform outvc allocation (i.e., select a free VC from the output port).
-        * For BODY/TAIL flits, decrement a credit in the output vc.
-    * Read the flit out from the input VC, and send it to the CrossbarSwitch
-    * Send a increment_credit signal to the upstream router for this input VC.
-        * for HEAD_TAIL/TAIL flits, mark is_free_signal as true in the credit.
-        * The input unit sends the credit out on the credit link to the upstream router.
-    * Reschedule the Router to wakeup next cycle for any flits ready for SA next cycle.
-
-- CrossbarSwitch.cc::wakeup()
-    * Loop through all input ports, and send the winning flit out of its output port onto the output link.
-    * The consuming flit output link of the router is put in the global event queue with a timestamp set to next cycle.
-      The eventqueue calls the wakeup function in the consumer.
-
-
diff --git a/src/mem/ruby/network/garnet2.0/Router.cc b/src/mem/ruby/network/garnet2.0/Router.cc
deleted file mode 100644 (file)
index 9802b69..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-
-using namespace std;
-
-Router::Router(const Params *p)
-  : BasicRouter(p), Consumer(this), m_latency(p->latency),
-    m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
-    m_num_vcs(m_virtual_networks * m_vc_per_vnet), m_bit_width(p->width),
-    m_network_ptr(nullptr), routingUnit(this), switchAllocator(this),
-    crossbarSwitch(this)
-{
-    m_input_unit.clear();
-    m_output_unit.clear();
-}
-
-void
-Router::init()
-{
-    BasicRouter::init();
-
-    switchAllocator.init();
-    crossbarSwitch.init();
-}
-
-void
-Router::wakeup()
-{
-    DPRINTF(RubyNetwork, "Router %d woke up\n", m_id);
-    assert(clockEdge() == curTick());
-
-    // check for incoming flits
-    for (int inport = 0; inport < m_input_unit.size(); inport++) {
-        m_input_unit[inport]->wakeup();
-    }
-
-    // check for incoming credits
-    // Note: the credit update is happening before SA
-    // buffer turnaround time =
-    //     credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
-    // if we want the credit update to take place after SA, this loop should
-    // be moved after the SA request
-    for (int outport = 0; outport < m_output_unit.size(); outport++) {
-        m_output_unit[outport]->wakeup();
-    }
-
-    // Switch Allocation
-    switchAllocator.wakeup();
-
-    // Switch Traversal
-    crossbarSwitch.wakeup();
-}
-
-void
-Router::addInPort(PortDirection inport_dirn,
-                  NetworkLink *in_link, CreditLink *credit_link)
-{
-    fatal_if(in_link->bitWidth != m_bit_width, "Widths of link %s(%d)does"
-            " not match that of Router%d(%d). Consider inserting SerDes "
-            "Units.", in_link->name(), in_link->bitWidth, m_id, m_bit_width);
-
-    int port_num = m_input_unit.size();
-    InputUnit *input_unit = new InputUnit(port_num, inport_dirn, this);
-
-    input_unit->set_in_link(in_link);
-    input_unit->set_credit_link(credit_link);
-    in_link->setLinkConsumer(this);
-    in_link->setVcsPerVnet(get_vc_per_vnet());
-    credit_link->setSourceQueue(input_unit->getCreditQueue(), this);
-    credit_link->setVcsPerVnet(get_vc_per_vnet());
-
-    m_input_unit.push_back(std::shared_ptr<InputUnit>(input_unit));
-
-    routingUnit.addInDirection(inport_dirn, port_num);
-}
-
-void
-Router::addOutPort(PortDirection outport_dirn,
-                   NetworkLink *out_link,
-                   std::vector<NetDest>& routing_table_entry, int link_weight,
-                   CreditLink *credit_link, uint32_t consumerVcs)
-{
-    fatal_if(out_link->bitWidth != m_bit_width, "Widths of units do not match."
-            " Consider inserting SerDes Units");
-
-    int port_num = m_output_unit.size();
-    OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this,
-                                             consumerVcs);
-
-    output_unit->set_out_link(out_link);
-    output_unit->set_credit_link(credit_link);
-    credit_link->setLinkConsumer(this);
-    credit_link->setVcsPerVnet(consumerVcs);
-    out_link->setSourceQueue(output_unit->getOutQueue(), this);
-    out_link->setVcsPerVnet(consumerVcs);
-
-    m_output_unit.push_back(std::shared_ptr<OutputUnit>(output_unit));
-
-    routingUnit.addRoute(routing_table_entry);
-    routingUnit.addWeight(link_weight);
-    routingUnit.addOutDirection(outport_dirn, port_num);
-}
-
-PortDirection
-Router::getOutportDirection(int outport)
-{
-    return m_output_unit[outport]->get_direction();
-}
-
-PortDirection
-Router::getInportDirection(int inport)
-{
-    return m_input_unit[inport]->get_direction();
-}
-
-int
-Router::route_compute(RouteInfo route, int inport, PortDirection inport_dirn)
-{
-    return routingUnit.outportCompute(route, inport, inport_dirn);
-}
-
-void
-Router::grant_switch(int inport, flit *t_flit)
-{
-    crossbarSwitch.update_sw_winner(inport, t_flit);
-}
-
-void
-Router::schedule_wakeup(Cycles time)
-{
-    // wake up after time cycles
-    scheduleEvent(time);
-}
-
-std::string
-Router::getPortDirectionName(PortDirection direction)
-{
-    // PortDirection is actually a string
-    // If not, then this function should add a switch
-    // statement to convert direction to a string
-    // that can be printed out
-    return direction;
-}
-
-void
-Router::regStats()
-{
-    BasicRouter::regStats();
-
-    m_buffer_reads
-        .name(name() + ".buffer_reads")
-        .flags(Stats::nozero)
-    ;
-
-    m_buffer_writes
-        .name(name() + ".buffer_writes")
-        .flags(Stats::nozero)
-    ;
-
-    m_crossbar_activity
-        .name(name() + ".crossbar_activity")
-        .flags(Stats::nozero)
-    ;
-
-    m_sw_input_arbiter_activity
-        .name(name() + ".sw_input_arbiter_activity")
-        .flags(Stats::nozero)
-    ;
-
-    m_sw_output_arbiter_activity
-        .name(name() + ".sw_output_arbiter_activity")
-        .flags(Stats::nozero)
-    ;
-}
-
-void
-Router::collateStats()
-{
-    for (int j = 0; j < m_virtual_networks; j++) {
-        for (int i = 0; i < m_input_unit.size(); i++) {
-            m_buffer_reads += m_input_unit[i]->get_buf_read_activity(j);
-            m_buffer_writes += m_input_unit[i]->get_buf_write_activity(j);
-        }
-    }
-
-    m_sw_input_arbiter_activity = switchAllocator.get_input_arbiter_activity();
-    m_sw_output_arbiter_activity =
-        switchAllocator.get_output_arbiter_activity();
-    m_crossbar_activity = crossbarSwitch.get_crossbar_activity();
-}
-
-void
-Router::resetStats()
-{
-    for (int i = 0; i < m_input_unit.size(); i++) {
-            m_input_unit[i]->resetStats();
-    }
-
-    crossbarSwitch.resetStats();
-    switchAllocator.resetStats();
-}
-
-void
-Router::printFaultVector(ostream& out)
-{
-    int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
-    int num_fault_types = m_network_ptr->fault_model->number_of_fault_types;
-    float fault_vector[num_fault_types];
-    get_fault_vector(temperature_celcius, fault_vector);
-    out << "Router-" << m_id << " fault vector: " << endl;
-    for (int fault_type_index = 0; fault_type_index < num_fault_types;
-         fault_type_index++) {
-        out << " - probability of (";
-        out <<
-        m_network_ptr->fault_model->fault_type_to_string(fault_type_index);
-        out << ") = ";
-        out << fault_vector[fault_type_index] << endl;
-    }
-}
-
-void
-Router::printAggregateFaultProbability(std::ostream& out)
-{
-    int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
-    float aggregate_fault_prob;
-    get_aggregate_fault_probability(temperature_celcius,
-                                    &aggregate_fault_prob);
-    out << "Router-" << m_id << " fault probability: ";
-    out << aggregate_fault_prob << endl;
-}
-
-uint32_t
-Router::functionalWrite(Packet *pkt)
-{
-    uint32_t num_functional_writes = 0;
-    num_functional_writes += crossbarSwitch.functionalWrite(pkt);
-
-    for (uint32_t i = 0; i < m_input_unit.size(); i++) {
-        num_functional_writes += m_input_unit[i]->functionalWrite(pkt);
-    }
-
-    for (uint32_t i = 0; i < m_output_unit.size(); i++) {
-        num_functional_writes += m_output_unit[i]->functionalWrite(pkt);
-    }
-
-    return num_functional_writes;
-}
-
-Router *
-GarnetRouterParams::create()
-{
-    return new Router(this);
-}
diff --git a/src/mem/ruby/network/garnet2.0/Router.hh b/src/mem/ruby/network/garnet2.0/Router.hh
deleted file mode 100644 (file)
index 312ab4d..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_ROUTER_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_ROUTER_HH__
-
-#include <iostream>
-#include <memory>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/ruby/network/BasicRouter.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
-#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-#include "params/GarnetRouter.hh"
-
-class NetworkLink;
-class CreditLink;
-class InputUnit;
-class OutputUnit;
-class FaultModel;
-
-class Router : public BasicRouter, public Consumer
-{
-  public:
-    typedef GarnetRouterParams Params;
-    Router(const Params *p);
-
-    ~Router() = default;
-
-    void wakeup();
-    void print(std::ostream& out) const {};
-
-    void init();
-    void addInPort(PortDirection inport_dirn, NetworkLink *link,
-                   CreditLink *credit_link);
-    void addOutPort(PortDirection outport_dirn, NetworkLink *link,
-                    std::vector<NetDest>& routing_table_entry,
-                    int link_weight, CreditLink *credit_link,
-                    uint32_t consumerVcs);
-
-    Cycles get_pipe_stages(){ return m_latency; }
-    uint32_t get_num_vcs()       { return m_num_vcs; }
-    uint32_t get_num_vnets()     { return m_virtual_networks; }
-    uint32_t get_vc_per_vnet()   { return m_vc_per_vnet; }
-    int get_num_inports()   { return m_input_unit.size(); }
-    int get_num_outports()  { return m_output_unit.size(); }
-    int get_id()            { return m_id; }
-
-    void init_net_ptr(GarnetNetwork* net_ptr)
-    {
-        m_network_ptr = net_ptr;
-    }
-
-    GarnetNetwork* get_net_ptr()                    { return m_network_ptr; }
-
-    InputUnit*
-    getInputUnit(unsigned port)
-    {
-        assert(port < m_input_unit.size());
-        return m_input_unit[port].get();
-    }
-
-    OutputUnit*
-    getOutputUnit(unsigned port)
-    {
-        assert(port < m_output_unit.size());
-        return m_output_unit[port].get();
-    }
-
-    int getBitWidth() { return m_bit_width; }
-
-    PortDirection getOutportDirection(int outport);
-    PortDirection getInportDirection(int inport);
-
-    int route_compute(RouteInfo route, int inport, PortDirection direction);
-    void grant_switch(int inport, flit *t_flit);
-    void schedule_wakeup(Cycles time);
-
-    std::string getPortDirectionName(PortDirection direction);
-    void printFaultVector(std::ostream& out);
-    void printAggregateFaultProbability(std::ostream& out);
-
-    void regStats();
-    void collateStats();
-    void resetStats();
-
-    // For Fault Model:
-    bool get_fault_vector(int temperature, float fault_vector[]) {
-        return m_network_ptr->fault_model->fault_vector(m_id, temperature,
-                                                        fault_vector);
-    }
-    bool get_aggregate_fault_probability(int temperature,
-                                         float *aggregate_fault_prob) {
-        return m_network_ptr->fault_model->fault_prob(m_id, temperature,
-                                                      aggregate_fault_prob);
-    }
-
-    uint32_t functionalWrite(Packet *);
-
-  private:
-    Cycles m_latency;
-    uint32_t m_virtual_networks, m_vc_per_vnet, m_num_vcs;
-    uint32_t m_bit_width;
-    GarnetNetwork *m_network_ptr;
-
-    RoutingUnit routingUnit;
-    SwitchAllocator switchAllocator;
-    CrossbarSwitch crossbarSwitch;
-
-    std::vector<std::shared_ptr<InputUnit>> m_input_unit;
-    std::vector<std::shared_ptr<OutputUnit>> m_output_unit;
-
-    // Statistical variables required for power computations
-    Stats::Scalar m_buffer_reads;
-    Stats::Scalar m_buffer_writes;
-
-    Stats::Scalar m_sw_input_arbiter_activity;
-    Stats::Scalar m_sw_output_arbiter_activity;
-
-    Stats::Scalar m_crossbar_activity;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_ROUTER_HH__
diff --git a/src/mem/ruby/network/garnet2.0/RoutingUnit.cc b/src/mem/ruby/network/garnet2.0/RoutingUnit.cc
deleted file mode 100644 (file)
index 5ba0dec..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
-
-#include "base/cast.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-RoutingUnit::RoutingUnit(Router *router)
-{
-    m_router = router;
-    m_routing_table.clear();
-    m_weight_table.clear();
-}
-
-void
-RoutingUnit::addRoute(std::vector<NetDest>& routing_table_entry)
-{
-    if (routing_table_entry.size() > m_routing_table.size()) {
-        m_routing_table.resize(routing_table_entry.size());
-    }
-    for (int v = 0; v < routing_table_entry.size(); v++) {
-        m_routing_table[v].push_back(routing_table_entry[v]);
-    }
-}
-
-void
-RoutingUnit::addWeight(int link_weight)
-{
-    m_weight_table.push_back(link_weight);
-}
-
-bool
-RoutingUnit::supportsVnet(int vnet, std::vector<int> sVnets)
-{
-    // If all vnets are supported, return true
-    if (sVnets.size() == 0) {
-        return true;
-    }
-
-    // Find the vnet in the vector, return true
-    if (std::find(sVnets.begin(), sVnets.end(), vnet) != sVnets.end()) {
-        return true;
-    }
-
-    // Not supported vnet
-    return false;
-}
-
-/*
- * This is the default routing algorithm in garnet.
- * The routing table is populated during topology creation.
- * Routes can be biased via weight assignments in the topology file.
- * Correct weight assignments are critical to provide deadlock avoidance.
- */
-int
-RoutingUnit::lookupRoutingTable(int vnet, NetDest msg_destination)
-{
-    // First find all possible output link candidates
-    // For ordered vnet, just choose the first
-    // (to make sure different packets don't choose different routes)
-    // For unordered vnet, randomly choose any of the links
-    // To have a strict ordering between links, they should be given
-    // different weights in the topology file
-
-    int output_link = -1;
-    int min_weight = INFINITE_;
-    std::vector<int> output_link_candidates;
-    int num_candidates = 0;
-
-    // Identify the minimum weight among the candidate output links
-    for (int link = 0; link < m_routing_table[vnet].size(); link++) {
-        if (msg_destination.intersectionIsNotEmpty(
-            m_routing_table[vnet][link])) {
-
-        if (m_weight_table[link] <= min_weight)
-            min_weight = m_weight_table[link];
-        }
-    }
-
-    // Collect all candidate output links with this minimum weight
-    for (int link = 0; link < m_routing_table[vnet].size(); link++) {
-        if (msg_destination.intersectionIsNotEmpty(
-            m_routing_table[vnet][link])) {
-
-            if (m_weight_table[link] == min_weight) {
-                num_candidates++;
-                output_link_candidates.push_back(link);
-            }
-        }
-    }
-
-    if (output_link_candidates.size() == 0) {
-        fatal("Fatal Error:: No Route exists from this Router.");
-        exit(0);
-    }
-
-    // Randomly select any candidate output link
-    int candidate = 0;
-    if (!(m_router->get_net_ptr())->isVNetOrdered(vnet))
-        candidate = rand() % num_candidates;
-
-    output_link = output_link_candidates.at(candidate);
-    return output_link;
-}
-
-
-void
-RoutingUnit::addInDirection(PortDirection inport_dirn, int inport_idx)
-{
-    m_inports_dirn2idx[inport_dirn] = inport_idx;
-    m_inports_idx2dirn[inport_idx]  = inport_dirn;
-}
-
-void
-RoutingUnit::addOutDirection(PortDirection outport_dirn, int outport_idx)
-{
-    m_outports_dirn2idx[outport_dirn] = outport_idx;
-    m_outports_idx2dirn[outport_idx]  = outport_dirn;
-}
-
-// outportCompute() is called by the InputUnit
-// It calls the routing table by default.
-// A template for adaptive topology-specific routing algorithm
-// implementations using port directions rather than a static routing
-// table is provided here.
-
-int
-RoutingUnit::outportCompute(RouteInfo route, int inport,
-                            PortDirection inport_dirn)
-{
-    int outport = -1;
-
-    if (route.dest_router == m_router->get_id()) {
-
-        // Multiple NIs may be connected to this router,
-        // all with output port direction = "Local"
-        // Get exact outport id from table
-        outport = lookupRoutingTable(route.vnet, route.net_dest);
-        return outport;
-    }
-
-    // Routing Algorithm set in GarnetNetwork.py
-    // Can be over-ridden from command line using --routing-algorithm = 1
-    RoutingAlgorithm routing_algorithm =
-        (RoutingAlgorithm) m_router->get_net_ptr()->getRoutingAlgorithm();
-
-    switch (routing_algorithm) {
-        case TABLE_:  outport =
-            lookupRoutingTable(route.vnet, route.net_dest); break;
-        case XY_:     outport =
-            outportComputeXY(route, inport, inport_dirn); break;
-        // any custom algorithm
-        case CUSTOM_: outport =
-            outportComputeCustom(route, inport, inport_dirn); break;
-        default: outport =
-            lookupRoutingTable(route.vnet, route.net_dest); break;
-    }
-
-    assert(outport != -1);
-    return outport;
-}
-
-// XY routing implemented using port directions
-// Only for reference purpose in a Mesh
-// By default Garnet uses the routing table
-int
-RoutingUnit::outportComputeXY(RouteInfo route,
-                              int inport,
-                              PortDirection inport_dirn)
-{
-    PortDirection outport_dirn = "Unknown";
-
-    int M5_VAR_USED num_rows = m_router->get_net_ptr()->getNumRows();
-    int num_cols = m_router->get_net_ptr()->getNumCols();
-    assert(num_rows > 0 && num_cols > 0);
-
-    int my_id = m_router->get_id();
-    int my_x = my_id % num_cols;
-    int my_y = my_id / num_cols;
-
-    int dest_id = route.dest_router;
-    int dest_x = dest_id % num_cols;
-    int dest_y = dest_id / num_cols;
-
-    int x_hops = abs(dest_x - my_x);
-    int y_hops = abs(dest_y - my_y);
-
-    bool x_dirn = (dest_x >= my_x);
-    bool y_dirn = (dest_y >= my_y);
-
-    // already checked that in outportCompute() function
-    assert(!(x_hops == 0 && y_hops == 0));
-
-    if (x_hops > 0) {
-        if (x_dirn) {
-            assert(inport_dirn == "Local" || inport_dirn == "West");
-            outport_dirn = "East";
-        } else {
-            assert(inport_dirn == "Local" || inport_dirn == "East");
-            outport_dirn = "West";
-        }
-    } else if (y_hops > 0) {
-        if (y_dirn) {
-            // "Local" or "South" or "West" or "East"
-            assert(inport_dirn != "North");
-            outport_dirn = "North";
-        } else {
-            // "Local" or "North" or "West" or "East"
-            assert(inport_dirn != "South");
-            outport_dirn = "South";
-        }
-    } else {
-        // x_hops == 0 and y_hops == 0
-        // this is not possible
-        // already checked that in outportCompute() function
-        panic("x_hops == y_hops == 0");
-    }
-
-    return m_outports_dirn2idx[outport_dirn];
-}
-
-// Template for implementing custom routing algorithm
-// using port directions. (Example adaptive)
-int
-RoutingUnit::outportComputeCustom(RouteInfo route,
-                                 int inport,
-                                 PortDirection inport_dirn)
-{
-    panic("%s placeholder executed", __FUNCTION__);
-}
diff --git a/src/mem/ruby/network/garnet2.0/RoutingUnit.hh b/src/mem/ruby/network/garnet2.0/RoutingUnit.hh
deleted file mode 100644 (file)
index a0ed901..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_ROUTINGUNIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_ROUTINGUNIT_HH__
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-class InputUnit;
-class Router;
-
-class RoutingUnit
-{
-  public:
-    RoutingUnit(Router *router);
-    int outportCompute(RouteInfo route,
-                      int inport,
-                      PortDirection inport_dirn);
-
-    // Topology-agnostic Routing Table based routing (default)
-    void addRoute(std::vector<NetDest>& routing_table_entry);
-    void addWeight(int link_weight);
-
-    // get output port from routing table
-    int  lookupRoutingTable(int vnet, NetDest net_dest);
-
-    // Topology-specific direction based routing
-    void addInDirection(PortDirection inport_dirn, int inport);
-    void addOutDirection(PortDirection outport_dirn, int outport);
-
-    // Routing for Mesh
-    int outportComputeXY(RouteInfo route,
-                         int inport,
-                         PortDirection inport_dirn);
-
-    // Custom Routing Algorithm using Port Directions
-    int outportComputeCustom(RouteInfo route,
-                             int inport,
-                             PortDirection inport_dirn);
-
-    // Returns true if vnet is present in the vector
-    // of vnets or if the vector supports all vnets.
-    bool supportsVnet(int vnet, std::vector<int> sVnets);
-
-
-  private:
-    Router *m_router;
-
-    // Routing Table
-    std::vector<std::vector<NetDest>> m_routing_table;
-    std::vector<int> m_weight_table;
-
-    // Inport and Outport direction to idx maps
-    std::map<PortDirection, int> m_inports_dirn2idx;
-    std::map<int, PortDirection> m_inports_idx2dirn;
-    std::map<int, PortDirection> m_outports_idx2dirn;
-    std::map<PortDirection, int> m_outports_dirn2idx;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_ROUTINGUNIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/SConscript b/src/mem/ruby/network/garnet2.0/SConscript
deleted file mode 100644 (file)
index e3bc110..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2016 Georgia Institute of Technology
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Import('*')
-
-if env['PROTOCOL'] == 'None':
-    Return()
-
-SimObject('GarnetLink.py')
-SimObject('GarnetNetwork.py')
-
-Source('GarnetLink.cc')
-Source('GarnetNetwork.cc')
-Source('InputUnit.cc')
-Source('NetworkInterface.cc')
-Source('NetworkLink.cc')
-Source('OutVcState.cc')
-Source('OutputUnit.cc')
-Source('Router.cc')
-Source('RoutingUnit.cc')
-Source('SwitchAllocator.cc')
-Source('CrossbarSwitch.cc')
-Source('VirtualChannel.cc')
-Source('flitBuffer.cc')
-Source('flit.cc')
-Source('Credit.cc')
-Source('NetworkBridge.cc')
diff --git a/src/mem/ruby/network/garnet2.0/SwitchAllocator.cc b/src/mem/ruby/network/garnet2.0/SwitchAllocator.cc
deleted file mode 100644 (file)
index 1ed6de1..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-SwitchAllocator::SwitchAllocator(Router *router)
-    : Consumer(router)
-{
-    m_router = router;
-    m_num_vcs = m_router->get_num_vcs();
-    m_vc_per_vnet = m_router->get_vc_per_vnet();
-
-    m_input_arbiter_activity = 0;
-    m_output_arbiter_activity = 0;
-}
-
-void
-SwitchAllocator::init()
-{
-    m_num_inports = m_router->get_num_inports();
-    m_num_outports = m_router->get_num_outports();
-    m_round_robin_inport.resize(m_num_outports);
-    m_round_robin_invc.resize(m_num_inports);
-    m_port_requests.resize(m_num_outports);
-    m_vc_winners.resize(m_num_outports);
-
-    for (int i = 0; i < m_num_inports; i++) {
-        m_round_robin_invc[i] = 0;
-    }
-
-    for (int i = 0; i < m_num_outports; i++) {
-        m_port_requests[i].resize(m_num_inports);
-        m_vc_winners[i].resize(m_num_inports);
-
-        m_round_robin_inport[i] = 0;
-
-        for (int j = 0; j < m_num_inports; j++) {
-            m_port_requests[i][j] = false; // [outport][inport]
-        }
-    }
-}
-
-/*
- * The wakeup function of the SwitchAllocator performs a 2-stage
- * seperable switch allocation. At the end of the 2nd stage, a free
- * output VC is assigned to the winning flits of each output port.
- * There is no separate VCAllocator stage like the one in garnet1.0.
- * At the end of this function, the router is rescheduled to wakeup
- * next cycle for peforming SA for any flits ready next cycle.
- */
-
-void
-SwitchAllocator::wakeup()
-{
-    arbitrate_inports(); // First stage of allocation
-    arbitrate_outports(); // Second stage of allocation
-
-    clear_request_vector();
-    check_for_wakeup();
-}
-
-/*
- * SA-I (or SA-i) loops through all input VCs at every input port,
- * and selects one in a round robin manner.
- *    - For HEAD/HEAD_TAIL flits only selects an input VC whose output port
- *     has at least one free output VC.
- *    - For BODY/TAIL flits, only selects an input VC that has credits
- *      in its output VC.
- * Places a request for the output port from this input VC.
- */
-
-void
-SwitchAllocator::arbitrate_inports()
-{
-    // Select a VC from each input in a round robin manner
-    // Independent arbiter at each input port
-    for (int inport = 0; inport < m_num_inports; inport++) {
-        int invc = m_round_robin_invc[inport];
-
-        for (int invc_iter = 0; invc_iter < m_num_vcs; invc_iter++) {
-            auto input_unit = m_router->getInputUnit(inport);
-
-            if (input_unit->need_stage(invc, SA_, curTick())) {
-                // This flit is in SA stage
-
-                int outport = input_unit->get_outport(invc);
-                int outvc = input_unit->get_outvc(invc);
-
-                // check if the flit in this InputVC is allowed to be sent
-                // send_allowed conditions described in that function.
-                bool make_request =
-                    send_allowed(inport, invc, outport, outvc);
-
-                if (make_request) {
-                    m_input_arbiter_activity++;
-                    m_port_requests[outport][inport] = true;
-                    m_vc_winners[outport][inport]= invc;
-
-                    break; // got one vc winner for this port
-                }
-            }
-
-            invc++;
-            if (invc >= m_num_vcs)
-                invc = 0;
-        }
-    }
-}
-
-/*
- * SA-II (or SA-o) loops through all output ports,
- * and selects one input VC (that placed a request during SA-I)
- * as the winner for this output port in a round robin manner.
- *      - For HEAD/HEAD_TAIL flits, performs simplified outvc allocation.
- *        (i.e., select a free VC from the output port).
- *      - For BODY/TAIL flits, decrement a credit in the output vc.
- * The winning flit is read out from the input VC and sent to the
- * CrossbarSwitch.
- * An increment_credit signal is sent from the InputUnit
- * to the upstream router. For HEAD_TAIL/TAIL flits, is_free_signal in the
- * credit is set to true.
- */
-
-void
-SwitchAllocator::arbitrate_outports()
-{
-    // Now there are a set of input vc requests for output vcs.
-    // Again do round robin arbitration on these requests
-    // Independent arbiter at each output port
-    for (int outport = 0; outport < m_num_outports; outport++) {
-        int inport = m_round_robin_inport[outport];
-
-        for (int inport_iter = 0; inport_iter < m_num_inports;
-                 inport_iter++) {
-
-            // inport has a request this cycle for outport
-            if (m_port_requests[outport][inport]) {
-                auto output_unit = m_router->getOutputUnit(outport);
-                auto input_unit = m_router->getInputUnit(inport);
-
-                // grant this outport to this inport
-                int invc = m_vc_winners[outport][inport];
-
-                int outvc = input_unit->get_outvc(invc);
-                if (outvc == -1) {
-                    // VC Allocation - select any free VC from outport
-                    outvc = vc_allocate(outport, inport, invc);
-                }
-
-                // remove flit from Input VC
-                flit *t_flit = input_unit->getTopFlit(invc);
-
-                DPRINTF(RubyNetwork, "SwitchAllocator at Router %d "
-                                     "granted outvc %d at outport %d "
-                                     "to invc %d at inport %d to flit %s at "
-                                     "cycle: %lld\n",
-                        m_router->get_id(), outvc,
-                        m_router->getPortDirectionName(
-                            output_unit->get_direction()),
-                        invc,
-                        m_router->getPortDirectionName(
-                            input_unit->get_direction()),
-                            *t_flit,
-                        m_router->curCycle());
-
-
-                // Update outport field in the flit since this is
-                // used by CrossbarSwitch code to send it out of
-                // correct outport.
-                // Note: post route compute in InputUnit,
-                // outport is updated in VC, but not in flit
-                t_flit->set_outport(outport);
-
-                // set outvc (i.e., invc for next hop) in flit
-                // (This was updated in VC by vc_allocate, but not in flit)
-                t_flit->set_vc(outvc);
-
-                // decrement credit in outvc
-                output_unit->decrement_credit(outvc);
-
-                // flit ready for Switch Traversal
-                t_flit->advance_stage(ST_, curTick());
-                m_router->grant_switch(inport, t_flit);
-                m_output_arbiter_activity++;
-
-                if ((t_flit->get_type() == TAIL_) ||
-                    t_flit->get_type() == HEAD_TAIL_) {
-
-                    // This Input VC should now be empty
-                    assert(!(input_unit->isReady(invc, curTick())));
-
-                    // Free this VC
-                    input_unit->set_vc_idle(invc, curTick());
-
-                    // Send a credit back
-                    // along with the information that this VC is now idle
-                    input_unit->increment_credit(invc, true, curTick());
-                } else {
-                    // Send a credit back
-                    // but do not indicate that the VC is idle
-                    input_unit->increment_credit(invc, false, curTick());
-                }
-
-                // remove this request
-                m_port_requests[outport][inport] = false;
-
-                // Update Round Robin pointer
-                m_round_robin_inport[outport] = inport + 1;
-                if (m_round_robin_inport[outport] >= m_num_inports)
-                    m_round_robin_inport[outport] = 0;
-
-                // Update Round Robin pointer to the next VC
-                // We do it here to keep it fair.
-                // Only the VC which got switch traversal
-                // is updated.
-                m_round_robin_invc[inport] = invc + 1;
-                if (m_round_robin_invc[inport] >= m_num_vcs)
-                    m_round_robin_invc[inport] = 0;
-
-
-                break; // got a input winner for this outport
-            }
-
-            inport++;
-            if (inport >= m_num_inports)
-                inport = 0;
-        }
-    }
-}
-
-/*
- * A flit can be sent only if
- * (1) there is at least one free output VC at the
- *     output port (for HEAD/HEAD_TAIL),
- *  or
- * (2) if there is at least one credit (i.e., buffer slot)
- *     within the VC for BODY/TAIL flits of multi-flit packets.
- * and
- * (3) pt-to-pt ordering is not violated in ordered vnets, i.e.,
- *     there should be no other flit in this input port
- *     within an ordered vnet
- *     that arrived before this flit and is requesting the same output port.
- */
-
-bool
-SwitchAllocator::send_allowed(int inport, int invc, int outport, int outvc)
-{
-    // Check if outvc needed
-    // Check if credit needed (for multi-flit packet)
-    // Check if ordering violated (in ordered vnet)
-
-    int vnet = get_vnet(invc);
-    bool has_outvc = (outvc != -1);
-    bool has_credit = false;
-
-    auto output_unit = m_router->getOutputUnit(outport);
-    if (!has_outvc) {
-
-        // needs outvc
-        // this is only true for HEAD and HEAD_TAIL flits.
-
-        if (output_unit->has_free_vc(vnet)) {
-
-            has_outvc = true;
-
-            // each VC has at least one buffer,
-            // so no need for additional credit check
-            has_credit = true;
-        }
-    } else {
-        has_credit = output_unit->has_credit(outvc);
-    }
-
-    // cannot send if no outvc or no credit.
-    if (!has_outvc || !has_credit)
-        return false;
-
-
-    // protocol ordering check
-    if ((m_router->get_net_ptr())->isVNetOrdered(vnet)) {
-        auto input_unit = m_router->getInputUnit(inport);
-
-        // enqueue time of this flit
-        Tick t_enqueue_time = input_unit->get_enqueue_time(invc);
-
-        // check if any other flit is ready for SA and for same output port
-        // and was enqueued before this flit
-        int vc_base = vnet*m_vc_per_vnet;
-        for (int vc_offset = 0; vc_offset < m_vc_per_vnet; vc_offset++) {
-            int temp_vc = vc_base + vc_offset;
-            if (input_unit->need_stage(temp_vc, SA_, curTick()) &&
-               (input_unit->get_outport(temp_vc) == outport) &&
-               (input_unit->get_enqueue_time(temp_vc) < t_enqueue_time)) {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-// Assign a free VC to the winner of the output port.
-int
-SwitchAllocator::vc_allocate(int outport, int inport, int invc)
-{
-    // Select a free VC from the output port
-    int outvc =
-        m_router->getOutputUnit(outport)->select_free_vc(get_vnet(invc));
-
-    // has to get a valid VC since it checked before performing SA
-    assert(outvc != -1);
-    m_router->getInputUnit(inport)->grant_outvc(invc, outvc);
-    return outvc;
-}
-
-// Wakeup the router next cycle to perform SA again
-// if there are flits ready.
-void
-SwitchAllocator::check_for_wakeup()
-{
-    Tick nextCycle = m_router->clockEdge(Cycles(1));
-
-    if (m_router->alreadyScheduled(nextCycle)) {
-        return;
-    }
-
-    for (int i = 0; i < m_num_inports; i++) {
-        for (int j = 0; j < m_num_vcs; j++) {
-            if (m_router->getInputUnit(i)->need_stage(j, SA_, nextCycle)) {
-                m_router->schedule_wakeup(Cycles(1));
-                return;
-            }
-        }
-    }
-}
-
-int
-SwitchAllocator::get_vnet(int invc)
-{
-    int vnet = invc/m_vc_per_vnet;
-    assert(vnet < m_router->get_num_vnets());
-    return vnet;
-}
-
-
-// Clear the request vector within the allocator at end of SA-II.
-// Was populated by SA-I.
-void
-SwitchAllocator::clear_request_vector()
-{
-    for (int i = 0; i < m_num_outports; i++) {
-        for (int j = 0; j < m_num_inports; j++) {
-            m_port_requests[i][j] = false;
-        }
-    }
-}
-
-void
-SwitchAllocator::resetStats()
-{
-    m_input_arbiter_activity = 0;
-    m_output_arbiter_activity = 0;
-}
diff --git a/src/mem/ruby/network/garnet2.0/SwitchAllocator.hh b/src/mem/ruby/network/garnet2.0/SwitchAllocator.hh
deleted file mode 100644 (file)
index b309735..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_SWITCHALLOCATOR_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_SWITCHALLOCATOR_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-
-class Router;
-class InputUnit;
-class OutputUnit;
-
-class SwitchAllocator : public Consumer
-{
-  public:
-    SwitchAllocator(Router *router);
-    void wakeup();
-    void init();
-    void clear_request_vector();
-    void check_for_wakeup();
-    int get_vnet (int invc);
-    void print(std::ostream& out) const {};
-    void arbitrate_inports();
-    void arbitrate_outports();
-    bool send_allowed(int inport, int invc, int outport, int outvc);
-    int vc_allocate(int outport, int inport, int invc);
-
-    inline double
-    get_input_arbiter_activity()
-    {
-        return m_input_arbiter_activity;
-    }
-    inline double
-    get_output_arbiter_activity()
-    {
-        return m_output_arbiter_activity;
-    }
-
-    void resetStats();
-
-  private:
-    int m_num_inports, m_num_outports;
-    int m_num_vcs, m_vc_per_vnet;
-
-    double m_input_arbiter_activity, m_output_arbiter_activity;
-
-    Router *m_router;
-    std::vector<int> m_round_robin_invc;
-    std::vector<int> m_round_robin_inport;
-    std::vector<std::vector<bool>> m_port_requests;
-    std::vector<std::vector<int>> m_vc_winners; // a list for each outport
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_SWITCHALLOCATOR_HH__
diff --git a/src/mem/ruby/network/garnet2.0/VirtualChannel.cc b/src/mem/ruby/network/garnet2.0/VirtualChannel.cc
deleted file mode 100644 (file)
index 0b53983..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
-
-VirtualChannel::VirtualChannel()
-  : inputBuffer(), m_vc_state(IDLE_, Tick(0)), m_output_port(-1),
-    m_enqueue_time(INFINITE_), m_output_vc(-1)
-{
-}
-
-void
-VirtualChannel::set_idle(Tick curTime)
-{
-    m_vc_state.first = IDLE_;
-    m_vc_state.second = curTime;
-    m_enqueue_time = Tick(INFINITE_);
-    m_output_port = -1;
-    m_output_vc = -1;
-}
-
-void
-VirtualChannel::set_active(Tick curTime)
-{
-    m_vc_state.first = ACTIVE_;
-    m_vc_state.second = curTime;
-    m_enqueue_time = curTime;
-}
-
-bool
-VirtualChannel::need_stage(flit_stage stage, Tick time)
-{
-    if (inputBuffer.isReady(time)) {
-        assert(m_vc_state.first == ACTIVE_ && m_vc_state.second <= time);
-        flit *t_flit = inputBuffer.peekTopFlit();
-        return(t_flit->is_stage(stage, time));
-    }
-    return false;
-}
-
-uint32_t
-VirtualChannel::functionalWrite(Packet *pkt)
-{
-    return inputBuffer.functionalWrite(pkt);
-}
diff --git a/src/mem/ruby/network/garnet2.0/VirtualChannel.hh b/src/mem/ruby/network/garnet2.0/VirtualChannel.hh
deleted file mode 100644 (file)
index f206299..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_VIRTUALCHANNEL_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_VIRTUALCHANNEL_HH__
-
-#include <utility>
-
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-class VirtualChannel
-{
-  public:
-    VirtualChannel();
-    ~VirtualChannel() = default;
-
-    bool need_stage(flit_stage stage, Tick time);
-    void set_idle(Tick curTime);
-    void set_active(Tick curTime);
-    void set_outvc(int outvc)               { m_output_vc = outvc; }
-    inline int get_outvc()                  { return m_output_vc; }
-    void set_outport(int outport)           { m_output_port = outport; };
-    inline int get_outport()                  { return m_output_port; }
-
-    inline Tick get_enqueue_time()          { return m_enqueue_time; }
-    inline void set_enqueue_time(Tick time) { m_enqueue_time = time; }
-    inline VC_state_type get_state()        { return m_vc_state.first; }
-
-    inline bool
-    isReady(Tick curTime)
-    {
-        return inputBuffer.isReady(curTime);
-    }
-
-    inline void
-    insertFlit(flit *t_flit)
-    {
-        inputBuffer.insert(t_flit);
-    }
-
-    inline void
-    set_state(VC_state_type m_state, Tick curTime)
-    {
-        m_vc_state.first = m_state;
-        m_vc_state.second = curTime;
-    }
-
-    inline flit*
-    peekTopFlit()
-    {
-        return inputBuffer.peekTopFlit();
-    }
-
-    inline flit*
-    getTopFlit()
-    {
-        return inputBuffer.getTopFlit();
-    }
-
-    uint32_t functionalWrite(Packet *pkt);
-
-  private:
-    flitBuffer inputBuffer;
-    std::pair<VC_state_type, Tick> m_vc_state;
-    int m_output_port;
-    Tick m_enqueue_time;
-    int m_output_vc;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_VIRTUALCHANNEL_HH__
diff --git a/src/mem/ruby/network/garnet2.0/flit.cc b/src/mem/ruby/network/garnet2.0/flit.cc
deleted file mode 100644 (file)
index 28a79d4..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-#include "base/intmath.hh"
-#include "debug/RubyNetwork.hh"
-
-// Constructor for the flit
-flit::flit(int id, int  vc, int vnet, RouteInfo route, int size,
-    MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime)
-{
-    m_size = size;
-    m_msg_ptr = msg_ptr;
-    m_enqueue_time = curTime;
-    m_dequeue_time = curTime;
-    m_time = curTime;
-    m_id = id;
-    m_vnet = vnet;
-    m_vc = vc;
-    m_route = route;
-    m_stage.first = I_;
-    m_stage.second = curTime;
-    m_width = bWidth;
-    msgSize = MsgSize;
-
-    if (size == 1) {
-        m_type = HEAD_TAIL_;
-        return;
-    }
-    if (id == 0)
-        m_type = HEAD_;
-    else if (id == (size - 1))
-        m_type = TAIL_;
-    else
-        m_type = BODY_;
-}
-
-flit *
-flit::serialize(int ser_id, int parts, uint32_t bWidth)
-{
-    assert(m_width > bWidth);
-
-    int ratio = (int)divCeil(m_width, bWidth);
-    int new_id = (m_id*ratio) + ser_id;
-    int new_size = (int)divCeil((float)msgSize, (float)bWidth);
-    assert(new_id < new_size);
-
-    flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
-                    new_size, m_msg_ptr, msgSize, bWidth, m_time);
-    fl->set_enqueue_time(m_enqueue_time);
-    fl->set_src_delay(src_delay);
-    return fl;
-}
-
-flit *
-flit::deserialize(int des_id, int num_flits, uint32_t bWidth)
-{
-    int ratio = (int)divCeil((float)bWidth, (float)m_width);
-    int new_id = ((int)divCeil((float)(m_id+1), (float)ratio)) - 1;
-    int new_size = (int)divCeil((float)msgSize, (float)bWidth);
-    assert(new_id < new_size);
-
-    flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
-                    new_size, m_msg_ptr, msgSize, bWidth, m_time);
-    fl->set_enqueue_time(m_enqueue_time);
-    fl->set_src_delay(src_delay);
-    return fl;
-}
-
-// Flit can be printed out for debugging purposes
-void
-flit::print(std::ostream& out) const
-{
-    out << "[flit:: ";
-    out << "Id=" << m_id << " ";
-    out << "Type=" << m_type << " ";
-    out << "Size=" << m_size << " ";
-    out << "Vnet=" << m_vnet << " ";
-    out << "VC=" << m_vc << " ";
-    out << "Src NI=" << m_route.src_ni << " ";
-    out << "Src Router=" << m_route.src_router << " ";
-    out << "Dest NI=" << m_route.dest_ni << " ";
-    out << "Dest Router=" << m_route.dest_router << " ";
-    out << "Set Time=" << m_time << " ";
-    out << "Width=" << m_width<< " ";
-    out << "]";
-}
-
-bool
-flit::functionalWrite(Packet *pkt)
-{
-    Message *msg = m_msg_ptr.get();
-    return msg->functionalWrite(pkt);
-}
diff --git a/src/mem/ruby/network/garnet2.0/flit.hh b/src/mem/ruby/network/garnet2.0/flit.hh
deleted file mode 100644 (file)
index 1bbd152..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_FLIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_FLIT_HH__
-
-#include <cassert>
-#include <iostream>
-
-#include "base/types.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-class flit
-{
-  public:
-    flit() {}
-    flit(int id, int vc, int vnet, RouteInfo route, int size,
-         MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime);
-
-    virtual ~flit(){};
-
-    int get_outport() {return m_outport; }
-    int get_size() { return m_size; }
-    Tick get_enqueue_time() { return m_enqueue_time; }
-    Tick get_dequeue_time() { return m_dequeue_time; }
-    int get_id() { return m_id; }
-    Tick get_time() { return m_time; }
-    int get_vnet() { return m_vnet; }
-    int get_vc() { return m_vc; }
-    RouteInfo get_route() { return m_route; }
-    MsgPtr& get_msg_ptr() { return m_msg_ptr; }
-    flit_type get_type() { return m_type; }
-    std::pair<flit_stage, Tick> get_stage() { return m_stage; }
-    Tick get_src_delay() { return src_delay; }
-
-    void set_outport(int port) { m_outport = port; }
-    void set_time(Tick time) { m_time = time; }
-    void set_vc(int vc) { m_vc = vc; }
-    void set_route(RouteInfo route) { m_route = route; }
-    void set_src_delay(Tick delay) { src_delay = delay; }
-    void set_dequeue_time(Tick time) { m_dequeue_time = time; }
-    void set_enqueue_time(Tick time) { m_enqueue_time = time; }
-
-    void increment_hops() { m_route.hops_traversed++; }
-    virtual void print(std::ostream& out) const;
-
-    bool
-    is_stage(flit_stage stage, Tick time)
-    {
-        return (stage == m_stage.first &&
-                time >= m_stage.second);
-    }
-
-    void
-    advance_stage(flit_stage t_stage, Tick newTime)
-    {
-        m_stage.first = t_stage;
-        m_stage.second = newTime;
-    }
-
-    static bool
-    greater(flit* n1, flit* n2)
-    {
-        if (n1->get_time() == n2->get_time()) {
-            //assert(n1->flit_id != n2->flit_id);
-            return (n1->get_id() > n2->get_id());
-        } else {
-            return (n1->get_time() > n2->get_time());
-        }
-    }
-
-    bool functionalWrite(Packet *pkt);
-
-    virtual flit* serialize(int ser_id, int parts, uint32_t bWidth);
-    virtual flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
-
-    uint32_t m_width;
-    int msgSize;
-  protected:
-    int m_id;
-    int m_vnet;
-    int m_vc;
-    RouteInfo m_route;
-    int m_size;
-    Tick m_enqueue_time, m_dequeue_time;
-    Tick m_time;
-    flit_type m_type;
-    MsgPtr m_msg_ptr;
-    int m_outport;
-    Tick src_delay;
-    std::pair<flit_stage, Tick> m_stage;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const flit& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_FLIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/flitBuffer.cc b/src/mem/ruby/network/garnet2.0/flitBuffer.cc
deleted file mode 100644 (file)
index c721639..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-flitBuffer::flitBuffer()
-{
-    max_size = INFINITE_;
-}
-
-flitBuffer::flitBuffer(int maximum_size)
-{
-    max_size = maximum_size;
-}
-
-bool
-flitBuffer::isEmpty()
-{
-    return (m_buffer.size() == 0);
-}
-
-bool
-flitBuffer::isReady(Tick curTime)
-{
-    if (m_buffer.size() != 0 ) {
-        flit *t_flit = peekTopFlit();
-        if (t_flit->get_time() <= curTime)
-            return true;
-    }
-    return false;
-}
-
-void
-flitBuffer::print(std::ostream& out) const
-{
-    out << "[flitBuffer: " << m_buffer.size() << "] " << std::endl;
-}
-
-bool
-flitBuffer::isFull()
-{
-    return (m_buffer.size() >= max_size);
-}
-
-void
-flitBuffer::setMaxSize(int maximum)
-{
-    max_size = maximum;
-}
-
-uint32_t
-flitBuffer::functionalWrite(Packet *pkt)
-{
-    uint32_t num_functional_writes = 0;
-
-    for (unsigned int i = 0; i < m_buffer.size(); ++i) {
-        if (m_buffer[i]->functionalWrite(pkt)) {
-            num_functional_writes++;
-        }
-    }
-
-    return num_functional_writes;
-}
diff --git a/src/mem/ruby/network/garnet2.0/flitBuffer.hh b/src/mem/ruby/network/garnet2.0/flitBuffer.hh
deleted file mode 100644 (file)
index f98ecf6..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_FLITBUFFER_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_FLITBUFFER_HH__
-
-#include <algorithm>
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-class flitBuffer
-{
-  public:
-    flitBuffer();
-    flitBuffer(int maximum_size);
-
-    bool isReady(Tick curTime);
-    bool isEmpty();
-    void print(std::ostream& out) const;
-    bool isFull();
-    void setMaxSize(int maximum);
-    int getSize() const { return m_buffer.size(); }
-
-    flit *
-    getTopFlit()
-    {
-        flit *f = m_buffer.front();
-        std::pop_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
-        m_buffer.pop_back();
-        return f;
-    }
-
-    flit *
-    peekTopFlit()
-    {
-        return m_buffer.front();
-    }
-
-    void
-    insert(flit *flt)
-    {
-        m_buffer.push_back(flt);
-        std::push_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
-    }
-
-    uint32_t functionalWrite(Packet *pkt);
-
-  private:
-    std::vector<flit *> m_buffer;
-    int max_size;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const flitBuffer& obj)
-{
-    obj.print(out);
-    out << std::flush;
-    return out;
-}
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_FLITBUFFER_HH__