summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTushar Krishna <tushar@ece.gatech.edu>2016-10-06 14:35:22 -0400
committerTushar Krishna <tushar@ece.gatech.edu>2016-10-06 14:35:22 -0400
commitdbe8892b761067c5c1e828f889a513ea085b044f (patch)
treed3101cc8dbf74f1d3bc2f3f9ead1b948fd4ac33e /src
parentb512f4bf71fac79fb6e17bb2a9e05c1f494f69f4 (diff)
downloadgem5-dbe8892b761067c5c1e828f889a513ea085b044f.tar.xz
ruby: garnet2.0
Revamped version of garnet with more optimized single-cycle routers, more configurability, and cleaner code.
Diffstat (limited to 'src')
-rw-r--r--src/base/statistics.cc4
-rw-r--r--src/mem/ruby/network/BasicRouter.py2
-rw-r--r--src/mem/ruby/network/garnet2.0/CommonTypes.hh65
-rw-r--r--src/mem/ruby/network/garnet2.0/Credit.cc46
-rw-r--r--src/mem/ruby/network/garnet2.0/Credit.hh60
-rw-r--r--src/mem/ruby/network/garnet2.0/CreditLink.hh47
-rw-r--r--src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc112
-rw-r--r--src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh72
-rw-r--r--src/mem/ruby/network/garnet2.0/GarnetLink.cc94
-rw-r--r--src/mem/ruby/network/garnet2.0/GarnetLink.hh97
-rw-r--r--src/mem/ruby/network/garnet2.0/GarnetLink.py79
-rw-r--r--src/mem/ruby/network/garnet2.0/GarnetNetwork.cc460
-rw-r--r--src/mem/ruby/network/garnet2.0/GarnetNetwork.hh208
-rw-r--r--src/mem/ruby/network/garnet2.0/GarnetNetwork.py68
-rw-r--r--src/mem/ruby/network/garnet2.0/InputUnit.cc171
-rw-r--r--src/mem/ruby/network/garnet2.0/InputUnit.hh170
-rw-r--r--src/mem/ruby/network/garnet2.0/NetworkInterface.cc443
-rw-r--r--src/mem/ruby/network/garnet2.0/NetworkInterface.hh108
-rw-r--r--src/mem/ruby/network/garnet2.0/NetworkLink.cc94
-rw-r--r--src/mem/ruby/network/garnet2.0/NetworkLink.hh88
-rw-r--r--src/mem/ruby/network/garnet2.0/OutVcState.cc65
-rw-r--r--src/mem/ruby/network/garnet2.0/OutVcState.hh70
-rw-r--r--src/mem/ruby/network/garnet2.0/OutputUnit.cc168
-rw-r--r--src/mem/ruby/network/garnet2.0/OutputUnit.hh113
-rw-r--r--src/mem/ruby/network/garnet2.0/README.txt71
-rw-r--r--src/mem/ruby/network/garnet2.0/Router.cc296
-rw-r--r--src/mem/ruby/network/garnet2.0/Router.hh140
-rw-r--r--src/mem/ruby/network/garnet2.0/RoutingUnit.cc241
-rw-r--r--src/mem/ruby/network/garnet2.0/RoutingUnit.hh89
-rw-r--r--src/mem/ruby/network/garnet2.0/SConscript53
-rw-r--r--src/mem/ruby/network/garnet2.0/SwitchAllocator.cc389
-rw-r--r--src/mem/ruby/network/garnet2.0/SwitchAllocator.hh88
-rw-r--r--src/mem/ruby/network/garnet2.0/VirtualChannel.cc85
-rw-r--r--src/mem/ruby/network/garnet2.0/VirtualChannel.hh101
-rw-r--r--src/mem/ruby/network/garnet2.0/flit.cc85
-rw-r--r--src/mem/ruby/network/garnet2.0/flit.hh122
-rw-r--r--src/mem/ruby/network/garnet2.0/flitBuffer.cc93
-rw-r--r--src/mem/ruby/network/garnet2.0/flitBuffer.hh93
38 files changed, 4848 insertions, 2 deletions
diff --git a/src/base/statistics.cc b/src/base/statistics.cc
index b32dafb8c..4c14bc522 100644
--- a/src/base/statistics.cc
+++ b/src/base/statistics.cc
@@ -180,8 +180,8 @@ Info::setName(const string &name)
bool result = p.second;
if (!result) {
- // using other->name instead of just name to avoid a compiler
- // warning. They should be the same.
+ // using other->name instead of just name to avoid a compiler
+ // warning. They should be the same.
panic("same statistic name used twice! name=%s\n", other->name);
}
diff --git a/src/mem/ruby/network/BasicRouter.py b/src/mem/ruby/network/BasicRouter.py
index 28fcdc47e..68a7b1d8b 100644
--- a/src/mem/ruby/network/BasicRouter.py
+++ b/src/mem/ruby/network/BasicRouter.py
@@ -34,4 +34,6 @@ class BasicRouter(ClockedObject):
type = 'BasicRouter'
cxx_header = "mem/ruby/network/BasicRouter.hh"
router_id = Param.Int("ID in relation to other routers")
+
+ # only used by garnet
latency = Param.Cycles(1, "number of cycles inside router")
diff --git a/src/mem/ruby/network/garnet2.0/CommonTypes.hh b/src/mem/ruby/network/garnet2.0/CommonTypes.hh
new file mode 100644
index 000000000..63fc464a6
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/CommonTypes.hh
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_COMMONTYPES_HH__
+#define __MEM_RUBY_NETWORK_GARNET_COMMONTYPES_HH__
+
+#include "mem/ruby/common/NetDest.hh"
+
+// All common enums and typedefs go here
+
+enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_, 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
+{
+ // 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_COMMONTYPES_HH__
diff --git a/src/mem/ruby/network/garnet2.0/Credit.cc b/src/mem/ruby/network/garnet2.0/Credit.cc
new file mode 100644
index 000000000..6bc7ca209
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/Credit.cc
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/Credit.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, Cycles curTime)
+{
+ m_id = 0;
+ m_vc = vc;
+ m_is_free_signal = is_free_signal;
+ m_time = curTime;
+}
diff --git a/src/mem/ruby/network/garnet2.0/Credit.hh b/src/mem/ruby/network/garnet2.0/Credit.hh
new file mode 100644
index 000000000..c2984e9ee
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/Credit.hh
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_CREDIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_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, Cycles curTime);
+
+ bool is_free_signal() { return m_is_free_signal; }
+
+ private:
+ bool m_is_free_signal;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_CREDIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/CreditLink.hh b/src/mem/ruby/network/garnet2.0/CreditLink.hh
new file mode 100644
index 000000000..207fb864d
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/CreditLink.hh
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_CREDIT_LINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_CREDIT_LINK_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_GARNET_CREDIT_LINK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc b/src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc
new file mode 100644
index 000000000..340f56d61
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
+
+#include "base/stl_helpers.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
+#include "mem/ruby/network/garnet2.0/Router.hh"
+
+using m5::stl_helpers::deletePointers;
+
+CrossbarSwitch::CrossbarSwitch(Router *router)
+ : Consumer(router)
+{
+ m_router = router;
+ m_num_vcs = m_router->get_num_vcs();
+ m_crossbar_activity = 0;
+}
+
+CrossbarSwitch::~CrossbarSwitch()
+{
+ deletePointers(m_switch_buffer);
+}
+
+void
+CrossbarSwitch::init()
+{
+ m_output_unit = m_router->get_outputUnit_ref();
+
+ m_num_inports = m_router->get_num_inports();
+ m_switch_buffer.resize(m_num_inports);
+ for (int i = 0; i < m_num_inports; i++) {
+ m_switch_buffer[i] = new flitBuffer();
+ }
+}
+
+/*
+ * 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 (int inport = 0; inport < m_num_inports; inport++) {
+ if (!m_switch_buffer[inport]->isReady(m_router->curCycle()))
+ continue;
+
+ flit *t_flit = m_switch_buffer[inport]->peekTopFlit();
+ if (t_flit->is_stage(ST_, m_router->curCycle())) {
+ int outport = t_flit->get_outport();
+
+ // flit performs LT_ in the next cycle
+ t_flit->advance_stage(LT_, m_router->curCycle() + Cycles(1));
+ t_flit->set_time(m_router->curCycle() + Cycles(1));
+
+ // This will take care of waking up the Network Link
+ // in the next cycle
+ m_output_unit[outport]->insert_flit(t_flit);
+ m_switch_buffer[inport]->getTopFlit();
+ m_crossbar_activity++;
+ }
+ }
+}
+
+uint32_t
+CrossbarSwitch::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ for (uint32_t i = 0; i < m_switch_buffer.size(); ++i) {
+ num_functional_writes += m_switch_buffer[i]->functionalWrite(pkt);
+ }
+
+ return num_functional_writes;
+}
diff --git a/src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh b/src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh
new file mode 100644
index 000000000..7aaeabf0c
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_CROSSBAR_SWITCH_HH__
+#define __MEM_RUBY_NETWORK_GARNET_CROSSBAR_SWITCH_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 OutputUnit;
+
+class CrossbarSwitch : public Consumer
+{
+ public:
+ CrossbarSwitch(Router *router);
+ ~CrossbarSwitch();
+ void wakeup();
+ void init();
+ void print(std::ostream& out) const {};
+
+ inline void update_sw_winner(int inport, flit *t_flit)
+ { m_switch_buffer[inport]->insert(t_flit); }
+
+ inline double get_crossbar_activity() { return m_crossbar_activity; }
+
+ uint32_t functionalWrite(Packet *pkt);
+
+ private:
+ int m_num_vcs;
+ int m_num_inports;
+ double m_crossbar_activity;
+ Router *m_router;
+ std::vector<flitBuffer *> m_switch_buffer;
+ std::vector<OutputUnit *> m_output_unit;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_CROSSBAR_SWITCH_HH__
diff --git a/src/mem/ruby/network/garnet2.0/GarnetLink.cc b/src/mem/ruby/network/garnet2.0/GarnetLink.cc
new file mode 100644
index 000000000..ac5386a52
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/GarnetLink.cc
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
+
+#include "mem/ruby/network/garnet2.0/CreditLink.hh"
+#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
+
+GarnetIntLink::GarnetIntLink(const Params *p)
+ : BasicLink(p)
+{
+ // Uni-directional
+
+ m_network_link = p->network_link;
+ m_credit_link = p->credit_link;
+}
+
+void
+GarnetIntLink::init()
+{
+}
+
+void
+GarnetIntLink::print(std::ostream& out) const
+{
+ out << name();
+}
+
+GarnetIntLink *
+GarnetIntLinkParams::create()
+{
+ return new GarnetIntLink(this);
+}
+
+GarnetExtLink::GarnetExtLink(const Params *p)
+ : BasicLink(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];
+}
+
+void
+GarnetExtLink::init()
+{
+}
+
+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
new file mode 100644
index 000000000..d7c582950
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/GarnetLink.hh
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_LINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_LINK_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/NetworkLink.hh"
+#include "params/GarnetExtLink.hh"
+#include "params/GarnetIntLink.hh"
+
+class GarnetIntLink : public BasicLink
+{
+ 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;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetIntLink& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+class GarnetExtLink : public BasicLink
+{
+ public:
+ typedef GarnetExtLinkParams Params;
+ GarnetExtLink(const Params *p);
+
+ void init();
+
+ void print(std::ostream& out) const;
+
+ friend class GarnetNetwork;
+
+ protected:
+ NetworkLink* m_network_links[2];
+ CreditLink* m_credit_links[2];
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetExtLink& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif // __MEM_RUBY_NETWORK_GARNET_LINK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/GarnetLink.py b/src/mem/ruby/network/garnet2.0/GarnetLink.py
new file mode 100644
index 000000000..fc5632d49
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/GarnetLink.py
@@ -0,0 +1,79 @@
+# 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.
+#
+# Authors: Steve Reinhardt
+# Brad Beckmann
+
+from m5.params import *
+from m5.proxy import *
+from ClockedObject import ClockedObject
+from BasicLink import BasicIntLink, BasicExtLink
+
+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")
+
+class CreditLink(NetworkLink):
+ type = 'CreditLink'
+ cxx_header = "mem/ruby/network/garnet2.0/CreditLink.hh"
+
+# 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")
+
+# 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")
diff --git a/src/mem/ruby/network/garnet2.0/GarnetNetwork.cc b/src/mem/ruby/network/garnet2.0/GarnetNetwork.cc
new file mode 100644
index 000000000..5fa764457
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/GarnetNetwork.cc
@@ -0,0 +1,460 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
+
+#include <cassert>
+
+#include "base/cast.hh"
+#include "base/stl_helpers.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;
+using m5::stl_helpers::deletePointers;
+
+/*
+ * 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_vcs_per_vnet = p->vcs_per_vnet;
+ 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);
+ }
+ }
+}
+
+GarnetNetwork::~GarnetNetwork()
+{
+ deletePointers(m_routers);
+ deletePointers(m_nis);
+ deletePointers(m_networklinks);
+ deletePointers(m_creditlinks);
+}
+
+/*
+ * 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 src, SwitchID dest, BasicLink* link,
+ const NetDest& routing_table_entry)
+{
+ assert(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_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
+ m_nis[src]->addOutPort(net_link, credit_link, dest);
+}
+
+/*
+ * 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 dest, BasicLink* link,
+ const NetDest& routing_table_entry)
+{
+ assert(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_routers[src]->addOutPort(src_outport_dirn, net_link,
+ routing_table_entry,
+ link->m_weight, credit_link);
+ m_nis[dest]->addInPort(net_link, credit_link);
+}
+
+/*
+ * 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,
+ const 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_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
+ m_routers[src]->addOutPort(src_outport_dirn, net_link,
+ routing_table_entry,
+ link->m_weight, credit_link);
+}
+
+// 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 ni)
+{
+ return m_nis[ni]->get_router_id();
+}
+
+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_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::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
new file mode 100644
index 000000000..3ced88740
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/GarnetNetwork.hh
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_NETWORK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_NETWORK_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();
+ 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 getVCsPerVnet() const { return m_vcs_per_vnet; }
+ 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 vc)
+ {
+ int vnet = vc/getVCsPerVnet();
+ return m_vnet_type[vnet];
+ }
+ int getNumRouters();
+ int get_router_id(int ni);
+
+
+ // Methods used by Topology to setup the network
+ void makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
+ const NetDest& routing_table_entry);
+ void makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
+ const NetDest& routing_table_entry);
+ void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
+ const 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 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(Cycles latency, int vnet)
+ {
+ m_packet_network_latency[vnet] += latency;
+ }
+
+ void
+ increment_packet_queueing_latency(Cycles 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(Cycles latency, int vnet)
+ {
+ m_flit_network_latency[vnet] += latency;
+ }
+
+ void
+ increment_flit_queueing_latency(Cycles 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_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_NETWORK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/GarnetNetwork.py b/src/mem/ruby/network/garnet2.0/GarnetNetwork.py
new file mode 100644
index 000000000..704532782
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/GarnetNetwork.py
@@ -0,0 +1,68 @@
+# 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 Network import RubyNetwork
+from BasicRouter import BasicRouter
+from 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");
+
+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")
+
+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")
diff --git a/src/mem/ruby/network/garnet2.0/InputUnit.cc b/src/mem/ruby/network/garnet2.0/InputUnit.cc
new file mode 100644
index 000000000..c03bf2a09
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/InputUnit.cc
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/InputUnit.hh"
+
+#include "base/stl_helpers.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet2.0/Credit.hh"
+#include "mem/ruby/network/garnet2.0/Router.hh"
+
+using namespace std;
+using m5::stl_helpers::deletePointers;
+
+InputUnit::InputUnit(int id, PortDirection direction, Router *router)
+ : Consumer(router)
+{
+ m_id = id;
+ m_direction = direction;
+ m_router = router;
+ m_num_vcs = m_router->get_num_vcs();
+ m_vc_per_vnet = m_router->get_vc_per_vnet();
+
+ 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;
+ }
+
+ creditQueue = new flitBuffer();
+ // Instantiating the virtual channels
+ m_vcs.resize(m_num_vcs);
+ for (int i=0; i < m_num_vcs; i++) {
+ m_vcs[i] = new VirtualChannel(i);
+ }
+}
+
+InputUnit::~InputUnit()
+{
+ delete creditQueue;
+ deletePointers(m_vcs);
+}
+
+/*
+ * 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(m_router->curCycle())) {
+
+ t_flit = m_in_link->consumeLink();
+ 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(m_vcs[vc]->get_state() == IDLE_);
+ set_vc_active(vc, m_router->curCycle());
+
+ // 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(m_vcs[vc]->get_state() == ACTIVE_);
+ }
+
+
+ // Buffer the flit
+ m_vcs[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_, m_router->curCycle());
+ } 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->curCycle() + wait_time);
+
+ // Wakeup the router in that cycle to perform SA
+ m_router->schedule_wakeup(Cycles(wait_time));
+ }
+ }
+}
+
+// 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, Cycles curTime)
+{
+ 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 (int i=0; i < m_num_vcs; i++) {
+ num_functional_writes += m_vcs[i]->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
new file mode 100644
index 000000000..26803ed86
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/InputUnit.hh
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_INPUT_UNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_INPUT_UNIT_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();
+
+ void wakeup();
+ void print(std::ostream& out) const {};
+
+ inline PortDirection get_direction() { return m_direction; }
+
+ inline void
+ set_vc_idle(int vc, Cycles curTime)
+ {
+ m_vcs[vc]->set_idle(curTime);
+ }
+
+ inline void
+ set_vc_active(int vc, Cycles curTime)
+ {
+ m_vcs[vc]->set_active(curTime);
+ }
+
+ inline void
+ grant_outport(int vc, int outport)
+ {
+ m_vcs[vc]->set_outport(outport);
+ }
+
+ inline void
+ grant_outvc(int vc, int outvc)
+ {
+ m_vcs[vc]->set_outvc(outvc);
+ }
+
+ inline int
+ get_outport(int invc)
+ {
+ return m_vcs[invc]->get_outport();
+ }
+
+ inline int
+ get_outvc(int invc)
+ {
+ return m_vcs[invc]->get_outvc();
+ }
+
+ inline Cycles
+ get_enqueue_time(int invc)
+ {
+ return m_vcs[invc]->get_enqueue_time();
+ }
+
+ void increment_credit(int in_vc, bool free_signal, Cycles curTime);
+
+ inline flit*
+ peekTopFlit(int vc)
+ {
+ return m_vcs[vc]->peekTopFlit();
+ }
+
+ inline flit*
+ getTopFlit(int vc)
+ {
+ return m_vcs[vc]->getTopFlit();
+ }
+
+ inline bool
+ need_stage(int vc, flit_stage stage, Cycles time)
+ {
+ return m_vcs[vc]->need_stage(stage, time);
+ }
+
+ inline bool
+ isReady(int invc, Cycles curTime)
+ {
+ return m_vcs[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:
+ int m_id;
+ PortDirection m_direction;
+ int m_num_vcs;
+ int m_vc_per_vnet;
+
+ Router *m_router;
+ NetworkLink *m_in_link;
+ CreditLink *m_credit_link;
+ flitBuffer *creditQueue;
+
+ // Input Virtual channels
+ std::vector<VirtualChannel *> m_vcs;
+
+ // Statistical variables
+ std::vector<double> m_num_buffer_writes;
+ std::vector<double> m_num_buffer_reads;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_INPUT_UNIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/NetworkInterface.cc b/src/mem/ruby/network/garnet2.0/NetworkInterface.cc
new file mode 100644
index 000000000..6bdaf39af
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/NetworkInterface.cc
@@ -0,0 +1,443 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
+
+#include <cassert>
+#include <cmath>
+
+#include "base/cast.hh"
+#include "base/stl_helpers.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;
+using m5::stl_helpers::deletePointers;
+
+NetworkInterface::NetworkInterface(const Params *p)
+ : ClockedObject(p), Consumer(this), m_id(p->id),
+ m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
+ m_num_vcs(m_vc_per_vnet * m_virtual_networks)
+{
+ m_router_id = -1;
+ m_vc_round_robin = 0;
+ m_ni_out_vcs.resize(m_num_vcs);
+ m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
+ outCreditQueue = new flitBuffer();
+
+ // instantiating the NI flit buffers
+ for (int i = 0; i < m_num_vcs; i++) {
+ m_ni_out_vcs[i] = new flitBuffer();
+ m_ni_out_vcs_enqueue_time[i] = Cycles(INFINITE_);
+ }
+
+ m_vc_allocator.resize(m_virtual_networks); // 1 allocator per vnet
+ for (int i = 0; i < m_virtual_networks; i++) {
+ m_vc_allocator[i] = 0;
+ }
+}
+
+void
+NetworkInterface::init()
+{
+ for (int i = 0; i < m_num_vcs; i++) {
+ m_out_vc_state.push_back(new OutVcState(i, m_net_ptr));
+ }
+}
+
+NetworkInterface::~NetworkInterface()
+{
+ deletePointers(m_out_vc_state);
+ deletePointers(m_ni_out_vcs);
+ delete outCreditQueue;
+ delete outFlitQueue;
+}
+
+void
+NetworkInterface::addInPort(NetworkLink *in_link,
+ CreditLink *credit_link)
+{
+ inNetLink = in_link;
+ in_link->setLinkConsumer(this);
+ outCreditLink = credit_link;
+ credit_link->setSourceQueue(outCreditQueue);
+}
+
+void
+NetworkInterface::addOutPort(NetworkLink *out_link,
+ CreditLink *credit_link,
+ SwitchID router_id)
+{
+ inCreditLink = credit_link;
+ credit_link->setLinkConsumer(this);
+
+ outNetLink = out_link;
+ outFlitQueue = new flitBuffer();
+ out_link->setSourceQueue(outFlitQueue);
+
+ m_router_id = router_id;
+}
+
+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);
+ }
+ }
+}
+
+
+/*
+ * 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()
+{
+ DPRINTF(RubyNetwork, "Network Interface %d connected to router %d "
+ "woke up at time: %lld\n", m_id, m_router_id, curCycle());
+
+ 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);
+ } else {
+ break;
+ }
+ }
+ }
+
+ scheduleOutputLink();
+ checkReschedule();
+
+ /*********** Check the incoming flit link **********/
+
+ if (inNetLink->isReady(curCycle())) {
+ flit *t_flit = inNetLink->consumeLink();
+ bool free_signal = false;
+ if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
+ free_signal = true;
+
+ // enqueue into the protocol buffers
+ outNode_ptr[t_flit->get_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 *t_credit = new Credit(t_flit->get_vc(), free_signal,
+ curCycle());
+ outCreditQueue->insert(t_credit);
+ outCreditLink->
+ scheduleEventAbsolute(clockEdge(Cycles(1)));
+
+ int vnet = t_flit->get_vnet();
+
+ // Update Stats
+
+ // Latency
+ m_net_ptr->increment_received_flits(vnet);
+ Cycles network_delay = curCycle() - t_flit->get_enqueue_time();
+ Cycles queueing_delay = t_flit->get_src_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);
+
+ delete t_flit;
+ }
+
+ /****************** Check the incoming credit link *******/
+
+ if (inCreditLink->isReady(curCycle())) {
+ Credit *t_credit = (Credit*) inCreditLink->consumeLink();
+ m_out_vc_state[t_credit->get_vc()]->increment_credit();
+ if (t_credit->is_free_signal()) {
+ m_out_vc_state[t_credit->get_vc()]->setState(IDLE_, curCycle());
+ }
+ delete t_credit;
+ }
+}
+
+
+// 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
+ int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(
+ net_msg_ptr->getMessageSize())/m_net_ptr->getNiFlitSize());
+
+ // 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 = m_router_id;
+ route.dest_ni = destID;
+ route.dest_router = m_net_ptr->get_router_id(destID);
+
+ // 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,
+ curCycle());
+
+ fl->set_src_delay(curCycle() - ticksToCycles(msg_ptr->getTime()));
+ m_ni_out_vcs[vc]->insert(fl);
+ }
+
+ m_ni_out_vcs_enqueue_time[vc] = curCycle();
+ m_out_vc_state[vc]->setState(ACTIVE_, curCycle());
+ }
+ 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 (m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(
+ IDLE_, curCycle())) {
+ return ((vnet*m_vc_per_vnet) + delta);
+ }
+ }
+ return -1;
+}
+
+
+/** 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()
+{
+ int vc = m_vc_round_robin;
+ m_vc_round_robin++;
+ if (m_vc_round_robin == m_num_vcs)
+ m_vc_round_robin = 0;
+
+ for (int i = 0; i < m_num_vcs; i++) {
+ vc++;
+ if (vc == m_num_vcs)
+ vc = 0;
+
+ // model buffer backpressure
+ if (m_ni_out_vcs[vc]->isReady(curCycle()) &&
+ m_out_vc_state[vc]->has_credit()) {
+
+ bool is_candidate_vc = true;
+ int t_vnet = get_vnet(vc);
+ 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 (m_ni_out_vcs[t_vc]->isReady(curCycle())) {
+ 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;
+
+ m_out_vc_state[vc]->decrement_credit();
+ // Just removing the flit
+ flit *t_flit = m_ni_out_vcs[vc]->getTopFlit();
+ t_flit->set_time(curCycle() + Cycles(1));
+ outFlitQueue->insert(t_flit);
+ // schedule the out link
+ outNetLink->scheduleEventAbsolute(clockEdge(Cycles(1)));
+
+ if (t_flit->get_type() == TAIL_ ||
+ t_flit->get_type() == HEAD_TAIL_) {
+ m_ni_out_vcs_enqueue_time[vc] = Cycles(INFINITE_);
+ }
+ 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
+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 (int vc = 0; vc < m_num_vcs; vc++) {
+ if (m_ni_out_vcs[vc]->isReady(curCycle() + Cycles(1))) {
+ 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 (unsigned int i = 0; i < m_num_vcs; ++i) {
+ num_functional_writes += m_ni_out_vcs[i]->functionalWrite(pkt);
+ }
+
+ num_functional_writes += 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
new file mode 100644
index 000000000..85e0145af
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/NetworkInterface.hh
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_NETWORK_INTERFACE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_NETWORK_INTERFACE_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/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();
+
+ void init();
+
+ void addInPort(NetworkLink *in_link, CreditLink *credit_link);
+ void addOutPort(NetworkLink *out_link, CreditLink *credit_link,
+ SwitchID router_id);
+
+ void wakeup();
+ void addNode(std::vector<MessageBuffer *> &inNode,
+ std::vector<MessageBuffer *> &outNode);
+
+ void print(std::ostream& out) const;
+ int get_vnet(int vc);
+ int get_router_id() { return m_router_id; }
+ void init_net_ptr(GarnetNetwork *net_ptr) { m_net_ptr = net_ptr; }
+
+ uint32_t functionalWrite(Packet *);
+
+ private:
+ GarnetNetwork *m_net_ptr;
+ const NodeID m_id;
+ const int m_virtual_networks, m_vc_per_vnet, m_num_vcs;
+ int m_router_id; // id of my router
+ std::vector<OutVcState *> m_out_vc_state;
+ std::vector<int> m_vc_allocator;
+ int m_vc_round_robin; // For round robin scheduling
+ flitBuffer *outFlitQueue; // For modeling link contention
+ flitBuffer *outCreditQueue;
+
+ NetworkLink *inNetLink;
+ NetworkLink *outNetLink;
+ CreditLink *inCreditLink;
+ CreditLink *outCreditLink;
+
+ // Input Flit Buffers
+ // The flit buffers which will serve the Consumer
+ std::vector<flitBuffer *> m_ni_out_vcs;
+ std::vector<Cycles> 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;
+
+ bool flitisizeMessage(MsgPtr msg_ptr, int vnet);
+ int calculateVC(int vnet);
+ void scheduleOutputLink();
+ void checkReschedule();
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_NETWORK_INTERFACE_HH__
diff --git a/src/mem/ruby/network/garnet2.0/NetworkLink.cc b/src/mem/ruby/network/garnet2.0/NetworkLink.cc
new file mode 100644
index 000000000..6010071f0
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/NetworkLink.cc
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/NetworkLink.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),
+ linkBuffer(new flitBuffer()), link_consumer(nullptr),
+ link_srcQueue(nullptr), m_link_utilized(0),
+ m_vc_load(p->vcs_per_vnet * p->virt_nets)
+{
+}
+
+NetworkLink::~NetworkLink()
+{
+ delete linkBuffer;
+}
+
+void
+NetworkLink::setLinkConsumer(Consumer *consumer)
+{
+ link_consumer = consumer;
+}
+
+void
+NetworkLink::setSourceQueue(flitBuffer *srcQueue)
+{
+ link_srcQueue = srcQueue;
+}
+
+void
+NetworkLink::wakeup()
+{
+ if (link_srcQueue->isReady(curCycle())) {
+ flit *t_flit = link_srcQueue->getTopFlit();
+ t_flit->set_time(curCycle() + m_latency);
+ linkBuffer->insert(t_flit);
+ link_consumer->scheduleEventAbsolute(clockEdge(m_latency));
+ m_link_utilized++;
+ m_vc_load[t_flit->get_vc()]++;
+ }
+}
+
+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
new file mode 100644
index 000000000..cb69b39ad
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/NetworkLink.hh
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_NETWORK_LINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_NETWORK_LINK_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();
+
+ void setLinkConsumer(Consumer *consumer);
+ void setSourceQueue(flitBuffer *srcQueue);
+ 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; }
+ void wakeup();
+
+ unsigned int getLinkUtilization() const { return m_link_utilized; }
+ const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; }
+
+ inline bool isReady(Cycles curTime)
+ { return linkBuffer->isReady(curTime); }
+
+ inline flit* peekLink() { return linkBuffer->peekTopFlit(); }
+ inline flit* consumeLink() { return linkBuffer->getTopFlit(); }
+
+ uint32_t functionalWrite(Packet *);
+
+ private:
+ const int m_id;
+ link_type m_type;
+ const Cycles m_latency;
+
+ flitBuffer *linkBuffer;
+ Consumer *link_consumer;
+ flitBuffer *link_srcQueue;
+
+ // Statistical variables
+ unsigned int m_link_utilized;
+ std::vector<unsigned int> m_vc_load;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_NETWORK_LINK_HH__
diff --git a/src/mem/ruby/network/garnet2.0/OutVcState.cc b/src/mem/ruby/network/garnet2.0/OutVcState.cc
new file mode 100644
index 000000000..1ad65ecd0
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/OutVcState.cc
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/OutVcState.hh"
+
+#include "mem/ruby/system/RubySystem.hh"
+
+OutVcState::OutVcState(int id, GarnetNetwork *network_ptr)
+ : m_time(0)
+{
+ m_id = id;
+ m_vc_state = IDLE_;
+
+ if (network_ptr->get_vnet_type(id) == 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
new file mode 100644
index 000000000..b9c008df6
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/OutVcState.hh
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_OUTVC_STATE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_OUTVC_STATE_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);
+
+ 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, Cycles request_time)
+ {
+ return ((m_vc_state == state) && (request_time >= m_time) );
+ }
+ inline void
+ setState(VC_state_type state, Cycles time)
+ {
+ m_vc_state = state;
+ m_time = time;
+ }
+
+ private:
+ int m_id ;
+ Cycles m_time;
+ VC_state_type m_vc_state;
+ int m_credit_count;
+ int m_max_credit_count;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_OUTVC_STATE_HH__
diff --git a/src/mem/ruby/network/garnet2.0/OutputUnit.cc b/src/mem/ruby/network/garnet2.0/OutputUnit.cc
new file mode 100644
index 000000000..85fef5e53
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/OutputUnit.cc
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
+
+#include "base/stl_helpers.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet2.0/Credit.hh"
+#include "mem/ruby/network/garnet2.0/Router.hh"
+
+using namespace std;
+using m5::stl_helpers::deletePointers;
+
+OutputUnit::OutputUnit(int id, PortDirection direction, Router *router)
+ : Consumer(router)
+{
+ m_id = id;
+ m_direction = direction;
+ m_router = router;
+ m_num_vcs = m_router->get_num_vcs();
+ m_vc_per_vnet = m_router->get_vc_per_vnet();
+ m_out_buffer = new flitBuffer();
+
+ for (int i = 0; i < m_num_vcs; i++) {
+ m_outvc_state.push_back(new OutVcState(i, m_router->get_net_ptr()));
+ }
+}
+
+OutputUnit::~OutputUnit()
+{
+ delete m_out_buffer;
+ deletePointers(m_outvc_state);
+}
+
+void
+OutputUnit::decrement_credit(int out_vc)
+{
+ DPRINTF(RubyNetwork, "Router %d OutputUnit %d decrementing credit for "
+ "outvc %d at time: %lld\n",
+ m_router->get_id(), m_id, out_vc, m_router->curCycle());
+
+ m_outvc_state[out_vc]->decrement_credit();
+}
+
+void
+OutputUnit::increment_credit(int out_vc)
+{
+ DPRINTF(RubyNetwork, "Router %d OutputUnit %d incrementing credit for "
+ "outvc %d at time: %lld\n",
+ m_router->get_id(), m_id, out_vc, m_router->curCycle());
+
+ m_outvc_state[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(m_outvc_state[out_vc]->isInState(ACTIVE_, m_router->curCycle()));
+ return m_outvc_state[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, m_router->curCycle()))
+ 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, m_router->curCycle())) {
+ m_outvc_state[vc]->setState(ACTIVE_, m_router->curCycle());
+ 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(m_router->curCycle())) {
+ 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(), m_router->curCycle());
+
+ delete t_credit;
+ }
+}
+
+flitBuffer*
+OutputUnit::getOutQueue()
+{
+ return m_out_buffer;
+}
+
+void
+OutputUnit::set_out_link(NetworkLink *link)
+{
+ m_out_link = link;
+}
+
+void
+OutputUnit::set_credit_link(CreditLink *credit_link)
+{
+ m_credit_link = credit_link;
+}
+
+uint32_t
+OutputUnit::functionalWrite(Packet *pkt)
+{
+ return m_out_buffer->functionalWrite(pkt);
+}
diff --git a/src/mem/ruby/network/garnet2.0/OutputUnit.hh b/src/mem/ruby/network/garnet2.0/OutputUnit.hh
new file mode 100644
index 000000000..7b6d5497c
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/OutputUnit.hh
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_OUTPUT_UNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_OUTPUT_UNIT_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/OutVcState.hh"
+#include "mem/ruby/network/garnet2.0/Router.hh"
+#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
+
+class OutputUnit : public Consumer
+{
+ public:
+ OutputUnit(int id, PortDirection direction, Router *router);
+ ~OutputUnit();
+ 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 m_outvc_state[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, Cycles curTime)
+ {
+ m_outvc_state[vc]->setState(state, curTime);
+ }
+
+ inline bool
+ is_vc_idle(int vc, Cycles curTime)
+ {
+ return (m_outvc_state[vc]->isInState(IDLE_, curTime));
+ }
+
+ inline void
+ insert_flit(flit *t_flit)
+ {
+ m_out_buffer->insert(t_flit);
+ m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
+ }
+
+ uint32_t functionalWrite(Packet *pkt);
+
+ private:
+ int m_id;
+ PortDirection m_direction;
+ int m_num_vcs;
+ int m_vc_per_vnet;
+ Router *m_router;
+ NetworkLink *m_out_link;
+ CreditLink *m_credit_link;
+
+ flitBuffer *m_out_buffer; // This is for the network link to consume
+ std::vector<OutVcState *> m_outvc_state; // vc state of downstream router
+
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_OUTPUT_UNIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/README.txt b/src/mem/ruby/network/garnet2.0/README.txt
new file mode 100644
index 000000000..817b1d48d
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/README.txt
@@ -0,0 +1,71 @@
+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
new file mode 100644
index 000000000..65a730096
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/Router.cc
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/Router.hh"
+
+#include "base/stl_helpers.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet2.0/CreditLink.hh"
+#include "mem/ruby/network/garnet2.0/CrossbarSwitch.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"
+#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
+#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
+
+using namespace std;
+using m5::stl_helpers::deletePointers;
+
+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_routing_unit = new RoutingUnit(this);
+ m_sw_alloc = new SwitchAllocator(this);
+ m_switch = new CrossbarSwitch(this);
+
+ m_input_unit.clear();
+ m_output_unit.clear();
+}
+
+Router::~Router()
+{
+ deletePointers(m_input_unit);
+ deletePointers(m_output_unit);
+ delete m_routing_unit;
+ delete m_sw_alloc;
+ delete m_switch;
+}
+
+void
+Router::init()
+{
+ BasicRouter::init();
+
+ m_sw_alloc->init();
+ m_switch->init();
+}
+
+void
+Router::wakeup()
+{
+ DPRINTF(RubyNetwork, "Router %d woke up\n", m_id);
+
+ // 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
+ m_sw_alloc->wakeup();
+
+ // Switch Traversal
+ m_switch->wakeup();
+}
+
+void
+Router::addInPort(PortDirection inport_dirn,
+ NetworkLink *in_link, CreditLink *credit_link)
+{
+ 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);
+ credit_link->setSourceQueue(input_unit->getCreditQueue());
+
+ m_input_unit.push_back(input_unit);
+
+ m_routing_unit->addInDirection(inport_dirn, port_num);
+}
+
+void
+Router::addOutPort(PortDirection outport_dirn,
+ NetworkLink *out_link,
+ const NetDest& routing_table_entry, int link_weight,
+ CreditLink *credit_link)
+{
+ int port_num = m_output_unit.size();
+ OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this);
+
+ output_unit->set_out_link(out_link);
+ output_unit->set_credit_link(credit_link);
+ credit_link->setLinkConsumer(this);
+ out_link->setSourceQueue(output_unit->getOutQueue());
+
+ m_output_unit.push_back(output_unit);
+
+ m_routing_unit->addRoute(routing_table_entry);
+ m_routing_unit->addWeight(link_weight);
+ m_routing_unit->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 m_routing_unit->outportCompute(route, inport, inport_dirn);
+}
+
+void
+Router::grant_switch(int inport, flit *t_flit)
+{
+ m_switch->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 = m_sw_alloc->get_input_arbiter_activity();
+ m_sw_output_arbiter_activity = m_sw_alloc->get_output_arbiter_activity();
+ m_crossbar_activity = m_switch->get_crossbar_activity();
+}
+
+void
+Router::resetStats()
+{
+ for (int j = 0; j < m_virtual_networks; j++) {
+ for (int i = 0; i < m_input_unit.size(); i++) {
+ m_input_unit[i]->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 += m_switch->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
new file mode 100644
index 000000000..a9ce5f80e
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/Router.hh
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_ROUTER_HH__
+#define __MEM_RUBY_NETWORK_GARNET_ROUTER_HH__
+
+#include <iostream>
+#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/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet2.0/flit.hh"
+#include "params/GarnetRouter.hh"
+
+class NetworkLink;
+class CreditLink;
+class InputUnit;
+class OutputUnit;
+class RoutingUnit;
+class SwitchAllocator;
+class CrossbarSwitch;
+class FaultModel;
+
+class Router : public BasicRouter, public Consumer
+{
+ public:
+ typedef GarnetRouterParams Params;
+ Router(const Params *p);
+
+ ~Router();
+
+ 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,
+ const NetDest& routing_table_entry,
+ int link_weight, CreditLink *credit_link);
+
+ Cycles get_pipe_stages(){ return m_latency; }
+ int get_num_vcs() { return m_num_vcs; }
+ int get_num_vnets() { return m_virtual_networks; }
+ int 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; }
+ std::vector<InputUnit *>& get_inputUnit_ref() { return m_input_unit; }
+ std::vector<OutputUnit *>& get_outputUnit_ref() { return m_output_unit; }
+ 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;
+ int m_virtual_networks, m_num_vcs, m_vc_per_vnet;
+ GarnetNetwork *m_network_ptr;
+
+ std::vector<InputUnit *> m_input_unit;
+ std::vector<OutputUnit *> m_output_unit;
+ RoutingUnit *m_routing_unit;
+ SwitchAllocator *m_sw_alloc;
+ CrossbarSwitch *m_switch;
+
+ // 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_ROUTER_HH__
diff --git a/src/mem/ruby/network/garnet2.0/RoutingUnit.cc b/src/mem/ruby/network/garnet2.0/RoutingUnit.cc
new file mode 100644
index 000000000..aa5ff53c1
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/RoutingUnit.cc
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
+
+#include "base/cast.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(const NetDest& routing_table_entry)
+{
+ m_routing_table.push_back(routing_table_entry);
+}
+
+void
+RoutingUnit::addWeight(int link_weight)
+{
+ m_weight_table.push_back(link_weight);
+}
+
+/*
+ * 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.size(); link++) {
+ if (msg_destination.intersectionIsNotEmpty(m_routing_table[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.size(); link++) {
+ if (msg_destination.intersectionIsNotEmpty(m_routing_table[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 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
+ assert(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)
+{
+ assert(0);
+}
diff --git a/src/mem/ruby/network/garnet2.0/RoutingUnit.hh b/src/mem/ruby/network/garnet2.0/RoutingUnit.hh
new file mode 100644
index 000000000..46b0969f3
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/RoutingUnit.hh
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_ROUTING_UNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_ROUTING_UNIT_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(const 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);
+
+ private:
+ Router *m_router;
+
+ // Routing Table
+ 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_ROUTING_UNIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/SConscript b/src/mem/ruby/network/garnet2.0/SConscript
new file mode 100644
index 000000000..866bab9ac
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/SConscript
@@ -0,0 +1,53 @@
+# -*- 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.
+#
+# Authors: Tushar Krishna
+
+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')
diff --git a/src/mem/ruby/network/garnet2.0/SwitchAllocator.cc b/src/mem/ruby/network/garnet2.0/SwitchAllocator.cc
new file mode 100644
index 000000000..7916802a5
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/SwitchAllocator.cc
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#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_input_unit = m_router->get_inputUnit_ref();
+ m_output_unit = m_router->get_outputUnit_ref();
+
+ 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];
+
+ // Select next round robin vc candidate within valid vnet
+ int next_round_robin_invc = invc;
+ next_round_robin_invc++;
+ if (next_round_robin_invc >= m_num_vcs)
+ next_round_robin_invc = 0;
+ m_round_robin_invc[inport] = next_round_robin_invc;
+
+ for (int invc_iter = 0; invc_iter < m_num_vcs; invc_iter++) {
+
+ if (m_input_unit[inport]->need_stage(invc, SA_,
+ m_router->curCycle())) {
+
+ // This flit is in SA stage
+
+ int outport = m_input_unit[inport]->get_outport(invc);
+ int outvc = m_input_unit[inport]->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];
+ m_round_robin_inport[outport]++;
+
+ if (m_round_robin_inport[outport] >= m_num_inports)
+ m_round_robin_inport[outport] = 0;
+
+ 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]) {
+
+ // grant this outport to this inport
+ int invc = m_vc_winners[outport][inport];
+
+ int outvc = m_input_unit[inport]->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 = m_input_unit[inport]->getTopFlit(invc);
+
+ DPRINTF(RubyNetwork, "SwitchAllocator at Router %d "
+ "granted outvc %d at outport %d "
+ "to invc %d at inport %d to flit %s at "
+ "time: %lld\n",
+ m_router->get_id(), outvc,
+ m_router->getPortDirectionName(
+ m_output_unit[outport]->get_direction()),
+ invc,
+ m_router->getPortDirectionName(
+ m_input_unit[inport]->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
+ m_output_unit[outport]->decrement_credit(outvc);
+
+ // flit ready for Switch Traversal
+ t_flit->advance_stage(ST_, m_router->curCycle());
+ 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(!(m_input_unit[inport]->isReady(invc,
+ m_router->curCycle())));
+
+ // Free this VC
+ m_input_unit[inport]->set_vc_idle(invc,
+ m_router->curCycle());
+
+ // Send a credit back
+ // along with the information that this VC is now idle
+ m_input_unit[inport]->increment_credit(invc, true,
+ m_router->curCycle());
+ } else {
+ // Send a credit back
+ // but do not indicate that the VC is idle
+ m_input_unit[inport]->increment_credit(invc, false,
+ m_router->curCycle());
+ }
+
+ // remove this request
+ m_port_requests[outport][inport] = false;
+
+ 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;
+
+ if (!has_outvc) {
+
+ // needs outvc
+ // this is only true for HEAD and HEAD_TAIL flits.
+
+ if (m_output_unit[outport]->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 = m_output_unit[outport]->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)) {
+
+ // enqueue time of this flit
+ Cycles t_enqueue_time = m_input_unit[inport]->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 (m_input_unit[inport]->need_stage(temp_vc, SA_,
+ m_router->curCycle()) &&
+ (m_input_unit[inport]->get_outport(temp_vc) == outport) &&
+ (m_input_unit[inport]->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_output_unit[outport]->select_free_vc(get_vnet(invc));
+
+ // has to get a valid VC since it checked before performing SA
+ assert(outvc != -1);
+ m_input_unit[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()
+{
+ Cycles nextCycle = m_router->curCycle() + Cycles(1);
+
+ for (int i = 0; i < m_num_inports; i++) {
+ for (int j = 0; j < m_num_vcs; j++) {
+ if (m_input_unit[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;
+ }
+ }
+}
diff --git a/src/mem/ruby/network/garnet2.0/SwitchAllocator.hh b/src/mem/ruby/network/garnet2.0/SwitchAllocator.hh
new file mode 100644
index 000000000..162264e85
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/SwitchAllocator.hh
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_SWITCH_ALLOCATOR_HH__
+#define __MEM_RUBY_NETWORK_GARNET_SWITCH_ALLOCATOR_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;
+ }
+
+ 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
+ std::vector<InputUnit *> m_input_unit;
+ std::vector<OutputUnit *> m_output_unit;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_SWITCH_ALLOCATOR_HH__
diff --git a/src/mem/ruby/network/garnet2.0/VirtualChannel.cc b/src/mem/ruby/network/garnet2.0/VirtualChannel.cc
new file mode 100644
index 000000000..55f2a874c
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/VirtualChannel.cc
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
+
+VirtualChannel::VirtualChannel(int id)
+ : m_enqueue_time(INFINITE_)
+{
+ m_id = id;
+ m_input_buffer = new flitBuffer();
+ m_vc_state.first = IDLE_;
+ m_vc_state.second = Cycles(0);
+ m_output_vc = -1;
+ m_output_port = -1;
+}
+
+VirtualChannel::~VirtualChannel()
+{
+ delete m_input_buffer;
+}
+
+void
+VirtualChannel::set_idle(Cycles curTime)
+{
+ m_vc_state.first = IDLE_;
+ m_vc_state.second = curTime;
+ m_enqueue_time = Cycles(INFINITE_);
+ m_output_port = -1;
+ m_output_vc = -1;
+}
+
+void
+VirtualChannel::set_active(Cycles curTime)
+{
+ m_vc_state.first = ACTIVE_;
+ m_vc_state.second = curTime;
+ m_enqueue_time = curTime;
+}
+
+bool
+VirtualChannel::need_stage(flit_stage stage, Cycles time)
+{
+ if (m_input_buffer->isReady(time)) {
+ assert(m_vc_state.first == ACTIVE_ && m_vc_state.second <= time);
+ flit *t_flit = m_input_buffer->peekTopFlit();
+ return(t_flit->is_stage(stage, time));
+ }
+ return false;
+}
+
+uint32_t
+VirtualChannel::functionalWrite(Packet *pkt)
+{
+ return m_input_buffer->functionalWrite(pkt);
+}
diff --git a/src/mem/ruby/network/garnet2.0/VirtualChannel.hh b/src/mem/ruby/network/garnet2.0/VirtualChannel.hh
new file mode 100644
index 000000000..d5f7687dc
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/VirtualChannel.hh
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_VIRTUAL_CHANNEL_HH__
+#define __MEM_RUBY_NETWORK_GARNET_VIRTUAL_CHANNEL_HH__
+
+#include <utility>
+
+#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
+#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
+
+class VirtualChannel
+{
+ public:
+ VirtualChannel(int id);
+ ~VirtualChannel();
+
+ bool need_stage(flit_stage stage, Cycles time);
+ void set_idle(Cycles curTime);
+ void set_active(Cycles 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 Cycles get_enqueue_time() { return m_enqueue_time; }
+ inline void set_enqueue_time(Cycles time) { m_enqueue_time = time; }
+ inline VC_state_type get_state() { return m_vc_state.first; }
+
+ inline bool isReady(Cycles curTime)
+ {
+ return m_input_buffer->isReady(curTime);
+ }
+
+ inline void
+ insertFlit(flit *t_flit)
+ {
+ m_input_buffer->insert(t_flit);
+ }
+
+ inline void
+ set_state(VC_state_type m_state, Cycles curTime)
+ {
+ m_vc_state.first = m_state;
+ m_vc_state.second = curTime;
+ }
+
+ inline flit*
+ peekTopFlit()
+ {
+ return m_input_buffer->peekTopFlit();
+ }
+
+ inline flit*
+ getTopFlit()
+ {
+ return m_input_buffer->getTopFlit();
+ }
+
+ uint32_t functionalWrite(Packet *pkt);
+
+ private:
+ int m_id;
+ flitBuffer *m_input_buffer;
+ std::pair<VC_state_type, Cycles> m_vc_state;
+ int m_output_port;
+ Cycles m_enqueue_time;
+ int m_output_vc;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_VIRTUAL_CHANNEL_HH__
diff --git a/src/mem/ruby/network/garnet2.0/flit.cc b/src/mem/ruby/network/garnet2.0/flit.cc
new file mode 100644
index 000000000..e507ea442
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/flit.cc
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#include "mem/ruby/network/garnet2.0/flit.hh"
+
+// Constructor for the flit
+flit::flit(int id, int vc, int vnet, RouteInfo route, int size,
+ MsgPtr msg_ptr, Cycles curTime)
+{
+ m_size = size;
+ m_msg_ptr = msg_ptr;
+ m_enqueue_time = curTime;
+ m_time = curTime;
+ m_id = id;
+ m_vnet = vnet;
+ m_vc = vc;
+ m_route = route;
+ m_stage.first = I_;
+ m_stage.second = m_time;
+
+ 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 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 << "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 << "Enqueue Time=" << m_enqueue_time << " ";
+ 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
new file mode 100644
index 000000000..3e30ec98c
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/flit.hh
@@ -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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_FLIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_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, Cycles curTime);
+
+ int get_outport() {return m_outport; }
+ int get_size() { return m_size; }
+ Cycles get_enqueue_time() { return m_enqueue_time; }
+ int get_id() { return m_id; }
+ Cycles 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, Cycles> get_stage() { return m_stage; }
+ Cycles get_src_delay() { return src_delay; }
+
+ void set_outport(int port) { m_outport = port; }
+ void set_time(Cycles time) { m_time = time; }
+ void set_vc(int vc) { m_vc = vc; }
+ void set_route(RouteInfo route) { m_route = route; }
+ void set_src_delay(Cycles delay) { src_delay = delay; }
+
+ void increment_hops() { m_route.hops_traversed++; }
+ void print(std::ostream& out) const;
+
+ bool
+ is_stage(flit_stage stage, Cycles time)
+ {
+ return (stage == m_stage.first &&
+ time >= m_stage.second);
+ }
+
+ void
+ advance_stage(flit_stage t_stage, Cycles 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);
+
+ protected:
+ int m_id;
+ int m_vnet;
+ int m_vc;
+ RouteInfo m_route;
+ int m_size;
+ Cycles m_enqueue_time, m_time;
+ flit_type m_type;
+ MsgPtr m_msg_ptr;
+ int m_outport;
+ Cycles src_delay;
+ std::pair<flit_stage, Cycles> 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_FLIT_HH__
diff --git a/src/mem/ruby/network/garnet2.0/flitBuffer.cc b/src/mem/ruby/network/garnet2.0/flitBuffer.cc
new file mode 100644
index 000000000..1a089936e
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/flitBuffer.cc
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#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(Cycles 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
new file mode 100644
index 000000000..eb6ad6167
--- /dev/null
+++ b/src/mem/ruby/network/garnet2.0/flitBuffer.hh
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ *
+ * Authors: Niket Agarwal
+ * Tushar Krishna
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_FLIT_BUFFER_HH__
+#define __MEM_RUBY_NETWORK_GARNET_FLIT_BUFFER_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(Cycles curTime);
+ bool isEmpty();
+ void print(std::ostream& out) const;
+ bool isFull();
+ void setMaxSize(int maximum);
+
+ 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_FLIT_BUFFER_HH__