import m5
from m5.objects import *
from m5.defines import buildEnv
-from m5.util import addToPath, fatal
+from m5.util import addToPath, fatal, warn
def define_options(parser):
# By default, ruby uses the simple timing cpu
parser.add_option("--mesh-rows", type="int", default=0,
help="the number of rows in the mesh topology")
parser.add_option("--network", type="choice", default="simple",
- choices=['simple', 'garnet2.0'],
- help="'simple'|'garnet2.0'")
+ choices=['simple', 'garnet'],
+ help="""'simple'|'garnet' (garnet2.0 will be
+ deprecated.)""")
parser.add_option("--router-latency", action="store", type="int",
default=1,
help="""number of pipeline stages in the garnet router.
default=0,
help="""routing algorithm in network.
0: weight-based table
- 1: XY (for Mesh. see garnet2.0/RoutingUnit.cc)
- 2: Custom (see garnet2.0/RoutingUnit.cc""")
+ 1: XY (for Mesh. see garnet/RoutingUnit.cc)
+ 2: Custom (see garnet/RoutingUnit.cc""")
parser.add_option("--network-fault-model", action="store_true",
default=False,
help="""enable network fault model:
def create_network(options, ruby):
- # Set the network classes based on the command line options
+ # Allow legacy users to use garnet through garnet2.0 option
+ # until next gem5 release.
if options.network == "garnet2.0":
+ warn("Usage of option 'garnet2.0' will be depracated. " \
+ "Please use 'garnet' for using the latest garnet " \
+ "version. Current version: 3.0")
+ options.network = "garnet"
+
+ # Set the network classes based on the command line options
+ if options.network == "garnet":
NetworkClass = GarnetNetwork
IntLinkClass = GarnetIntLink
ExtLinkClass = GarnetExtLink
def init_network(options, network, InterfaceClass):
- if options.network == "garnet2.0":
+ if options.network == "garnet":
network.num_rows = options.mesh_rows
network.vcs_per_vnet = options.vcs_per_vnet
network.ni_flit_size = options.link_width_bits / 8
network.netifs = netifs
if options.network_fault_model:
- assert(options.network == "garnet2.0")
+ assert(options.network == "garnet")
network.enable_fault_model = True
network.fault_model = FaultModel()
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_COMMONTYPES_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_COMMONTYPES_HH__
+
+#include "mem/ruby/common/NetDest.hh"
+
+// All common enums and typedefs go here
+
+enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_,
+ CREDIT_, NUM_FLIT_TYPE_};
+enum VC_state_type {IDLE_, VC_AB_, ACTIVE_, NUM_VC_STATE_TYPE_};
+enum VNET_type {CTRL_VNET_, DATA_VNET_, NULL_VNET_, NUM_VNET_TYPE_};
+enum flit_stage {I_, VA_, SA_, ST_, LT_, NUM_FLIT_STAGE_};
+enum link_type { EXT_IN_, EXT_OUT_, INT_, NUM_LINK_TYPES_ };
+enum RoutingAlgorithm { TABLE_ = 0, XY_ = 1, CUSTOM_ = 2,
+ NUM_ROUTING_ALGORITHM_};
+
+struct RouteInfo
+{
+ RouteInfo()
+ : vnet(0), src_ni(0), src_router(0), dest_ni(0), dest_router(0),
+ hops_traversed(0)
+ {}
+
+ // destination format for table-based routing
+ int vnet;
+ NetDest net_dest;
+
+ // src and dest format for topology-specific routing
+ int src_ni;
+ int src_router;
+ int dest_ni;
+ int dest_router;
+ int hops_traversed;
+};
+
+#define INFINITE_ 10000
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_COMMONTYPES_HH__
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "mem/ruby/network/garnet/Credit.hh"
+
+#include "base/trace.hh"
+#include "debug/RubyNetwork.hh"
+
+// Credit Signal for buffers inside VC
+// Carries m_vc (inherits from flit.hh)
+// and m_is_free_signal (whether VC is free or not)
+
+Credit::Credit(int vc, bool is_free_signal, Tick curTime)
+ : flit(0, vc, 0, RouteInfo(), 0, nullptr, 0, 0, curTime)
+{
+ m_is_free_signal = is_free_signal;
+ m_type = CREDIT_;
+}
+
+flit *
+Credit::serialize(int ser_id, int parts, uint32_t bWidth)
+{
+ DPRINTF(RubyNetwork, "Serializing a credit\n");
+ bool new_free = false;
+ if ((ser_id+1 == parts) && m_is_free_signal) {
+ new_free = true;
+ }
+ Credit *new_credit_flit = new Credit(m_vc, new_free, m_time);
+ return new_credit_flit;
+}
+
+flit *
+Credit::deserialize(int des_id, int num_flits, uint32_t bWidth)
+{
+ DPRINTF(RubyNetwork, "DeSerializing a credit vc:%d free:%d\n",
+ m_vc, m_is_free_signal);
+ if (m_is_free_signal) {
+ // We are not going to get anymore credits for this vc
+ // So send a credit in any case
+ return new Credit(m_vc, true, m_time);
+ }
+
+ return new Credit(m_vc, false, m_time);
+}
+
+void
+Credit::print(std::ostream& out) const
+{
+ out << "[Credit:: ";
+ out << "Type=" << m_type << " ";
+ out << "VC=" << m_vc << " ";
+ out << "FreeVC=" << m_is_free_signal << " ";
+ out << "Set Time=" << m_time << " ";
+ out << "]";
+}
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_CREDIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_CREDIT_HH__
+
+#include <cassert>
+#include <iostream>
+
+#include "base/types.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+
+// Credit Signal for buffers inside VC
+// Carries m_vc (inherits from flit.hh)
+// and m_is_free_signal (whether VC is free or not)
+
+class Credit : public flit
+{
+ public:
+ Credit() {};
+ Credit(int vc, bool is_free_signal, Tick curTime);
+
+ // Functions used by SerDes
+ flit* serialize(int ser_id, int parts, uint32_t bWidth);
+ flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
+ void print(std::ostream& out) const;
+
+ ~Credit() {};
+
+ bool is_free_signal() { return m_is_free_signal; }
+
+ private:
+ bool m_is_free_signal;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_CREDIT_HH__
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_CREDITLINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_CREDITLINK_HH__
+
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "params/CreditLink.hh"
+
+class CreditLink : public NetworkLink
+{
+ public:
+ typedef CreditLinkParams Params;
+ CreditLink(const Params *p) : NetworkLink(p) {}
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_CREDITLINK_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/CrossbarSwitch.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+
+CrossbarSwitch::CrossbarSwitch(Router *router)
+ : Consumer(router), m_router(router), m_num_vcs(m_router->get_num_vcs()),
+ m_crossbar_activity(0), switchBuffers(0)
+{
+}
+
+void
+CrossbarSwitch::init()
+{
+ switchBuffers.resize(m_router->get_num_inports());
+}
+
+/*
+ * The wakeup function of the CrossbarSwitch loops through all input ports,
+ * and sends the winning flit (from SA) out of its output port on to the
+ * output link. The output link is scheduled for wakeup in the next cycle.
+ */
+
+void
+CrossbarSwitch::wakeup()
+{
+ DPRINTF(RubyNetwork, "CrossbarSwitch at Router %d woke up "
+ "at time: %lld\n",
+ m_router->get_id(), m_router->curCycle());
+
+ for (auto& switch_buffer : switchBuffers) {
+ if (!switch_buffer.isReady(curTick())) {
+ continue;
+ }
+
+ flit *t_flit = switch_buffer.peekTopFlit();
+ if (t_flit->is_stage(ST_, curTick())) {
+ int outport = t_flit->get_outport();
+
+ // flit performs LT_ in the next cycle
+ t_flit->advance_stage(LT_, m_router->clockEdge(Cycles(1)));
+ t_flit->set_time(m_router->clockEdge(Cycles(1)));
+
+ // This will take care of waking up the Network Link
+ // in the next cycle
+ m_router->getOutputUnit(outport)->insert_flit(t_flit);
+ switch_buffer.getTopFlit();
+ m_crossbar_activity++;
+ }
+ }
+}
+
+uint32_t
+CrossbarSwitch::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ for (auto& switch_buffer : switchBuffers) {
+ num_functional_writes += switch_buffer.functionalWrite(pkt);
+ }
+
+ return num_functional_writes;
+}
+
+void
+CrossbarSwitch::resetStats()
+{
+ m_crossbar_activity = 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_CROSSBARSWITCH_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_CROSSBARSWITCH_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+class Router;
+
+class CrossbarSwitch : public Consumer
+{
+ public:
+ CrossbarSwitch(Router *router);
+ ~CrossbarSwitch() = default;
+ void wakeup();
+ void init();
+ void print(std::ostream& out) const {};
+
+ inline void
+ update_sw_winner(int inport, flit *t_flit)
+ {
+ switchBuffers[inport].insert(t_flit);
+ }
+
+ inline double get_crossbar_activity() { return m_crossbar_activity; }
+
+ uint32_t functionalWrite(Packet *pkt);
+ void resetStats();
+
+ private:
+ Router *m_router;
+ int m_num_vcs;
+ double m_crossbar_activity;
+ std::vector<flitBuffer> switchBuffers;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_CROSSBARSWITCH_HH__
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/GarnetLink.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/NetworkBridge.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+
+GarnetIntLink::GarnetIntLink(const Params *p)
+ : BasicIntLink(p)
+{
+ // Uni-directional
+
+ m_network_link = p->network_link;
+ m_credit_link = p->credit_link;
+
+ srcCdcEn = p->src_cdc;
+ dstCdcEn = p->dst_cdc;
+
+ srcSerdesEn = p->src_serdes;
+ dstSerdesEn = p->dst_serdes;
+
+ srcBridgeEn = false;
+ dstBridgeEn = false;
+
+ if (srcCdcEn || srcSerdesEn) {
+ srcBridgeEn = true;
+ srcNetBridge = p->src_net_bridge;
+ srcCredBridge = p->src_cred_bridge;
+ }
+ if (dstCdcEn || dstSerdesEn) {
+ dstBridgeEn = true;
+ dstNetBridge = p->dst_net_bridge;
+ dstCredBridge = p->dst_cred_bridge;
+ }
+
+}
+
+void
+GarnetIntLink::init()
+{
+ if (srcBridgeEn) {
+ assert(srcNetBridge && srcCredBridge);
+ srcNetBridge->initBridge(srcCredBridge, srcCdcEn, srcSerdesEn);
+ srcCredBridge->initBridge(srcNetBridge, srcCdcEn, srcSerdesEn);
+ }
+
+ if (dstBridgeEn) {
+ assert(dstNetBridge && dstCredBridge);
+ dstNetBridge->initBridge(dstCredBridge, dstCdcEn, dstSerdesEn);
+ dstCredBridge->initBridge(dstNetBridge, dstCdcEn, dstSerdesEn);
+ }
+}
+
+void
+GarnetIntLink::print(std::ostream& out) const
+{
+ out << name();
+}
+
+GarnetIntLink *
+GarnetIntLinkParams::create()
+{
+ return new GarnetIntLink(this);
+}
+
+GarnetExtLink::GarnetExtLink(const Params *p)
+ : BasicExtLink(p)
+{
+ // Bi-directional
+
+ // In
+ m_network_links[0] = p->network_links[0];
+ m_credit_links[0] = p->credit_links[0];
+
+ // Out
+ m_network_links[1] = p->network_links[1];
+ m_credit_links[1] = p->credit_links[1];
+
+
+ extCdcEn = p->ext_cdc;
+ intCdcEn = p->int_cdc;
+
+ extSerdesEn = p->ext_serdes;
+ intSerdesEn = p->int_serdes;
+
+ extBridgeEn = false;
+ intBridgeEn = false;
+
+ if (extCdcEn || extSerdesEn) {
+ extBridgeEn = true;
+ extNetBridge[0] = p->ext_net_bridge[0];
+ extCredBridge[0] = p->ext_cred_bridge[0];
+ extNetBridge[1] = p->ext_net_bridge[1];
+ extCredBridge[1] = p->ext_cred_bridge[1];
+ }
+
+ if (intCdcEn || intSerdesEn) {
+ intBridgeEn = true;
+ intNetBridge[0] = p->int_net_bridge[0];
+ intNetBridge[1] = p->int_net_bridge[1];
+ intCredBridge[0] = p->int_cred_bridge[0];
+ intCredBridge[1] = p->int_cred_bridge[1];
+ }
+
+}
+
+void
+GarnetExtLink::init()
+{
+ if (extBridgeEn) {
+ assert(extNetBridge[0] && extCredBridge[0] &&
+ extNetBridge[1] && extCredBridge[1]);
+ extNetBridge[0]->initBridge(extCredBridge[0], extCdcEn, extSerdesEn);
+ extCredBridge[0]->initBridge(extNetBridge[0], extCdcEn, extSerdesEn);
+ extNetBridge[1]->initBridge(extCredBridge[1], extCdcEn, extSerdesEn);
+ extCredBridge[1]->initBridge(extNetBridge[1], extCdcEn, extSerdesEn);
+ }
+
+ if (intBridgeEn) {
+ assert(intNetBridge[0] && intCredBridge[0] &&
+ intNetBridge[1] && intCredBridge[1]);
+ intNetBridge[0]->initBridge(intCredBridge[0], intCdcEn, intSerdesEn);
+ intCredBridge[0]->initBridge(intNetBridge[0], intCdcEn, intSerdesEn);
+ intNetBridge[1]->initBridge(intCredBridge[1], intCdcEn, intSerdesEn);
+ intCredBridge[1]->initBridge(intNetBridge[1], intCdcEn, intSerdesEn);
+ }
+}
+
+void
+GarnetExtLink::print(std::ostream& out) const
+{
+ out << name();
+}
+
+GarnetExtLink *
+GarnetExtLinkParams::create()
+{
+ return new GarnetExtLink(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_GARNETLINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_GARNETLINK_HH__
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "mem/ruby/network/BasicLink.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/NetworkBridge.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "params/GarnetExtLink.hh"
+#include "params/GarnetIntLink.hh"
+
+class GarnetIntLink : public BasicIntLink
+{
+ public:
+ typedef GarnetIntLinkParams Params;
+ GarnetIntLink(const Params *p);
+
+ void init();
+
+ void print(std::ostream& out) const;
+
+ friend class GarnetNetwork;
+
+ protected:
+ NetworkLink* m_network_link;
+ CreditLink* m_credit_link;
+
+ bool srcBridgeEn;
+ bool dstBridgeEn;
+
+ bool srcSerdesEn;
+ bool dstSerdesEn;
+
+ bool srcCdcEn;
+ bool dstCdcEn;
+
+ NetworkBridge* srcNetBridge;
+ NetworkBridge* dstNetBridge;
+
+ NetworkBridge* srcCredBridge;
+ NetworkBridge* dstCredBridge;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetIntLink& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+class GarnetExtLink : public BasicExtLink
+{
+ public:
+ typedef GarnetExtLinkParams Params;
+ GarnetExtLink(const Params *p);
+
+ void init();
+
+ void print(std::ostream& out) const;
+
+ friend class GarnetNetwork;
+
+ protected:
+ bool extBridgeEn;
+ bool intBridgeEn;
+
+ bool extSerdesEn;
+ bool intSerdesEn;
+
+ bool extCdcEn;
+ bool intCdcEn;
+
+ NetworkLink* m_network_links[2];
+ CreditLink* m_credit_links[2];
+
+ NetworkBridge* extNetBridge[2];
+ NetworkBridge* intNetBridge[2];
+
+ NetworkBridge* extCredBridge[2];
+ NetworkBridge* intCredBridge[2];
+
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetExtLink& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_GARNETLINK_HH__
--- /dev/null
+# Copyright (c) 2008 Princeton University
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from m5.params import *
+from m5.proxy import *
+from m5.objects.ClockedObject import ClockedObject
+from m5.objects.BasicLink import BasicIntLink, BasicExtLink
+
+class CDCType(Enum): vals = [
+ 'LINK_OBJECT',
+ 'OBJECT_LINK',
+ ]
+
+class NetworkLink(ClockedObject):
+ type = 'NetworkLink'
+ cxx_header = "mem/ruby/network/garnet/NetworkLink.hh"
+ link_id = Param.Int(Parent.link_id, "link id")
+ link_latency = Param.Cycles(Parent.latency, "link latency")
+ vcs_per_vnet = Param.Int(Parent.vcs_per_vnet,
+ "virtual channels per virtual network")
+ virt_nets = Param.Int(Parent.number_of_virtual_networks,
+ "number of virtual networks")
+ supported_vnets = VectorParam.Int(Parent.supported_vnets,
+ "Vnets supported")
+ width = Param.UInt32(Parent.width, "bit-width of the link")
+
+class CreditLink(NetworkLink):
+ type = 'CreditLink'
+ cxx_header = "mem/ruby/network/garnet/CreditLink.hh"
+
+class NetworkBridge(CreditLink):
+ type = 'NetworkBridge'
+ cxx_header = "mem/ruby/network/garnet/NetworkBridge.hh"
+ link = Param.NetworkLink("Associated Network Link")
+ vtype = Param.CDCType('LINK_OBJECT',
+ "Direction of CDC LINK->OBJECT or OBJECT->LINK")
+ serdes_latency = Param.Cycles(1, "Latency of SerDes Unit")
+ cdc_latency = Param.Cycles(1, "Latency of CDC Unit")
+
+# Interior fixed pipeline links between routers
+class GarnetIntLink(BasicIntLink):
+ type = 'GarnetIntLink'
+ cxx_header = "mem/ruby/network/garnet/GarnetLink.hh"
+ # The internal link includes one forward link (for flit)
+ # and one backward flow-control link (for credit)
+ network_link = Param.NetworkLink(NetworkLink(), "forward link")
+ credit_link = Param.CreditLink(CreditLink(), "backward flow-control link")
+
+ # The src_cdc and dst_cdc flags are used to enable the
+ # clock domain crossing(CDC) at the source and destination
+ # end of the link respectively. This is required when the
+ # link and the objected connected to the link are operating
+ # at different clock domains. These flags should be set
+ # in the network topology files.
+ src_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+ dst_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+
+ # The src_serdes and dst_serdes flags are used to enable
+ # the Serializer-Deserializer units at the source and
+ # destination end of the link respectively. Enabling
+ # these flags is necessary when the connecting object
+ # supports a different flit width.
+ src_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+ dst_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+
+ # The network bridge encapsulates both the CDC and Ser-Des
+ # units in HeteroGarnet. This is automatically enabled when
+ # either CDC or Ser-Des is enabled.
+ src_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at source")
+ dst_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at dest")
+ src_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at source")
+ dst_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at dest")
+
+ width = Param.UInt32(Parent.ni_flit_size,
+ "bit width supported by the router")
+
+# Exterior fixed pipeline links between a router and a controller
+class GarnetExtLink(BasicExtLink):
+ type = 'GarnetExtLink'
+ cxx_header = "mem/ruby/network/garnet/GarnetLink.hh"
+ # The external link is bi-directional.
+ # It includes two forward links (for flits)
+ # and two backward flow-control links (for credits),
+ # one per direction
+ _nls = []
+ # In uni-directional link
+ _nls.append(NetworkLink());
+ # Out uni-directional link
+ _nls.append(NetworkLink());
+ network_links = VectorParam.NetworkLink(_nls, "forward links")
+
+ _cls = []
+ # In uni-directional link
+ _cls.append(CreditLink());
+ # Out uni-directional link
+ _cls.append(CreditLink());
+ credit_links = VectorParam.CreditLink(_cls, "backward flow-control links")
+
+ # The ext_cdc and intt_cdc flags are used to enable the
+ # clock domain crossing(CDC) at the external and internal
+ # end of the link respectively. This is required when the
+ # link and the objected connected to the link are operating
+ # at different clock domains. These flags should be set
+ # in the network topology files.
+ ext_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+ int_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
+
+ # The ext_serdes and int_serdes flags are used to enable
+ # the Serializer-Deserializer units at the external and
+ # internal end of the link respectively. Enabling
+ # these flags is necessary when the connecting object
+ # supports a different flit width.
+ ext_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+ int_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
+
+ # The network bridge encapsulates both the CDC and Ser-Des
+ # units in HeteroGarnet. This is automatically enabled when
+ # either CDC or Ser-Des is enabled.
+ ext_net_bridge = VectorParam.NetworkBridge([],
+ "Network Bridge at external end")
+ ext_cred_bridge = VectorParam.NetworkBridge([],
+ "Credit Bridge at external end")
+ int_net_bridge = VectorParam.NetworkBridge([],
+ "Network Bridge at internal end")
+ int_cred_bridge = VectorParam.NetworkBridge([],
+ "Credit Bridge at internal end")
+
+
+ width = Param.UInt32(Parent.ni_flit_size,
+ "bit width supported by the router")
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+
+#include <cassert>
+
+#include "base/cast.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/common/NetDest.hh"
+#include "mem/ruby/network/MessageBuffer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetLink.hh"
+#include "mem/ruby/network/garnet/NetworkInterface.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/system/RubySystem.hh"
+
+using namespace std;
+
+/*
+ * GarnetNetwork sets up the routers and links and collects stats.
+ * Default parameters (GarnetNetwork.py) can be overwritten from command line
+ * (see configs/network/Network.py)
+ */
+
+GarnetNetwork::GarnetNetwork(const Params *p)
+ : Network(p)
+{
+ m_num_rows = p->num_rows;
+ m_ni_flit_size = p->ni_flit_size;
+ m_max_vcs_per_vnet = 0;
+ m_buffers_per_data_vc = p->buffers_per_data_vc;
+ m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
+ m_routing_algorithm = p->routing_algorithm;
+
+ m_enable_fault_model = p->enable_fault_model;
+ if (m_enable_fault_model)
+ fault_model = p->fault_model;
+
+ m_vnet_type.resize(m_virtual_networks);
+
+ for (int i = 0 ; i < m_virtual_networks ; i++) {
+ if (m_vnet_type_names[i] == "response")
+ m_vnet_type[i] = DATA_VNET_; // carries data (and ctrl) packets
+ else
+ m_vnet_type[i] = CTRL_VNET_; // carries only ctrl packets
+ }
+
+ // record the routers
+ for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
+ i != p->routers.end(); ++i) {
+ Router* router = safe_cast<Router*>(*i);
+ m_routers.push_back(router);
+
+ // initialize the router's network pointers
+ router->init_net_ptr(this);
+ }
+
+ // record the network interfaces
+ for (vector<ClockedObject*>::const_iterator i = p->netifs.begin();
+ i != p->netifs.end(); ++i) {
+ NetworkInterface *ni = safe_cast<NetworkInterface *>(*i);
+ m_nis.push_back(ni);
+ ni->init_net_ptr(this);
+ }
+
+ // Print Garnet version
+ inform("Garnet version %s\n", garnetVersion);
+}
+
+void
+GarnetNetwork::init()
+{
+ Network::init();
+
+ for (int i=0; i < m_nodes; i++) {
+ m_nis[i]->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
+ }
+
+ // The topology pointer should have already been initialized in the
+ // parent network constructor
+ assert(m_topology_ptr != NULL);
+ m_topology_ptr->createLinks(this);
+
+ // Initialize topology specific parameters
+ if (getNumRows() > 0) {
+ // Only for Mesh topology
+ // m_num_rows and m_num_cols are only used for
+ // implementing XY or custom routing in RoutingUnit.cc
+ m_num_rows = getNumRows();
+ m_num_cols = m_routers.size() / m_num_rows;
+ assert(m_num_rows * m_num_cols == m_routers.size());
+ } else {
+ m_num_rows = -1;
+ m_num_cols = -1;
+ }
+
+ // FaultModel: declare each router to the fault model
+ if (isFaultModelEnabled()) {
+ for (vector<Router*>::const_iterator i= m_routers.begin();
+ i != m_routers.end(); ++i) {
+ Router* router = safe_cast<Router*>(*i);
+ int router_id M5_VAR_USED =
+ fault_model->declare_router(router->get_num_inports(),
+ router->get_num_outports(),
+ router->get_vc_per_vnet(),
+ getBuffersPerDataVC(),
+ getBuffersPerCtrlVC());
+ assert(router_id == router->get_id());
+ router->printAggregateFaultProbability(cout);
+ router->printFaultVector(cout);
+ }
+ }
+}
+
+/*
+ * This function creates a link from the Network Interface (NI)
+ * into the Network.
+ * It creates a Network Link from the NI to a Router and a Credit Link from
+ * the Router to the NI
+*/
+
+void
+GarnetNetwork::makeExtInLink(NodeID global_src, SwitchID dest, BasicLink* link,
+ std::vector<NetDest>& routing_table_entry)
+{
+ NodeID local_src = getLocalNodeID(global_src);
+ assert(local_src < m_nodes);
+
+ GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
+
+ // GarnetExtLink is bi-directional
+ NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_In];
+ net_link->setType(EXT_IN_);
+ CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_In];
+
+ m_networklinks.push_back(net_link);
+ m_creditlinks.push_back(credit_link);
+
+ PortDirection dst_inport_dirn = "Local";
+
+ m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
+ m_routers[dest]->get_vc_per_vnet());
+
+ /*
+ * We check if a bridge was enabled at any end of the link.
+ * The bridge is enabled if either of clock domain
+ * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
+ * enabled for the link at each end. The bridge encapsulates
+ * the functionality for both CDC and SerDes and is a Consumer
+ * object similiar to a NetworkLink.
+ *
+ * If a bridge was enabled we connect the NI and Routers to
+ * bridge before connecting the link. Example, if an external
+ * bridge is enabled, we would connect:
+ * NI--->NetworkBridge--->GarnetExtLink---->Router
+ */
+ if (garnet_link->extBridgeEn) {
+ DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
+ garnet_link->name());
+ m_nis[local_src]->
+ addOutPort(garnet_link->extNetBridge[LinkDirection_In],
+ garnet_link->extCredBridge[LinkDirection_In],
+ dest, m_routers[dest]->get_vc_per_vnet());
+ } else {
+ m_nis[local_src]->addOutPort(net_link, credit_link, dest,
+ m_routers[dest]->get_vc_per_vnet());
+ }
+
+ if (garnet_link->intBridgeEn) {
+ DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
+ garnet_link->name());
+ m_routers[dest]->
+ addInPort(dst_inport_dirn,
+ garnet_link->intNetBridge[LinkDirection_In],
+ garnet_link->intCredBridge[LinkDirection_In]);
+ } else {
+ m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
+ }
+
+}
+
+/*
+ * This function creates a link from the Network to a NI.
+ * It creates a Network Link from a Router to the NI and
+ * a Credit Link from NI to the Router
+*/
+
+void
+GarnetNetwork::makeExtOutLink(SwitchID src, NodeID global_dest,
+ BasicLink* link,
+ std::vector<NetDest>& routing_table_entry)
+{
+ NodeID local_dest = getLocalNodeID(global_dest);
+ assert(local_dest < m_nodes);
+ assert(src < m_routers.size());
+ assert(m_routers[src] != NULL);
+
+ GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
+
+ // GarnetExtLink is bi-directional
+ NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_Out];
+ net_link->setType(EXT_OUT_);
+ CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_Out];
+
+ m_networklinks.push_back(net_link);
+ m_creditlinks.push_back(credit_link);
+
+ PortDirection src_outport_dirn = "Local";
+
+ m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
+ m_routers[src]->get_vc_per_vnet());
+
+ /*
+ * We check if a bridge was enabled at any end of the link.
+ * The bridge is enabled if either of clock domain
+ * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
+ * enabled for the link at each end. The bridge encapsulates
+ * the functionality for both CDC and SerDes and is a Consumer
+ * object similiar to a NetworkLink.
+ *
+ * If a bridge was enabled we connect the NI and Routers to
+ * bridge before connecting the link. Example, if an external
+ * bridge is enabled, we would connect:
+ * NI<---NetworkBridge<---GarnetExtLink<----Router
+ */
+ if (garnet_link->extBridgeEn) {
+ DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
+ garnet_link->name());
+ m_nis[local_dest]->
+ addInPort(garnet_link->extNetBridge[LinkDirection_Out],
+ garnet_link->extCredBridge[LinkDirection_Out]);
+ } else {
+ m_nis[local_dest]->addInPort(net_link, credit_link);
+ }
+
+ if (garnet_link->intBridgeEn) {
+ DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
+ garnet_link->name());
+ m_routers[src]->
+ addOutPort(src_outport_dirn,
+ garnet_link->intNetBridge[LinkDirection_Out],
+ routing_table_entry, link->m_weight,
+ garnet_link->intCredBridge[LinkDirection_Out],
+ m_routers[src]->get_vc_per_vnet());
+ } else {
+ m_routers[src]->
+ addOutPort(src_outport_dirn, net_link,
+ routing_table_entry,
+ link->m_weight, credit_link,
+ m_routers[src]->get_vc_per_vnet());
+ }
+}
+
+/*
+ * This function creates an internal network link between two routers.
+ * It adds both the network link and an opposite credit link.
+*/
+
+void
+GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
+ std::vector<NetDest>& routing_table_entry,
+ PortDirection src_outport_dirn,
+ PortDirection dst_inport_dirn)
+{
+ GarnetIntLink* garnet_link = safe_cast<GarnetIntLink*>(link);
+
+ // GarnetIntLink is unidirectional
+ NetworkLink* net_link = garnet_link->m_network_link;
+ net_link->setType(INT_);
+ CreditLink* credit_link = garnet_link->m_credit_link;
+
+ m_networklinks.push_back(net_link);
+ m_creditlinks.push_back(credit_link);
+
+ m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
+ std::max(m_routers[dest]->get_vc_per_vnet(),
+ m_routers[src]->get_vc_per_vnet()));
+
+ /*
+ * We check if a bridge was enabled at any end of the link.
+ * The bridge is enabled if either of clock domain
+ * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
+ * enabled for the link at each end. The bridge encapsulates
+ * the functionality for both CDC and SerDes and is a Consumer
+ * object similiar to a NetworkLink.
+ *
+ * If a bridge was enabled we connect the NI and Routers to
+ * bridge before connecting the link. Example, if a source
+ * bridge is enabled, we would connect:
+ * Router--->NetworkBridge--->GarnetIntLink---->Router
+ */
+ if (garnet_link->dstBridgeEn) {
+ DPRINTF(RubyNetwork, "Enable destination bridge for %s\n",
+ garnet_link->name());
+ m_routers[dest]->addInPort(dst_inport_dirn,
+ garnet_link->dstNetBridge, garnet_link->dstCredBridge);
+ } else {
+ m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
+ }
+
+ if (garnet_link->srcBridgeEn) {
+ DPRINTF(RubyNetwork, "Enable source bridge for %s\n",
+ garnet_link->name());
+ m_routers[src]->
+ addOutPort(src_outport_dirn, garnet_link->srcNetBridge,
+ routing_table_entry,
+ link->m_weight, garnet_link->srcCredBridge,
+ m_routers[dest]->get_vc_per_vnet());
+ } else {
+ m_routers[src]->addOutPort(src_outport_dirn, net_link,
+ routing_table_entry,
+ link->m_weight, credit_link,
+ m_routers[dest]->get_vc_per_vnet());
+ }
+}
+
+// Total routers in the network
+int
+GarnetNetwork::getNumRouters()
+{
+ return m_routers.size();
+}
+
+// Get ID of router connected to a NI.
+int
+GarnetNetwork::get_router_id(int global_ni, int vnet)
+{
+ NodeID local_ni = getLocalNodeID(global_ni);
+
+ return m_nis[local_ni]->get_router_id(vnet);
+}
+
+void
+GarnetNetwork::regStats()
+{
+ Network::regStats();
+
+ // Packets
+ m_packets_received
+ .init(m_virtual_networks)
+ .name(name() + ".packets_received")
+ .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+ ;
+
+ m_packets_injected
+ .init(m_virtual_networks)
+ .name(name() + ".packets_injected")
+ .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+ ;
+
+ m_packet_network_latency
+ .init(m_virtual_networks)
+ .name(name() + ".packet_network_latency")
+ .flags(Stats::oneline)
+ ;
+
+ m_packet_queueing_latency
+ .init(m_virtual_networks)
+ .name(name() + ".packet_queueing_latency")
+ .flags(Stats::oneline)
+ ;
+
+ for (int i = 0; i < m_virtual_networks; i++) {
+ m_packets_received.subname(i, csprintf("vnet-%i", i));
+ m_packets_injected.subname(i, csprintf("vnet-%i", i));
+ m_packet_network_latency.subname(i, csprintf("vnet-%i", i));
+ m_packet_queueing_latency.subname(i, csprintf("vnet-%i", i));
+ }
+
+ m_avg_packet_vnet_latency
+ .name(name() + ".average_packet_vnet_latency")
+ .flags(Stats::oneline);
+ m_avg_packet_vnet_latency =
+ m_packet_network_latency / m_packets_received;
+
+ m_avg_packet_vqueue_latency
+ .name(name() + ".average_packet_vqueue_latency")
+ .flags(Stats::oneline);
+ m_avg_packet_vqueue_latency =
+ m_packet_queueing_latency / m_packets_received;
+
+ m_avg_packet_network_latency
+ .name(name() + ".average_packet_network_latency");
+ m_avg_packet_network_latency =
+ sum(m_packet_network_latency) / sum(m_packets_received);
+
+ m_avg_packet_queueing_latency
+ .name(name() + ".average_packet_queueing_latency");
+ m_avg_packet_queueing_latency
+ = sum(m_packet_queueing_latency) / sum(m_packets_received);
+
+ m_avg_packet_latency
+ .name(name() + ".average_packet_latency");
+ m_avg_packet_latency
+ = m_avg_packet_network_latency + m_avg_packet_queueing_latency;
+
+ // Flits
+ m_flits_received
+ .init(m_virtual_networks)
+ .name(name() + ".flits_received")
+ .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+ ;
+
+ m_flits_injected
+ .init(m_virtual_networks)
+ .name(name() + ".flits_injected")
+ .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+ ;
+
+ m_flit_network_latency
+ .init(m_virtual_networks)
+ .name(name() + ".flit_network_latency")
+ .flags(Stats::oneline)
+ ;
+
+ m_flit_queueing_latency
+ .init(m_virtual_networks)
+ .name(name() + ".flit_queueing_latency")
+ .flags(Stats::oneline)
+ ;
+
+ for (int i = 0; i < m_virtual_networks; i++) {
+ m_flits_received.subname(i, csprintf("vnet-%i", i));
+ m_flits_injected.subname(i, csprintf("vnet-%i", i));
+ m_flit_network_latency.subname(i, csprintf("vnet-%i", i));
+ m_flit_queueing_latency.subname(i, csprintf("vnet-%i", i));
+ }
+
+ m_avg_flit_vnet_latency
+ .name(name() + ".average_flit_vnet_latency")
+ .flags(Stats::oneline);
+ m_avg_flit_vnet_latency = m_flit_network_latency / m_flits_received;
+
+ m_avg_flit_vqueue_latency
+ .name(name() + ".average_flit_vqueue_latency")
+ .flags(Stats::oneline);
+ m_avg_flit_vqueue_latency =
+ m_flit_queueing_latency / m_flits_received;
+
+ m_avg_flit_network_latency
+ .name(name() + ".average_flit_network_latency");
+ m_avg_flit_network_latency =
+ sum(m_flit_network_latency) / sum(m_flits_received);
+
+ m_avg_flit_queueing_latency
+ .name(name() + ".average_flit_queueing_latency");
+ m_avg_flit_queueing_latency =
+ sum(m_flit_queueing_latency) / sum(m_flits_received);
+
+ m_avg_flit_latency
+ .name(name() + ".average_flit_latency");
+ m_avg_flit_latency =
+ m_avg_flit_network_latency + m_avg_flit_queueing_latency;
+
+
+ // Hops
+ m_avg_hops.name(name() + ".average_hops");
+ m_avg_hops = m_total_hops / sum(m_flits_received);
+
+ // Links
+ m_total_ext_in_link_utilization
+ .name(name() + ".ext_in_link_utilization");
+ m_total_ext_out_link_utilization
+ .name(name() + ".ext_out_link_utilization");
+ m_total_int_link_utilization
+ .name(name() + ".int_link_utilization");
+ m_average_link_utilization
+ .name(name() + ".avg_link_utilization");
+ m_average_vc_load
+ .init(m_virtual_networks * m_max_vcs_per_vnet)
+ .name(name() + ".avg_vc_load")
+ .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
+ ;
+}
+
+void
+GarnetNetwork::collateStats()
+{
+ RubySystem *rs = params()->ruby_system;
+ double time_delta = double(curCycle() - rs->getStartCycle());
+
+ for (int i = 0; i < m_networklinks.size(); i++) {
+ link_type type = m_networklinks[i]->getType();
+ int activity = m_networklinks[i]->getLinkUtilization();
+
+ if (type == EXT_IN_)
+ m_total_ext_in_link_utilization += activity;
+ else if (type == EXT_OUT_)
+ m_total_ext_out_link_utilization += activity;
+ else if (type == INT_)
+ m_total_int_link_utilization += activity;
+
+ m_average_link_utilization +=
+ (double(activity) / time_delta);
+
+ vector<unsigned int> vc_load = m_networklinks[i]->getVcLoad();
+ for (int j = 0; j < vc_load.size(); j++) {
+ m_average_vc_load[j] += ((double)vc_load[j] / time_delta);
+ }
+ }
+
+ // Ask the routers to collate their statistics
+ for (int i = 0; i < m_routers.size(); i++) {
+ m_routers[i]->collateStats();
+ }
+}
+
+void
+GarnetNetwork::resetStats()
+{
+ for (int i = 0; i < m_routers.size(); i++) {
+ m_routers[i]->resetStats();
+ }
+ for (int i = 0; i < m_networklinks.size(); i++) {
+ m_networklinks[i]->resetStats();
+ }
+ for (int i = 0; i < m_creditlinks.size(); i++) {
+ m_creditlinks[i]->resetStats();
+ }
+}
+
+void
+GarnetNetwork::print(ostream& out) const
+{
+ out << "[GarnetNetwork]";
+}
+
+GarnetNetwork *
+GarnetNetworkParams::create()
+{
+ return new GarnetNetwork(this);
+}
+
+uint32_t
+GarnetNetwork::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ for (unsigned int i = 0; i < m_routers.size(); i++) {
+ num_functional_writes += m_routers[i]->functionalWrite(pkt);
+ }
+
+ for (unsigned int i = 0; i < m_nis.size(); ++i) {
+ num_functional_writes += m_nis[i]->functionalWrite(pkt);
+ }
+
+ for (unsigned int i = 0; i < m_networklinks.size(); ++i) {
+ num_functional_writes += m_networklinks[i]->functionalWrite(pkt);
+ }
+
+ return num_functional_writes;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_GARNETNETWORK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_GARNETNETWORK_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/network/Network.hh"
+#include "mem/ruby/network/fault_model/FaultModel.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "params/GarnetNetwork.hh"
+
+class FaultModel;
+class NetworkInterface;
+class Router;
+class NetDest;
+class NetworkLink;
+class CreditLink;
+
+class GarnetNetwork : public Network
+{
+ public:
+ typedef GarnetNetworkParams Params;
+ GarnetNetwork(const Params *p);
+ ~GarnetNetwork() = default;
+
+ void init();
+
+ const char *garnetVersion = "3.0";
+
+ // Configuration (set externally)
+
+ // for 2D topology
+ int getNumRows() const { return m_num_rows; }
+ int getNumCols() { return m_num_cols; }
+
+ // for network
+ uint32_t getNiFlitSize() const { return m_ni_flit_size; }
+ uint32_t getBuffersPerDataVC() { return m_buffers_per_data_vc; }
+ uint32_t getBuffersPerCtrlVC() { return m_buffers_per_ctrl_vc; }
+ int getRoutingAlgorithm() const { return m_routing_algorithm; }
+
+ bool isFaultModelEnabled() const { return m_enable_fault_model; }
+ FaultModel* fault_model;
+
+
+ // Internal configuration
+ bool isVNetOrdered(int vnet) const { return m_ordered[vnet]; }
+ VNET_type
+ get_vnet_type(int vnet)
+ {
+ return m_vnet_type[vnet];
+ }
+ int getNumRouters();
+ int get_router_id(int ni, int vnet);
+
+
+ // Methods used by Topology to setup the network
+ void makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
+ std::vector<NetDest>& routing_table_entry);
+ void makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
+ std::vector<NetDest>& routing_table_entry);
+ void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
+ std::vector<NetDest>& routing_table_entry,
+ PortDirection src_outport_dirn,
+ PortDirection dest_inport_dirn);
+
+ //! Function for performing a functional write. The return value
+ //! indicates the number of messages that were written.
+ uint32_t functionalWrite(Packet *pkt);
+
+ // Stats
+ void collateStats();
+ void regStats();
+ void resetStats();
+ void print(std::ostream& out) const;
+
+ // increment counters
+ void increment_injected_packets(int vnet) { m_packets_injected[vnet]++; }
+ void increment_received_packets(int vnet) { m_packets_received[vnet]++; }
+
+ void
+ increment_packet_network_latency(Tick latency, int vnet)
+ {
+ m_packet_network_latency[vnet] += latency;
+ }
+
+ void
+ increment_packet_queueing_latency(Tick latency, int vnet)
+ {
+ m_packet_queueing_latency[vnet] += latency;
+ }
+
+ void increment_injected_flits(int vnet) { m_flits_injected[vnet]++; }
+ void increment_received_flits(int vnet) { m_flits_received[vnet]++; }
+
+ void
+ increment_flit_network_latency(Tick latency, int vnet)
+ {
+ m_flit_network_latency[vnet] += latency;
+ }
+
+ void
+ increment_flit_queueing_latency(Tick latency, int vnet)
+ {
+ m_flit_queueing_latency[vnet] += latency;
+ }
+
+ void
+ increment_total_hops(int hops)
+ {
+ m_total_hops += hops;
+ }
+
+ protected:
+ // Configuration
+ int m_num_rows;
+ int m_num_cols;
+ uint32_t m_ni_flit_size;
+ uint32_t m_max_vcs_per_vnet;
+ uint32_t m_buffers_per_ctrl_vc;
+ uint32_t m_buffers_per_data_vc;
+ int m_routing_algorithm;
+ bool m_enable_fault_model;
+
+ // Statistical variables
+ Stats::Vector m_packets_received;
+ Stats::Vector m_packets_injected;
+ Stats::Vector m_packet_network_latency;
+ Stats::Vector m_packet_queueing_latency;
+
+ Stats::Formula m_avg_packet_vnet_latency;
+ Stats::Formula m_avg_packet_vqueue_latency;
+ Stats::Formula m_avg_packet_network_latency;
+ Stats::Formula m_avg_packet_queueing_latency;
+ Stats::Formula m_avg_packet_latency;
+
+ Stats::Vector m_flits_received;
+ Stats::Vector m_flits_injected;
+ Stats::Vector m_flit_network_latency;
+ Stats::Vector m_flit_queueing_latency;
+
+ Stats::Formula m_avg_flit_vnet_latency;
+ Stats::Formula m_avg_flit_vqueue_latency;
+ Stats::Formula m_avg_flit_network_latency;
+ Stats::Formula m_avg_flit_queueing_latency;
+ Stats::Formula m_avg_flit_latency;
+
+ Stats::Scalar m_total_ext_in_link_utilization;
+ Stats::Scalar m_total_ext_out_link_utilization;
+ Stats::Scalar m_total_int_link_utilization;
+ Stats::Scalar m_average_link_utilization;
+ Stats::Vector m_average_vc_load;
+
+ Stats::Scalar m_total_hops;
+ Stats::Formula m_avg_hops;
+
+ private:
+ GarnetNetwork(const GarnetNetwork& obj);
+ GarnetNetwork& operator=(const GarnetNetwork& obj);
+
+ std::vector<VNET_type > m_vnet_type;
+ std::vector<Router *> m_routers; // All Routers in Network
+ std::vector<NetworkLink *> m_networklinks; // All flit links in the network
+ std::vector<CreditLink *> m_creditlinks; // All credit links in the network
+ std::vector<NetworkInterface *> m_nis; // All NI's in Network
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const GarnetNetwork& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_GARNETNETWORK_HH__
--- /dev/null
+# Copyright (c) 2008 Princeton University
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: Tushar Krishna
+#
+
+from m5.params import *
+from m5.proxy import *
+from m5.objects.Network import RubyNetwork
+from m5.objects.BasicRouter import BasicRouter
+from m5.objects.ClockedObject import ClockedObject
+
+class GarnetNetwork(RubyNetwork):
+ type = 'GarnetNetwork'
+ cxx_header = "mem/ruby/network/garnet/GarnetNetwork.hh"
+ num_rows = Param.Int(0, "number of rows if 2D (mesh/torus/..) topology");
+ ni_flit_size = Param.UInt32(16, "network interface flit size in bytes")
+ vcs_per_vnet = Param.UInt32(4, "virtual channels per virtual network");
+ buffers_per_data_vc = Param.UInt32(4, "buffers per data virtual channel");
+ buffers_per_ctrl_vc = Param.UInt32(1, "buffers per ctrl virtual channel");
+ routing_algorithm = Param.Int(0,
+ "0: Weight-based Table, 1: XY, 2: Custom");
+ enable_fault_model = Param.Bool(False, "enable network fault model");
+ fault_model = Param.FaultModel(NULL, "network fault model");
+ garnet_deadlock_threshold = Param.UInt32(50000,
+ "network-level deadlock threshold")
+
+class GarnetNetworkInterface(ClockedObject):
+ type = 'GarnetNetworkInterface'
+ cxx_class = 'NetworkInterface'
+ cxx_header = "mem/ruby/network/garnet/NetworkInterface.hh"
+
+ id = Param.UInt32("ID in relation to other network interfaces")
+ vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
+ "virtual channels per virtual network")
+ virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
+ "number of virtual networks")
+ garnet_deadlock_threshold = Param.UInt32(Parent.garnet_deadlock_threshold,
+ "network-level deadlock threshold")
+
+class GarnetRouter(BasicRouter):
+ type = 'GarnetRouter'
+ cxx_class = 'Router'
+ cxx_header = "mem/ruby/network/garnet/Router.hh"
+ vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
+ "virtual channels per virtual network")
+ virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
+ "number of virtual networks")
+ width = Param.UInt32(Parent.ni_flit_size,
+ "bit width supported by the router")
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/InputUnit.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+
+using namespace std;
+
+InputUnit::InputUnit(int id, PortDirection direction, Router *router)
+ : Consumer(router), m_router(router), m_id(id), m_direction(direction),
+ m_vc_per_vnet(m_router->get_vc_per_vnet())
+{
+ const int m_num_vcs = m_router->get_num_vcs();
+ m_num_buffer_reads.resize(m_num_vcs/m_vc_per_vnet);
+ m_num_buffer_writes.resize(m_num_vcs/m_vc_per_vnet);
+ for (int i = 0; i < m_num_buffer_reads.size(); i++) {
+ m_num_buffer_reads[i] = 0;
+ m_num_buffer_writes[i] = 0;
+ }
+
+ // Instantiating the virtual channels
+ virtualChannels.reserve(m_num_vcs);
+ for (int i=0; i < m_num_vcs; i++) {
+ virtualChannels.emplace_back();
+ }
+}
+
+/*
+ * The InputUnit wakeup function reads the input flit from its input link.
+ * Each flit arrives with an input VC.
+ * For HEAD/HEAD_TAIL flits, performs route computation,
+ * and updates route in the input VC.
+ * The flit is buffered for (m_latency - 1) cycles in the input VC
+ * and marked as valid for SwitchAllocation starting that cycle.
+ *
+ */
+
+void
+InputUnit::wakeup()
+{
+ flit *t_flit;
+ if (m_in_link->isReady(curTick())) {
+
+ t_flit = m_in_link->consumeLink();
+ DPRINTF(RubyNetwork, "Router[%d] Consuming:%s Width: %d Flit:%s\n",
+ m_router->get_id(), m_in_link->name(),
+ m_router->getBitWidth(), *t_flit);
+ assert(t_flit->m_width == m_router->getBitWidth());
+ int vc = t_flit->get_vc();
+ t_flit->increment_hops(); // for stats
+
+ if ((t_flit->get_type() == HEAD_) ||
+ (t_flit->get_type() == HEAD_TAIL_)) {
+
+ assert(virtualChannels[vc].get_state() == IDLE_);
+ set_vc_active(vc, curTick());
+
+ // Route computation for this vc
+ int outport = m_router->route_compute(t_flit->get_route(),
+ m_id, m_direction);
+
+ // Update output port in VC
+ // All flits in this packet will use this output port
+ // The output port field in the flit is updated after it wins SA
+ grant_outport(vc, outport);
+
+ } else {
+ assert(virtualChannels[vc].get_state() == ACTIVE_);
+ }
+
+
+ // Buffer the flit
+ virtualChannels[vc].insertFlit(t_flit);
+
+ int vnet = vc/m_vc_per_vnet;
+ // number of writes same as reads
+ // any flit that is written will be read only once
+ m_num_buffer_writes[vnet]++;
+ m_num_buffer_reads[vnet]++;
+
+ Cycles pipe_stages = m_router->get_pipe_stages();
+ if (pipe_stages == 1) {
+ // 1-cycle router
+ // Flit goes for SA directly
+ t_flit->advance_stage(SA_, curTick());
+ } else {
+ assert(pipe_stages > 1);
+ // Router delay is modeled by making flit wait in buffer for
+ // (pipe_stages cycles - 1) cycles before going for SA
+
+ Cycles wait_time = pipe_stages - Cycles(1);
+ t_flit->advance_stage(SA_, m_router->clockEdge(wait_time));
+
+ // Wakeup the router in that cycle to perform SA
+ m_router->schedule_wakeup(Cycles(wait_time));
+ }
+
+ if (m_in_link->isReady(curTick())) {
+ m_router->schedule_wakeup(Cycles(1));
+ }
+ }
+}
+
+// Send a credit back to upstream router for this VC.
+// Called by SwitchAllocator when the flit in this VC wins the Switch.
+void
+InputUnit::increment_credit(int in_vc, bool free_signal, Tick curTime)
+{
+ DPRINTF(RubyNetwork, "Router[%d]: Sending a credit vc:%d free:%d to %s\n",
+ m_router->get_id(), in_vc, free_signal, m_credit_link->name());
+ Credit *t_credit = new Credit(in_vc, free_signal, curTime);
+ creditQueue.insert(t_credit);
+ m_credit_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
+}
+
+
+uint32_t
+InputUnit::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+ for (auto& virtual_channel : virtualChannels) {
+ num_functional_writes += virtual_channel.functionalWrite(pkt);
+ }
+
+ return num_functional_writes;
+}
+
+void
+InputUnit::resetStats()
+{
+ for (int j = 0; j < m_num_buffer_reads.size(); j++) {
+ m_num_buffer_reads[j] = 0;
+ m_num_buffer_writes[j] = 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_INPUTUNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_INPUTUNIT_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/network/garnet/VirtualChannel.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+class InputUnit : public Consumer
+{
+ public:
+ InputUnit(int id, PortDirection direction, Router *router);
+ ~InputUnit() = default;
+
+ void wakeup();
+ void print(std::ostream& out) const {};
+
+ inline PortDirection get_direction() { return m_direction; }
+
+ inline void
+ set_vc_idle(int vc, Tick curTime)
+ {
+ virtualChannels[vc].set_idle(curTime);
+ }
+
+ inline void
+ set_vc_active(int vc, Tick curTime)
+ {
+ virtualChannels[vc].set_active(curTime);
+ }
+
+ inline void
+ grant_outport(int vc, int outport)
+ {
+ virtualChannels[vc].set_outport(outport);
+ }
+
+ inline void
+ grant_outvc(int vc, int outvc)
+ {
+ virtualChannels[vc].set_outvc(outvc);
+ }
+
+ inline int
+ get_outport(int invc)
+ {
+ return virtualChannels[invc].get_outport();
+ }
+
+ inline int
+ get_outvc(int invc)
+ {
+ return virtualChannels[invc].get_outvc();
+ }
+
+ inline Tick
+ get_enqueue_time(int invc)
+ {
+ return virtualChannels[invc].get_enqueue_time();
+ }
+
+ void increment_credit(int in_vc, bool free_signal, Tick curTime);
+
+ inline flit*
+ peekTopFlit(int vc)
+ {
+ return virtualChannels[vc].peekTopFlit();
+ }
+
+ inline flit*
+ getTopFlit(int vc)
+ {
+ return virtualChannels[vc].getTopFlit();
+ }
+
+ inline bool
+ need_stage(int vc, flit_stage stage, Tick time)
+ {
+ return virtualChannels[vc].need_stage(stage, time);
+ }
+
+ inline bool
+ isReady(int invc, Tick curTime)
+ {
+ return virtualChannels[invc].isReady(curTime);
+ }
+
+ flitBuffer* getCreditQueue() { return &creditQueue; }
+
+ inline void
+ set_in_link(NetworkLink *link)
+ {
+ m_in_link = link;
+ }
+
+ inline int get_inlink_id() { return m_in_link->get_id(); }
+
+ inline void
+ set_credit_link(CreditLink *credit_link)
+ {
+ m_credit_link = credit_link;
+ }
+
+ double get_buf_read_activity(unsigned int vnet) const
+ { return m_num_buffer_reads[vnet]; }
+ double get_buf_write_activity(unsigned int vnet) const
+ { return m_num_buffer_writes[vnet]; }
+
+ uint32_t functionalWrite(Packet *pkt);
+ void resetStats();
+
+ private:
+ Router *m_router;
+ int m_id;
+ PortDirection m_direction;
+ int m_vc_per_vnet;
+ NetworkLink *m_in_link;
+ CreditLink *m_credit_link;
+ flitBuffer creditQueue;
+
+ // Input Virtual channels
+ std::vector<VirtualChannel> virtualChannels;
+
+ // Statistical variables
+ std::vector<double> m_num_buffer_writes;
+ std::vector<double> m_num_buffer_reads;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_INPUTUNIT_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Srikant Bharadwaj
+ */
+
+
+#include "mem/ruby/network/garnet/NetworkBridge.hh"
+
+#include <cmath>
+
+#include "debug/RubyNetwork.hh"
+#include "params/GarnetIntLink.hh"
+
+NetworkBridge::NetworkBridge(const Params *p)
+ :CreditLink(p)
+{
+ enCdc = true;
+ enSerDes = true;
+ mType = p->vtype;
+
+ cdcLatency = p->cdc_latency;
+ serDesLatency = p->serdes_latency;
+ lastScheduledAt = 0;
+
+ nLink = p->link;
+ if (mType == Enums::LINK_OBJECT) {
+ nLink->setLinkConsumer(this);
+ setSourceQueue(nLink->getBuffer(), nLink);
+ } else if (mType == Enums::OBJECT_LINK) {
+ nLink->setSourceQueue(&linkBuffer, this);
+ setLinkConsumer(nLink);
+ } else {
+ // CDC type must be set
+ panic("CDC type must be set");
+ }
+}
+
+void
+NetworkBridge::setVcsPerVnet(uint32_t consumerVcs)
+{
+ DPRINTF(RubyNetwork, "VcsPerVnet VC: %d\n", consumerVcs);
+ NetworkLink::setVcsPerVnet(consumerVcs);
+ lenBuffer.resize(consumerVcs * m_virt_nets);
+ sizeSent.resize(consumerVcs * m_virt_nets);
+ flitsSent.resize(consumerVcs * m_virt_nets);
+ extraCredit.resize(consumerVcs * m_virt_nets);
+
+ nLink->setVcsPerVnet(consumerVcs);
+}
+
+void
+NetworkBridge::initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en)
+{
+ coBridge = coBrid;
+ enCdc = cdc_en;
+ enSerDes = serdes_en;
+}
+
+NetworkBridge::~NetworkBridge()
+{
+}
+
+void
+NetworkBridge::scheduleFlit(flit *t_flit, Cycles latency)
+{
+ Cycles totLatency = latency;
+
+ if (enCdc) {
+ // Add the CDC latency
+ totLatency = latency + cdcLatency;
+ }
+
+ Tick sendTime = link_consumer->getObject()->clockEdge(totLatency);
+ Tick nextAvailTick = lastScheduledAt + link_consumer->getObject()->\
+ cyclesToTicks(Cycles(1));
+ sendTime = std::max(nextAvailTick, sendTime);
+ t_flit->set_time(sendTime);
+ lastScheduledAt = sendTime;
+ linkBuffer.insert(t_flit);
+ link_consumer->scheduleEventAbsolute(sendTime);
+}
+
+void
+NetworkBridge::neutralize(int vc, int eCredit)
+{
+ extraCredit[vc].push(eCredit);
+}
+
+void
+NetworkBridge::flitisizeAndSend(flit *t_flit)
+{
+ // Serialize-Deserialize only if it is enabled
+ if (enSerDes) {
+ // Calculate the target-width
+ int target_width = bitWidth;
+ int cur_width = nLink->bitWidth;
+ if (mType == Enums::OBJECT_LINK) {
+ target_width = nLink->bitWidth;
+ cur_width = bitWidth;
+ }
+
+ DPRINTF(RubyNetwork, "Target width: %d Current: %d\n",
+ target_width, cur_width);
+ assert(target_width != cur_width);
+
+ int vc = t_flit->get_vc();
+
+ if (target_width > cur_width) {
+ // Deserialize
+ // This deserializer combines flits from the
+ // same message together
+ int num_flits = 0;
+ int flitPossible = 0;
+ if (t_flit->get_type() == CREDIT_) {
+ lenBuffer[vc]++;
+ assert(extraCredit[vc].front());
+ if (lenBuffer[vc] == extraCredit[vc].front()) {
+ flitPossible = 1;
+ extraCredit[vc].pop();
+ lenBuffer[vc] = 0;
+ }
+ } else if (t_flit->get_type() == TAIL_ ||
+ t_flit->get_type() == HEAD_TAIL_) {
+ // If its the end of packet, then send whatever
+ // is available.
+ int sizeAvail = (t_flit->msgSize - sizeSent[vc]);
+ flitPossible = ceil((float)sizeAvail/(float)target_width);
+ assert (flitPossible < 2);
+ num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
+ // Stop tracking the packet.
+ flitsSent[vc] = 0;
+ sizeSent[vc] = 0;
+ } else {
+ // If we are yet to receive the complete packet
+ // track the size recieved and flits deserialized.
+ int sizeAvail =
+ ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
+ flitPossible = floor((float)sizeAvail/(float)target_width);
+ assert (flitPossible < 2);
+ num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
+ if (flitPossible) {
+ sizeSent[vc] += target_width;
+ flitsSent[vc] = t_flit->get_id() + 1;
+ }
+ }
+
+ DPRINTF(RubyNetwork, "Deserialize :%dB -----> %dB "
+ " vc:%d\n", cur_width, target_width, vc);
+
+ flit *fl = NULL;
+ if (flitPossible) {
+ fl = t_flit->deserialize(lenBuffer[vc], num_flits,
+ target_width);
+ }
+
+ // Inform the credit serializer about the number
+ // of flits that were generated.
+ if (t_flit->get_type() != CREDIT_ && fl) {
+ coBridge->neutralize(vc, num_flits);
+ }
+
+ // Schedule only if we are done deserializing
+ if (fl) {
+ DPRINTF(RubyNetwork, "Scheduling a flit\n");
+ lenBuffer[vc] = 0;
+ scheduleFlit(fl, serDesLatency);
+ }
+ // Delete this flit, new flit is sent in any case
+ delete t_flit;
+ } else {
+ // Serialize
+ DPRINTF(RubyNetwork, "Serializing flit :%d -----> %d "
+ "(vc:%d, Original Message Size: %d)\n",
+ cur_width, target_width, vc, t_flit->msgSize);
+
+ int flitPossible = 0;
+ if (t_flit->get_type() == CREDIT_) {
+ // We store the deserialization ratio and then
+ // access it when serializing credits in the
+ // oppposite direction.
+ assert(extraCredit[vc].front());
+ flitPossible = extraCredit[vc].front();
+ extraCredit[vc].pop();
+ } else if (t_flit->get_type() == HEAD_ ||
+ t_flit->get_type() == BODY_) {
+ int sizeAvail =
+ ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
+ flitPossible = floor((float)sizeAvail/(float)target_width);
+ if (flitPossible) {
+ sizeSent[vc] += flitPossible*target_width;
+ flitsSent[vc] += flitPossible;
+ }
+ } else {
+ int sizeAvail = t_flit->msgSize - sizeSent[vc];
+ flitPossible = ceil((float)sizeAvail/(float)target_width);
+ sizeSent[vc] = 0;
+ flitsSent[vc] = 0;
+ }
+ assert(flitPossible > 0);
+
+ // Schedule all the flits
+ // num_flits could be zero for credits
+ for (int i = 0; i < flitPossible; i++) {
+ // Ignore neutralized credits
+ flit *fl = t_flit->serialize(i, flitPossible, target_width);
+ scheduleFlit(fl, serDesLatency);
+ DPRINTF(RubyNetwork, "Serialized to flit[%d of %d parts]:"
+ " %s\n", i+1, flitPossible, *fl);
+ }
+
+ if (t_flit->get_type() != CREDIT_) {
+ coBridge->neutralize(vc, flitPossible);
+ }
+ // Delete this flit, new flit is sent in any case
+ delete t_flit;
+ }
+ return;
+ }
+
+ // If only CDC is enabled schedule it
+ scheduleFlit(t_flit, Cycles(0));
+}
+void
+NetworkBridge::wakeup()
+{
+ flit *t_flit;
+
+ if (link_srcQueue->isReady(curTick())) {
+ t_flit = link_srcQueue->getTopFlit();
+ DPRINTF(RubyNetwork, "Recieved flit %s\n", *t_flit);
+ flitisizeAndSend(t_flit);
+ return;
+ }
+ assert(!link_srcQueue->getSize());
+}
+
+NetworkBridge *
+NetworkBridgeParams::create()
+{
+ return new NetworkBridge(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Srikant Bharadwaj
+ */
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_NETWORK_BRIDGE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_NETWORK_BRIDGE_HH__
+
+#include <iostream>
+#include <queue>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetLink.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+#include "params/NetworkBridge.hh"
+
+class GarnetNetwork;
+
+class NetworkBridge: public CreditLink
+{
+ public:
+ typedef NetworkBridgeParams Params;
+ NetworkBridge(const Params *p);
+ ~NetworkBridge();
+
+ void initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en);
+
+ void wakeup();
+ void neutralize(int vc, int eCredit);
+
+ void scheduleFlit(flit *t_flit, Cycles latency);
+ void flitisizeAndSend(flit *t_flit);
+ void setVcsPerVnet(uint32_t consumerVcs);
+
+ protected:
+ // Pointer to co-existing bridge
+ // CreditBridge for Network Bridge and vice versa
+ NetworkBridge *coBridge;
+
+ // Link connected toBridge
+ // could be a source or destination
+ // depending on mType
+ NetworkLink *nLink;
+
+ // CDC enable/disable
+ bool enCdc;
+ // SerDes enable/disable
+ bool enSerDes;
+
+ // Type of Bridge
+ int mType;
+
+ Cycles cdcLatency;
+ Cycles serDesLatency;
+
+ Tick lastScheduledAt;
+
+ // Used by Credit Deserializer
+ std::vector<int> lenBuffer;
+ std::vector<int> sizeSent;
+ std::vector<int> flitsSent;
+ std::vector<std::queue<int>> extraCredit;
+
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_NETWORK_BRIDGE_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/NetworkInterface.hh"
+
+#include <cassert>
+#include <cmath>
+
+#include "base/cast.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/MessageBuffer.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+
+using namespace std;
+
+NetworkInterface::NetworkInterface(const Params *p)
+ : ClockedObject(p), Consumer(this), m_id(p->id),
+ m_virtual_networks(p->virt_nets), m_vc_per_vnet(0),
+ m_vc_allocator(m_virtual_networks, 0),
+ m_deadlock_threshold(p->garnet_deadlock_threshold),
+ vc_busy_counter(m_virtual_networks, 0)
+{
+ m_stall_count.resize(m_virtual_networks);
+ niOutVcs.resize(0);
+}
+
+void
+NetworkInterface::addInPort(NetworkLink *in_link,
+ CreditLink *credit_link)
+{
+ InputPort *newInPort = new InputPort(in_link, credit_link);
+ inPorts.push_back(newInPort);
+ DPRINTF(RubyNetwork, "Adding input port:%s with vnets %s\n",
+ in_link->name(), newInPort->printVnets());
+
+ in_link->setLinkConsumer(this);
+ credit_link->setSourceQueue(newInPort->outCreditQueue(), this);
+ if (m_vc_per_vnet != 0) {
+ in_link->setVcsPerVnet(m_vc_per_vnet);
+ credit_link->setVcsPerVnet(m_vc_per_vnet);
+ }
+
+}
+
+void
+NetworkInterface::addOutPort(NetworkLink *out_link,
+ CreditLink *credit_link,
+ SwitchID router_id, uint32_t consumerVcs)
+{
+ OutputPort *newOutPort = new OutputPort(out_link, credit_link, router_id);
+ outPorts.push_back(newOutPort);
+
+ assert(consumerVcs > 0);
+ // We are not allowing different physical links to have different vcs
+ // If it is required that the Network Interface support different VCs
+ // for every physical link connected to it. Then they need to change
+ // the logic within outport and inport.
+ if (niOutVcs.size() == 0) {
+ m_vc_per_vnet = consumerVcs;
+ int m_num_vcs = consumerVcs * m_virtual_networks;
+ niOutVcs.resize(m_num_vcs);
+ outVcState.reserve(m_num_vcs);
+ m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
+ // instantiating the NI flit buffers
+ for (int i = 0; i < m_num_vcs; i++) {
+ m_ni_out_vcs_enqueue_time[i] = Tick(INFINITE_);
+ outVcState.emplace_back(i, m_net_ptr, consumerVcs);
+ }
+
+ // Reset VC Per VNET for input links already instantiated
+ for (auto &iPort: inPorts) {
+ NetworkLink *inNetLink = iPort->inNetLink();
+ inNetLink->setVcsPerVnet(m_vc_per_vnet);
+ credit_link->setVcsPerVnet(m_vc_per_vnet);
+ }
+ } else {
+ fatal_if(consumerVcs != m_vc_per_vnet,
+ "%s: Connected Physical links have different vc requests: %d and %d\n",
+ name(), consumerVcs, m_vc_per_vnet);
+ }
+
+ DPRINTF(RubyNetwork, "OutputPort:%s Vnet: %s\n",
+ out_link->name(), newOutPort->printVnets());
+
+ out_link->setSourceQueue(newOutPort->outFlitQueue(), this);
+ out_link->setVcsPerVnet(m_vc_per_vnet);
+ credit_link->setLinkConsumer(this);
+ credit_link->setVcsPerVnet(m_vc_per_vnet);
+}
+
+void
+NetworkInterface::addNode(vector<MessageBuffer *>& in,
+ vector<MessageBuffer *>& out)
+{
+ inNode_ptr = in;
+ outNode_ptr = out;
+
+ for (auto& it : in) {
+ if (it != nullptr) {
+ it->setConsumer(this);
+ }
+ }
+}
+
+void
+NetworkInterface::dequeueCallback()
+{
+ // An output MessageBuffer has dequeued something this cycle and there
+ // is now space to enqueue a stalled message. However, we cannot wake
+ // on the same cycle as the dequeue. Schedule a wake at the soonest
+ // possible time (next cycle).
+ scheduleEventAbsolute(clockEdge(Cycles(1)));
+}
+
+void
+NetworkInterface::incrementStats(flit *t_flit)
+{
+ int vnet = t_flit->get_vnet();
+
+ // Latency
+ m_net_ptr->increment_received_flits(vnet);
+ Tick network_delay =
+ t_flit->get_dequeue_time() -
+ t_flit->get_enqueue_time() - cyclesToTicks(Cycles(1));
+ Tick src_queueing_delay = t_flit->get_src_delay();
+ Tick dest_queueing_delay = (curTick() - t_flit->get_dequeue_time());
+ Tick queueing_delay = src_queueing_delay + dest_queueing_delay;
+
+ m_net_ptr->increment_flit_network_latency(network_delay, vnet);
+ m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
+
+ if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
+ m_net_ptr->increment_received_packets(vnet);
+ m_net_ptr->increment_packet_network_latency(network_delay, vnet);
+ m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
+ }
+
+ // Hops
+ m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
+}
+
+/*
+ * The NI wakeup checks whether there are any ready messages in the protocol
+ * buffer. If yes, it picks that up, flitisizes it into a number of flits and
+ * puts it into an output buffer and schedules the output link. On a wakeup
+ * it also checks whether there are flits in the input link. If yes, it picks
+ * them up and if the flit is a tail, the NI inserts the corresponding message
+ * into the protocol buffer. It also checks for credits being sent by the
+ * downstream router.
+ */
+
+void
+NetworkInterface::wakeup()
+{
+ std::ostringstream oss;
+ for (auto &oPort: outPorts) {
+ oss << oPort->routerID() << "[" << oPort->printVnets() << "] ";
+ }
+ DPRINTF(RubyNetwork, "Network Interface %d connected to router:%s "
+ "woke up. Period: %ld\n", m_id, oss.str(), clockPeriod());
+
+ assert(curTick() == clockEdge());
+ MsgPtr msg_ptr;
+ Tick curTime = clockEdge();
+
+ // Checking for messages coming from the protocol
+ // can pick up a message/cycle for each virtual net
+ for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
+ MessageBuffer *b = inNode_ptr[vnet];
+ if (b == nullptr) {
+ continue;
+ }
+
+ if (b->isReady(curTime)) { // Is there a message waiting
+ msg_ptr = b->peekMsgPtr();
+ if (flitisizeMessage(msg_ptr, vnet)) {
+ b->dequeue(curTime);
+ }
+ }
+ }
+
+ scheduleOutputLink();
+
+ // Check if there are flits stalling a virtual channel. Track if a
+ // message is enqueued to restrict ejection to one message per cycle.
+ checkStallQueue();
+
+ /*********** Check the incoming flit link **********/
+ DPRINTF(RubyNetwork, "Number of input ports: %d\n", inPorts.size());
+ for (auto &iPort: inPorts) {
+ NetworkLink *inNetLink = iPort->inNetLink();
+ if (inNetLink->isReady(curTick())) {
+ flit *t_flit = inNetLink->consumeLink();
+ DPRINTF(RubyNetwork, "Recieved flit:%s\n", *t_flit);
+ assert(t_flit->m_width == iPort->bitWidth());
+
+ int vnet = t_flit->get_vnet();
+ t_flit->set_dequeue_time(curTick());
+
+ // If a tail flit is received, enqueue into the protocol buffers
+ // if space is available. Otherwise, exchange non-tail flits for
+ // credits.
+ if (t_flit->get_type() == TAIL_ ||
+ t_flit->get_type() == HEAD_TAIL_) {
+ if (!iPort->messageEnqueuedThisCycle &&
+ outNode_ptr[vnet]->areNSlotsAvailable(1, curTime)) {
+ // Space is available. Enqueue to protocol buffer.
+ outNode_ptr[vnet]->enqueue(t_flit->get_msg_ptr(), curTime,
+ cyclesToTicks(Cycles(1)));
+
+ // Simply send a credit back since we are not buffering
+ // this flit in the NI
+ Credit *cFlit = new Credit(t_flit->get_vc(),
+ true, curTick());
+ iPort->sendCredit(cFlit);
+ // Update stats and delete flit pointer
+ incrementStats(t_flit);
+ delete t_flit;
+ } else {
+ // No space available- Place tail flit in stall queue and
+ // set up a callback for when protocol buffer is dequeued.
+ // Stat update and flit pointer deletion will occur upon
+ // unstall.
+ iPort->m_stall_queue.push_back(t_flit);
+ m_stall_count[vnet]++;
+
+ outNode_ptr[vnet]->registerDequeueCallback([this]() {
+ dequeueCallback(); });
+ }
+ } else {
+ // Non-tail flit. Send back a credit but not VC free signal.
+ Credit *cFlit = new Credit(t_flit->get_vc(), false,
+ curTick());
+ // Simply send a credit back since we are not buffering
+ // this flit in the NI
+ iPort->sendCredit(cFlit);
+
+ // Update stats and delete flit pointer.
+ incrementStats(t_flit);
+ delete t_flit;
+ }
+ }
+ }
+
+ /****************** Check the incoming credit link *******/
+
+ for (auto &oPort: outPorts) {
+ CreditLink *inCreditLink = oPort->inCreditLink();
+ if (inCreditLink->isReady(curTick())) {
+ Credit *t_credit = (Credit*) inCreditLink->consumeLink();
+ outVcState[t_credit->get_vc()].increment_credit();
+ if (t_credit->is_free_signal()) {
+ outVcState[t_credit->get_vc()].setState(IDLE_,
+ curTick());
+ }
+ delete t_credit;
+ }
+ }
+
+
+ // It is possible to enqueue multiple outgoing credit flits if a message
+ // was unstalled in the same cycle as a new message arrives. In this
+ // case, we should schedule another wakeup to ensure the credit is sent
+ // back.
+ for (auto &iPort: inPorts) {
+ if (iPort->outCreditQueue()->getSize() > 0) {
+ DPRINTF(RubyNetwork, "Sending a credit %s via %s at %ld\n",
+ *(iPort->outCreditQueue()->peekTopFlit()),
+ iPort->outCreditLink()->name(), clockEdge(Cycles(1)));
+ iPort->outCreditLink()->
+ scheduleEventAbsolute(clockEdge(Cycles(1)));
+ }
+ }
+ checkReschedule();
+}
+
+void
+NetworkInterface::checkStallQueue()
+{
+ // Check all stall queues.
+ // There is one stall queue for each input link
+ for (auto &iPort: inPorts) {
+ iPort->messageEnqueuedThisCycle = false;
+ Tick curTime = clockEdge();
+
+ if (!iPort->m_stall_queue.empty()) {
+ for (auto stallIter = iPort->m_stall_queue.begin();
+ stallIter != iPort->m_stall_queue.end(); ) {
+ flit *stallFlit = *stallIter;
+ int vnet = stallFlit->get_vnet();
+
+ // If we can now eject to the protocol buffer,
+ // send back credits
+ if (outNode_ptr[vnet]->areNSlotsAvailable(1,
+ curTime)) {
+ outNode_ptr[vnet]->enqueue(stallFlit->get_msg_ptr(),
+ curTime, cyclesToTicks(Cycles(1)));
+
+ // Send back a credit with free signal now that the
+ // VC is no longer stalled.
+ Credit *cFlit = new Credit(stallFlit->get_vc(), true,
+ curTick());
+ iPort->sendCredit(cFlit);
+
+ // Update Stats
+ incrementStats(stallFlit);
+
+ // Flit can now safely be deleted and removed from stall
+ // queue
+ delete stallFlit;
+ iPort->m_stall_queue.erase(stallIter);
+ m_stall_count[vnet]--;
+
+ // If there are no more stalled messages for this vnet, the
+ // callback on it's MessageBuffer is not needed.
+ if (m_stall_count[vnet] == 0)
+ outNode_ptr[vnet]->unregisterDequeueCallback();
+
+ iPort->messageEnqueuedThisCycle = true;
+ break;
+ } else {
+ ++stallIter;
+ }
+ }
+ }
+ }
+}
+
+// Embed the protocol message into flits
+bool
+NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
+{
+ Message *net_msg_ptr = msg_ptr.get();
+ NetDest net_msg_dest = net_msg_ptr->getDestination();
+
+ // gets all the destinations associated with this message.
+ vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
+
+ // Number of flits is dependent on the link bandwidth available.
+ // This is expressed in terms of bytes/cycle or the flit size
+ OutputPort *oPort = getOutportForVnet(vnet);
+ assert(oPort);
+ int num_flits = (int)divCeil((float) m_net_ptr->MessageSizeType_to_int(
+ net_msg_ptr->getMessageSize()), (float)oPort->bitWidth());
+
+ DPRINTF(RubyNetwork, "Message Size:%d vnet:%d bitWidth:%d\n",
+ m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize()),
+ vnet, oPort->bitWidth());
+
+ // loop to convert all multicast messages into unicast messages
+ for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
+
+ // this will return a free output virtual channel
+ int vc = calculateVC(vnet);
+
+ if (vc == -1) {
+ return false ;
+ }
+ MsgPtr new_msg_ptr = msg_ptr->clone();
+ NodeID destID = dest_nodes[ctr];
+
+ Message *new_net_msg_ptr = new_msg_ptr.get();
+ if (dest_nodes.size() > 1) {
+ NetDest personal_dest;
+ for (int m = 0; m < (int) MachineType_NUM; m++) {
+ if ((destID >= MachineType_base_number((MachineType) m)) &&
+ destID < MachineType_base_number((MachineType) (m+1))) {
+ // calculating the NetDest associated with this destID
+ personal_dest.clear();
+ personal_dest.add((MachineID) {(MachineType) m, (destID -
+ MachineType_base_number((MachineType) m))});
+ new_net_msg_ptr->getDestination() = personal_dest;
+ break;
+ }
+ }
+ net_msg_dest.removeNetDest(personal_dest);
+ // removing the destination from the original message to reflect
+ // that a message with this particular destination has been
+ // flitisized and an output vc is acquired
+ net_msg_ptr->getDestination().removeNetDest(personal_dest);
+ }
+
+ // Embed Route into the flits
+ // NetDest format is used by the routing table
+ // Custom routing algorithms just need destID
+
+ RouteInfo route;
+ route.vnet = vnet;
+ route.net_dest = new_net_msg_ptr->getDestination();
+ route.src_ni = m_id;
+ route.src_router = oPort->routerID();
+ route.dest_ni = destID;
+ route.dest_router = m_net_ptr->get_router_id(destID, vnet);
+
+ // initialize hops_traversed to -1
+ // so that the first router increments it to 0
+ route.hops_traversed = -1;
+
+ m_net_ptr->increment_injected_packets(vnet);
+ for (int i = 0; i < num_flits; i++) {
+ m_net_ptr->increment_injected_flits(vnet);
+ flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
+ m_net_ptr->MessageSizeType_to_int(
+ net_msg_ptr->getMessageSize()),
+ oPort->bitWidth(), curTick());
+
+ fl->set_src_delay(curTick() - ticksToCycles(msg_ptr->getTime()));
+ niOutVcs[vc].insert(fl);
+ }
+
+ m_ni_out_vcs_enqueue_time[vc] = curTick();
+ outVcState[vc].setState(ACTIVE_, curTick());
+ }
+ return true ;
+}
+
+// Looking for a free output vc
+int
+NetworkInterface::calculateVC(int vnet)
+{
+ for (int i = 0; i < m_vc_per_vnet; i++) {
+ int delta = m_vc_allocator[vnet];
+ m_vc_allocator[vnet]++;
+ if (m_vc_allocator[vnet] == m_vc_per_vnet)
+ m_vc_allocator[vnet] = 0;
+
+ if (outVcState[(vnet*m_vc_per_vnet) + delta].isInState(
+ IDLE_, curTick())) {
+ vc_busy_counter[vnet] = 0;
+ return ((vnet*m_vc_per_vnet) + delta);
+ }
+ }
+
+ vc_busy_counter[vnet] += 1;
+ panic_if(vc_busy_counter[vnet] > m_deadlock_threshold,
+ "%s: Possible network deadlock in vnet: %d at time: %llu \n",
+ name(), vnet, curTick());
+
+ return -1;
+}
+
+void
+NetworkInterface::scheduleOutputPort(OutputPort *oPort)
+{
+ int vc = oPort->vcRoundRobin();
+
+ for (int i = 0; i < niOutVcs.size(); i++) {
+ vc++;
+ if (vc == niOutVcs.size())
+ vc = 0;
+
+ int t_vnet = get_vnet(vc);
+ if (oPort->isVnetSupported(t_vnet)) {
+ // model buffer backpressure
+ if (niOutVcs[vc].isReady(curTick()) &&
+ outVcState[vc].has_credit()) {
+
+ bool is_candidate_vc = true;
+ int vc_base = t_vnet * m_vc_per_vnet;
+
+ if (m_net_ptr->isVNetOrdered(t_vnet)) {
+ for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
+ vc_offset++) {
+ int t_vc = vc_base + vc_offset;
+ if (niOutVcs[t_vc].isReady(curTick())) {
+ if (m_ni_out_vcs_enqueue_time[t_vc] <
+ m_ni_out_vcs_enqueue_time[vc]) {
+ is_candidate_vc = false;
+ break;
+ }
+ }
+ }
+ }
+ if (!is_candidate_vc)
+ continue;
+
+ // Update the round robin arbiter
+ oPort->vcRoundRobin(vc);
+
+ outVcState[vc].decrement_credit();
+
+ // Just removing the top flit
+ flit *t_flit = niOutVcs[vc].getTopFlit();
+ t_flit->set_time(clockEdge(Cycles(1)));
+
+ // Scheduling the flit
+ scheduleFlit(t_flit);
+
+ if (t_flit->get_type() == TAIL_ ||
+ t_flit->get_type() == HEAD_TAIL_) {
+ m_ni_out_vcs_enqueue_time[vc] = Tick(INFINITE_);
+ }
+
+ // Done with this port, continue to schedule
+ // other ports
+ return;
+ }
+ }
+ }
+}
+
+
+
+/** This function looks at the NI buffers
+ * if some buffer has flits which are ready to traverse the link in the next
+ * cycle, and the downstream output vc associated with this flit has buffers
+ * left, the link is scheduled for the next cycle
+ */
+
+void
+NetworkInterface::scheduleOutputLink()
+{
+ // Schedule each output link
+ for (auto &oPort: outPorts) {
+ scheduleOutputPort(oPort);
+ }
+}
+
+NetworkInterface::InputPort *
+NetworkInterface::getInportForVnet(int vnet)
+{
+ for (auto &iPort : inPorts) {
+ if (iPort->isVnetSupported(vnet)) {
+ return iPort;
+ }
+ }
+
+ return nullptr;
+}
+
+/*
+ * This function returns the outport which supports the given vnet.
+ * Currently, HeteroGarnet does not support multiple outports to
+ * support same vnet. Thus, this function returns the first-and
+ * only outport which supports the vnet.
+ */
+NetworkInterface::OutputPort *
+NetworkInterface::getOutportForVnet(int vnet)
+{
+ for (auto &oPort : outPorts) {
+ if (oPort->isVnetSupported(vnet)) {
+ return oPort;
+ }
+ }
+
+ return nullptr;
+}
+void
+NetworkInterface::scheduleFlit(flit *t_flit)
+{
+ OutputPort *oPort = getOutportForVnet(t_flit->get_vnet());
+
+ if (oPort) {
+ DPRINTF(RubyNetwork, "Scheduling at %s time:%ld flit:%s Message:%s\n",
+ oPort->outNetLink()->name(), clockEdge(Cycles(1)),
+ *t_flit, *(t_flit->get_msg_ptr()));
+ oPort->outFlitQueue()->insert(t_flit);
+ oPort->outNetLink()->scheduleEventAbsolute(clockEdge(Cycles(1)));
+ return;
+ }
+
+ panic("No output port found for vnet:%d\n", t_flit->get_vnet());
+ return;
+}
+
+int
+NetworkInterface::get_vnet(int vc)
+{
+ for (int i = 0; i < m_virtual_networks; i++) {
+ if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
+ return i;
+ }
+ }
+ fatal("Could not determine vc");
+}
+
+
+// Wakeup the NI in the next cycle if there are waiting
+// messages in the protocol buffer, or waiting flits in the
+// output VC buffer.
+// Also check if we have to reschedule because of a clock period
+// difference.
+void
+NetworkInterface::checkReschedule()
+{
+ for (const auto& it : inNode_ptr) {
+ if (it == nullptr) {
+ continue;
+ }
+
+ while (it->isReady(clockEdge())) { // Is there a message waiting
+ scheduleEvent(Cycles(1));
+ return;
+ }
+ }
+
+ for (auto& ni_out_vc : niOutVcs) {
+ if (ni_out_vc.isReady(clockEdge(Cycles(1)))) {
+ scheduleEvent(Cycles(1));
+ return;
+ }
+ }
+
+ // Check if any input links have flits to be popped.
+ // This can happen if the links are operating at
+ // a higher frequency.
+ for (auto &iPort : inPorts) {
+ NetworkLink *inNetLink = iPort->inNetLink();
+ if (inNetLink->isReady(curTick())) {
+ scheduleEvent(Cycles(1));
+ return;
+ }
+ }
+
+ for (auto &oPort : outPorts) {
+ CreditLink *inCreditLink = oPort->inCreditLink();
+ if (inCreditLink->isReady(curTick())) {
+ scheduleEvent(Cycles(1));
+ return;
+ }
+ }
+}
+
+void
+NetworkInterface::print(std::ostream& out) const
+{
+ out << "[Network Interface]";
+}
+
+uint32_t
+NetworkInterface::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+ for (auto& ni_out_vc : niOutVcs) {
+ num_functional_writes += ni_out_vc.functionalWrite(pkt);
+ }
+
+ for (auto &oPort: outPorts) {
+ num_functional_writes += oPort->outFlitQueue()->functionalWrite(pkt);
+ }
+ return num_functional_writes;
+}
+
+NetworkInterface *
+GarnetNetworkInterfaceParams::create()
+{
+ return new NetworkInterface(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_NETWORKINTERFACE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_NETWORKINTERFACE_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/OutVcState.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+#include "params/GarnetNetworkInterface.hh"
+
+class MessageBuffer;
+class flitBuffer;
+
+class NetworkInterface : public ClockedObject, public Consumer
+{
+ public:
+ typedef GarnetNetworkInterfaceParams Params;
+ NetworkInterface(const Params *p);
+ ~NetworkInterface() = default;
+
+ void addInPort(NetworkLink *in_link, CreditLink *credit_link);
+ void addOutPort(NetworkLink *out_link, CreditLink *credit_link,
+ SwitchID router_id, uint32_t consumerVcs);
+
+ void dequeueCallback();
+ void wakeup();
+ void addNode(std::vector<MessageBuffer *> &inNode,
+ std::vector<MessageBuffer *> &outNode);
+
+ void print(std::ostream& out) const;
+ int get_vnet(int vc);
+ void init_net_ptr(GarnetNetwork *net_ptr) { m_net_ptr = net_ptr; }
+
+ uint32_t functionalWrite(Packet *);
+
+ void scheduleFlit(flit *t_flit);
+
+ int get_router_id(int vnet)
+ {
+ OutputPort *oPort = getOutportForVnet(vnet);
+ assert(oPort);
+ return oPort->routerID();
+ }
+
+ class OutputPort
+ {
+ public:
+ OutputPort(NetworkLink *outLink, CreditLink *creditLink,
+ int routerID)
+ {
+ _vnets = outLink->mVnets;
+ _outFlitQueue = new flitBuffer();
+
+ _outNetLink = outLink;
+ _inCreditLink = creditLink;
+
+ _routerID = routerID;
+ _bitWidth = outLink->bitWidth;
+ _vcRoundRobin = 0;
+
+ }
+
+ flitBuffer *
+ outFlitQueue()
+ {
+ return _outFlitQueue;
+ }
+
+ NetworkLink *
+ outNetLink()
+ {
+ return _outNetLink;
+ }
+
+ CreditLink *
+ inCreditLink()
+ {
+ return _inCreditLink;
+ }
+
+ int
+ routerID()
+ {
+ return _routerID;
+ }
+
+ uint32_t bitWidth()
+ {
+ return _bitWidth;
+ }
+
+ bool isVnetSupported(int pVnet)
+ {
+ if (!_vnets.size()) {
+ return true;
+ }
+
+ for (auto &it : _vnets) {
+ if (it == pVnet) {
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ std::string
+ printVnets()
+ {
+ std::stringstream ss;
+ for (auto &it : _vnets) {
+ ss << it;
+ ss << " ";
+ }
+ return ss.str();
+ }
+
+ int vcRoundRobin()
+ {
+ return _vcRoundRobin;
+ }
+
+ void vcRoundRobin(int vc)
+ {
+ _vcRoundRobin = vc;
+ }
+
+
+ private:
+ std::vector<int> _vnets;
+ flitBuffer *_outFlitQueue;
+
+ NetworkLink *_outNetLink;
+ CreditLink *_inCreditLink;
+
+ int _vcRoundRobin; // For round robin scheduling
+
+ int _routerID;
+ uint32_t _bitWidth;
+ };
+
+ class InputPort
+ {
+ public:
+ InputPort(NetworkLink *inLink, CreditLink *creditLink)
+ {
+ _vnets = inLink->mVnets;
+ _outCreditQueue = new flitBuffer();
+
+ _inNetLink = inLink;
+ _outCreditLink = creditLink;
+ _bitWidth = inLink->bitWidth;
+ }
+
+ flitBuffer *
+ outCreditQueue()
+ {
+ return _outCreditQueue;
+ }
+
+ NetworkLink *
+ inNetLink()
+ {
+ return _inNetLink;
+ }
+
+ CreditLink *
+ outCreditLink()
+ {
+ return _outCreditLink;
+ }
+
+ bool isVnetSupported(int pVnet)
+ {
+ if (!_vnets.size()) {
+ return true;
+ }
+
+ for (auto &it : _vnets) {
+ if (it == pVnet) {
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ void sendCredit(Credit *cFlit)
+ {
+ _outCreditQueue->insert(cFlit);
+ }
+
+ uint32_t bitWidth()
+ {
+ return _bitWidth;
+ }
+
+ std::string
+ printVnets()
+ {
+ std::stringstream ss;
+ for (auto &it : _vnets) {
+ ss << it;
+ ss << " ";
+ }
+ return ss.str();
+ }
+
+ // Queue for stalled flits
+ std::deque<flit *> m_stall_queue;
+ bool messageEnqueuedThisCycle;
+ private:
+ std::vector<int> _vnets;
+ flitBuffer *_outCreditQueue;
+
+ NetworkLink *_inNetLink;
+ CreditLink *_outCreditLink;
+ uint32_t _bitWidth;
+ };
+
+
+ private:
+ GarnetNetwork *m_net_ptr;
+ const NodeID m_id;
+ const int m_virtual_networks;
+ int m_vc_per_vnet;
+ std::vector<int> m_vc_allocator;
+ std::vector<OutputPort *> outPorts;
+ std::vector<InputPort *> inPorts;
+ int m_deadlock_threshold;
+ std::vector<OutVcState> outVcState;
+
+ std::vector<int> m_stall_count;
+
+ // Input Flit Buffers
+ // The flit buffers which will serve the Consumer
+ std::vector<flitBuffer> niOutVcs;
+ std::vector<Tick> m_ni_out_vcs_enqueue_time;
+
+ // The Message buffers that takes messages from the protocol
+ std::vector<MessageBuffer *> inNode_ptr;
+ // The Message buffers that provides messages to the protocol
+ std::vector<MessageBuffer *> outNode_ptr;
+ // When a vc stays busy for a long time, it indicates a deadlock
+ std::vector<int> vc_busy_counter;
+
+ void checkStallQueue();
+ bool flitisizeMessage(MsgPtr msg_ptr, int vnet);
+ int calculateVC(int vnet);
+
+
+ void scheduleOutputPort(OutputPort *oPort);
+ void scheduleOutputLink();
+ void checkReschedule();
+
+ void incrementStats(flit *t_flit);
+
+ InputPort *getInportForVnet(int vnet);
+ OutputPort *getOutportForVnet(int vnet);
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_NETWORKINTERFACE_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+
+#include "base/trace.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+
+NetworkLink::NetworkLink(const Params *p)
+ : ClockedObject(p), Consumer(this), m_id(p->link_id),
+ m_type(NUM_LINK_TYPES_),
+ m_latency(p->link_latency), m_link_utilized(0),
+ m_virt_nets(p->virt_nets), linkBuffer(),
+ link_consumer(nullptr), link_srcQueue(nullptr)
+{
+ int num_vnets = (p->supported_vnets).size();
+ mVnets.resize(num_vnets);
+ bitWidth = p->width;
+ for (int i = 0; i < num_vnets; i++) {
+ mVnets[i] = p->supported_vnets[i];
+ }
+}
+
+void
+NetworkLink::setLinkConsumer(Consumer *consumer)
+{
+ link_consumer = consumer;
+}
+
+void
+NetworkLink::setVcsPerVnet(uint32_t consumerVcs)
+{
+ m_vc_load.resize(m_virt_nets * consumerVcs);
+}
+
+void
+NetworkLink::setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObj)
+{
+ link_srcQueue = src_queue;
+ src_object = srcClockObj;
+}
+
+void
+NetworkLink::wakeup()
+{
+ DPRINTF(RubyNetwork, "Woke up to transfer flits from %s\n",
+ src_object->name());
+ assert(link_srcQueue != nullptr);
+ assert(curTick() == clockEdge());
+ if (link_srcQueue->isReady(curTick())) {
+ flit *t_flit = link_srcQueue->getTopFlit();
+ DPRINTF(RubyNetwork, "Transmission will finish at %ld :%s\n",
+ clockEdge(m_latency), *t_flit);
+ if (m_type != NUM_LINK_TYPES_) {
+ // Only for assertions and debug messages
+ assert(t_flit->m_width == bitWidth);
+ assert((std::find(mVnets.begin(), mVnets.end(),
+ t_flit->get_vnet()) != mVnets.end()) ||
+ (mVnets.size() == 0));
+ }
+ t_flit->set_time(clockEdge(m_latency));
+ linkBuffer.insert(t_flit);
+ link_consumer->scheduleEventAbsolute(clockEdge(m_latency));
+ m_link_utilized++;
+ m_vc_load[t_flit->get_vc()]++;
+ }
+
+ if (!link_srcQueue->isEmpty()) {
+ scheduleEvent(Cycles(1));
+ }
+}
+
+void
+NetworkLink::resetStats()
+{
+ for (int i = 0; i < m_vc_load.size(); i++) {
+ m_vc_load[i] = 0;
+ }
+
+ m_link_utilized = 0;
+}
+
+NetworkLink *
+NetworkLinkParams::create()
+{
+ return new NetworkLink(this);
+}
+
+CreditLink *
+CreditLinkParams::create()
+{
+ return new CreditLink(this);
+}
+
+uint32_t
+NetworkLink::functionalWrite(Packet *pkt)
+{
+ return linkBuffer.functionalWrite(pkt);
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_NETWORKLINK_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_NETWORKLINK_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+#include "params/NetworkLink.hh"
+#include "sim/clocked_object.hh"
+
+class GarnetNetwork;
+
+class NetworkLink : public ClockedObject, public Consumer
+{
+ public:
+ typedef NetworkLinkParams Params;
+ NetworkLink(const Params *p);
+ ~NetworkLink() = default;
+
+ void setLinkConsumer(Consumer *consumer);
+ void setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObject);
+ virtual void setVcsPerVnet(uint32_t consumerVcs);
+ void setType(link_type type) { m_type = type; }
+ link_type getType() { return m_type; }
+ void print(std::ostream& out) const {}
+ int get_id() const { return m_id; }
+ flitBuffer *getBuffer() { return &linkBuffer;}
+ virtual void wakeup();
+
+ unsigned int getLinkUtilization() const { return m_link_utilized; }
+ const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; }
+
+ inline bool isReady(Tick curTime)
+ {
+ return linkBuffer.isReady(curTime);
+ }
+
+ inline flit* peekLink() { return linkBuffer.peekTopFlit(); }
+ inline flit* consumeLink() { return linkBuffer.getTopFlit(); }
+
+ uint32_t functionalWrite(Packet *);
+ void resetStats();
+
+ std::vector<int> mVnets;
+ uint32_t bitWidth;
+
+ private:
+ const int m_id;
+ link_type m_type;
+ const Cycles m_latency;
+
+ ClockedObject *src_object;
+
+ // Statistical variables
+ unsigned int m_link_utilized;
+ std::vector<unsigned int> m_vc_load;
+
+ protected:
+ uint32_t m_virt_nets;
+ flitBuffer linkBuffer;
+ Consumer *link_consumer;
+ flitBuffer *link_srcQueue;
+
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_NETWORKLINK_HH__
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/OutVcState.hh"
+
+#include "mem/ruby/system/RubySystem.hh"
+
+OutVcState::OutVcState(int id, GarnetNetwork *network_ptr,
+ uint32_t consumerVcs)
+ : m_time(0)
+{
+ m_id = id;
+ m_vc_state = IDLE_;
+ /*
+ * We find the virtual network using the number of
+ * vcs per vnet. This assumes that the same vcs per
+ * vnet is used throughout the given object.
+ */
+ int vnet = floor(id/consumerVcs);
+
+ if (network_ptr->get_vnet_type(vnet) == DATA_VNET_)
+ m_max_credit_count = network_ptr->getBuffersPerDataVC();
+ else
+ m_max_credit_count = network_ptr->getBuffersPerCtrlVC();
+
+ m_credit_count = m_max_credit_count;
+ assert(m_credit_count >= 1);
+}
+
+void
+OutVcState::increment_credit()
+{
+ m_credit_count++;
+ assert(m_credit_count <= m_max_credit_count);
+}
+
+void
+OutVcState::decrement_credit()
+{
+ m_credit_count--;
+ assert(m_credit_count >= 0);
+}
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_OUTVCSTATE_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_OUTVCSTATE_HH__
+
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+
+class OutVcState
+{
+ public:
+ OutVcState(int id, GarnetNetwork *network_ptr, uint32_t consumerVcs);
+
+ int get_credit_count() { return m_credit_count; }
+ inline bool has_credit() { return (m_credit_count > 0); }
+ void increment_credit();
+ void decrement_credit();
+
+ inline bool
+ isInState(VC_state_type state, Tick request_time)
+ {
+ return ((m_vc_state == state) && (request_time >= m_time) );
+ }
+ inline void
+ setState(VC_state_type state, Tick time)
+ {
+ m_vc_state = state;
+ m_time = time;
+ }
+
+ private:
+ int m_id ;
+ Tick m_time;
+ VC_state_type m_vc_state;
+ int m_credit_count;
+ int m_max_credit_count;
+};
+
+#endif //__MEM_RUBY_NETWORK_GARNET_0_OUTVCSTATE_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/Credit.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+OutputUnit::OutputUnit(int id, PortDirection direction, Router *router,
+ uint32_t consumerVcs)
+ : Consumer(router), m_router(router), m_id(id), m_direction(direction),
+ m_vc_per_vnet(consumerVcs)
+{
+ const int m_num_vcs = consumerVcs * m_router->get_num_vnets();
+ outVcState.reserve(m_num_vcs);
+ for (int i = 0; i < m_num_vcs; i++) {
+ outVcState.emplace_back(i, m_router->get_net_ptr(), consumerVcs);
+ }
+}
+
+void
+OutputUnit::decrement_credit(int out_vc)
+{
+ DPRINTF(RubyNetwork, "Router %d OutputUnit %s decrementing credit:%d for "
+ "outvc %d at time: %lld for %s\n", m_router->get_id(),
+ m_router->getPortDirectionName(get_direction()),
+ outVcState[out_vc].get_credit_count(),
+ out_vc, m_router->curCycle(), m_credit_link->name());
+
+ outVcState[out_vc].decrement_credit();
+}
+
+void
+OutputUnit::increment_credit(int out_vc)
+{
+ DPRINTF(RubyNetwork, "Router %d OutputUnit %s incrementing credit:%d for "
+ "outvc %d at time: %lld from:%s\n", m_router->get_id(),
+ m_router->getPortDirectionName(get_direction()),
+ outVcState[out_vc].get_credit_count(),
+ out_vc, m_router->curCycle(), m_credit_link->name());
+
+ outVcState[out_vc].increment_credit();
+}
+
+// Check if the output VC (i.e., input VC at next router)
+// has free credits (i..e, buffer slots).
+// This is tracked by OutVcState
+bool
+OutputUnit::has_credit(int out_vc)
+{
+ assert(outVcState[out_vc].isInState(ACTIVE_, curTick()));
+ return outVcState[out_vc].has_credit();
+}
+
+
+// Check if the output port (i.e., input port at next router) has free VCs.
+bool
+OutputUnit::has_free_vc(int vnet)
+{
+ int vc_base = vnet*m_vc_per_vnet;
+ for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
+ if (is_vc_idle(vc, curTick()))
+ return true;
+ }
+
+ return false;
+}
+
+// Assign a free output VC to the winner of Switch Allocation
+int
+OutputUnit::select_free_vc(int vnet)
+{
+ int vc_base = vnet*m_vc_per_vnet;
+ for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
+ if (is_vc_idle(vc, curTick())) {
+ outVcState[vc].setState(ACTIVE_, curTick());
+ return vc;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * The wakeup function of the OutputUnit reads the credit signal from the
+ * downstream router for the output VC (i.e., input VC at downstream router).
+ * It increments the credit count in the appropriate output VC state.
+ * If the credit carries is_free_signal as true,
+ * the output VC is marked IDLE.
+ */
+
+void
+OutputUnit::wakeup()
+{
+ if (m_credit_link->isReady(curTick())) {
+ Credit *t_credit = (Credit*) m_credit_link->consumeLink();
+ increment_credit(t_credit->get_vc());
+
+ if (t_credit->is_free_signal())
+ set_vc_state(IDLE_, t_credit->get_vc(), curTick());
+
+ delete t_credit;
+
+ if (m_credit_link->isReady(curTick())) {
+ scheduleEvent(Cycles(1));
+ }
+ }
+}
+
+flitBuffer*
+OutputUnit::getOutQueue()
+{
+ return &outBuffer;
+}
+
+void
+OutputUnit::set_out_link(NetworkLink *link)
+{
+ m_out_link = link;
+}
+
+void
+OutputUnit::set_credit_link(CreditLink *credit_link)
+{
+ m_credit_link = credit_link;
+}
+
+void
+OutputUnit::insert_flit(flit *t_flit)
+{
+ outBuffer.insert(t_flit);
+ m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
+}
+
+uint32_t
+OutputUnit::functionalWrite(Packet *pkt)
+{
+ return outBuffer.functionalWrite(pkt);
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_OUTPUTUNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_OUTPUTUNIT_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "base/compiler.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/OutVcState.hh"
+
+class CreditLink;
+class Router;
+
+class OutputUnit : public Consumer
+{
+ public:
+ OutputUnit(int id, PortDirection direction, Router *router,
+ uint32_t consumerVcs);
+ ~OutputUnit() = default;
+ void set_out_link(NetworkLink *link);
+ void set_credit_link(CreditLink *credit_link);
+ void wakeup();
+ flitBuffer* getOutQueue();
+ void print(std::ostream& out) const {};
+ void decrement_credit(int out_vc);
+ void increment_credit(int out_vc);
+ bool has_credit(int out_vc);
+ bool has_free_vc(int vnet);
+ int select_free_vc(int vnet);
+
+ inline PortDirection get_direction() { return m_direction; }
+
+ int
+ get_credit_count(int vc)
+ {
+ return outVcState[vc].get_credit_count();
+ }
+
+ inline int
+ get_outlink_id()
+ {
+ return m_out_link->get_id();
+ }
+
+ inline void
+ set_vc_state(VC_state_type state, int vc, Tick curTime)
+ {
+ outVcState[vc].setState(state, curTime);
+ }
+
+ inline bool
+ is_vc_idle(int vc, Tick curTime)
+ {
+ return (outVcState[vc].isInState(IDLE_, curTime));
+ }
+
+ void insert_flit(flit *t_flit);
+
+ inline int
+ getVcsPerVnet()
+ {
+ return m_vc_per_vnet;
+ }
+
+ uint32_t functionalWrite(Packet *pkt);
+
+ private:
+ Router *m_router;
+ int M5_CLASS_VAR_USED m_id;
+ PortDirection m_direction;
+ int m_vc_per_vnet;
+ NetworkLink *m_out_link;
+ CreditLink *m_credit_link;
+
+ // This is for the network link to consume
+ flitBuffer outBuffer;
+ // vc state of downstream router
+ std::vector<OutVcState> outVcState;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_OUTPUTUNIT_HH__
--- /dev/null
+README for Garnet3.0
+Written By: Tushar Krishna (tushar@ece.gatech.edu)
+Last Updated: Sep 9, 2020
+-------------------------------------------------------
+
+Garnet Network Parameters and Setup:
+- GarnetNetwork.py
+ * defaults can be overwritten from command line (see configs/network/Network.py)
+- GarnetNetwork.hh/cc
+ * sets up the routers and links
+ * collects stats
+
+
+CODE FLOW
+- NetworkInterface.cc::wakeup()
+ * Every NI connected to one coherence protocol controller on one end, and one router on the other.
+ * receives messages from coherence protocol buffer in appropriate vnet and converts them into network packets and sends them into the network.
+ * garnet adds the ability to capture a network trace at this point.
+ * receives flits from the network, extracts the protocol message and sends it to the coherence protocol buffer in appropriate vnet.
+ * manages flow-control (i.e., credits) with its attached router.
+ * The consuming flit/credit output link of the NI is put in the global event queue with a timestamp set to next cycle.
+ The eventqueue calls the wakeup function in the consumer.
+
+- NetworkLink.cc::wakeup()
+ * receives flits from NI/router and sends it to NI/router after m_latency cycles delay
+ * Default latency value for every link can be set from command line (see configs/network/Network.py)
+ * Per link latency can be overwritten in the topology file
+ * The consumer of the link (NI/router) is put in the global event queue with a timestamp set after m_latency cycles.
+ The eventqueue calls the wakeup function in the consumer.
+
+- Router.cc::wakeup()
+ * Loop through all InputUnits and call their wakeup()
+ * Loop through all OutputUnits and call their wakeup()
+ * Call SwitchAllocator's wakeup()
+ * Call CrossbarSwitch's wakeup()
+ * The router's wakeup function is called whenever any of its modules (InputUnit, OutputUnit, SwitchAllocator, CrossbarSwitch) have
+ a ready flit/credit to act upon this cycle.
+
+- InputUnit.cc::wakeup()
+ * Read input flit from upstream router if it is ready for this cycle
+ * For HEAD/HEAD_TAIL flits, perform route computation, and update route in the VC.
+ * Buffer the flit for (m_latency - 1) cycles and mark it valid for SwitchAllocation starting that cycle.
+ * Default latency for every router can be set from command line (see configs/network/Network.py)
+ * Per router latency (i.e., num pipeline stages) can be set in the topology file
+
+- OutputUnit.cc::wakeup()
+ * Read input credit from downstream router if it is ready for this cycle
+ * Increment the credit in the appropriate output VC state.
+ * Mark output VC as free if the credit carries is_free_signal as true
+
+- SwitchAllocator.cc::wakeup()
+ * Note: SwitchAllocator performs VC arbitration and selection within it.
+ * SA-I (or SA-i): Loop through all input VCs at every input port, and select one in a round robin manner.
+ * For HEAD/HEAD_TAIL flits only select an input VC whose output port has at least one free output VC.
+ * For BODY/TAIL flits, only select an input VC that has credits in its output VC.
+ * Place a request for the output port from this VC.
+ * SA-II (or SA-o): Loop through all output ports, and select one input VC (that placed a request during SA-I) as the winner for this output port in a round robin manner.
+ * For HEAD/HEAD_TAIL flits, perform outvc allocation (i.e., select a free VC from the output port).
+ * For BODY/TAIL flits, decrement a credit in the output vc.
+ * Read the flit out from the input VC, and send it to the CrossbarSwitch
+ * Send a increment_credit signal to the upstream router for this input VC.
+ * for HEAD_TAIL/TAIL flits, mark is_free_signal as true in the credit.
+ * The input unit sends the credit out on the credit link to the upstream router.
+ * Reschedule the Router to wakeup next cycle for any flits ready for SA next cycle.
+
+- CrossbarSwitch.cc::wakeup()
+ * Loop through all input ports, and send the winning flit out of its output port onto the output link.
+ * The consuming flit output link of the router is put in the global event queue with a timestamp set to next cycle.
+ The eventqueue calls the wakeup function in the consumer.
+
+
+If a clock domain crossing(CDC) or Serializer-Deserializer unit is
+instantiated, then the Network Brisge takes over the flit in HeteroGarnet.
+- NetworkBridge::wakeup()
+ * Check if SerDes is enabled and do appropriate calculations for
+ serializing or deserializing the flits
+ * Check if CDC is enabled and schedule all the flits according
+ to the consumers clock domain.
+
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/Router.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/CreditLink.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/InputUnit.hh"
+#include "mem/ruby/network/garnet/NetworkLink.hh"
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+
+using namespace std;
+
+Router::Router(const Params *p)
+ : BasicRouter(p), Consumer(this), m_latency(p->latency),
+ m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
+ m_num_vcs(m_virtual_networks * m_vc_per_vnet), m_bit_width(p->width),
+ m_network_ptr(nullptr), routingUnit(this), switchAllocator(this),
+ crossbarSwitch(this)
+{
+ m_input_unit.clear();
+ m_output_unit.clear();
+}
+
+void
+Router::init()
+{
+ BasicRouter::init();
+
+ switchAllocator.init();
+ crossbarSwitch.init();
+}
+
+void
+Router::wakeup()
+{
+ DPRINTF(RubyNetwork, "Router %d woke up\n", m_id);
+ assert(clockEdge() == curTick());
+
+ // check for incoming flits
+ for (int inport = 0; inport < m_input_unit.size(); inport++) {
+ m_input_unit[inport]->wakeup();
+ }
+
+ // check for incoming credits
+ // Note: the credit update is happening before SA
+ // buffer turnaround time =
+ // credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
+ // if we want the credit update to take place after SA, this loop should
+ // be moved after the SA request
+ for (int outport = 0; outport < m_output_unit.size(); outport++) {
+ m_output_unit[outport]->wakeup();
+ }
+
+ // Switch Allocation
+ switchAllocator.wakeup();
+
+ // Switch Traversal
+ crossbarSwitch.wakeup();
+}
+
+void
+Router::addInPort(PortDirection inport_dirn,
+ NetworkLink *in_link, CreditLink *credit_link)
+{
+ fatal_if(in_link->bitWidth != m_bit_width, "Widths of link %s(%d)does"
+ " not match that of Router%d(%d). Consider inserting SerDes "
+ "Units.", in_link->name(), in_link->bitWidth, m_id, m_bit_width);
+
+ int port_num = m_input_unit.size();
+ InputUnit *input_unit = new InputUnit(port_num, inport_dirn, this);
+
+ input_unit->set_in_link(in_link);
+ input_unit->set_credit_link(credit_link);
+ in_link->setLinkConsumer(this);
+ in_link->setVcsPerVnet(get_vc_per_vnet());
+ credit_link->setSourceQueue(input_unit->getCreditQueue(), this);
+ credit_link->setVcsPerVnet(get_vc_per_vnet());
+
+ m_input_unit.push_back(std::shared_ptr<InputUnit>(input_unit));
+
+ routingUnit.addInDirection(inport_dirn, port_num);
+}
+
+void
+Router::addOutPort(PortDirection outport_dirn,
+ NetworkLink *out_link,
+ std::vector<NetDest>& routing_table_entry, int link_weight,
+ CreditLink *credit_link, uint32_t consumerVcs)
+{
+ fatal_if(out_link->bitWidth != m_bit_width, "Widths of units do not match."
+ " Consider inserting SerDes Units");
+
+ int port_num = m_output_unit.size();
+ OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this,
+ consumerVcs);
+
+ output_unit->set_out_link(out_link);
+ output_unit->set_credit_link(credit_link);
+ credit_link->setLinkConsumer(this);
+ credit_link->setVcsPerVnet(consumerVcs);
+ out_link->setSourceQueue(output_unit->getOutQueue(), this);
+ out_link->setVcsPerVnet(consumerVcs);
+
+ m_output_unit.push_back(std::shared_ptr<OutputUnit>(output_unit));
+
+ routingUnit.addRoute(routing_table_entry);
+ routingUnit.addWeight(link_weight);
+ routingUnit.addOutDirection(outport_dirn, port_num);
+}
+
+PortDirection
+Router::getOutportDirection(int outport)
+{
+ return m_output_unit[outport]->get_direction();
+}
+
+PortDirection
+Router::getInportDirection(int inport)
+{
+ return m_input_unit[inport]->get_direction();
+}
+
+int
+Router::route_compute(RouteInfo route, int inport, PortDirection inport_dirn)
+{
+ return routingUnit.outportCompute(route, inport, inport_dirn);
+}
+
+void
+Router::grant_switch(int inport, flit *t_flit)
+{
+ crossbarSwitch.update_sw_winner(inport, t_flit);
+}
+
+void
+Router::schedule_wakeup(Cycles time)
+{
+ // wake up after time cycles
+ scheduleEvent(time);
+}
+
+std::string
+Router::getPortDirectionName(PortDirection direction)
+{
+ // PortDirection is actually a string
+ // If not, then this function should add a switch
+ // statement to convert direction to a string
+ // that can be printed out
+ return direction;
+}
+
+void
+Router::regStats()
+{
+ BasicRouter::regStats();
+
+ m_buffer_reads
+ .name(name() + ".buffer_reads")
+ .flags(Stats::nozero)
+ ;
+
+ m_buffer_writes
+ .name(name() + ".buffer_writes")
+ .flags(Stats::nozero)
+ ;
+
+ m_crossbar_activity
+ .name(name() + ".crossbar_activity")
+ .flags(Stats::nozero)
+ ;
+
+ m_sw_input_arbiter_activity
+ .name(name() + ".sw_input_arbiter_activity")
+ .flags(Stats::nozero)
+ ;
+
+ m_sw_output_arbiter_activity
+ .name(name() + ".sw_output_arbiter_activity")
+ .flags(Stats::nozero)
+ ;
+}
+
+void
+Router::collateStats()
+{
+ for (int j = 0; j < m_virtual_networks; j++) {
+ for (int i = 0; i < m_input_unit.size(); i++) {
+ m_buffer_reads += m_input_unit[i]->get_buf_read_activity(j);
+ m_buffer_writes += m_input_unit[i]->get_buf_write_activity(j);
+ }
+ }
+
+ m_sw_input_arbiter_activity = switchAllocator.get_input_arbiter_activity();
+ m_sw_output_arbiter_activity =
+ switchAllocator.get_output_arbiter_activity();
+ m_crossbar_activity = crossbarSwitch.get_crossbar_activity();
+}
+
+void
+Router::resetStats()
+{
+ for (int i = 0; i < m_input_unit.size(); i++) {
+ m_input_unit[i]->resetStats();
+ }
+
+ crossbarSwitch.resetStats();
+ switchAllocator.resetStats();
+}
+
+void
+Router::printFaultVector(ostream& out)
+{
+ int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
+ int num_fault_types = m_network_ptr->fault_model->number_of_fault_types;
+ float fault_vector[num_fault_types];
+ get_fault_vector(temperature_celcius, fault_vector);
+ out << "Router-" << m_id << " fault vector: " << endl;
+ for (int fault_type_index = 0; fault_type_index < num_fault_types;
+ fault_type_index++) {
+ out << " - probability of (";
+ out <<
+ m_network_ptr->fault_model->fault_type_to_string(fault_type_index);
+ out << ") = ";
+ out << fault_vector[fault_type_index] << endl;
+ }
+}
+
+void
+Router::printAggregateFaultProbability(std::ostream& out)
+{
+ int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
+ float aggregate_fault_prob;
+ get_aggregate_fault_probability(temperature_celcius,
+ &aggregate_fault_prob);
+ out << "Router-" << m_id << " fault probability: ";
+ out << aggregate_fault_prob << endl;
+}
+
+uint32_t
+Router::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+ num_functional_writes += crossbarSwitch.functionalWrite(pkt);
+
+ for (uint32_t i = 0; i < m_input_unit.size(); i++) {
+ num_functional_writes += m_input_unit[i]->functionalWrite(pkt);
+ }
+
+ for (uint32_t i = 0; i < m_output_unit.size(); i++) {
+ num_functional_writes += m_output_unit[i]->functionalWrite(pkt);
+ }
+
+ return num_functional_writes;
+}
+
+Router *
+GarnetRouterParams::create()
+{
+ return new Router(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_ROUTER_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_ROUTER_HH__
+
+#include <iostream>
+#include <memory>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/NetDest.hh"
+#include "mem/ruby/network/BasicRouter.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/CrossbarSwitch.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/RoutingUnit.hh"
+#include "mem/ruby/network/garnet/SwitchAllocator.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+#include "params/GarnetRouter.hh"
+
+class NetworkLink;
+class CreditLink;
+class InputUnit;
+class OutputUnit;
+class FaultModel;
+
+class Router : public BasicRouter, public Consumer
+{
+ public:
+ typedef GarnetRouterParams Params;
+ Router(const Params *p);
+
+ ~Router() = default;
+
+ void wakeup();
+ void print(std::ostream& out) const {};
+
+ void init();
+ void addInPort(PortDirection inport_dirn, NetworkLink *link,
+ CreditLink *credit_link);
+ void addOutPort(PortDirection outport_dirn, NetworkLink *link,
+ std::vector<NetDest>& routing_table_entry,
+ int link_weight, CreditLink *credit_link,
+ uint32_t consumerVcs);
+
+ Cycles get_pipe_stages(){ return m_latency; }
+ uint32_t get_num_vcs() { return m_num_vcs; }
+ uint32_t get_num_vnets() { return m_virtual_networks; }
+ uint32_t get_vc_per_vnet() { return m_vc_per_vnet; }
+ int get_num_inports() { return m_input_unit.size(); }
+ int get_num_outports() { return m_output_unit.size(); }
+ int get_id() { return m_id; }
+
+ void init_net_ptr(GarnetNetwork* net_ptr)
+ {
+ m_network_ptr = net_ptr;
+ }
+
+ GarnetNetwork* get_net_ptr() { return m_network_ptr; }
+
+ InputUnit*
+ getInputUnit(unsigned port)
+ {
+ assert(port < m_input_unit.size());
+ return m_input_unit[port].get();
+ }
+
+ OutputUnit*
+ getOutputUnit(unsigned port)
+ {
+ assert(port < m_output_unit.size());
+ return m_output_unit[port].get();
+ }
+
+ int getBitWidth() { return m_bit_width; }
+
+ PortDirection getOutportDirection(int outport);
+ PortDirection getInportDirection(int inport);
+
+ int route_compute(RouteInfo route, int inport, PortDirection direction);
+ void grant_switch(int inport, flit *t_flit);
+ void schedule_wakeup(Cycles time);
+
+ std::string getPortDirectionName(PortDirection direction);
+ void printFaultVector(std::ostream& out);
+ void printAggregateFaultProbability(std::ostream& out);
+
+ void regStats();
+ void collateStats();
+ void resetStats();
+
+ // For Fault Model:
+ bool get_fault_vector(int temperature, float fault_vector[]) {
+ return m_network_ptr->fault_model->fault_vector(m_id, temperature,
+ fault_vector);
+ }
+ bool get_aggregate_fault_probability(int temperature,
+ float *aggregate_fault_prob) {
+ return m_network_ptr->fault_model->fault_prob(m_id, temperature,
+ aggregate_fault_prob);
+ }
+
+ uint32_t functionalWrite(Packet *);
+
+ private:
+ Cycles m_latency;
+ uint32_t m_virtual_networks, m_vc_per_vnet, m_num_vcs;
+ uint32_t m_bit_width;
+ GarnetNetwork *m_network_ptr;
+
+ RoutingUnit routingUnit;
+ SwitchAllocator switchAllocator;
+ CrossbarSwitch crossbarSwitch;
+
+ std::vector<std::shared_ptr<InputUnit>> m_input_unit;
+ std::vector<std::shared_ptr<OutputUnit>> m_output_unit;
+
+ // Statistical variables required for power computations
+ Stats::Scalar m_buffer_reads;
+ Stats::Scalar m_buffer_writes;
+
+ Stats::Scalar m_sw_input_arbiter_activity;
+ Stats::Scalar m_sw_output_arbiter_activity;
+
+ Stats::Scalar m_crossbar_activity;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_ROUTER_HH__
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/RoutingUnit.hh"
+
+#include "base/cast.hh"
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/InputUnit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+
+RoutingUnit::RoutingUnit(Router *router)
+{
+ m_router = router;
+ m_routing_table.clear();
+ m_weight_table.clear();
+}
+
+void
+RoutingUnit::addRoute(std::vector<NetDest>& routing_table_entry)
+{
+ if (routing_table_entry.size() > m_routing_table.size()) {
+ m_routing_table.resize(routing_table_entry.size());
+ }
+ for (int v = 0; v < routing_table_entry.size(); v++) {
+ m_routing_table[v].push_back(routing_table_entry[v]);
+ }
+}
+
+void
+RoutingUnit::addWeight(int link_weight)
+{
+ m_weight_table.push_back(link_weight);
+}
+
+bool
+RoutingUnit::supportsVnet(int vnet, std::vector<int> sVnets)
+{
+ // If all vnets are supported, return true
+ if (sVnets.size() == 0) {
+ return true;
+ }
+
+ // Find the vnet in the vector, return true
+ if (std::find(sVnets.begin(), sVnets.end(), vnet) != sVnets.end()) {
+ return true;
+ }
+
+ // Not supported vnet
+ return false;
+}
+
+/*
+ * This is the default routing algorithm in garnet.
+ * The routing table is populated during topology creation.
+ * Routes can be biased via weight assignments in the topology file.
+ * Correct weight assignments are critical to provide deadlock avoidance.
+ */
+int
+RoutingUnit::lookupRoutingTable(int vnet, NetDest msg_destination)
+{
+ // First find all possible output link candidates
+ // For ordered vnet, just choose the first
+ // (to make sure different packets don't choose different routes)
+ // For unordered vnet, randomly choose any of the links
+ // To have a strict ordering between links, they should be given
+ // different weights in the topology file
+
+ int output_link = -1;
+ int min_weight = INFINITE_;
+ std::vector<int> output_link_candidates;
+ int num_candidates = 0;
+
+ // Identify the minimum weight among the candidate output links
+ for (int link = 0; link < m_routing_table[vnet].size(); link++) {
+ if (msg_destination.intersectionIsNotEmpty(
+ m_routing_table[vnet][link])) {
+
+ if (m_weight_table[link] <= min_weight)
+ min_weight = m_weight_table[link];
+ }
+ }
+
+ // Collect all candidate output links with this minimum weight
+ for (int link = 0; link < m_routing_table[vnet].size(); link++) {
+ if (msg_destination.intersectionIsNotEmpty(
+ m_routing_table[vnet][link])) {
+
+ if (m_weight_table[link] == min_weight) {
+ num_candidates++;
+ output_link_candidates.push_back(link);
+ }
+ }
+ }
+
+ if (output_link_candidates.size() == 0) {
+ fatal("Fatal Error:: No Route exists from this Router.");
+ exit(0);
+ }
+
+ // Randomly select any candidate output link
+ int candidate = 0;
+ if (!(m_router->get_net_ptr())->isVNetOrdered(vnet))
+ candidate = rand() % num_candidates;
+
+ output_link = output_link_candidates.at(candidate);
+ return output_link;
+}
+
+
+void
+RoutingUnit::addInDirection(PortDirection inport_dirn, int inport_idx)
+{
+ m_inports_dirn2idx[inport_dirn] = inport_idx;
+ m_inports_idx2dirn[inport_idx] = inport_dirn;
+}
+
+void
+RoutingUnit::addOutDirection(PortDirection outport_dirn, int outport_idx)
+{
+ m_outports_dirn2idx[outport_dirn] = outport_idx;
+ m_outports_idx2dirn[outport_idx] = outport_dirn;
+}
+
+// outportCompute() is called by the InputUnit
+// It calls the routing table by default.
+// A template for adaptive topology-specific routing algorithm
+// implementations using port directions rather than a static routing
+// table is provided here.
+
+int
+RoutingUnit::outportCompute(RouteInfo route, int inport,
+ PortDirection inport_dirn)
+{
+ int outport = -1;
+
+ if (route.dest_router == m_router->get_id()) {
+
+ // Multiple NIs may be connected to this router,
+ // all with output port direction = "Local"
+ // Get exact outport id from table
+ outport = lookupRoutingTable(route.vnet, route.net_dest);
+ return outport;
+ }
+
+ // Routing Algorithm set in GarnetNetwork.py
+ // Can be over-ridden from command line using --routing-algorithm = 1
+ RoutingAlgorithm routing_algorithm =
+ (RoutingAlgorithm) m_router->get_net_ptr()->getRoutingAlgorithm();
+
+ switch (routing_algorithm) {
+ case TABLE_: outport =
+ lookupRoutingTable(route.vnet, route.net_dest); break;
+ case XY_: outport =
+ outportComputeXY(route, inport, inport_dirn); break;
+ // any custom algorithm
+ case CUSTOM_: outport =
+ outportComputeCustom(route, inport, inport_dirn); break;
+ default: outport =
+ lookupRoutingTable(route.vnet, route.net_dest); break;
+ }
+
+ assert(outport != -1);
+ return outport;
+}
+
+// XY routing implemented using port directions
+// Only for reference purpose in a Mesh
+// By default Garnet uses the routing table
+int
+RoutingUnit::outportComputeXY(RouteInfo route,
+ int inport,
+ PortDirection inport_dirn)
+{
+ PortDirection outport_dirn = "Unknown";
+
+ int M5_VAR_USED num_rows = m_router->get_net_ptr()->getNumRows();
+ int num_cols = m_router->get_net_ptr()->getNumCols();
+ assert(num_rows > 0 && num_cols > 0);
+
+ int my_id = m_router->get_id();
+ int my_x = my_id % num_cols;
+ int my_y = my_id / num_cols;
+
+ int dest_id = route.dest_router;
+ int dest_x = dest_id % num_cols;
+ int dest_y = dest_id / num_cols;
+
+ int x_hops = abs(dest_x - my_x);
+ int y_hops = abs(dest_y - my_y);
+
+ bool x_dirn = (dest_x >= my_x);
+ bool y_dirn = (dest_y >= my_y);
+
+ // already checked that in outportCompute() function
+ assert(!(x_hops == 0 && y_hops == 0));
+
+ if (x_hops > 0) {
+ if (x_dirn) {
+ assert(inport_dirn == "Local" || inport_dirn == "West");
+ outport_dirn = "East";
+ } else {
+ assert(inport_dirn == "Local" || inport_dirn == "East");
+ outport_dirn = "West";
+ }
+ } else if (y_hops > 0) {
+ if (y_dirn) {
+ // "Local" or "South" or "West" or "East"
+ assert(inport_dirn != "North");
+ outport_dirn = "North";
+ } else {
+ // "Local" or "North" or "West" or "East"
+ assert(inport_dirn != "South");
+ outport_dirn = "South";
+ }
+ } else {
+ // x_hops == 0 and y_hops == 0
+ // this is not possible
+ // already checked that in outportCompute() function
+ panic("x_hops == y_hops == 0");
+ }
+
+ return m_outports_dirn2idx[outport_dirn];
+}
+
+// Template for implementing custom routing algorithm
+// using port directions. (Example adaptive)
+int
+RoutingUnit::outportComputeCustom(RouteInfo route,
+ int inport,
+ PortDirection inport_dirn)
+{
+ panic("%s placeholder executed", __FUNCTION__);
+}
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_ROUTINGUNIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_ROUTINGUNIT_HH__
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/NetDest.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+
+class InputUnit;
+class Router;
+
+class RoutingUnit
+{
+ public:
+ RoutingUnit(Router *router);
+ int outportCompute(RouteInfo route,
+ int inport,
+ PortDirection inport_dirn);
+
+ // Topology-agnostic Routing Table based routing (default)
+ void addRoute(std::vector<NetDest>& routing_table_entry);
+ void addWeight(int link_weight);
+
+ // get output port from routing table
+ int lookupRoutingTable(int vnet, NetDest net_dest);
+
+ // Topology-specific direction based routing
+ void addInDirection(PortDirection inport_dirn, int inport);
+ void addOutDirection(PortDirection outport_dirn, int outport);
+
+ // Routing for Mesh
+ int outportComputeXY(RouteInfo route,
+ int inport,
+ PortDirection inport_dirn);
+
+ // Custom Routing Algorithm using Port Directions
+ int outportComputeCustom(RouteInfo route,
+ int inport,
+ PortDirection inport_dirn);
+
+ // Returns true if vnet is present in the vector
+ // of vnets or if the vector supports all vnets.
+ bool supportsVnet(int vnet, std::vector<int> sVnets);
+
+
+ private:
+ Router *m_router;
+
+ // Routing Table
+ std::vector<std::vector<NetDest>> m_routing_table;
+ std::vector<int> m_weight_table;
+
+ // Inport and Outport direction to idx maps
+ std::map<PortDirection, int> m_inports_dirn2idx;
+ std::map<int, PortDirection> m_inports_idx2dirn;
+ std::map<int, PortDirection> m_outports_idx2dirn;
+ std::map<PortDirection, int> m_outports_dirn2idx;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_ROUTINGUNIT_HH__
--- /dev/null
+# -*- mode:python -*-
+
+# Copyright (c) 2016 Georgia Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('*')
+
+if env['PROTOCOL'] == 'None':
+ Return()
+
+SimObject('GarnetLink.py')
+SimObject('GarnetNetwork.py')
+
+Source('GarnetLink.cc')
+Source('GarnetNetwork.cc')
+Source('InputUnit.cc')
+Source('NetworkInterface.cc')
+Source('NetworkLink.cc')
+Source('OutVcState.cc')
+Source('OutputUnit.cc')
+Source('Router.cc')
+Source('RoutingUnit.cc')
+Source('SwitchAllocator.cc')
+Source('CrossbarSwitch.cc')
+Source('VirtualChannel.cc')
+Source('flitBuffer.cc')
+Source('flit.cc')
+Source('Credit.cc')
+Source('NetworkBridge.cc')
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/SwitchAllocator.hh"
+
+#include "debug/RubyNetwork.hh"
+#include "mem/ruby/network/garnet/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet/InputUnit.hh"
+#include "mem/ruby/network/garnet/OutputUnit.hh"
+#include "mem/ruby/network/garnet/Router.hh"
+
+SwitchAllocator::SwitchAllocator(Router *router)
+ : Consumer(router)
+{
+ m_router = router;
+ m_num_vcs = m_router->get_num_vcs();
+ m_vc_per_vnet = m_router->get_vc_per_vnet();
+
+ m_input_arbiter_activity = 0;
+ m_output_arbiter_activity = 0;
+}
+
+void
+SwitchAllocator::init()
+{
+ m_num_inports = m_router->get_num_inports();
+ m_num_outports = m_router->get_num_outports();
+ m_round_robin_inport.resize(m_num_outports);
+ m_round_robin_invc.resize(m_num_inports);
+ m_port_requests.resize(m_num_outports);
+ m_vc_winners.resize(m_num_outports);
+
+ for (int i = 0; i < m_num_inports; i++) {
+ m_round_robin_invc[i] = 0;
+ }
+
+ for (int i = 0; i < m_num_outports; i++) {
+ m_port_requests[i].resize(m_num_inports);
+ m_vc_winners[i].resize(m_num_inports);
+
+ m_round_robin_inport[i] = 0;
+
+ for (int j = 0; j < m_num_inports; j++) {
+ m_port_requests[i][j] = false; // [outport][inport]
+ }
+ }
+}
+
+/*
+ * The wakeup function of the SwitchAllocator performs a 2-stage
+ * seperable switch allocation. At the end of the 2nd stage, a free
+ * output VC is assigned to the winning flits of each output port.
+ * There is no separate VCAllocator stage like the one in garnet1.0.
+ * At the end of this function, the router is rescheduled to wakeup
+ * next cycle for peforming SA for any flits ready next cycle.
+ */
+
+void
+SwitchAllocator::wakeup()
+{
+ arbitrate_inports(); // First stage of allocation
+ arbitrate_outports(); // Second stage of allocation
+
+ clear_request_vector();
+ check_for_wakeup();
+}
+
+/*
+ * SA-I (or SA-i) loops through all input VCs at every input port,
+ * and selects one in a round robin manner.
+ * - For HEAD/HEAD_TAIL flits only selects an input VC whose output port
+ * has at least one free output VC.
+ * - For BODY/TAIL flits, only selects an input VC that has credits
+ * in its output VC.
+ * Places a request for the output port from this input VC.
+ */
+
+void
+SwitchAllocator::arbitrate_inports()
+{
+ // Select a VC from each input in a round robin manner
+ // Independent arbiter at each input port
+ for (int inport = 0; inport < m_num_inports; inport++) {
+ int invc = m_round_robin_invc[inport];
+
+ for (int invc_iter = 0; invc_iter < m_num_vcs; invc_iter++) {
+ auto input_unit = m_router->getInputUnit(inport);
+
+ if (input_unit->need_stage(invc, SA_, curTick())) {
+ // This flit is in SA stage
+
+ int outport = input_unit->get_outport(invc);
+ int outvc = input_unit->get_outvc(invc);
+
+ // check if the flit in this InputVC is allowed to be sent
+ // send_allowed conditions described in that function.
+ bool make_request =
+ send_allowed(inport, invc, outport, outvc);
+
+ if (make_request) {
+ m_input_arbiter_activity++;
+ m_port_requests[outport][inport] = true;
+ m_vc_winners[outport][inport]= invc;
+
+ break; // got one vc winner for this port
+ }
+ }
+
+ invc++;
+ if (invc >= m_num_vcs)
+ invc = 0;
+ }
+ }
+}
+
+/*
+ * SA-II (or SA-o) loops through all output ports,
+ * and selects one input VC (that placed a request during SA-I)
+ * as the winner for this output port in a round robin manner.
+ * - For HEAD/HEAD_TAIL flits, performs simplified outvc allocation.
+ * (i.e., select a free VC from the output port).
+ * - For BODY/TAIL flits, decrement a credit in the output vc.
+ * The winning flit is read out from the input VC and sent to the
+ * CrossbarSwitch.
+ * An increment_credit signal is sent from the InputUnit
+ * to the upstream router. For HEAD_TAIL/TAIL flits, is_free_signal in the
+ * credit is set to true.
+ */
+
+void
+SwitchAllocator::arbitrate_outports()
+{
+ // Now there are a set of input vc requests for output vcs.
+ // Again do round robin arbitration on these requests
+ // Independent arbiter at each output port
+ for (int outport = 0; outport < m_num_outports; outport++) {
+ int inport = m_round_robin_inport[outport];
+
+ for (int inport_iter = 0; inport_iter < m_num_inports;
+ inport_iter++) {
+
+ // inport has a request this cycle for outport
+ if (m_port_requests[outport][inport]) {
+ auto output_unit = m_router->getOutputUnit(outport);
+ auto input_unit = m_router->getInputUnit(inport);
+
+ // grant this outport to this inport
+ int invc = m_vc_winners[outport][inport];
+
+ int outvc = input_unit->get_outvc(invc);
+ if (outvc == -1) {
+ // VC Allocation - select any free VC from outport
+ outvc = vc_allocate(outport, inport, invc);
+ }
+
+ // remove flit from Input VC
+ flit *t_flit = input_unit->getTopFlit(invc);
+
+ DPRINTF(RubyNetwork, "SwitchAllocator at Router %d "
+ "granted outvc %d at outport %d "
+ "to invc %d at inport %d to flit %s at "
+ "cycle: %lld\n",
+ m_router->get_id(), outvc,
+ m_router->getPortDirectionName(
+ output_unit->get_direction()),
+ invc,
+ m_router->getPortDirectionName(
+ input_unit->get_direction()),
+ *t_flit,
+ m_router->curCycle());
+
+
+ // Update outport field in the flit since this is
+ // used by CrossbarSwitch code to send it out of
+ // correct outport.
+ // Note: post route compute in InputUnit,
+ // outport is updated in VC, but not in flit
+ t_flit->set_outport(outport);
+
+ // set outvc (i.e., invc for next hop) in flit
+ // (This was updated in VC by vc_allocate, but not in flit)
+ t_flit->set_vc(outvc);
+
+ // decrement credit in outvc
+ output_unit->decrement_credit(outvc);
+
+ // flit ready for Switch Traversal
+ t_flit->advance_stage(ST_, curTick());
+ m_router->grant_switch(inport, t_flit);
+ m_output_arbiter_activity++;
+
+ if ((t_flit->get_type() == TAIL_) ||
+ t_flit->get_type() == HEAD_TAIL_) {
+
+ // This Input VC should now be empty
+ assert(!(input_unit->isReady(invc, curTick())));
+
+ // Free this VC
+ input_unit->set_vc_idle(invc, curTick());
+
+ // Send a credit back
+ // along with the information that this VC is now idle
+ input_unit->increment_credit(invc, true, curTick());
+ } else {
+ // Send a credit back
+ // but do not indicate that the VC is idle
+ input_unit->increment_credit(invc, false, curTick());
+ }
+
+ // remove this request
+ m_port_requests[outport][inport] = false;
+
+ // Update Round Robin pointer
+ m_round_robin_inport[outport] = inport + 1;
+ if (m_round_robin_inport[outport] >= m_num_inports)
+ m_round_robin_inport[outport] = 0;
+
+ // Update Round Robin pointer to the next VC
+ // We do it here to keep it fair.
+ // Only the VC which got switch traversal
+ // is updated.
+ m_round_robin_invc[inport] = invc + 1;
+ if (m_round_robin_invc[inport] >= m_num_vcs)
+ m_round_robin_invc[inport] = 0;
+
+
+ break; // got a input winner for this outport
+ }
+
+ inport++;
+ if (inport >= m_num_inports)
+ inport = 0;
+ }
+ }
+}
+
+/*
+ * A flit can be sent only if
+ * (1) there is at least one free output VC at the
+ * output port (for HEAD/HEAD_TAIL),
+ * or
+ * (2) if there is at least one credit (i.e., buffer slot)
+ * within the VC for BODY/TAIL flits of multi-flit packets.
+ * and
+ * (3) pt-to-pt ordering is not violated in ordered vnets, i.e.,
+ * there should be no other flit in this input port
+ * within an ordered vnet
+ * that arrived before this flit and is requesting the same output port.
+ */
+
+bool
+SwitchAllocator::send_allowed(int inport, int invc, int outport, int outvc)
+{
+ // Check if outvc needed
+ // Check if credit needed (for multi-flit packet)
+ // Check if ordering violated (in ordered vnet)
+
+ int vnet = get_vnet(invc);
+ bool has_outvc = (outvc != -1);
+ bool has_credit = false;
+
+ auto output_unit = m_router->getOutputUnit(outport);
+ if (!has_outvc) {
+
+ // needs outvc
+ // this is only true for HEAD and HEAD_TAIL flits.
+
+ if (output_unit->has_free_vc(vnet)) {
+
+ has_outvc = true;
+
+ // each VC has at least one buffer,
+ // so no need for additional credit check
+ has_credit = true;
+ }
+ } else {
+ has_credit = output_unit->has_credit(outvc);
+ }
+
+ // cannot send if no outvc or no credit.
+ if (!has_outvc || !has_credit)
+ return false;
+
+
+ // protocol ordering check
+ if ((m_router->get_net_ptr())->isVNetOrdered(vnet)) {
+ auto input_unit = m_router->getInputUnit(inport);
+
+ // enqueue time of this flit
+ Tick t_enqueue_time = input_unit->get_enqueue_time(invc);
+
+ // check if any other flit is ready for SA and for same output port
+ // and was enqueued before this flit
+ int vc_base = vnet*m_vc_per_vnet;
+ for (int vc_offset = 0; vc_offset < m_vc_per_vnet; vc_offset++) {
+ int temp_vc = vc_base + vc_offset;
+ if (input_unit->need_stage(temp_vc, SA_, curTick()) &&
+ (input_unit->get_outport(temp_vc) == outport) &&
+ (input_unit->get_enqueue_time(temp_vc) < t_enqueue_time)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Assign a free VC to the winner of the output port.
+int
+SwitchAllocator::vc_allocate(int outport, int inport, int invc)
+{
+ // Select a free VC from the output port
+ int outvc =
+ m_router->getOutputUnit(outport)->select_free_vc(get_vnet(invc));
+
+ // has to get a valid VC since it checked before performing SA
+ assert(outvc != -1);
+ m_router->getInputUnit(inport)->grant_outvc(invc, outvc);
+ return outvc;
+}
+
+// Wakeup the router next cycle to perform SA again
+// if there are flits ready.
+void
+SwitchAllocator::check_for_wakeup()
+{
+ Tick nextCycle = m_router->clockEdge(Cycles(1));
+
+ if (m_router->alreadyScheduled(nextCycle)) {
+ return;
+ }
+
+ for (int i = 0; i < m_num_inports; i++) {
+ for (int j = 0; j < m_num_vcs; j++) {
+ if (m_router->getInputUnit(i)->need_stage(j, SA_, nextCycle)) {
+ m_router->schedule_wakeup(Cycles(1));
+ return;
+ }
+ }
+ }
+}
+
+int
+SwitchAllocator::get_vnet(int invc)
+{
+ int vnet = invc/m_vc_per_vnet;
+ assert(vnet < m_router->get_num_vnets());
+ return vnet;
+}
+
+
+// Clear the request vector within the allocator at end of SA-II.
+// Was populated by SA-I.
+void
+SwitchAllocator::clear_request_vector()
+{
+ for (int i = 0; i < m_num_outports; i++) {
+ for (int j = 0; j < m_num_inports; j++) {
+ m_port_requests[i][j] = false;
+ }
+ }
+}
+
+void
+SwitchAllocator::resetStats()
+{
+ m_input_arbiter_activity = 0;
+ m_output_arbiter_activity = 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_SWITCHALLOCATOR_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_SWITCHALLOCATOR_HH__
+
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+
+class Router;
+class InputUnit;
+class OutputUnit;
+
+class SwitchAllocator : public Consumer
+{
+ public:
+ SwitchAllocator(Router *router);
+ void wakeup();
+ void init();
+ void clear_request_vector();
+ void check_for_wakeup();
+ int get_vnet (int invc);
+ void print(std::ostream& out) const {};
+ void arbitrate_inports();
+ void arbitrate_outports();
+ bool send_allowed(int inport, int invc, int outport, int outvc);
+ int vc_allocate(int outport, int inport, int invc);
+
+ inline double
+ get_input_arbiter_activity()
+ {
+ return m_input_arbiter_activity;
+ }
+ inline double
+ get_output_arbiter_activity()
+ {
+ return m_output_arbiter_activity;
+ }
+
+ void resetStats();
+
+ private:
+ int m_num_inports, m_num_outports;
+ int m_num_vcs, m_vc_per_vnet;
+
+ double m_input_arbiter_activity, m_output_arbiter_activity;
+
+ Router *m_router;
+ std::vector<int> m_round_robin_invc;
+ std::vector<int> m_round_robin_inport;
+ std::vector<std::vector<bool>> m_port_requests;
+ std::vector<std::vector<int>> m_vc_winners; // a list for each outport
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_SWITCHALLOCATOR_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/VirtualChannel.hh"
+
+VirtualChannel::VirtualChannel()
+ : inputBuffer(), m_vc_state(IDLE_, Tick(0)), m_output_port(-1),
+ m_enqueue_time(INFINITE_), m_output_vc(-1)
+{
+}
+
+void
+VirtualChannel::set_idle(Tick curTime)
+{
+ m_vc_state.first = IDLE_;
+ m_vc_state.second = curTime;
+ m_enqueue_time = Tick(INFINITE_);
+ m_output_port = -1;
+ m_output_vc = -1;
+}
+
+void
+VirtualChannel::set_active(Tick curTime)
+{
+ m_vc_state.first = ACTIVE_;
+ m_vc_state.second = curTime;
+ m_enqueue_time = curTime;
+}
+
+bool
+VirtualChannel::need_stage(flit_stage stage, Tick time)
+{
+ if (inputBuffer.isReady(time)) {
+ assert(m_vc_state.first == ACTIVE_ && m_vc_state.second <= time);
+ flit *t_flit = inputBuffer.peekTopFlit();
+ return(t_flit->is_stage(stage, time));
+ }
+ return false;
+}
+
+uint32_t
+VirtualChannel::functionalWrite(Packet *pkt)
+{
+ return inputBuffer.functionalWrite(pkt);
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Inria
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * Copyright (c) 2008 Princeton University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_VIRTUALCHANNEL_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_VIRTUALCHANNEL_HH__
+
+#include <utility>
+
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+class VirtualChannel
+{
+ public:
+ VirtualChannel();
+ ~VirtualChannel() = default;
+
+ bool need_stage(flit_stage stage, Tick time);
+ void set_idle(Tick curTime);
+ void set_active(Tick curTime);
+ void set_outvc(int outvc) { m_output_vc = outvc; }
+ inline int get_outvc() { return m_output_vc; }
+ void set_outport(int outport) { m_output_port = outport; };
+ inline int get_outport() { return m_output_port; }
+
+ inline Tick get_enqueue_time() { return m_enqueue_time; }
+ inline void set_enqueue_time(Tick time) { m_enqueue_time = time; }
+ inline VC_state_type get_state() { return m_vc_state.first; }
+
+ inline bool
+ isReady(Tick curTime)
+ {
+ return inputBuffer.isReady(curTime);
+ }
+
+ inline void
+ insertFlit(flit *t_flit)
+ {
+ inputBuffer.insert(t_flit);
+ }
+
+ inline void
+ set_state(VC_state_type m_state, Tick curTime)
+ {
+ m_vc_state.first = m_state;
+ m_vc_state.second = curTime;
+ }
+
+ inline flit*
+ peekTopFlit()
+ {
+ return inputBuffer.peekTopFlit();
+ }
+
+ inline flit*
+ getTopFlit()
+ {
+ return inputBuffer.getTopFlit();
+ }
+
+ uint32_t functionalWrite(Packet *pkt);
+
+ private:
+ flitBuffer inputBuffer;
+ std::pair<VC_state_type, Tick> m_vc_state;
+ int m_output_port;
+ Tick m_enqueue_time;
+ int m_output_vc;
+};
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_VIRTUALCHANNEL_HH__
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/flit.hh"
+
+#include "base/intmath.hh"
+#include "debug/RubyNetwork.hh"
+
+// Constructor for the flit
+flit::flit(int id, int vc, int vnet, RouteInfo route, int size,
+ MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime)
+{
+ m_size = size;
+ m_msg_ptr = msg_ptr;
+ m_enqueue_time = curTime;
+ m_dequeue_time = curTime;
+ m_time = curTime;
+ m_id = id;
+ m_vnet = vnet;
+ m_vc = vc;
+ m_route = route;
+ m_stage.first = I_;
+ m_stage.second = curTime;
+ m_width = bWidth;
+ msgSize = MsgSize;
+
+ if (size == 1) {
+ m_type = HEAD_TAIL_;
+ return;
+ }
+ if (id == 0)
+ m_type = HEAD_;
+ else if (id == (size - 1))
+ m_type = TAIL_;
+ else
+ m_type = BODY_;
+}
+
+flit *
+flit::serialize(int ser_id, int parts, uint32_t bWidth)
+{
+ assert(m_width > bWidth);
+
+ int ratio = (int)divCeil(m_width, bWidth);
+ int new_id = (m_id*ratio) + ser_id;
+ int new_size = (int)divCeil((float)msgSize, (float)bWidth);
+ assert(new_id < new_size);
+
+ flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
+ new_size, m_msg_ptr, msgSize, bWidth, m_time);
+ fl->set_enqueue_time(m_enqueue_time);
+ fl->set_src_delay(src_delay);
+ return fl;
+}
+
+flit *
+flit::deserialize(int des_id, int num_flits, uint32_t bWidth)
+{
+ int ratio = (int)divCeil((float)bWidth, (float)m_width);
+ int new_id = ((int)divCeil((float)(m_id+1), (float)ratio)) - 1;
+ int new_size = (int)divCeil((float)msgSize, (float)bWidth);
+ assert(new_id < new_size);
+
+ flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
+ new_size, m_msg_ptr, msgSize, bWidth, m_time);
+ fl->set_enqueue_time(m_enqueue_time);
+ fl->set_src_delay(src_delay);
+ return fl;
+}
+
+// Flit can be printed out for debugging purposes
+void
+flit::print(std::ostream& out) const
+{
+ out << "[flit:: ";
+ out << "Id=" << m_id << " ";
+ out << "Type=" << m_type << " ";
+ out << "Size=" << m_size << " ";
+ out << "Vnet=" << m_vnet << " ";
+ out << "VC=" << m_vc << " ";
+ out << "Src NI=" << m_route.src_ni << " ";
+ out << "Src Router=" << m_route.src_router << " ";
+ out << "Dest NI=" << m_route.dest_ni << " ";
+ out << "Dest Router=" << m_route.dest_router << " ";
+ out << "Set Time=" << m_time << " ";
+ out << "Width=" << m_width<< " ";
+ out << "]";
+}
+
+bool
+flit::functionalWrite(Packet *pkt)
+{
+ Message *msg = m_msg_ptr.get();
+ return msg->functionalWrite(pkt);
+}
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_FLIT_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_FLIT_HH__
+
+#include <cassert>
+#include <iostream>
+
+#include "base/types.hh"
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
+
+class flit
+{
+ public:
+ flit() {}
+ flit(int id, int vc, int vnet, RouteInfo route, int size,
+ MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime);
+
+ virtual ~flit(){};
+
+ int get_outport() {return m_outport; }
+ int get_size() { return m_size; }
+ Tick get_enqueue_time() { return m_enqueue_time; }
+ Tick get_dequeue_time() { return m_dequeue_time; }
+ int get_id() { return m_id; }
+ Tick get_time() { return m_time; }
+ int get_vnet() { return m_vnet; }
+ int get_vc() { return m_vc; }
+ RouteInfo get_route() { return m_route; }
+ MsgPtr& get_msg_ptr() { return m_msg_ptr; }
+ flit_type get_type() { return m_type; }
+ std::pair<flit_stage, Tick> get_stage() { return m_stage; }
+ Tick get_src_delay() { return src_delay; }
+
+ void set_outport(int port) { m_outport = port; }
+ void set_time(Tick time) { m_time = time; }
+ void set_vc(int vc) { m_vc = vc; }
+ void set_route(RouteInfo route) { m_route = route; }
+ void set_src_delay(Tick delay) { src_delay = delay; }
+ void set_dequeue_time(Tick time) { m_dequeue_time = time; }
+ void set_enqueue_time(Tick time) { m_enqueue_time = time; }
+
+ void increment_hops() { m_route.hops_traversed++; }
+ virtual void print(std::ostream& out) const;
+
+ bool
+ is_stage(flit_stage stage, Tick time)
+ {
+ return (stage == m_stage.first &&
+ time >= m_stage.second);
+ }
+
+ void
+ advance_stage(flit_stage t_stage, Tick newTime)
+ {
+ m_stage.first = t_stage;
+ m_stage.second = newTime;
+ }
+
+ static bool
+ greater(flit* n1, flit* n2)
+ {
+ if (n1->get_time() == n2->get_time()) {
+ //assert(n1->flit_id != n2->flit_id);
+ return (n1->get_id() > n2->get_id());
+ } else {
+ return (n1->get_time() > n2->get_time());
+ }
+ }
+
+ bool functionalWrite(Packet *pkt);
+
+ virtual flit* serialize(int ser_id, int parts, uint32_t bWidth);
+ virtual flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
+
+ uint32_t m_width;
+ int msgSize;
+ protected:
+ int m_id;
+ int m_vnet;
+ int m_vc;
+ RouteInfo m_route;
+ int m_size;
+ Tick m_enqueue_time, m_dequeue_time;
+ Tick m_time;
+ flit_type m_type;
+ MsgPtr m_msg_ptr;
+ int m_outport;
+ Tick src_delay;
+ std::pair<flit_stage, Tick> m_stage;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const flit& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_FLIT_HH__
--- /dev/null
+/*
+ * Copyright (c) 2020 Advanced Micro Devices, Inc.
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "mem/ruby/network/garnet/flitBuffer.hh"
+
+flitBuffer::flitBuffer()
+{
+ max_size = INFINITE_;
+}
+
+flitBuffer::flitBuffer(int maximum_size)
+{
+ max_size = maximum_size;
+}
+
+bool
+flitBuffer::isEmpty()
+{
+ return (m_buffer.size() == 0);
+}
+
+bool
+flitBuffer::isReady(Tick curTime)
+{
+ if (m_buffer.size() != 0 ) {
+ flit *t_flit = peekTopFlit();
+ if (t_flit->get_time() <= curTime)
+ return true;
+ }
+ return false;
+}
+
+void
+flitBuffer::print(std::ostream& out) const
+{
+ out << "[flitBuffer: " << m_buffer.size() << "] " << std::endl;
+}
+
+bool
+flitBuffer::isFull()
+{
+ return (m_buffer.size() >= max_size);
+}
+
+void
+flitBuffer::setMaxSize(int maximum)
+{
+ max_size = maximum;
+}
+
+uint32_t
+flitBuffer::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ for (unsigned int i = 0; i < m_buffer.size(); ++i) {
+ if (m_buffer[i]->functionalWrite(pkt)) {
+ num_functional_writes++;
+ }
+ }
+
+ return num_functional_writes;
+}
--- /dev/null
+/*
+ * Copyright (c) 2008 Princeton University
+ * Copyright (c) 2016 Georgia Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEM_RUBY_NETWORK_GARNET_0_FLITBUFFER_HH__
+#define __MEM_RUBY_NETWORK_GARNET_0_FLITBUFFER_HH__
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "mem/ruby/network/garnet/CommonTypes.hh"
+#include "mem/ruby/network/garnet/flit.hh"
+
+class flitBuffer
+{
+ public:
+ flitBuffer();
+ flitBuffer(int maximum_size);
+
+ bool isReady(Tick curTime);
+ bool isEmpty();
+ void print(std::ostream& out) const;
+ bool isFull();
+ void setMaxSize(int maximum);
+ int getSize() const { return m_buffer.size(); }
+
+ flit *
+ getTopFlit()
+ {
+ flit *f = m_buffer.front();
+ std::pop_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
+ m_buffer.pop_back();
+ return f;
+ }
+
+ flit *
+ peekTopFlit()
+ {
+ return m_buffer.front();
+ }
+
+ void
+ insert(flit *flt)
+ {
+ m_buffer.push_back(flt);
+ std::push_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
+ }
+
+ uint32_t functionalWrite(Packet *pkt);
+
+ private:
+ std::vector<flit *> m_buffer;
+ int max_size;
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, const flitBuffer& obj)
+{
+ obj.print(out);
+ out << std::flush;
+ return out;
+}
+
+#endif // __MEM_RUBY_NETWORK_GARNET_0_FLITBUFFER_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_COMMONTYPES_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_COMMONTYPES_HH__
-
-#include "mem/ruby/common/NetDest.hh"
-
-// All common enums and typedefs go here
-
-enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_,
- CREDIT_, NUM_FLIT_TYPE_};
-enum VC_state_type {IDLE_, VC_AB_, ACTIVE_, NUM_VC_STATE_TYPE_};
-enum VNET_type {CTRL_VNET_, DATA_VNET_, NULL_VNET_, NUM_VNET_TYPE_};
-enum flit_stage {I_, VA_, SA_, ST_, LT_, NUM_FLIT_STAGE_};
-enum link_type { EXT_IN_, EXT_OUT_, INT_, NUM_LINK_TYPES_ };
-enum RoutingAlgorithm { TABLE_ = 0, XY_ = 1, CUSTOM_ = 2,
- NUM_ROUTING_ALGORITHM_};
-
-struct RouteInfo
-{
- RouteInfo()
- : vnet(0), src_ni(0), src_router(0), dest_ni(0), dest_router(0),
- hops_traversed(0)
- {}
-
- // destination format for table-based routing
- int vnet;
- NetDest net_dest;
-
- // src and dest format for topology-specific routing
- int src_ni;
- int src_router;
- int dest_ni;
- int dest_router;
- int hops_traversed;
-};
-
-#define INFINITE_ 10000
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_COMMONTYPES_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-
-#include "base/trace.hh"
-#include "debug/RubyNetwork.hh"
-
-// Credit Signal for buffers inside VC
-// Carries m_vc (inherits from flit.hh)
-// and m_is_free_signal (whether VC is free or not)
-
-Credit::Credit(int vc, bool is_free_signal, Tick curTime)
- : flit(0, vc, 0, RouteInfo(), 0, nullptr, 0, 0, curTime)
-{
- m_is_free_signal = is_free_signal;
- m_type = CREDIT_;
-}
-
-flit *
-Credit::serialize(int ser_id, int parts, uint32_t bWidth)
-{
- DPRINTF(RubyNetwork, "Serializing a credit\n");
- bool new_free = false;
- if ((ser_id+1 == parts) && m_is_free_signal) {
- new_free = true;
- }
- Credit *new_credit_flit = new Credit(m_vc, new_free, m_time);
- return new_credit_flit;
-}
-
-flit *
-Credit::deserialize(int des_id, int num_flits, uint32_t bWidth)
-{
- DPRINTF(RubyNetwork, "DeSerializing a credit vc:%d free:%d\n",
- m_vc, m_is_free_signal);
- if (m_is_free_signal) {
- // We are not going to get anymore credits for this vc
- // So send a credit in any case
- return new Credit(m_vc, true, m_time);
- }
-
- return new Credit(m_vc, false, m_time);
-}
-
-void
-Credit::print(std::ostream& out) const
-{
- out << "[Credit:: ";
- out << "Type=" << m_type << " ";
- out << "VC=" << m_vc << " ";
- out << "FreeVC=" << m_is_free_signal << " ";
- out << "Set Time=" << m_time << " ";
- out << "]";
-}
-
-
-
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_CREDIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_CREDIT_HH__
-
-#include <cassert>
-#include <iostream>
-
-#include "base/types.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-// Credit Signal for buffers inside VC
-// Carries m_vc (inherits from flit.hh)
-// and m_is_free_signal (whether VC is free or not)
-
-class Credit : public flit
-{
- public:
- Credit() {};
- Credit(int vc, bool is_free_signal, Tick curTime);
-
- // Functions used by SerDes
- flit* serialize(int ser_id, int parts, uint32_t bWidth);
- flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
- void print(std::ostream& out) const;
-
- ~Credit() {};
-
- bool is_free_signal() { return m_is_free_signal; }
-
- private:
- bool m_is_free_signal;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_CREDIT_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_CREDITLINK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_CREDITLINK_HH__
-
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "params/CreditLink.hh"
-
-class CreditLink : public NetworkLink
-{
- public:
- typedef CreditLinkParams Params;
- CreditLink(const Params *p) : NetworkLink(p) {}
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_CREDITLINK_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-CrossbarSwitch::CrossbarSwitch(Router *router)
- : Consumer(router), m_router(router), m_num_vcs(m_router->get_num_vcs()),
- m_crossbar_activity(0), switchBuffers(0)
-{
-}
-
-void
-CrossbarSwitch::init()
-{
- switchBuffers.resize(m_router->get_num_inports());
-}
-
-/*
- * The wakeup function of the CrossbarSwitch loops through all input ports,
- * and sends the winning flit (from SA) out of its output port on to the
- * output link. The output link is scheduled for wakeup in the next cycle.
- */
-
-void
-CrossbarSwitch::wakeup()
-{
- DPRINTF(RubyNetwork, "CrossbarSwitch at Router %d woke up "
- "at time: %lld\n",
- m_router->get_id(), m_router->curCycle());
-
- for (auto& switch_buffer : switchBuffers) {
- if (!switch_buffer.isReady(curTick())) {
- continue;
- }
-
- flit *t_flit = switch_buffer.peekTopFlit();
- if (t_flit->is_stage(ST_, curTick())) {
- int outport = t_flit->get_outport();
-
- // flit performs LT_ in the next cycle
- t_flit->advance_stage(LT_, m_router->clockEdge(Cycles(1)));
- t_flit->set_time(m_router->clockEdge(Cycles(1)));
-
- // This will take care of waking up the Network Link
- // in the next cycle
- m_router->getOutputUnit(outport)->insert_flit(t_flit);
- switch_buffer.getTopFlit();
- m_crossbar_activity++;
- }
- }
-}
-
-uint32_t
-CrossbarSwitch::functionalWrite(Packet *pkt)
-{
- uint32_t num_functional_writes = 0;
-
- for (auto& switch_buffer : switchBuffers) {
- num_functional_writes += switch_buffer.functionalWrite(pkt);
- }
-
- return num_functional_writes;
-}
-
-void
-CrossbarSwitch::resetStats()
-{
- m_crossbar_activity = 0;
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_CROSSBARSWITCH_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_CROSSBARSWITCH_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-class Router;
-
-class CrossbarSwitch : public Consumer
-{
- public:
- CrossbarSwitch(Router *router);
- ~CrossbarSwitch() = default;
- void wakeup();
- void init();
- void print(std::ostream& out) const {};
-
- inline void
- update_sw_winner(int inport, flit *t_flit)
- {
- switchBuffers[inport].insert(t_flit);
- }
-
- inline double get_crossbar_activity() { return m_crossbar_activity; }
-
- uint32_t functionalWrite(Packet *pkt);
- void resetStats();
-
- private:
- Router *m_router;
- int m_num_vcs;
- double m_crossbar_activity;
- std::vector<flitBuffer> switchBuffers;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_CROSSBARSWITCH_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-
-GarnetIntLink::GarnetIntLink(const Params *p)
- : BasicIntLink(p)
-{
- // Uni-directional
-
- m_network_link = p->network_link;
- m_credit_link = p->credit_link;
-
- srcCdcEn = p->src_cdc;
- dstCdcEn = p->dst_cdc;
-
- srcSerdesEn = p->src_serdes;
- dstSerdesEn = p->dst_serdes;
-
- srcBridgeEn = false;
- dstBridgeEn = false;
-
- if (srcCdcEn || srcSerdesEn) {
- srcBridgeEn = true;
- srcNetBridge = p->src_net_bridge;
- srcCredBridge = p->src_cred_bridge;
- }
- if (dstCdcEn || dstSerdesEn) {
- dstBridgeEn = true;
- dstNetBridge = p->dst_net_bridge;
- dstCredBridge = p->dst_cred_bridge;
- }
-
-}
-
-void
-GarnetIntLink::init()
-{
- if (srcBridgeEn) {
- assert(srcNetBridge && srcCredBridge);
- srcNetBridge->initBridge(srcCredBridge, srcCdcEn, srcSerdesEn);
- srcCredBridge->initBridge(srcNetBridge, srcCdcEn, srcSerdesEn);
- }
-
- if (dstBridgeEn) {
- assert(dstNetBridge && dstCredBridge);
- dstNetBridge->initBridge(dstCredBridge, dstCdcEn, dstSerdesEn);
- dstCredBridge->initBridge(dstNetBridge, dstCdcEn, dstSerdesEn);
- }
-}
-
-void
-GarnetIntLink::print(std::ostream& out) const
-{
- out << name();
-}
-
-GarnetIntLink *
-GarnetIntLinkParams::create()
-{
- return new GarnetIntLink(this);
-}
-
-GarnetExtLink::GarnetExtLink(const Params *p)
- : BasicExtLink(p)
-{
- // Bi-directional
-
- // In
- m_network_links[0] = p->network_links[0];
- m_credit_links[0] = p->credit_links[0];
-
- // Out
- m_network_links[1] = p->network_links[1];
- m_credit_links[1] = p->credit_links[1];
-
-
- extCdcEn = p->ext_cdc;
- intCdcEn = p->int_cdc;
-
- extSerdesEn = p->ext_serdes;
- intSerdesEn = p->int_serdes;
-
- extBridgeEn = false;
- intBridgeEn = false;
-
- if (extCdcEn || extSerdesEn) {
- extBridgeEn = true;
- extNetBridge[0] = p->ext_net_bridge[0];
- extCredBridge[0] = p->ext_cred_bridge[0];
- extNetBridge[1] = p->ext_net_bridge[1];
- extCredBridge[1] = p->ext_cred_bridge[1];
- }
-
- if (intCdcEn || intSerdesEn) {
- intBridgeEn = true;
- intNetBridge[0] = p->int_net_bridge[0];
- intNetBridge[1] = p->int_net_bridge[1];
- intCredBridge[0] = p->int_cred_bridge[0];
- intCredBridge[1] = p->int_cred_bridge[1];
- }
-
-}
-
-void
-GarnetExtLink::init()
-{
- if (extBridgeEn) {
- assert(extNetBridge[0] && extCredBridge[0] &&
- extNetBridge[1] && extCredBridge[1]);
- extNetBridge[0]->initBridge(extCredBridge[0], extCdcEn, extSerdesEn);
- extCredBridge[0]->initBridge(extNetBridge[0], extCdcEn, extSerdesEn);
- extNetBridge[1]->initBridge(extCredBridge[1], extCdcEn, extSerdesEn);
- extCredBridge[1]->initBridge(extNetBridge[1], extCdcEn, extSerdesEn);
- }
-
- if (intBridgeEn) {
- assert(intNetBridge[0] && intCredBridge[0] &&
- intNetBridge[1] && intCredBridge[1]);
- intNetBridge[0]->initBridge(intCredBridge[0], intCdcEn, intSerdesEn);
- intCredBridge[0]->initBridge(intNetBridge[0], intCdcEn, intSerdesEn);
- intNetBridge[1]->initBridge(intCredBridge[1], intCdcEn, intSerdesEn);
- intCredBridge[1]->initBridge(intNetBridge[1], intCdcEn, intSerdesEn);
- }
-}
-
-void
-GarnetExtLink::print(std::ostream& out) const
-{
- out << name();
-}
-
-GarnetExtLink *
-GarnetExtLinkParams::create()
-{
- return new GarnetExtLink(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_GARNETLINK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_GARNETLINK_HH__
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "mem/ruby/network/BasicLink.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "params/GarnetExtLink.hh"
-#include "params/GarnetIntLink.hh"
-
-class GarnetIntLink : public BasicIntLink
-{
- public:
- typedef GarnetIntLinkParams Params;
- GarnetIntLink(const Params *p);
-
- void init();
-
- void print(std::ostream& out) const;
-
- friend class GarnetNetwork;
-
- protected:
- NetworkLink* m_network_link;
- CreditLink* m_credit_link;
-
- bool srcBridgeEn;
- bool dstBridgeEn;
-
- bool srcSerdesEn;
- bool dstSerdesEn;
-
- bool srcCdcEn;
- bool dstCdcEn;
-
- NetworkBridge* srcNetBridge;
- NetworkBridge* dstNetBridge;
-
- NetworkBridge* srcCredBridge;
- NetworkBridge* dstCredBridge;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const GarnetIntLink& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-class GarnetExtLink : public BasicExtLink
-{
- public:
- typedef GarnetExtLinkParams Params;
- GarnetExtLink(const Params *p);
-
- void init();
-
- void print(std::ostream& out) const;
-
- friend class GarnetNetwork;
-
- protected:
- bool extBridgeEn;
- bool intBridgeEn;
-
- bool extSerdesEn;
- bool intSerdesEn;
-
- bool extCdcEn;
- bool intCdcEn;
-
- NetworkLink* m_network_links[2];
- CreditLink* m_credit_links[2];
-
- NetworkBridge* extNetBridge[2];
- NetworkBridge* intNetBridge[2];
-
- NetworkBridge* extCredBridge[2];
- NetworkBridge* intCredBridge[2];
-
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const GarnetExtLink& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_GARNETLINK_HH__
+++ /dev/null
-# Copyright (c) 2008 Princeton University
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from m5.params import *
-from m5.proxy import *
-from m5.objects.ClockedObject import ClockedObject
-from m5.objects.BasicLink import BasicIntLink, BasicExtLink
-
-class CDCType(Enum): vals = [
- 'LINK_OBJECT',
- 'OBJECT_LINK',
- ]
-
-class NetworkLink(ClockedObject):
- type = 'NetworkLink'
- cxx_header = "mem/ruby/network/garnet2.0/NetworkLink.hh"
- link_id = Param.Int(Parent.link_id, "link id")
- link_latency = Param.Cycles(Parent.latency, "link latency")
- vcs_per_vnet = Param.Int(Parent.vcs_per_vnet,
- "virtual channels per virtual network")
- virt_nets = Param.Int(Parent.number_of_virtual_networks,
- "number of virtual networks")
- supported_vnets = VectorParam.Int(Parent.supported_vnets,
- "Vnets supported")
- width = Param.UInt32(Parent.width, "bit-width of the link")
-
-class CreditLink(NetworkLink):
- type = 'CreditLink'
- cxx_header = "mem/ruby/network/garnet2.0/CreditLink.hh"
-
-class NetworkBridge(CreditLink):
- type = 'NetworkBridge'
- cxx_header = "mem/ruby/network/garnet2.0/NetworkBridge.hh"
- link = Param.NetworkLink("Associated Network Link")
- vtype = Param.CDCType('LINK_OBJECT',
- "Direction of CDC LINK->OBJECT or OBJECT->LINK")
- serdes_latency = Param.Cycles(1, "Latency of SerDes Unit")
- cdc_latency = Param.Cycles(1, "Latency of CDC Unit")
-
-# Interior fixed pipeline links between routers
-class GarnetIntLink(BasicIntLink):
- type = 'GarnetIntLink'
- cxx_header = "mem/ruby/network/garnet2.0/GarnetLink.hh"
- # The internal link includes one forward link (for flit)
- # and one backward flow-control link (for credit)
- network_link = Param.NetworkLink(NetworkLink(), "forward link")
- credit_link = Param.CreditLink(CreditLink(), "backward flow-control link")
-
- # The src_cdc and dst_cdc flags are used to enable the
- # clock domain crossing(CDC) at the source and destination
- # end of the link respectively. This is required when the
- # link and the objected connected to the link are operating
- # at different clock domains. These flags should be set
- # in the network topology files.
- src_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
- dst_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
-
- # The src_serdes and dst_serdes flags are used to enable
- # the Serializer-Deserializer units at the source and
- # destination end of the link respectively. Enabling
- # these flags is necessary when the connecting object
- # supports a different flit width.
- src_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
- dst_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
-
- # The network bridge encapsulates both the CDC and Ser-Des
- # units in HeteroGarnet. This is automatically enabled when
- # either CDC or Ser-Des is enabled.
- src_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at source")
- dst_net_bridge = Param.NetworkBridge(NULL, "Network Bridge at dest")
- src_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at source")
- dst_cred_bridge = Param.NetworkBridge(NULL, "Credit Bridge at dest")
-
- width = Param.UInt32(Parent.ni_flit_size,
- "bit width supported by the router")
-
-# Exterior fixed pipeline links between a router and a controller
-class GarnetExtLink(BasicExtLink):
- type = 'GarnetExtLink'
- cxx_header = "mem/ruby/network/garnet2.0/GarnetLink.hh"
- # The external link is bi-directional.
- # It includes two forward links (for flits)
- # and two backward flow-control links (for credits),
- # one per direction
- _nls = []
- # In uni-directional link
- _nls.append(NetworkLink());
- # Out uni-directional link
- _nls.append(NetworkLink());
- network_links = VectorParam.NetworkLink(_nls, "forward links")
-
- _cls = []
- # In uni-directional link
- _cls.append(CreditLink());
- # Out uni-directional link
- _cls.append(CreditLink());
- credit_links = VectorParam.CreditLink(_cls, "backward flow-control links")
-
- # The ext_cdc and intt_cdc flags are used to enable the
- # clock domain crossing(CDC) at the external and internal
- # end of the link respectively. This is required when the
- # link and the objected connected to the link are operating
- # at different clock domains. These flags should be set
- # in the network topology files.
- ext_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
- int_cdc = Param.Bool(False, "Enable Clock Domain Crossing")
-
- # The ext_serdes and int_serdes flags are used to enable
- # the Serializer-Deserializer units at the external and
- # internal end of the link respectively. Enabling
- # these flags is necessary when the connecting object
- # supports a different flit width.
- ext_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
- int_serdes = Param.Bool(False, "Enable Serializer-Deserializer")
-
- # The network bridge encapsulates both the CDC and Ser-Des
- # units in HeteroGarnet. This is automatically enabled when
- # either CDC or Ser-Des is enabled.
- ext_net_bridge = VectorParam.NetworkBridge([],
- "Network Bridge at external end")
- ext_cred_bridge = VectorParam.NetworkBridge([],
- "Credit Bridge at external end")
- int_net_bridge = VectorParam.NetworkBridge([],
- "Network Bridge at internal end")
- int_cred_bridge = VectorParam.NetworkBridge([],
- "Credit Bridge at internal end")
-
-
- width = Param.UInt32(Parent.ni_flit_size,
- "bit width supported by the router")
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-
-#include <cassert>
-
-#include "base/cast.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/ruby/network/MessageBuffer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/system/RubySystem.hh"
-
-using namespace std;
-
-/*
- * GarnetNetwork sets up the routers and links and collects stats.
- * Default parameters (GarnetNetwork.py) can be overwritten from command line
- * (see configs/network/Network.py)
- */
-
-GarnetNetwork::GarnetNetwork(const Params *p)
- : Network(p)
-{
- m_num_rows = p->num_rows;
- m_ni_flit_size = p->ni_flit_size;
- m_max_vcs_per_vnet = 0;
- m_buffers_per_data_vc = p->buffers_per_data_vc;
- m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
- m_routing_algorithm = p->routing_algorithm;
-
- m_enable_fault_model = p->enable_fault_model;
- if (m_enable_fault_model)
- fault_model = p->fault_model;
-
- m_vnet_type.resize(m_virtual_networks);
-
- for (int i = 0 ; i < m_virtual_networks ; i++) {
- if (m_vnet_type_names[i] == "response")
- m_vnet_type[i] = DATA_VNET_; // carries data (and ctrl) packets
- else
- m_vnet_type[i] = CTRL_VNET_; // carries only ctrl packets
- }
-
- // record the routers
- for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
- i != p->routers.end(); ++i) {
- Router* router = safe_cast<Router*>(*i);
- m_routers.push_back(router);
-
- // initialize the router's network pointers
- router->init_net_ptr(this);
- }
-
- // record the network interfaces
- for (vector<ClockedObject*>::const_iterator i = p->netifs.begin();
- i != p->netifs.end(); ++i) {
- NetworkInterface *ni = safe_cast<NetworkInterface *>(*i);
- m_nis.push_back(ni);
- ni->init_net_ptr(this);
- }
-}
-
-void
-GarnetNetwork::init()
-{
- Network::init();
-
- for (int i=0; i < m_nodes; i++) {
- m_nis[i]->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
- }
-
- // The topology pointer should have already been initialized in the
- // parent network constructor
- assert(m_topology_ptr != NULL);
- m_topology_ptr->createLinks(this);
-
- // Initialize topology specific parameters
- if (getNumRows() > 0) {
- // Only for Mesh topology
- // m_num_rows and m_num_cols are only used for
- // implementing XY or custom routing in RoutingUnit.cc
- m_num_rows = getNumRows();
- m_num_cols = m_routers.size() / m_num_rows;
- assert(m_num_rows * m_num_cols == m_routers.size());
- } else {
- m_num_rows = -1;
- m_num_cols = -1;
- }
-
- // FaultModel: declare each router to the fault model
- if (isFaultModelEnabled()) {
- for (vector<Router*>::const_iterator i= m_routers.begin();
- i != m_routers.end(); ++i) {
- Router* router = safe_cast<Router*>(*i);
- int router_id M5_VAR_USED =
- fault_model->declare_router(router->get_num_inports(),
- router->get_num_outports(),
- router->get_vc_per_vnet(),
- getBuffersPerDataVC(),
- getBuffersPerCtrlVC());
- assert(router_id == router->get_id());
- router->printAggregateFaultProbability(cout);
- router->printFaultVector(cout);
- }
- }
-}
-
-/*
- * This function creates a link from the Network Interface (NI)
- * into the Network.
- * It creates a Network Link from the NI to a Router and a Credit Link from
- * the Router to the NI
-*/
-
-void
-GarnetNetwork::makeExtInLink(NodeID global_src, SwitchID dest, BasicLink* link,
- std::vector<NetDest>& routing_table_entry)
-{
- NodeID local_src = getLocalNodeID(global_src);
- assert(local_src < m_nodes);
-
- GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
-
- // GarnetExtLink is bi-directional
- NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_In];
- net_link->setType(EXT_IN_);
- CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_In];
-
- m_networklinks.push_back(net_link);
- m_creditlinks.push_back(credit_link);
-
- PortDirection dst_inport_dirn = "Local";
-
- m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
- m_routers[dest]->get_vc_per_vnet());
-
- /*
- * We check if a bridge was enabled at any end of the link.
- * The bridge is enabled if either of clock domain
- * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
- * enabled for the link at each end. The bridge encapsulates
- * the functionality for both CDC and SerDes and is a Consumer
- * object similiar to a NetworkLink.
- *
- * If a bridge was enabled we connect the NI and Routers to
- * bridge before connecting the link. Example, if an external
- * bridge is enabled, we would connect:
- * NI--->NetworkBridge--->GarnetExtLink---->Router
- */
- if (garnet_link->extBridgeEn) {
- DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
- garnet_link->name());
- m_nis[local_src]->
- addOutPort(garnet_link->extNetBridge[LinkDirection_In],
- garnet_link->extCredBridge[LinkDirection_In],
- dest, m_routers[dest]->get_vc_per_vnet());
- } else {
- m_nis[local_src]->addOutPort(net_link, credit_link, dest,
- m_routers[dest]->get_vc_per_vnet());
- }
-
- if (garnet_link->intBridgeEn) {
- DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
- garnet_link->name());
- m_routers[dest]->
- addInPort(dst_inport_dirn,
- garnet_link->intNetBridge[LinkDirection_In],
- garnet_link->intCredBridge[LinkDirection_In]);
- } else {
- m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
- }
-
-}
-
-/*
- * This function creates a link from the Network to a NI.
- * It creates a Network Link from a Router to the NI and
- * a Credit Link from NI to the Router
-*/
-
-void
-GarnetNetwork::makeExtOutLink(SwitchID src, NodeID global_dest,
- BasicLink* link,
- std::vector<NetDest>& routing_table_entry)
-{
- NodeID local_dest = getLocalNodeID(global_dest);
- assert(local_dest < m_nodes);
- assert(src < m_routers.size());
- assert(m_routers[src] != NULL);
-
- GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
-
- // GarnetExtLink is bi-directional
- NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_Out];
- net_link->setType(EXT_OUT_);
- CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_Out];
-
- m_networklinks.push_back(net_link);
- m_creditlinks.push_back(credit_link);
-
- PortDirection src_outport_dirn = "Local";
-
- m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
- m_routers[src]->get_vc_per_vnet());
-
- /*
- * We check if a bridge was enabled at any end of the link.
- * The bridge is enabled if either of clock domain
- * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
- * enabled for the link at each end. The bridge encapsulates
- * the functionality for both CDC and SerDes and is a Consumer
- * object similiar to a NetworkLink.
- *
- * If a bridge was enabled we connect the NI and Routers to
- * bridge before connecting the link. Example, if an external
- * bridge is enabled, we would connect:
- * NI<---NetworkBridge<---GarnetExtLink<----Router
- */
- if (garnet_link->extBridgeEn) {
- DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
- garnet_link->name());
- m_nis[local_dest]->
- addInPort(garnet_link->extNetBridge[LinkDirection_Out],
- garnet_link->extCredBridge[LinkDirection_Out]);
- } else {
- m_nis[local_dest]->addInPort(net_link, credit_link);
- }
-
- if (garnet_link->intBridgeEn) {
- DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
- garnet_link->name());
- m_routers[src]->
- addOutPort(src_outport_dirn,
- garnet_link->intNetBridge[LinkDirection_Out],
- routing_table_entry, link->m_weight,
- garnet_link->intCredBridge[LinkDirection_Out],
- m_routers[src]->get_vc_per_vnet());
- } else {
- m_routers[src]->
- addOutPort(src_outport_dirn, net_link,
- routing_table_entry,
- link->m_weight, credit_link,
- m_routers[src]->get_vc_per_vnet());
- }
-}
-
-/*
- * This function creates an internal network link between two routers.
- * It adds both the network link and an opposite credit link.
-*/
-
-void
-GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
- std::vector<NetDest>& routing_table_entry,
- PortDirection src_outport_dirn,
- PortDirection dst_inport_dirn)
-{
- GarnetIntLink* garnet_link = safe_cast<GarnetIntLink*>(link);
-
- // GarnetIntLink is unidirectional
- NetworkLink* net_link = garnet_link->m_network_link;
- net_link->setType(INT_);
- CreditLink* credit_link = garnet_link->m_credit_link;
-
- m_networklinks.push_back(net_link);
- m_creditlinks.push_back(credit_link);
-
- m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
- std::max(m_routers[dest]->get_vc_per_vnet(),
- m_routers[src]->get_vc_per_vnet()));
-
- /*
- * We check if a bridge was enabled at any end of the link.
- * The bridge is enabled if either of clock domain
- * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
- * enabled for the link at each end. The bridge encapsulates
- * the functionality for both CDC and SerDes and is a Consumer
- * object similiar to a NetworkLink.
- *
- * If a bridge was enabled we connect the NI and Routers to
- * bridge before connecting the link. Example, if a source
- * bridge is enabled, we would connect:
- * Router--->NetworkBridge--->GarnetIntLink---->Router
- */
- if (garnet_link->dstBridgeEn) {
- DPRINTF(RubyNetwork, "Enable destination bridge for %s\n",
- garnet_link->name());
- m_routers[dest]->addInPort(dst_inport_dirn,
- garnet_link->dstNetBridge, garnet_link->dstCredBridge);
- } else {
- m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
- }
-
- if (garnet_link->srcBridgeEn) {
- DPRINTF(RubyNetwork, "Enable source bridge for %s\n",
- garnet_link->name());
- m_routers[src]->
- addOutPort(src_outport_dirn, garnet_link->srcNetBridge,
- routing_table_entry,
- link->m_weight, garnet_link->srcCredBridge,
- m_routers[dest]->get_vc_per_vnet());
- } else {
- m_routers[src]->addOutPort(src_outport_dirn, net_link,
- routing_table_entry,
- link->m_weight, credit_link,
- m_routers[dest]->get_vc_per_vnet());
- }
-}
-
-// Total routers in the network
-int
-GarnetNetwork::getNumRouters()
-{
- return m_routers.size();
-}
-
-// Get ID of router connected to a NI.
-int
-GarnetNetwork::get_router_id(int global_ni, int vnet)
-{
- NodeID local_ni = getLocalNodeID(global_ni);
-
- return m_nis[local_ni]->get_router_id(vnet);
-}
-
-void
-GarnetNetwork::regStats()
-{
- Network::regStats();
-
- // Packets
- m_packets_received
- .init(m_virtual_networks)
- .name(name() + ".packets_received")
- .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
- ;
-
- m_packets_injected
- .init(m_virtual_networks)
- .name(name() + ".packets_injected")
- .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
- ;
-
- m_packet_network_latency
- .init(m_virtual_networks)
- .name(name() + ".packet_network_latency")
- .flags(Stats::oneline)
- ;
-
- m_packet_queueing_latency
- .init(m_virtual_networks)
- .name(name() + ".packet_queueing_latency")
- .flags(Stats::oneline)
- ;
-
- for (int i = 0; i < m_virtual_networks; i++) {
- m_packets_received.subname(i, csprintf("vnet-%i", i));
- m_packets_injected.subname(i, csprintf("vnet-%i", i));
- m_packet_network_latency.subname(i, csprintf("vnet-%i", i));
- m_packet_queueing_latency.subname(i, csprintf("vnet-%i", i));
- }
-
- m_avg_packet_vnet_latency
- .name(name() + ".average_packet_vnet_latency")
- .flags(Stats::oneline);
- m_avg_packet_vnet_latency =
- m_packet_network_latency / m_packets_received;
-
- m_avg_packet_vqueue_latency
- .name(name() + ".average_packet_vqueue_latency")
- .flags(Stats::oneline);
- m_avg_packet_vqueue_latency =
- m_packet_queueing_latency / m_packets_received;
-
- m_avg_packet_network_latency
- .name(name() + ".average_packet_network_latency");
- m_avg_packet_network_latency =
- sum(m_packet_network_latency) / sum(m_packets_received);
-
- m_avg_packet_queueing_latency
- .name(name() + ".average_packet_queueing_latency");
- m_avg_packet_queueing_latency
- = sum(m_packet_queueing_latency) / sum(m_packets_received);
-
- m_avg_packet_latency
- .name(name() + ".average_packet_latency");
- m_avg_packet_latency
- = m_avg_packet_network_latency + m_avg_packet_queueing_latency;
-
- // Flits
- m_flits_received
- .init(m_virtual_networks)
- .name(name() + ".flits_received")
- .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
- ;
-
- m_flits_injected
- .init(m_virtual_networks)
- .name(name() + ".flits_injected")
- .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
- ;
-
- m_flit_network_latency
- .init(m_virtual_networks)
- .name(name() + ".flit_network_latency")
- .flags(Stats::oneline)
- ;
-
- m_flit_queueing_latency
- .init(m_virtual_networks)
- .name(name() + ".flit_queueing_latency")
- .flags(Stats::oneline)
- ;
-
- for (int i = 0; i < m_virtual_networks; i++) {
- m_flits_received.subname(i, csprintf("vnet-%i", i));
- m_flits_injected.subname(i, csprintf("vnet-%i", i));
- m_flit_network_latency.subname(i, csprintf("vnet-%i", i));
- m_flit_queueing_latency.subname(i, csprintf("vnet-%i", i));
- }
-
- m_avg_flit_vnet_latency
- .name(name() + ".average_flit_vnet_latency")
- .flags(Stats::oneline);
- m_avg_flit_vnet_latency = m_flit_network_latency / m_flits_received;
-
- m_avg_flit_vqueue_latency
- .name(name() + ".average_flit_vqueue_latency")
- .flags(Stats::oneline);
- m_avg_flit_vqueue_latency =
- m_flit_queueing_latency / m_flits_received;
-
- m_avg_flit_network_latency
- .name(name() + ".average_flit_network_latency");
- m_avg_flit_network_latency =
- sum(m_flit_network_latency) / sum(m_flits_received);
-
- m_avg_flit_queueing_latency
- .name(name() + ".average_flit_queueing_latency");
- m_avg_flit_queueing_latency =
- sum(m_flit_queueing_latency) / sum(m_flits_received);
-
- m_avg_flit_latency
- .name(name() + ".average_flit_latency");
- m_avg_flit_latency =
- m_avg_flit_network_latency + m_avg_flit_queueing_latency;
-
-
- // Hops
- m_avg_hops.name(name() + ".average_hops");
- m_avg_hops = m_total_hops / sum(m_flits_received);
-
- // Links
- m_total_ext_in_link_utilization
- .name(name() + ".ext_in_link_utilization");
- m_total_ext_out_link_utilization
- .name(name() + ".ext_out_link_utilization");
- m_total_int_link_utilization
- .name(name() + ".int_link_utilization");
- m_average_link_utilization
- .name(name() + ".avg_link_utilization");
- m_average_vc_load
- .init(m_virtual_networks * m_max_vcs_per_vnet)
- .name(name() + ".avg_vc_load")
- .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
- ;
-}
-
-void
-GarnetNetwork::collateStats()
-{
- RubySystem *rs = params()->ruby_system;
- double time_delta = double(curCycle() - rs->getStartCycle());
-
- for (int i = 0; i < m_networklinks.size(); i++) {
- link_type type = m_networklinks[i]->getType();
- int activity = m_networklinks[i]->getLinkUtilization();
-
- if (type == EXT_IN_)
- m_total_ext_in_link_utilization += activity;
- else if (type == EXT_OUT_)
- m_total_ext_out_link_utilization += activity;
- else if (type == INT_)
- m_total_int_link_utilization += activity;
-
- m_average_link_utilization +=
- (double(activity) / time_delta);
-
- vector<unsigned int> vc_load = m_networklinks[i]->getVcLoad();
- for (int j = 0; j < vc_load.size(); j++) {
- m_average_vc_load[j] += ((double)vc_load[j] / time_delta);
- }
- }
-
- // Ask the routers to collate their statistics
- for (int i = 0; i < m_routers.size(); i++) {
- m_routers[i]->collateStats();
- }
-}
-
-void
-GarnetNetwork::resetStats()
-{
- for (int i = 0; i < m_routers.size(); i++) {
- m_routers[i]->resetStats();
- }
- for (int i = 0; i < m_networklinks.size(); i++) {
- m_networklinks[i]->resetStats();
- }
- for (int i = 0; i < m_creditlinks.size(); i++) {
- m_creditlinks[i]->resetStats();
- }
-}
-
-void
-GarnetNetwork::print(ostream& out) const
-{
- out << "[GarnetNetwork]";
-}
-
-GarnetNetwork *
-GarnetNetworkParams::create()
-{
- return new GarnetNetwork(this);
-}
-
-uint32_t
-GarnetNetwork::functionalWrite(Packet *pkt)
-{
- uint32_t num_functional_writes = 0;
-
- for (unsigned int i = 0; i < m_routers.size(); i++) {
- num_functional_writes += m_routers[i]->functionalWrite(pkt);
- }
-
- for (unsigned int i = 0; i < m_nis.size(); ++i) {
- num_functional_writes += m_nis[i]->functionalWrite(pkt);
- }
-
- for (unsigned int i = 0; i < m_networklinks.size(); ++i) {
- num_functional_writes += m_networklinks[i]->functionalWrite(pkt);
- }
-
- return num_functional_writes;
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_GARNETNETWORK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_GARNETNETWORK_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/network/Network.hh"
-#include "mem/ruby/network/fault_model/FaultModel.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "params/GarnetNetwork.hh"
-
-class FaultModel;
-class NetworkInterface;
-class Router;
-class NetDest;
-class NetworkLink;
-class CreditLink;
-
-class GarnetNetwork : public Network
-{
- public:
- typedef GarnetNetworkParams Params;
- GarnetNetwork(const Params *p);
- ~GarnetNetwork() = default;
-
- void init();
-
- // Configuration (set externally)
-
- // for 2D topology
- int getNumRows() const { return m_num_rows; }
- int getNumCols() { return m_num_cols; }
-
- // for network
- uint32_t getNiFlitSize() const { return m_ni_flit_size; }
- uint32_t getBuffersPerDataVC() { return m_buffers_per_data_vc; }
- uint32_t getBuffersPerCtrlVC() { return m_buffers_per_ctrl_vc; }
- int getRoutingAlgorithm() const { return m_routing_algorithm; }
-
- bool isFaultModelEnabled() const { return m_enable_fault_model; }
- FaultModel* fault_model;
-
-
- // Internal configuration
- bool isVNetOrdered(int vnet) const { return m_ordered[vnet]; }
- VNET_type
- get_vnet_type(int vnet)
- {
- return m_vnet_type[vnet];
- }
- int getNumRouters();
- int get_router_id(int ni, int vnet);
-
-
- // Methods used by Topology to setup the network
- void makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
- std::vector<NetDest>& routing_table_entry);
- void makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
- std::vector<NetDest>& routing_table_entry);
- void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
- std::vector<NetDest>& routing_table_entry,
- PortDirection src_outport_dirn,
- PortDirection dest_inport_dirn);
-
- //! Function for performing a functional write. The return value
- //! indicates the number of messages that were written.
- uint32_t functionalWrite(Packet *pkt);
-
- // Stats
- void collateStats();
- void regStats();
- void resetStats();
- void print(std::ostream& out) const;
-
- // increment counters
- void increment_injected_packets(int vnet) { m_packets_injected[vnet]++; }
- void increment_received_packets(int vnet) { m_packets_received[vnet]++; }
-
- void
- increment_packet_network_latency(Tick latency, int vnet)
- {
- m_packet_network_latency[vnet] += latency;
- }
-
- void
- increment_packet_queueing_latency(Tick latency, int vnet)
- {
- m_packet_queueing_latency[vnet] += latency;
- }
-
- void increment_injected_flits(int vnet) { m_flits_injected[vnet]++; }
- void increment_received_flits(int vnet) { m_flits_received[vnet]++; }
-
- void
- increment_flit_network_latency(Tick latency, int vnet)
- {
- m_flit_network_latency[vnet] += latency;
- }
-
- void
- increment_flit_queueing_latency(Tick latency, int vnet)
- {
- m_flit_queueing_latency[vnet] += latency;
- }
-
- void
- increment_total_hops(int hops)
- {
- m_total_hops += hops;
- }
-
- protected:
- // Configuration
- int m_num_rows;
- int m_num_cols;
- uint32_t m_ni_flit_size;
- uint32_t m_max_vcs_per_vnet;
- uint32_t m_buffers_per_ctrl_vc;
- uint32_t m_buffers_per_data_vc;
- int m_routing_algorithm;
- bool m_enable_fault_model;
-
- // Statistical variables
- Stats::Vector m_packets_received;
- Stats::Vector m_packets_injected;
- Stats::Vector m_packet_network_latency;
- Stats::Vector m_packet_queueing_latency;
-
- Stats::Formula m_avg_packet_vnet_latency;
- Stats::Formula m_avg_packet_vqueue_latency;
- Stats::Formula m_avg_packet_network_latency;
- Stats::Formula m_avg_packet_queueing_latency;
- Stats::Formula m_avg_packet_latency;
-
- Stats::Vector m_flits_received;
- Stats::Vector m_flits_injected;
- Stats::Vector m_flit_network_latency;
- Stats::Vector m_flit_queueing_latency;
-
- Stats::Formula m_avg_flit_vnet_latency;
- Stats::Formula m_avg_flit_vqueue_latency;
- Stats::Formula m_avg_flit_network_latency;
- Stats::Formula m_avg_flit_queueing_latency;
- Stats::Formula m_avg_flit_latency;
-
- Stats::Scalar m_total_ext_in_link_utilization;
- Stats::Scalar m_total_ext_out_link_utilization;
- Stats::Scalar m_total_int_link_utilization;
- Stats::Scalar m_average_link_utilization;
- Stats::Vector m_average_vc_load;
-
- Stats::Scalar m_total_hops;
- Stats::Formula m_avg_hops;
-
- private:
- GarnetNetwork(const GarnetNetwork& obj);
- GarnetNetwork& operator=(const GarnetNetwork& obj);
-
- std::vector<VNET_type > m_vnet_type;
- std::vector<Router *> m_routers; // All Routers in Network
- std::vector<NetworkLink *> m_networklinks; // All flit links in the network
- std::vector<CreditLink *> m_creditlinks; // All credit links in the network
- std::vector<NetworkInterface *> m_nis; // All NI's in Network
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const GarnetNetwork& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_GARNETNETWORK_HH__
+++ /dev/null
-# Copyright (c) 2008 Princeton University
-# Copyright (c) 2009 Advanced Micro Devices, Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Author: Tushar Krishna
-#
-
-from m5.params import *
-from m5.proxy import *
-from m5.objects.Network import RubyNetwork
-from m5.objects.BasicRouter import BasicRouter
-from m5.objects.ClockedObject import ClockedObject
-
-class GarnetNetwork(RubyNetwork):
- type = 'GarnetNetwork'
- cxx_header = "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
- num_rows = Param.Int(0, "number of rows if 2D (mesh/torus/..) topology");
- ni_flit_size = Param.UInt32(16, "network interface flit size in bytes")
- vcs_per_vnet = Param.UInt32(4, "virtual channels per virtual network");
- buffers_per_data_vc = Param.UInt32(4, "buffers per data virtual channel");
- buffers_per_ctrl_vc = Param.UInt32(1, "buffers per ctrl virtual channel");
- routing_algorithm = Param.Int(0,
- "0: Weight-based Table, 1: XY, 2: Custom");
- enable_fault_model = Param.Bool(False, "enable network fault model");
- fault_model = Param.FaultModel(NULL, "network fault model");
- garnet_deadlock_threshold = Param.UInt32(50000,
- "network-level deadlock threshold")
-
-class GarnetNetworkInterface(ClockedObject):
- type = 'GarnetNetworkInterface'
- cxx_class = 'NetworkInterface'
- cxx_header = "mem/ruby/network/garnet2.0/NetworkInterface.hh"
-
- id = Param.UInt32("ID in relation to other network interfaces")
- vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
- "virtual channels per virtual network")
- virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
- "number of virtual networks")
- garnet_deadlock_threshold = Param.UInt32(Parent.garnet_deadlock_threshold,
- "network-level deadlock threshold")
-
-class GarnetRouter(BasicRouter):
- type = 'GarnetRouter'
- cxx_class = 'Router'
- cxx_header = "mem/ruby/network/garnet2.0/Router.hh"
- vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
- "virtual channels per virtual network")
- virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
- "number of virtual networks")
- width = Param.UInt32(Parent.ni_flit_size,
- "bit width supported by the router")
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-using namespace std;
-
-InputUnit::InputUnit(int id, PortDirection direction, Router *router)
- : Consumer(router), m_router(router), m_id(id), m_direction(direction),
- m_vc_per_vnet(m_router->get_vc_per_vnet())
-{
- const int m_num_vcs = m_router->get_num_vcs();
- m_num_buffer_reads.resize(m_num_vcs/m_vc_per_vnet);
- m_num_buffer_writes.resize(m_num_vcs/m_vc_per_vnet);
- for (int i = 0; i < m_num_buffer_reads.size(); i++) {
- m_num_buffer_reads[i] = 0;
- m_num_buffer_writes[i] = 0;
- }
-
- // Instantiating the virtual channels
- virtualChannels.reserve(m_num_vcs);
- for (int i=0; i < m_num_vcs; i++) {
- virtualChannels.emplace_back();
- }
-}
-
-/*
- * The InputUnit wakeup function reads the input flit from its input link.
- * Each flit arrives with an input VC.
- * For HEAD/HEAD_TAIL flits, performs route computation,
- * and updates route in the input VC.
- * The flit is buffered for (m_latency - 1) cycles in the input VC
- * and marked as valid for SwitchAllocation starting that cycle.
- *
- */
-
-void
-InputUnit::wakeup()
-{
- flit *t_flit;
- if (m_in_link->isReady(curTick())) {
-
- t_flit = m_in_link->consumeLink();
- DPRINTF(RubyNetwork, "Router[%d] Consuming:%s Width: %d Flit:%s\n",
- m_router->get_id(), m_in_link->name(),
- m_router->getBitWidth(), *t_flit);
- assert(t_flit->m_width == m_router->getBitWidth());
- int vc = t_flit->get_vc();
- t_flit->increment_hops(); // for stats
-
- if ((t_flit->get_type() == HEAD_) ||
- (t_flit->get_type() == HEAD_TAIL_)) {
-
- assert(virtualChannels[vc].get_state() == IDLE_);
- set_vc_active(vc, curTick());
-
- // Route computation for this vc
- int outport = m_router->route_compute(t_flit->get_route(),
- m_id, m_direction);
-
- // Update output port in VC
- // All flits in this packet will use this output port
- // The output port field in the flit is updated after it wins SA
- grant_outport(vc, outport);
-
- } else {
- assert(virtualChannels[vc].get_state() == ACTIVE_);
- }
-
-
- // Buffer the flit
- virtualChannels[vc].insertFlit(t_flit);
-
- int vnet = vc/m_vc_per_vnet;
- // number of writes same as reads
- // any flit that is written will be read only once
- m_num_buffer_writes[vnet]++;
- m_num_buffer_reads[vnet]++;
-
- Cycles pipe_stages = m_router->get_pipe_stages();
- if (pipe_stages == 1) {
- // 1-cycle router
- // Flit goes for SA directly
- t_flit->advance_stage(SA_, curTick());
- } else {
- assert(pipe_stages > 1);
- // Router delay is modeled by making flit wait in buffer for
- // (pipe_stages cycles - 1) cycles before going for SA
-
- Cycles wait_time = pipe_stages - Cycles(1);
- t_flit->advance_stage(SA_, m_router->clockEdge(wait_time));
-
- // Wakeup the router in that cycle to perform SA
- m_router->schedule_wakeup(Cycles(wait_time));
- }
-
- if (m_in_link->isReady(curTick())) {
- m_router->schedule_wakeup(Cycles(1));
- }
- }
-}
-
-// Send a credit back to upstream router for this VC.
-// Called by SwitchAllocator when the flit in this VC wins the Switch.
-void
-InputUnit::increment_credit(int in_vc, bool free_signal, Tick curTime)
-{
- DPRINTF(RubyNetwork, "Router[%d]: Sending a credit vc:%d free:%d to %s\n",
- m_router->get_id(), in_vc, free_signal, m_credit_link->name());
- Credit *t_credit = new Credit(in_vc, free_signal, curTime);
- creditQueue.insert(t_credit);
- m_credit_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
-}
-
-
-uint32_t
-InputUnit::functionalWrite(Packet *pkt)
-{
- uint32_t num_functional_writes = 0;
- for (auto& virtual_channel : virtualChannels) {
- num_functional_writes += virtual_channel.functionalWrite(pkt);
- }
-
- return num_functional_writes;
-}
-
-void
-InputUnit::resetStats()
-{
- for (int j = 0; j < m_num_buffer_reads.size(); j++) {
- m_num_buffer_reads[j] = 0;
- m_num_buffer_writes[j] = 0;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_INPUTUNIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_INPUTUNIT_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-class InputUnit : public Consumer
-{
- public:
- InputUnit(int id, PortDirection direction, Router *router);
- ~InputUnit() = default;
-
- void wakeup();
- void print(std::ostream& out) const {};
-
- inline PortDirection get_direction() { return m_direction; }
-
- inline void
- set_vc_idle(int vc, Tick curTime)
- {
- virtualChannels[vc].set_idle(curTime);
- }
-
- inline void
- set_vc_active(int vc, Tick curTime)
- {
- virtualChannels[vc].set_active(curTime);
- }
-
- inline void
- grant_outport(int vc, int outport)
- {
- virtualChannels[vc].set_outport(outport);
- }
-
- inline void
- grant_outvc(int vc, int outvc)
- {
- virtualChannels[vc].set_outvc(outvc);
- }
-
- inline int
- get_outport(int invc)
- {
- return virtualChannels[invc].get_outport();
- }
-
- inline int
- get_outvc(int invc)
- {
- return virtualChannels[invc].get_outvc();
- }
-
- inline Tick
- get_enqueue_time(int invc)
- {
- return virtualChannels[invc].get_enqueue_time();
- }
-
- void increment_credit(int in_vc, bool free_signal, Tick curTime);
-
- inline flit*
- peekTopFlit(int vc)
- {
- return virtualChannels[vc].peekTopFlit();
- }
-
- inline flit*
- getTopFlit(int vc)
- {
- return virtualChannels[vc].getTopFlit();
- }
-
- inline bool
- need_stage(int vc, flit_stage stage, Tick time)
- {
- return virtualChannels[vc].need_stage(stage, time);
- }
-
- inline bool
- isReady(int invc, Tick curTime)
- {
- return virtualChannels[invc].isReady(curTime);
- }
-
- flitBuffer* getCreditQueue() { return &creditQueue; }
-
- inline void
- set_in_link(NetworkLink *link)
- {
- m_in_link = link;
- }
-
- inline int get_inlink_id() { return m_in_link->get_id(); }
-
- inline void
- set_credit_link(CreditLink *credit_link)
- {
- m_credit_link = credit_link;
- }
-
- double get_buf_read_activity(unsigned int vnet) const
- { return m_num_buffer_reads[vnet]; }
- double get_buf_write_activity(unsigned int vnet) const
- { return m_num_buffer_writes[vnet]; }
-
- uint32_t functionalWrite(Packet *pkt);
- void resetStats();
-
- private:
- Router *m_router;
- int m_id;
- PortDirection m_direction;
- int m_vc_per_vnet;
- NetworkLink *m_in_link;
- CreditLink *m_credit_link;
- flitBuffer creditQueue;
-
- // Input Virtual channels
- std::vector<VirtualChannel> virtualChannels;
-
- // Statistical variables
- std::vector<double> m_num_buffer_writes;
- std::vector<double> m_num_buffer_reads;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_INPUTUNIT_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * For use for simulation and test purposes only
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Srikant Bharadwaj
- */
-
-
-#include "mem/ruby/network/garnet2.0/NetworkBridge.hh"
-
-#include <cmath>
-
-#include "debug/RubyNetwork.hh"
-#include "params/GarnetIntLink.hh"
-
-NetworkBridge::NetworkBridge(const Params *p)
- :CreditLink(p)
-{
- enCdc = true;
- enSerDes = true;
- mType = p->vtype;
-
- cdcLatency = p->cdc_latency;
- serDesLatency = p->serdes_latency;
- lastScheduledAt = 0;
-
- nLink = p->link;
- if (mType == Enums::LINK_OBJECT) {
- nLink->setLinkConsumer(this);
- setSourceQueue(nLink->getBuffer(), nLink);
- } else if (mType == Enums::OBJECT_LINK) {
- nLink->setSourceQueue(&linkBuffer, this);
- setLinkConsumer(nLink);
- } else {
- // CDC type must be set
- panic("CDC type must be set");
- }
-}
-
-void
-NetworkBridge::setVcsPerVnet(uint32_t consumerVcs)
-{
- DPRINTF(RubyNetwork, "VcsPerVnet VC: %d\n", consumerVcs);
- NetworkLink::setVcsPerVnet(consumerVcs);
- lenBuffer.resize(consumerVcs * m_virt_nets);
- sizeSent.resize(consumerVcs * m_virt_nets);
- flitsSent.resize(consumerVcs * m_virt_nets);
- extraCredit.resize(consumerVcs * m_virt_nets);
-
- nLink->setVcsPerVnet(consumerVcs);
-}
-
-void
-NetworkBridge::initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en)
-{
- coBridge = coBrid;
- enCdc = cdc_en;
- enSerDes = serdes_en;
-}
-
-NetworkBridge::~NetworkBridge()
-{
-}
-
-void
-NetworkBridge::scheduleFlit(flit *t_flit, Cycles latency)
-{
- Cycles totLatency = latency;
-
- if (enCdc) {
- // Add the CDC latency
- totLatency = latency + cdcLatency;
- }
-
- Tick sendTime = link_consumer->getObject()->clockEdge(totLatency);
- Tick nextAvailTick = lastScheduledAt + link_consumer->getObject()->\
- cyclesToTicks(Cycles(1));
- sendTime = std::max(nextAvailTick, sendTime);
- t_flit->set_time(sendTime);
- lastScheduledAt = sendTime;
- linkBuffer.insert(t_flit);
- link_consumer->scheduleEventAbsolute(sendTime);
-}
-
-void
-NetworkBridge::neutralize(int vc, int eCredit)
-{
- extraCredit[vc].push(eCredit);
-}
-
-void
-NetworkBridge::flitisizeAndSend(flit *t_flit)
-{
- // Serialize-Deserialize only if it is enabled
- if (enSerDes) {
- // Calculate the target-width
- int target_width = bitWidth;
- int cur_width = nLink->bitWidth;
- if (mType == Enums::OBJECT_LINK) {
- target_width = nLink->bitWidth;
- cur_width = bitWidth;
- }
-
- DPRINTF(RubyNetwork, "Target width: %d Current: %d\n",
- target_width, cur_width);
- assert(target_width != cur_width);
-
- int vc = t_flit->get_vc();
-
- if (target_width > cur_width) {
- // Deserialize
- // This deserializer combines flits from the
- // same message together
- int num_flits = 0;
- int flitPossible = 0;
- if (t_flit->get_type() == CREDIT_) {
- lenBuffer[vc]++;
- assert(extraCredit[vc].front());
- if (lenBuffer[vc] == extraCredit[vc].front()) {
- flitPossible = 1;
- extraCredit[vc].pop();
- lenBuffer[vc] = 0;
- }
- } else if (t_flit->get_type() == TAIL_ ||
- t_flit->get_type() == HEAD_TAIL_) {
- // If its the end of packet, then send whatever
- // is available.
- int sizeAvail = (t_flit->msgSize - sizeSent[vc]);
- flitPossible = ceil((float)sizeAvail/(float)target_width);
- assert (flitPossible < 2);
- num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
- // Stop tracking the packet.
- flitsSent[vc] = 0;
- sizeSent[vc] = 0;
- } else {
- // If we are yet to receive the complete packet
- // track the size recieved and flits deserialized.
- int sizeAvail =
- ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
- flitPossible = floor((float)sizeAvail/(float)target_width);
- assert (flitPossible < 2);
- num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
- if (flitPossible) {
- sizeSent[vc] += target_width;
- flitsSent[vc] = t_flit->get_id() + 1;
- }
- }
-
- DPRINTF(RubyNetwork, "Deserialize :%dB -----> %dB "
- " vc:%d\n", cur_width, target_width, vc);
-
- flit *fl = NULL;
- if (flitPossible) {
- fl = t_flit->deserialize(lenBuffer[vc], num_flits,
- target_width);
- }
-
- // Inform the credit serializer about the number
- // of flits that were generated.
- if (t_flit->get_type() != CREDIT_ && fl) {
- coBridge->neutralize(vc, num_flits);
- }
-
- // Schedule only if we are done deserializing
- if (fl) {
- DPRINTF(RubyNetwork, "Scheduling a flit\n");
- lenBuffer[vc] = 0;
- scheduleFlit(fl, serDesLatency);
- }
- // Delete this flit, new flit is sent in any case
- delete t_flit;
- } else {
- // Serialize
- DPRINTF(RubyNetwork, "Serializing flit :%d -----> %d "
- "(vc:%d, Original Message Size: %d)\n",
- cur_width, target_width, vc, t_flit->msgSize);
-
- int flitPossible = 0;
- if (t_flit->get_type() == CREDIT_) {
- // We store the deserialization ratio and then
- // access it when serializing credits in the
- // oppposite direction.
- assert(extraCredit[vc].front());
- flitPossible = extraCredit[vc].front();
- extraCredit[vc].pop();
- } else if (t_flit->get_type() == HEAD_ ||
- t_flit->get_type() == BODY_) {
- int sizeAvail =
- ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
- flitPossible = floor((float)sizeAvail/(float)target_width);
- if (flitPossible) {
- sizeSent[vc] += flitPossible*target_width;
- flitsSent[vc] += flitPossible;
- }
- } else {
- int sizeAvail = t_flit->msgSize - sizeSent[vc];
- flitPossible = ceil((float)sizeAvail/(float)target_width);
- sizeSent[vc] = 0;
- flitsSent[vc] = 0;
- }
- assert(flitPossible > 0);
-
- // Schedule all the flits
- // num_flits could be zero for credits
- for (int i = 0; i < flitPossible; i++) {
- // Ignore neutralized credits
- flit *fl = t_flit->serialize(i, flitPossible, target_width);
- scheduleFlit(fl, serDesLatency);
- DPRINTF(RubyNetwork, "Serialized to flit[%d of %d parts]:"
- " %s\n", i+1, flitPossible, *fl);
- }
-
- if (t_flit->get_type() != CREDIT_) {
- coBridge->neutralize(vc, flitPossible);
- }
- // Delete this flit, new flit is sent in any case
- delete t_flit;
- }
- return;
- }
-
- // If only CDC is enabled schedule it
- scheduleFlit(t_flit, Cycles(0));
-}
-void
-NetworkBridge::wakeup()
-{
- flit *t_flit;
-
- if (link_srcQueue->isReady(curTick())) {
- t_flit = link_srcQueue->getTopFlit();
- DPRINTF(RubyNetwork, "Recieved flit %s\n", *t_flit);
- flitisizeAndSend(t_flit);
- return;
- }
- assert(!link_srcQueue->getSize());
-}
-
-NetworkBridge *
-NetworkBridgeParams::create()
-{
- return new NetworkBridge(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * For use for simulation and test purposes only
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Srikant Bharadwaj
- */
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_NETWORK_BRIDGE_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_NETWORK_BRIDGE_HH__
-
-#include <iostream>
-#include <queue>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-#include "params/NetworkBridge.hh"
-
-class GarnetNetwork;
-
-class NetworkBridge: public CreditLink
-{
- public:
- typedef NetworkBridgeParams Params;
- NetworkBridge(const Params *p);
- ~NetworkBridge();
-
- void initBridge(NetworkBridge *coBrid, bool cdc_en, bool serdes_en);
-
- void wakeup();
- void neutralize(int vc, int eCredit);
-
- void scheduleFlit(flit *t_flit, Cycles latency);
- void flitisizeAndSend(flit *t_flit);
- void setVcsPerVnet(uint32_t consumerVcs);
-
- protected:
- // Pointer to co-existing bridge
- // CreditBridge for Network Bridge and vice versa
- NetworkBridge *coBridge;
-
- // Link connected toBridge
- // could be a source or destination
- // depending on mType
- NetworkLink *nLink;
-
- // CDC enable/disable
- bool enCdc;
- // SerDes enable/disable
- bool enSerDes;
-
- // Type of Bridge
- int mType;
-
- Cycles cdcLatency;
- Cycles serDesLatency;
-
- Tick lastScheduledAt;
-
- // Used by Credit Deserializer
- std::vector<int> lenBuffer;
- std::vector<int> sizeSent;
- std::vector<int> flitsSent;
- std::vector<std::queue<int>> extraCredit;
-
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_NETWORK_BRIDGE_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
-
-#include <cassert>
-#include <cmath>
-
-#include "base/cast.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/MessageBuffer.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-using namespace std;
-
-NetworkInterface::NetworkInterface(const Params *p)
- : ClockedObject(p), Consumer(this), m_id(p->id),
- m_virtual_networks(p->virt_nets), m_vc_per_vnet(0),
- m_vc_allocator(m_virtual_networks, 0),
- m_deadlock_threshold(p->garnet_deadlock_threshold),
- vc_busy_counter(m_virtual_networks, 0)
-{
- m_stall_count.resize(m_virtual_networks);
- niOutVcs.resize(0);
-}
-
-void
-NetworkInterface::addInPort(NetworkLink *in_link,
- CreditLink *credit_link)
-{
- InputPort *newInPort = new InputPort(in_link, credit_link);
- inPorts.push_back(newInPort);
- DPRINTF(RubyNetwork, "Adding input port:%s with vnets %s\n",
- in_link->name(), newInPort->printVnets());
-
- in_link->setLinkConsumer(this);
- credit_link->setSourceQueue(newInPort->outCreditQueue(), this);
- if (m_vc_per_vnet != 0) {
- in_link->setVcsPerVnet(m_vc_per_vnet);
- credit_link->setVcsPerVnet(m_vc_per_vnet);
- }
-
-}
-
-void
-NetworkInterface::addOutPort(NetworkLink *out_link,
- CreditLink *credit_link,
- SwitchID router_id, uint32_t consumerVcs)
-{
- OutputPort *newOutPort = new OutputPort(out_link, credit_link, router_id);
- outPorts.push_back(newOutPort);
-
- assert(consumerVcs > 0);
- // We are not allowing different physical links to have different vcs
- // If it is required that the Network Interface support different VCs
- // for every physical link connected to it. Then they need to change
- // the logic within outport and inport.
- if (niOutVcs.size() == 0) {
- m_vc_per_vnet = consumerVcs;
- int m_num_vcs = consumerVcs * m_virtual_networks;
- niOutVcs.resize(m_num_vcs);
- outVcState.reserve(m_num_vcs);
- m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
- // instantiating the NI flit buffers
- for (int i = 0; i < m_num_vcs; i++) {
- m_ni_out_vcs_enqueue_time[i] = Tick(INFINITE_);
- outVcState.emplace_back(i, m_net_ptr, consumerVcs);
- }
-
- // Reset VC Per VNET for input links already instantiated
- for (auto &iPort: inPorts) {
- NetworkLink *inNetLink = iPort->inNetLink();
- inNetLink->setVcsPerVnet(m_vc_per_vnet);
- credit_link->setVcsPerVnet(m_vc_per_vnet);
- }
- } else {
- fatal_if(consumerVcs != m_vc_per_vnet,
- "%s: Connected Physical links have different vc requests: %d and %d\n",
- name(), consumerVcs, m_vc_per_vnet);
- }
-
- DPRINTF(RubyNetwork, "OutputPort:%s Vnet: %s\n",
- out_link->name(), newOutPort->printVnets());
-
- out_link->setSourceQueue(newOutPort->outFlitQueue(), this);
- out_link->setVcsPerVnet(m_vc_per_vnet);
- credit_link->setLinkConsumer(this);
- credit_link->setVcsPerVnet(m_vc_per_vnet);
-}
-
-void
-NetworkInterface::addNode(vector<MessageBuffer *>& in,
- vector<MessageBuffer *>& out)
-{
- inNode_ptr = in;
- outNode_ptr = out;
-
- for (auto& it : in) {
- if (it != nullptr) {
- it->setConsumer(this);
- }
- }
-}
-
-void
-NetworkInterface::dequeueCallback()
-{
- // An output MessageBuffer has dequeued something this cycle and there
- // is now space to enqueue a stalled message. However, we cannot wake
- // on the same cycle as the dequeue. Schedule a wake at the soonest
- // possible time (next cycle).
- scheduleEventAbsolute(clockEdge(Cycles(1)));
-}
-
-void
-NetworkInterface::incrementStats(flit *t_flit)
-{
- int vnet = t_flit->get_vnet();
-
- // Latency
- m_net_ptr->increment_received_flits(vnet);
- Tick network_delay =
- t_flit->get_dequeue_time() -
- t_flit->get_enqueue_time() - cyclesToTicks(Cycles(1));
- Tick src_queueing_delay = t_flit->get_src_delay();
- Tick dest_queueing_delay = (curTick() - t_flit->get_dequeue_time());
- Tick queueing_delay = src_queueing_delay + dest_queueing_delay;
-
- m_net_ptr->increment_flit_network_latency(network_delay, vnet);
- m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
-
- if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
- m_net_ptr->increment_received_packets(vnet);
- m_net_ptr->increment_packet_network_latency(network_delay, vnet);
- m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
- }
-
- // Hops
- m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
-}
-
-/*
- * The NI wakeup checks whether there are any ready messages in the protocol
- * buffer. If yes, it picks that up, flitisizes it into a number of flits and
- * puts it into an output buffer and schedules the output link. On a wakeup
- * it also checks whether there are flits in the input link. If yes, it picks
- * them up and if the flit is a tail, the NI inserts the corresponding message
- * into the protocol buffer. It also checks for credits being sent by the
- * downstream router.
- */
-
-void
-NetworkInterface::wakeup()
-{
- std::ostringstream oss;
- for (auto &oPort: outPorts) {
- oss << oPort->routerID() << "[" << oPort->printVnets() << "] ";
- }
- DPRINTF(RubyNetwork, "Network Interface %d connected to router:%s "
- "woke up. Period: %ld\n", m_id, oss.str(), clockPeriod());
-
- assert(curTick() == clockEdge());
- MsgPtr msg_ptr;
- Tick curTime = clockEdge();
-
- // Checking for messages coming from the protocol
- // can pick up a message/cycle for each virtual net
- for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
- MessageBuffer *b = inNode_ptr[vnet];
- if (b == nullptr) {
- continue;
- }
-
- if (b->isReady(curTime)) { // Is there a message waiting
- msg_ptr = b->peekMsgPtr();
- if (flitisizeMessage(msg_ptr, vnet)) {
- b->dequeue(curTime);
- }
- }
- }
-
- scheduleOutputLink();
-
- // Check if there are flits stalling a virtual channel. Track if a
- // message is enqueued to restrict ejection to one message per cycle.
- checkStallQueue();
-
- /*********** Check the incoming flit link **********/
- DPRINTF(RubyNetwork, "Number of input ports: %d\n", inPorts.size());
- for (auto &iPort: inPorts) {
- NetworkLink *inNetLink = iPort->inNetLink();
- if (inNetLink->isReady(curTick())) {
- flit *t_flit = inNetLink->consumeLink();
- DPRINTF(RubyNetwork, "Recieved flit:%s\n", *t_flit);
- assert(t_flit->m_width == iPort->bitWidth());
-
- int vnet = t_flit->get_vnet();
- t_flit->set_dequeue_time(curTick());
-
- // If a tail flit is received, enqueue into the protocol buffers
- // if space is available. Otherwise, exchange non-tail flits for
- // credits.
- if (t_flit->get_type() == TAIL_ ||
- t_flit->get_type() == HEAD_TAIL_) {
- if (!iPort->messageEnqueuedThisCycle &&
- outNode_ptr[vnet]->areNSlotsAvailable(1, curTime)) {
- // Space is available. Enqueue to protocol buffer.
- outNode_ptr[vnet]->enqueue(t_flit->get_msg_ptr(), curTime,
- cyclesToTicks(Cycles(1)));
-
- // Simply send a credit back since we are not buffering
- // this flit in the NI
- Credit *cFlit = new Credit(t_flit->get_vc(),
- true, curTick());
- iPort->sendCredit(cFlit);
- // Update stats and delete flit pointer
- incrementStats(t_flit);
- delete t_flit;
- } else {
- // No space available- Place tail flit in stall queue and
- // set up a callback for when protocol buffer is dequeued.
- // Stat update and flit pointer deletion will occur upon
- // unstall.
- iPort->m_stall_queue.push_back(t_flit);
- m_stall_count[vnet]++;
-
- outNode_ptr[vnet]->registerDequeueCallback([this]() {
- dequeueCallback(); });
- }
- } else {
- // Non-tail flit. Send back a credit but not VC free signal.
- Credit *cFlit = new Credit(t_flit->get_vc(), false,
- curTick());
- // Simply send a credit back since we are not buffering
- // this flit in the NI
- iPort->sendCredit(cFlit);
-
- // Update stats and delete flit pointer.
- incrementStats(t_flit);
- delete t_flit;
- }
- }
- }
-
- /****************** Check the incoming credit link *******/
-
- for (auto &oPort: outPorts) {
- CreditLink *inCreditLink = oPort->inCreditLink();
- if (inCreditLink->isReady(curTick())) {
- Credit *t_credit = (Credit*) inCreditLink->consumeLink();
- outVcState[t_credit->get_vc()].increment_credit();
- if (t_credit->is_free_signal()) {
- outVcState[t_credit->get_vc()].setState(IDLE_,
- curTick());
- }
- delete t_credit;
- }
- }
-
-
- // It is possible to enqueue multiple outgoing credit flits if a message
- // was unstalled in the same cycle as a new message arrives. In this
- // case, we should schedule another wakeup to ensure the credit is sent
- // back.
- for (auto &iPort: inPorts) {
- if (iPort->outCreditQueue()->getSize() > 0) {
- DPRINTF(RubyNetwork, "Sending a credit %s via %s at %ld\n",
- *(iPort->outCreditQueue()->peekTopFlit()),
- iPort->outCreditLink()->name(), clockEdge(Cycles(1)));
- iPort->outCreditLink()->
- scheduleEventAbsolute(clockEdge(Cycles(1)));
- }
- }
- checkReschedule();
-}
-
-void
-NetworkInterface::checkStallQueue()
-{
- // Check all stall queues.
- // There is one stall queue for each input link
- for (auto &iPort: inPorts) {
- iPort->messageEnqueuedThisCycle = false;
- Tick curTime = clockEdge();
-
- if (!iPort->m_stall_queue.empty()) {
- for (auto stallIter = iPort->m_stall_queue.begin();
- stallIter != iPort->m_stall_queue.end(); ) {
- flit *stallFlit = *stallIter;
- int vnet = stallFlit->get_vnet();
-
- // If we can now eject to the protocol buffer,
- // send back credits
- if (outNode_ptr[vnet]->areNSlotsAvailable(1,
- curTime)) {
- outNode_ptr[vnet]->enqueue(stallFlit->get_msg_ptr(),
- curTime, cyclesToTicks(Cycles(1)));
-
- // Send back a credit with free signal now that the
- // VC is no longer stalled.
- Credit *cFlit = new Credit(stallFlit->get_vc(), true,
- curTick());
- iPort->sendCredit(cFlit);
-
- // Update Stats
- incrementStats(stallFlit);
-
- // Flit can now safely be deleted and removed from stall
- // queue
- delete stallFlit;
- iPort->m_stall_queue.erase(stallIter);
- m_stall_count[vnet]--;
-
- // If there are no more stalled messages for this vnet, the
- // callback on it's MessageBuffer is not needed.
- if (m_stall_count[vnet] == 0)
- outNode_ptr[vnet]->unregisterDequeueCallback();
-
- iPort->messageEnqueuedThisCycle = true;
- break;
- } else {
- ++stallIter;
- }
- }
- }
- }
-}
-
-// Embed the protocol message into flits
-bool
-NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
-{
- Message *net_msg_ptr = msg_ptr.get();
- NetDest net_msg_dest = net_msg_ptr->getDestination();
-
- // gets all the destinations associated with this message.
- vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
-
- // Number of flits is dependent on the link bandwidth available.
- // This is expressed in terms of bytes/cycle or the flit size
- OutputPort *oPort = getOutportForVnet(vnet);
- assert(oPort);
- int num_flits = (int)divCeil((float) m_net_ptr->MessageSizeType_to_int(
- net_msg_ptr->getMessageSize()), (float)oPort->bitWidth());
-
- DPRINTF(RubyNetwork, "Message Size:%d vnet:%d bitWidth:%d\n",
- m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize()),
- vnet, oPort->bitWidth());
-
- // loop to convert all multicast messages into unicast messages
- for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
-
- // this will return a free output virtual channel
- int vc = calculateVC(vnet);
-
- if (vc == -1) {
- return false ;
- }
- MsgPtr new_msg_ptr = msg_ptr->clone();
- NodeID destID = dest_nodes[ctr];
-
- Message *new_net_msg_ptr = new_msg_ptr.get();
- if (dest_nodes.size() > 1) {
- NetDest personal_dest;
- for (int m = 0; m < (int) MachineType_NUM; m++) {
- if ((destID >= MachineType_base_number((MachineType) m)) &&
- destID < MachineType_base_number((MachineType) (m+1))) {
- // calculating the NetDest associated with this destID
- personal_dest.clear();
- personal_dest.add((MachineID) {(MachineType) m, (destID -
- MachineType_base_number((MachineType) m))});
- new_net_msg_ptr->getDestination() = personal_dest;
- break;
- }
- }
- net_msg_dest.removeNetDest(personal_dest);
- // removing the destination from the original message to reflect
- // that a message with this particular destination has been
- // flitisized and an output vc is acquired
- net_msg_ptr->getDestination().removeNetDest(personal_dest);
- }
-
- // Embed Route into the flits
- // NetDest format is used by the routing table
- // Custom routing algorithms just need destID
-
- RouteInfo route;
- route.vnet = vnet;
- route.net_dest = new_net_msg_ptr->getDestination();
- route.src_ni = m_id;
- route.src_router = oPort->routerID();
- route.dest_ni = destID;
- route.dest_router = m_net_ptr->get_router_id(destID, vnet);
-
- // initialize hops_traversed to -1
- // so that the first router increments it to 0
- route.hops_traversed = -1;
-
- m_net_ptr->increment_injected_packets(vnet);
- for (int i = 0; i < num_flits; i++) {
- m_net_ptr->increment_injected_flits(vnet);
- flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
- m_net_ptr->MessageSizeType_to_int(
- net_msg_ptr->getMessageSize()),
- oPort->bitWidth(), curTick());
-
- fl->set_src_delay(curTick() - ticksToCycles(msg_ptr->getTime()));
- niOutVcs[vc].insert(fl);
- }
-
- m_ni_out_vcs_enqueue_time[vc] = curTick();
- outVcState[vc].setState(ACTIVE_, curTick());
- }
- return true ;
-}
-
-// Looking for a free output vc
-int
-NetworkInterface::calculateVC(int vnet)
-{
- for (int i = 0; i < m_vc_per_vnet; i++) {
- int delta = m_vc_allocator[vnet];
- m_vc_allocator[vnet]++;
- if (m_vc_allocator[vnet] == m_vc_per_vnet)
- m_vc_allocator[vnet] = 0;
-
- if (outVcState[(vnet*m_vc_per_vnet) + delta].isInState(
- IDLE_, curTick())) {
- vc_busy_counter[vnet] = 0;
- return ((vnet*m_vc_per_vnet) + delta);
- }
- }
-
- vc_busy_counter[vnet] += 1;
- panic_if(vc_busy_counter[vnet] > m_deadlock_threshold,
- "%s: Possible network deadlock in vnet: %d at time: %llu \n",
- name(), vnet, curTick());
-
- return -1;
-}
-
-void
-NetworkInterface::scheduleOutputPort(OutputPort *oPort)
-{
- int vc = oPort->vcRoundRobin();
-
- for (int i = 0; i < niOutVcs.size(); i++) {
- vc++;
- if (vc == niOutVcs.size())
- vc = 0;
-
- int t_vnet = get_vnet(vc);
- if (oPort->isVnetSupported(t_vnet)) {
- // model buffer backpressure
- if (niOutVcs[vc].isReady(curTick()) &&
- outVcState[vc].has_credit()) {
-
- bool is_candidate_vc = true;
- int vc_base = t_vnet * m_vc_per_vnet;
-
- if (m_net_ptr->isVNetOrdered(t_vnet)) {
- for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
- vc_offset++) {
- int t_vc = vc_base + vc_offset;
- if (niOutVcs[t_vc].isReady(curTick())) {
- if (m_ni_out_vcs_enqueue_time[t_vc] <
- m_ni_out_vcs_enqueue_time[vc]) {
- is_candidate_vc = false;
- break;
- }
- }
- }
- }
- if (!is_candidate_vc)
- continue;
-
- // Update the round robin arbiter
- oPort->vcRoundRobin(vc);
-
- outVcState[vc].decrement_credit();
-
- // Just removing the top flit
- flit *t_flit = niOutVcs[vc].getTopFlit();
- t_flit->set_time(clockEdge(Cycles(1)));
-
- // Scheduling the flit
- scheduleFlit(t_flit);
-
- if (t_flit->get_type() == TAIL_ ||
- t_flit->get_type() == HEAD_TAIL_) {
- m_ni_out_vcs_enqueue_time[vc] = Tick(INFINITE_);
- }
-
- // Done with this port, continue to schedule
- // other ports
- return;
- }
- }
- }
-}
-
-
-
-/** This function looks at the NI buffers
- * if some buffer has flits which are ready to traverse the link in the next
- * cycle, and the downstream output vc associated with this flit has buffers
- * left, the link is scheduled for the next cycle
- */
-
-void
-NetworkInterface::scheduleOutputLink()
-{
- // Schedule each output link
- for (auto &oPort: outPorts) {
- scheduleOutputPort(oPort);
- }
-}
-
-NetworkInterface::InputPort *
-NetworkInterface::getInportForVnet(int vnet)
-{
- for (auto &iPort : inPorts) {
- if (iPort->isVnetSupported(vnet)) {
- return iPort;
- }
- }
-
- return nullptr;
-}
-
-/*
- * This function returns the outport which supports the given vnet.
- * Currently, HeteroGarnet does not support multiple outports to
- * support same vnet. Thus, this function returns the first-and
- * only outport which supports the vnet.
- */
-NetworkInterface::OutputPort *
-NetworkInterface::getOutportForVnet(int vnet)
-{
- for (auto &oPort : outPorts) {
- if (oPort->isVnetSupported(vnet)) {
- return oPort;
- }
- }
-
- return nullptr;
-}
-void
-NetworkInterface::scheduleFlit(flit *t_flit)
-{
- OutputPort *oPort = getOutportForVnet(t_flit->get_vnet());
-
- if (oPort) {
- DPRINTF(RubyNetwork, "Scheduling at %s time:%ld flit:%s Message:%s\n",
- oPort->outNetLink()->name(), clockEdge(Cycles(1)),
- *t_flit, *(t_flit->get_msg_ptr()));
- oPort->outFlitQueue()->insert(t_flit);
- oPort->outNetLink()->scheduleEventAbsolute(clockEdge(Cycles(1)));
- return;
- }
-
- panic("No output port found for vnet:%d\n", t_flit->get_vnet());
- return;
-}
-
-int
-NetworkInterface::get_vnet(int vc)
-{
- for (int i = 0; i < m_virtual_networks; i++) {
- if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
- return i;
- }
- }
- fatal("Could not determine vc");
-}
-
-
-// Wakeup the NI in the next cycle if there are waiting
-// messages in the protocol buffer, or waiting flits in the
-// output VC buffer.
-// Also check if we have to reschedule because of a clock period
-// difference.
-void
-NetworkInterface::checkReschedule()
-{
- for (const auto& it : inNode_ptr) {
- if (it == nullptr) {
- continue;
- }
-
- while (it->isReady(clockEdge())) { // Is there a message waiting
- scheduleEvent(Cycles(1));
- return;
- }
- }
-
- for (auto& ni_out_vc : niOutVcs) {
- if (ni_out_vc.isReady(clockEdge(Cycles(1)))) {
- scheduleEvent(Cycles(1));
- return;
- }
- }
-
- // Check if any input links have flits to be popped.
- // This can happen if the links are operating at
- // a higher frequency.
- for (auto &iPort : inPorts) {
- NetworkLink *inNetLink = iPort->inNetLink();
- if (inNetLink->isReady(curTick())) {
- scheduleEvent(Cycles(1));
- return;
- }
- }
-
- for (auto &oPort : outPorts) {
- CreditLink *inCreditLink = oPort->inCreditLink();
- if (inCreditLink->isReady(curTick())) {
- scheduleEvent(Cycles(1));
- return;
- }
- }
-}
-
-void
-NetworkInterface::print(std::ostream& out) const
-{
- out << "[Network Interface]";
-}
-
-uint32_t
-NetworkInterface::functionalWrite(Packet *pkt)
-{
- uint32_t num_functional_writes = 0;
- for (auto& ni_out_vc : niOutVcs) {
- num_functional_writes += ni_out_vc.functionalWrite(pkt);
- }
-
- for (auto &oPort: outPorts) {
- num_functional_writes += oPort->outFlitQueue()->functionalWrite(pkt);
- }
- return num_functional_writes;
-}
-
-NetworkInterface *
-GarnetNetworkInterfaceParams::create()
-{
- return new NetworkInterface(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_NETWORKINTERFACE_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_NETWORKINTERFACE_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/OutVcState.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-#include "params/GarnetNetworkInterface.hh"
-
-class MessageBuffer;
-class flitBuffer;
-
-class NetworkInterface : public ClockedObject, public Consumer
-{
- public:
- typedef GarnetNetworkInterfaceParams Params;
- NetworkInterface(const Params *p);
- ~NetworkInterface() = default;
-
- void addInPort(NetworkLink *in_link, CreditLink *credit_link);
- void addOutPort(NetworkLink *out_link, CreditLink *credit_link,
- SwitchID router_id, uint32_t consumerVcs);
-
- void dequeueCallback();
- void wakeup();
- void addNode(std::vector<MessageBuffer *> &inNode,
- std::vector<MessageBuffer *> &outNode);
-
- void print(std::ostream& out) const;
- int get_vnet(int vc);
- void init_net_ptr(GarnetNetwork *net_ptr) { m_net_ptr = net_ptr; }
-
- uint32_t functionalWrite(Packet *);
-
- void scheduleFlit(flit *t_flit);
-
- int get_router_id(int vnet)
- {
- OutputPort *oPort = getOutportForVnet(vnet);
- assert(oPort);
- return oPort->routerID();
- }
-
- class OutputPort
- {
- public:
- OutputPort(NetworkLink *outLink, CreditLink *creditLink,
- int routerID)
- {
- _vnets = outLink->mVnets;
- _outFlitQueue = new flitBuffer();
-
- _outNetLink = outLink;
- _inCreditLink = creditLink;
-
- _routerID = routerID;
- _bitWidth = outLink->bitWidth;
- _vcRoundRobin = 0;
-
- }
-
- flitBuffer *
- outFlitQueue()
- {
- return _outFlitQueue;
- }
-
- NetworkLink *
- outNetLink()
- {
- return _outNetLink;
- }
-
- CreditLink *
- inCreditLink()
- {
- return _inCreditLink;
- }
-
- int
- routerID()
- {
- return _routerID;
- }
-
- uint32_t bitWidth()
- {
- return _bitWidth;
- }
-
- bool isVnetSupported(int pVnet)
- {
- if (!_vnets.size()) {
- return true;
- }
-
- for (auto &it : _vnets) {
- if (it == pVnet) {
- return true;
- }
- }
- return false;
-
- }
-
- std::string
- printVnets()
- {
- std::stringstream ss;
- for (auto &it : _vnets) {
- ss << it;
- ss << " ";
- }
- return ss.str();
- }
-
- int vcRoundRobin()
- {
- return _vcRoundRobin;
- }
-
- void vcRoundRobin(int vc)
- {
- _vcRoundRobin = vc;
- }
-
-
- private:
- std::vector<int> _vnets;
- flitBuffer *_outFlitQueue;
-
- NetworkLink *_outNetLink;
- CreditLink *_inCreditLink;
-
- int _vcRoundRobin; // For round robin scheduling
-
- int _routerID;
- uint32_t _bitWidth;
- };
-
- class InputPort
- {
- public:
- InputPort(NetworkLink *inLink, CreditLink *creditLink)
- {
- _vnets = inLink->mVnets;
- _outCreditQueue = new flitBuffer();
-
- _inNetLink = inLink;
- _outCreditLink = creditLink;
- _bitWidth = inLink->bitWidth;
- }
-
- flitBuffer *
- outCreditQueue()
- {
- return _outCreditQueue;
- }
-
- NetworkLink *
- inNetLink()
- {
- return _inNetLink;
- }
-
- CreditLink *
- outCreditLink()
- {
- return _outCreditLink;
- }
-
- bool isVnetSupported(int pVnet)
- {
- if (!_vnets.size()) {
- return true;
- }
-
- for (auto &it : _vnets) {
- if (it == pVnet) {
- return true;
- }
- }
- return false;
-
- }
-
- void sendCredit(Credit *cFlit)
- {
- _outCreditQueue->insert(cFlit);
- }
-
- uint32_t bitWidth()
- {
- return _bitWidth;
- }
-
- std::string
- printVnets()
- {
- std::stringstream ss;
- for (auto &it : _vnets) {
- ss << it;
- ss << " ";
- }
- return ss.str();
- }
-
- // Queue for stalled flits
- std::deque<flit *> m_stall_queue;
- bool messageEnqueuedThisCycle;
- private:
- std::vector<int> _vnets;
- flitBuffer *_outCreditQueue;
-
- NetworkLink *_inNetLink;
- CreditLink *_outCreditLink;
- uint32_t _bitWidth;
- };
-
-
- private:
- GarnetNetwork *m_net_ptr;
- const NodeID m_id;
- const int m_virtual_networks;
- int m_vc_per_vnet;
- std::vector<int> m_vc_allocator;
- std::vector<OutputPort *> outPorts;
- std::vector<InputPort *> inPorts;
- int m_deadlock_threshold;
- std::vector<OutVcState> outVcState;
-
- std::vector<int> m_stall_count;
-
- // Input Flit Buffers
- // The flit buffers which will serve the Consumer
- std::vector<flitBuffer> niOutVcs;
- std::vector<Tick> m_ni_out_vcs_enqueue_time;
-
- // The Message buffers that takes messages from the protocol
- std::vector<MessageBuffer *> inNode_ptr;
- // The Message buffers that provides messages to the protocol
- std::vector<MessageBuffer *> outNode_ptr;
- // When a vc stays busy for a long time, it indicates a deadlock
- std::vector<int> vc_busy_counter;
-
- void checkStallQueue();
- bool flitisizeMessage(MsgPtr msg_ptr, int vnet);
- int calculateVC(int vnet);
-
-
- void scheduleOutputPort(OutputPort *oPort);
- void scheduleOutputLink();
- void checkReschedule();
-
- void incrementStats(flit *t_flit);
-
- InputPort *getInportForVnet(int vnet);
- OutputPort *getOutportForVnet(int vnet);
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_NETWORKINTERFACE_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-
-#include "base/trace.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-
-NetworkLink::NetworkLink(const Params *p)
- : ClockedObject(p), Consumer(this), m_id(p->link_id),
- m_type(NUM_LINK_TYPES_),
- m_latency(p->link_latency), m_link_utilized(0),
- m_virt_nets(p->virt_nets), linkBuffer(),
- link_consumer(nullptr), link_srcQueue(nullptr)
-{
- int num_vnets = (p->supported_vnets).size();
- mVnets.resize(num_vnets);
- bitWidth = p->width;
- for (int i = 0; i < num_vnets; i++) {
- mVnets[i] = p->supported_vnets[i];
- }
-}
-
-void
-NetworkLink::setLinkConsumer(Consumer *consumer)
-{
- link_consumer = consumer;
-}
-
-void
-NetworkLink::setVcsPerVnet(uint32_t consumerVcs)
-{
- m_vc_load.resize(m_virt_nets * consumerVcs);
-}
-
-void
-NetworkLink::setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObj)
-{
- link_srcQueue = src_queue;
- src_object = srcClockObj;
-}
-
-void
-NetworkLink::wakeup()
-{
- DPRINTF(RubyNetwork, "Woke up to transfer flits from %s\n",
- src_object->name());
- assert(link_srcQueue != nullptr);
- assert(curTick() == clockEdge());
- if (link_srcQueue->isReady(curTick())) {
- flit *t_flit = link_srcQueue->getTopFlit();
- DPRINTF(RubyNetwork, "Transmission will finish at %ld :%s\n",
- clockEdge(m_latency), *t_flit);
- if (m_type != NUM_LINK_TYPES_) {
- // Only for assertions and debug messages
- assert(t_flit->m_width == bitWidth);
- assert((std::find(mVnets.begin(), mVnets.end(),
- t_flit->get_vnet()) != mVnets.end()) ||
- (mVnets.size() == 0));
- }
- t_flit->set_time(clockEdge(m_latency));
- linkBuffer.insert(t_flit);
- link_consumer->scheduleEventAbsolute(clockEdge(m_latency));
- m_link_utilized++;
- m_vc_load[t_flit->get_vc()]++;
- }
-
- if (!link_srcQueue->isEmpty()) {
- scheduleEvent(Cycles(1));
- }
-}
-
-void
-NetworkLink::resetStats()
-{
- for (int i = 0; i < m_vc_load.size(); i++) {
- m_vc_load[i] = 0;
- }
-
- m_link_utilized = 0;
-}
-
-NetworkLink *
-NetworkLinkParams::create()
-{
- return new NetworkLink(this);
-}
-
-CreditLink *
-CreditLinkParams::create()
-{
- return new CreditLink(this);
-}
-
-uint32_t
-NetworkLink::functionalWrite(Packet *pkt)
-{
- return linkBuffer.functionalWrite(pkt);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_NETWORKLINK_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_NETWORKLINK_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-#include "params/NetworkLink.hh"
-#include "sim/clocked_object.hh"
-
-class GarnetNetwork;
-
-class NetworkLink : public ClockedObject, public Consumer
-{
- public:
- typedef NetworkLinkParams Params;
- NetworkLink(const Params *p);
- ~NetworkLink() = default;
-
- void setLinkConsumer(Consumer *consumer);
- void setSourceQueue(flitBuffer *src_queue, ClockedObject *srcClockObject);
- virtual void setVcsPerVnet(uint32_t consumerVcs);
- void setType(link_type type) { m_type = type; }
- link_type getType() { return m_type; }
- void print(std::ostream& out) const {}
- int get_id() const { return m_id; }
- flitBuffer *getBuffer() { return &linkBuffer;}
- virtual void wakeup();
-
- unsigned int getLinkUtilization() const { return m_link_utilized; }
- const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; }
-
- inline bool isReady(Tick curTime)
- {
- return linkBuffer.isReady(curTime);
- }
-
- inline flit* peekLink() { return linkBuffer.peekTopFlit(); }
- inline flit* consumeLink() { return linkBuffer.getTopFlit(); }
-
- uint32_t functionalWrite(Packet *);
- void resetStats();
-
- std::vector<int> mVnets;
- uint32_t bitWidth;
-
- private:
- const int m_id;
- link_type m_type;
- const Cycles m_latency;
-
- ClockedObject *src_object;
-
- // Statistical variables
- unsigned int m_link_utilized;
- std::vector<unsigned int> m_vc_load;
-
- protected:
- uint32_t m_virt_nets;
- flitBuffer linkBuffer;
- Consumer *link_consumer;
- flitBuffer *link_srcQueue;
-
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_NETWORKLINK_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/OutVcState.hh"
-
-#include "mem/ruby/system/RubySystem.hh"
-
-OutVcState::OutVcState(int id, GarnetNetwork *network_ptr,
- uint32_t consumerVcs)
- : m_time(0)
-{
- m_id = id;
- m_vc_state = IDLE_;
- /*
- * We find the virtual network using the number of
- * vcs per vnet. This assumes that the same vcs per
- * vnet is used throughout the given object.
- */
- int vnet = floor(id/consumerVcs);
-
- if (network_ptr->get_vnet_type(vnet) == DATA_VNET_)
- m_max_credit_count = network_ptr->getBuffersPerDataVC();
- else
- m_max_credit_count = network_ptr->getBuffersPerCtrlVC();
-
- m_credit_count = m_max_credit_count;
- assert(m_credit_count >= 1);
-}
-
-void
-OutVcState::increment_credit()
-{
- m_credit_count++;
- assert(m_credit_count <= m_max_credit_count);
-}
-
-void
-OutVcState::decrement_credit()
-{
- m_credit_count--;
- assert(m_credit_count >= 0);
-}
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_OUTVCSTATE_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_OUTVCSTATE_HH__
-
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-
-class OutVcState
-{
- public:
- OutVcState(int id, GarnetNetwork *network_ptr, uint32_t consumerVcs);
-
- int get_credit_count() { return m_credit_count; }
- inline bool has_credit() { return (m_credit_count > 0); }
- void increment_credit();
- void decrement_credit();
-
- inline bool
- isInState(VC_state_type state, Tick request_time)
- {
- return ((m_vc_state == state) && (request_time >= m_time) );
- }
- inline void
- setState(VC_state_type state, Tick time)
- {
- m_vc_state = state;
- m_time = time;
- }
-
- private:
- int m_id ;
- Tick m_time;
- VC_state_type m_vc_state;
- int m_credit_count;
- int m_max_credit_count;
-};
-
-#endif //__MEM_RUBY_NETWORK_GARNET2_0_OUTVCSTATE_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/Credit.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-OutputUnit::OutputUnit(int id, PortDirection direction, Router *router,
- uint32_t consumerVcs)
- : Consumer(router), m_router(router), m_id(id), m_direction(direction),
- m_vc_per_vnet(consumerVcs)
-{
- const int m_num_vcs = consumerVcs * m_router->get_num_vnets();
- outVcState.reserve(m_num_vcs);
- for (int i = 0; i < m_num_vcs; i++) {
- outVcState.emplace_back(i, m_router->get_net_ptr(), consumerVcs);
- }
-}
-
-void
-OutputUnit::decrement_credit(int out_vc)
-{
- DPRINTF(RubyNetwork, "Router %d OutputUnit %s decrementing credit:%d for "
- "outvc %d at time: %lld for %s\n", m_router->get_id(),
- m_router->getPortDirectionName(get_direction()),
- outVcState[out_vc].get_credit_count(),
- out_vc, m_router->curCycle(), m_credit_link->name());
-
- outVcState[out_vc].decrement_credit();
-}
-
-void
-OutputUnit::increment_credit(int out_vc)
-{
- DPRINTF(RubyNetwork, "Router %d OutputUnit %s incrementing credit:%d for "
- "outvc %d at time: %lld from:%s\n", m_router->get_id(),
- m_router->getPortDirectionName(get_direction()),
- outVcState[out_vc].get_credit_count(),
- out_vc, m_router->curCycle(), m_credit_link->name());
-
- outVcState[out_vc].increment_credit();
-}
-
-// Check if the output VC (i.e., input VC at next router)
-// has free credits (i..e, buffer slots).
-// This is tracked by OutVcState
-bool
-OutputUnit::has_credit(int out_vc)
-{
- assert(outVcState[out_vc].isInState(ACTIVE_, curTick()));
- return outVcState[out_vc].has_credit();
-}
-
-
-// Check if the output port (i.e., input port at next router) has free VCs.
-bool
-OutputUnit::has_free_vc(int vnet)
-{
- int vc_base = vnet*m_vc_per_vnet;
- for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
- if (is_vc_idle(vc, curTick()))
- return true;
- }
-
- return false;
-}
-
-// Assign a free output VC to the winner of Switch Allocation
-int
-OutputUnit::select_free_vc(int vnet)
-{
- int vc_base = vnet*m_vc_per_vnet;
- for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
- if (is_vc_idle(vc, curTick())) {
- outVcState[vc].setState(ACTIVE_, curTick());
- return vc;
- }
- }
-
- return -1;
-}
-
-/*
- * The wakeup function of the OutputUnit reads the credit signal from the
- * downstream router for the output VC (i.e., input VC at downstream router).
- * It increments the credit count in the appropriate output VC state.
- * If the credit carries is_free_signal as true,
- * the output VC is marked IDLE.
- */
-
-void
-OutputUnit::wakeup()
-{
- if (m_credit_link->isReady(curTick())) {
- Credit *t_credit = (Credit*) m_credit_link->consumeLink();
- increment_credit(t_credit->get_vc());
-
- if (t_credit->is_free_signal())
- set_vc_state(IDLE_, t_credit->get_vc(), curTick());
-
- delete t_credit;
-
- if (m_credit_link->isReady(curTick())) {
- scheduleEvent(Cycles(1));
- }
- }
-}
-
-flitBuffer*
-OutputUnit::getOutQueue()
-{
- return &outBuffer;
-}
-
-void
-OutputUnit::set_out_link(NetworkLink *link)
-{
- m_out_link = link;
-}
-
-void
-OutputUnit::set_credit_link(CreditLink *credit_link)
-{
- m_credit_link = credit_link;
-}
-
-void
-OutputUnit::insert_flit(flit *t_flit)
-{
- outBuffer.insert(t_flit);
- m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
-}
-
-uint32_t
-OutputUnit::functionalWrite(Packet *pkt)
-{
- return outBuffer.functionalWrite(pkt);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_OUTPUTUNIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_OUTPUTUNIT_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "base/compiler.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/OutVcState.hh"
-
-class CreditLink;
-class Router;
-
-class OutputUnit : public Consumer
-{
- public:
- OutputUnit(int id, PortDirection direction, Router *router,
- uint32_t consumerVcs);
- ~OutputUnit() = default;
- void set_out_link(NetworkLink *link);
- void set_credit_link(CreditLink *credit_link);
- void wakeup();
- flitBuffer* getOutQueue();
- void print(std::ostream& out) const {};
- void decrement_credit(int out_vc);
- void increment_credit(int out_vc);
- bool has_credit(int out_vc);
- bool has_free_vc(int vnet);
- int select_free_vc(int vnet);
-
- inline PortDirection get_direction() { return m_direction; }
-
- int
- get_credit_count(int vc)
- {
- return outVcState[vc].get_credit_count();
- }
-
- inline int
- get_outlink_id()
- {
- return m_out_link->get_id();
- }
-
- inline void
- set_vc_state(VC_state_type state, int vc, Tick curTime)
- {
- outVcState[vc].setState(state, curTime);
- }
-
- inline bool
- is_vc_idle(int vc, Tick curTime)
- {
- return (outVcState[vc].isInState(IDLE_, curTime));
- }
-
- void insert_flit(flit *t_flit);
-
- inline int
- getVcsPerVnet()
- {
- return m_vc_per_vnet;
- }
-
- uint32_t functionalWrite(Packet *pkt);
-
- private:
- Router *m_router;
- int M5_CLASS_VAR_USED m_id;
- PortDirection m_direction;
- int m_vc_per_vnet;
- NetworkLink *m_out_link;
- CreditLink *m_credit_link;
-
- // This is for the network link to consume
- flitBuffer outBuffer;
- // vc state of downstream router
- std::vector<OutVcState> outVcState;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_OUTPUTUNIT_HH__
+++ /dev/null
-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.
-
-
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/CreditLink.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-
-using namespace std;
-
-Router::Router(const Params *p)
- : BasicRouter(p), Consumer(this), m_latency(p->latency),
- m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
- m_num_vcs(m_virtual_networks * m_vc_per_vnet), m_bit_width(p->width),
- m_network_ptr(nullptr), routingUnit(this), switchAllocator(this),
- crossbarSwitch(this)
-{
- m_input_unit.clear();
- m_output_unit.clear();
-}
-
-void
-Router::init()
-{
- BasicRouter::init();
-
- switchAllocator.init();
- crossbarSwitch.init();
-}
-
-void
-Router::wakeup()
-{
- DPRINTF(RubyNetwork, "Router %d woke up\n", m_id);
- assert(clockEdge() == curTick());
-
- // check for incoming flits
- for (int inport = 0; inport < m_input_unit.size(); inport++) {
- m_input_unit[inport]->wakeup();
- }
-
- // check for incoming credits
- // Note: the credit update is happening before SA
- // buffer turnaround time =
- // credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
- // if we want the credit update to take place after SA, this loop should
- // be moved after the SA request
- for (int outport = 0; outport < m_output_unit.size(); outport++) {
- m_output_unit[outport]->wakeup();
- }
-
- // Switch Allocation
- switchAllocator.wakeup();
-
- // Switch Traversal
- crossbarSwitch.wakeup();
-}
-
-void
-Router::addInPort(PortDirection inport_dirn,
- NetworkLink *in_link, CreditLink *credit_link)
-{
- fatal_if(in_link->bitWidth != m_bit_width, "Widths of link %s(%d)does"
- " not match that of Router%d(%d). Consider inserting SerDes "
- "Units.", in_link->name(), in_link->bitWidth, m_id, m_bit_width);
-
- int port_num = m_input_unit.size();
- InputUnit *input_unit = new InputUnit(port_num, inport_dirn, this);
-
- input_unit->set_in_link(in_link);
- input_unit->set_credit_link(credit_link);
- in_link->setLinkConsumer(this);
- in_link->setVcsPerVnet(get_vc_per_vnet());
- credit_link->setSourceQueue(input_unit->getCreditQueue(), this);
- credit_link->setVcsPerVnet(get_vc_per_vnet());
-
- m_input_unit.push_back(std::shared_ptr<InputUnit>(input_unit));
-
- routingUnit.addInDirection(inport_dirn, port_num);
-}
-
-void
-Router::addOutPort(PortDirection outport_dirn,
- NetworkLink *out_link,
- std::vector<NetDest>& routing_table_entry, int link_weight,
- CreditLink *credit_link, uint32_t consumerVcs)
-{
- fatal_if(out_link->bitWidth != m_bit_width, "Widths of units do not match."
- " Consider inserting SerDes Units");
-
- int port_num = m_output_unit.size();
- OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this,
- consumerVcs);
-
- output_unit->set_out_link(out_link);
- output_unit->set_credit_link(credit_link);
- credit_link->setLinkConsumer(this);
- credit_link->setVcsPerVnet(consumerVcs);
- out_link->setSourceQueue(output_unit->getOutQueue(), this);
- out_link->setVcsPerVnet(consumerVcs);
-
- m_output_unit.push_back(std::shared_ptr<OutputUnit>(output_unit));
-
- routingUnit.addRoute(routing_table_entry);
- routingUnit.addWeight(link_weight);
- routingUnit.addOutDirection(outport_dirn, port_num);
-}
-
-PortDirection
-Router::getOutportDirection(int outport)
-{
- return m_output_unit[outport]->get_direction();
-}
-
-PortDirection
-Router::getInportDirection(int inport)
-{
- return m_input_unit[inport]->get_direction();
-}
-
-int
-Router::route_compute(RouteInfo route, int inport, PortDirection inport_dirn)
-{
- return routingUnit.outportCompute(route, inport, inport_dirn);
-}
-
-void
-Router::grant_switch(int inport, flit *t_flit)
-{
- crossbarSwitch.update_sw_winner(inport, t_flit);
-}
-
-void
-Router::schedule_wakeup(Cycles time)
-{
- // wake up after time cycles
- scheduleEvent(time);
-}
-
-std::string
-Router::getPortDirectionName(PortDirection direction)
-{
- // PortDirection is actually a string
- // If not, then this function should add a switch
- // statement to convert direction to a string
- // that can be printed out
- return direction;
-}
-
-void
-Router::regStats()
-{
- BasicRouter::regStats();
-
- m_buffer_reads
- .name(name() + ".buffer_reads")
- .flags(Stats::nozero)
- ;
-
- m_buffer_writes
- .name(name() + ".buffer_writes")
- .flags(Stats::nozero)
- ;
-
- m_crossbar_activity
- .name(name() + ".crossbar_activity")
- .flags(Stats::nozero)
- ;
-
- m_sw_input_arbiter_activity
- .name(name() + ".sw_input_arbiter_activity")
- .flags(Stats::nozero)
- ;
-
- m_sw_output_arbiter_activity
- .name(name() + ".sw_output_arbiter_activity")
- .flags(Stats::nozero)
- ;
-}
-
-void
-Router::collateStats()
-{
- for (int j = 0; j < m_virtual_networks; j++) {
- for (int i = 0; i < m_input_unit.size(); i++) {
- m_buffer_reads += m_input_unit[i]->get_buf_read_activity(j);
- m_buffer_writes += m_input_unit[i]->get_buf_write_activity(j);
- }
- }
-
- m_sw_input_arbiter_activity = switchAllocator.get_input_arbiter_activity();
- m_sw_output_arbiter_activity =
- switchAllocator.get_output_arbiter_activity();
- m_crossbar_activity = crossbarSwitch.get_crossbar_activity();
-}
-
-void
-Router::resetStats()
-{
- for (int i = 0; i < m_input_unit.size(); i++) {
- m_input_unit[i]->resetStats();
- }
-
- crossbarSwitch.resetStats();
- switchAllocator.resetStats();
-}
-
-void
-Router::printFaultVector(ostream& out)
-{
- int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
- int num_fault_types = m_network_ptr->fault_model->number_of_fault_types;
- float fault_vector[num_fault_types];
- get_fault_vector(temperature_celcius, fault_vector);
- out << "Router-" << m_id << " fault vector: " << endl;
- for (int fault_type_index = 0; fault_type_index < num_fault_types;
- fault_type_index++) {
- out << " - probability of (";
- out <<
- m_network_ptr->fault_model->fault_type_to_string(fault_type_index);
- out << ") = ";
- out << fault_vector[fault_type_index] << endl;
- }
-}
-
-void
-Router::printAggregateFaultProbability(std::ostream& out)
-{
- int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
- float aggregate_fault_prob;
- get_aggregate_fault_probability(temperature_celcius,
- &aggregate_fault_prob);
- out << "Router-" << m_id << " fault probability: ";
- out << aggregate_fault_prob << endl;
-}
-
-uint32_t
-Router::functionalWrite(Packet *pkt)
-{
- uint32_t num_functional_writes = 0;
- num_functional_writes += crossbarSwitch.functionalWrite(pkt);
-
- for (uint32_t i = 0; i < m_input_unit.size(); i++) {
- num_functional_writes += m_input_unit[i]->functionalWrite(pkt);
- }
-
- for (uint32_t i = 0; i < m_output_unit.size(); i++) {
- num_functional_writes += m_output_unit[i]->functionalWrite(pkt);
- }
-
- return num_functional_writes;
-}
-
-Router *
-GarnetRouterParams::create()
-{
- return new Router(this);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_ROUTER_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_ROUTER_HH__
-
-#include <iostream>
-#include <memory>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/ruby/network/BasicRouter.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
-#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-#include "params/GarnetRouter.hh"
-
-class NetworkLink;
-class CreditLink;
-class InputUnit;
-class OutputUnit;
-class FaultModel;
-
-class Router : public BasicRouter, public Consumer
-{
- public:
- typedef GarnetRouterParams Params;
- Router(const Params *p);
-
- ~Router() = default;
-
- void wakeup();
- void print(std::ostream& out) const {};
-
- void init();
- void addInPort(PortDirection inport_dirn, NetworkLink *link,
- CreditLink *credit_link);
- void addOutPort(PortDirection outport_dirn, NetworkLink *link,
- std::vector<NetDest>& routing_table_entry,
- int link_weight, CreditLink *credit_link,
- uint32_t consumerVcs);
-
- Cycles get_pipe_stages(){ return m_latency; }
- uint32_t get_num_vcs() { return m_num_vcs; }
- uint32_t get_num_vnets() { return m_virtual_networks; }
- uint32_t get_vc_per_vnet() { return m_vc_per_vnet; }
- int get_num_inports() { return m_input_unit.size(); }
- int get_num_outports() { return m_output_unit.size(); }
- int get_id() { return m_id; }
-
- void init_net_ptr(GarnetNetwork* net_ptr)
- {
- m_network_ptr = net_ptr;
- }
-
- GarnetNetwork* get_net_ptr() { return m_network_ptr; }
-
- InputUnit*
- getInputUnit(unsigned port)
- {
- assert(port < m_input_unit.size());
- return m_input_unit[port].get();
- }
-
- OutputUnit*
- getOutputUnit(unsigned port)
- {
- assert(port < m_output_unit.size());
- return m_output_unit[port].get();
- }
-
- int getBitWidth() { return m_bit_width; }
-
- PortDirection getOutportDirection(int outport);
- PortDirection getInportDirection(int inport);
-
- int route_compute(RouteInfo route, int inport, PortDirection direction);
- void grant_switch(int inport, flit *t_flit);
- void schedule_wakeup(Cycles time);
-
- std::string getPortDirectionName(PortDirection direction);
- void printFaultVector(std::ostream& out);
- void printAggregateFaultProbability(std::ostream& out);
-
- void regStats();
- void collateStats();
- void resetStats();
-
- // For Fault Model:
- bool get_fault_vector(int temperature, float fault_vector[]) {
- return m_network_ptr->fault_model->fault_vector(m_id, temperature,
- fault_vector);
- }
- bool get_aggregate_fault_probability(int temperature,
- float *aggregate_fault_prob) {
- return m_network_ptr->fault_model->fault_prob(m_id, temperature,
- aggregate_fault_prob);
- }
-
- uint32_t functionalWrite(Packet *);
-
- private:
- Cycles m_latency;
- uint32_t m_virtual_networks, m_vc_per_vnet, m_num_vcs;
- uint32_t m_bit_width;
- GarnetNetwork *m_network_ptr;
-
- RoutingUnit routingUnit;
- SwitchAllocator switchAllocator;
- CrossbarSwitch crossbarSwitch;
-
- std::vector<std::shared_ptr<InputUnit>> m_input_unit;
- std::vector<std::shared_ptr<OutputUnit>> m_output_unit;
-
- // Statistical variables required for power computations
- Stats::Scalar m_buffer_reads;
- Stats::Scalar m_buffer_writes;
-
- Stats::Scalar m_sw_input_arbiter_activity;
- Stats::Scalar m_sw_output_arbiter_activity;
-
- Stats::Scalar m_crossbar_activity;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_ROUTER_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
-
-#include "base/cast.hh"
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-RoutingUnit::RoutingUnit(Router *router)
-{
- m_router = router;
- m_routing_table.clear();
- m_weight_table.clear();
-}
-
-void
-RoutingUnit::addRoute(std::vector<NetDest>& routing_table_entry)
-{
- if (routing_table_entry.size() > m_routing_table.size()) {
- m_routing_table.resize(routing_table_entry.size());
- }
- for (int v = 0; v < routing_table_entry.size(); v++) {
- m_routing_table[v].push_back(routing_table_entry[v]);
- }
-}
-
-void
-RoutingUnit::addWeight(int link_weight)
-{
- m_weight_table.push_back(link_weight);
-}
-
-bool
-RoutingUnit::supportsVnet(int vnet, std::vector<int> sVnets)
-{
- // If all vnets are supported, return true
- if (sVnets.size() == 0) {
- return true;
- }
-
- // Find the vnet in the vector, return true
- if (std::find(sVnets.begin(), sVnets.end(), vnet) != sVnets.end()) {
- return true;
- }
-
- // Not supported vnet
- return false;
-}
-
-/*
- * This is the default routing algorithm in garnet.
- * The routing table is populated during topology creation.
- * Routes can be biased via weight assignments in the topology file.
- * Correct weight assignments are critical to provide deadlock avoidance.
- */
-int
-RoutingUnit::lookupRoutingTable(int vnet, NetDest msg_destination)
-{
- // First find all possible output link candidates
- // For ordered vnet, just choose the first
- // (to make sure different packets don't choose different routes)
- // For unordered vnet, randomly choose any of the links
- // To have a strict ordering between links, they should be given
- // different weights in the topology file
-
- int output_link = -1;
- int min_weight = INFINITE_;
- std::vector<int> output_link_candidates;
- int num_candidates = 0;
-
- // Identify the minimum weight among the candidate output links
- for (int link = 0; link < m_routing_table[vnet].size(); link++) {
- if (msg_destination.intersectionIsNotEmpty(
- m_routing_table[vnet][link])) {
-
- if (m_weight_table[link] <= min_weight)
- min_weight = m_weight_table[link];
- }
- }
-
- // Collect all candidate output links with this minimum weight
- for (int link = 0; link < m_routing_table[vnet].size(); link++) {
- if (msg_destination.intersectionIsNotEmpty(
- m_routing_table[vnet][link])) {
-
- if (m_weight_table[link] == min_weight) {
- num_candidates++;
- output_link_candidates.push_back(link);
- }
- }
- }
-
- if (output_link_candidates.size() == 0) {
- fatal("Fatal Error:: No Route exists from this Router.");
- exit(0);
- }
-
- // Randomly select any candidate output link
- int candidate = 0;
- if (!(m_router->get_net_ptr())->isVNetOrdered(vnet))
- candidate = rand() % num_candidates;
-
- output_link = output_link_candidates.at(candidate);
- return output_link;
-}
-
-
-void
-RoutingUnit::addInDirection(PortDirection inport_dirn, int inport_idx)
-{
- m_inports_dirn2idx[inport_dirn] = inport_idx;
- m_inports_idx2dirn[inport_idx] = inport_dirn;
-}
-
-void
-RoutingUnit::addOutDirection(PortDirection outport_dirn, int outport_idx)
-{
- m_outports_dirn2idx[outport_dirn] = outport_idx;
- m_outports_idx2dirn[outport_idx] = outport_dirn;
-}
-
-// outportCompute() is called by the InputUnit
-// It calls the routing table by default.
-// A template for adaptive topology-specific routing algorithm
-// implementations using port directions rather than a static routing
-// table is provided here.
-
-int
-RoutingUnit::outportCompute(RouteInfo route, int inport,
- PortDirection inport_dirn)
-{
- int outport = -1;
-
- if (route.dest_router == m_router->get_id()) {
-
- // Multiple NIs may be connected to this router,
- // all with output port direction = "Local"
- // Get exact outport id from table
- outport = lookupRoutingTable(route.vnet, route.net_dest);
- return outport;
- }
-
- // Routing Algorithm set in GarnetNetwork.py
- // Can be over-ridden from command line using --routing-algorithm = 1
- RoutingAlgorithm routing_algorithm =
- (RoutingAlgorithm) m_router->get_net_ptr()->getRoutingAlgorithm();
-
- switch (routing_algorithm) {
- case TABLE_: outport =
- lookupRoutingTable(route.vnet, route.net_dest); break;
- case XY_: outport =
- outportComputeXY(route, inport, inport_dirn); break;
- // any custom algorithm
- case CUSTOM_: outport =
- outportComputeCustom(route, inport, inport_dirn); break;
- default: outport =
- lookupRoutingTable(route.vnet, route.net_dest); break;
- }
-
- assert(outport != -1);
- return outport;
-}
-
-// XY routing implemented using port directions
-// Only for reference purpose in a Mesh
-// By default Garnet uses the routing table
-int
-RoutingUnit::outportComputeXY(RouteInfo route,
- int inport,
- PortDirection inport_dirn)
-{
- PortDirection outport_dirn = "Unknown";
-
- int M5_VAR_USED num_rows = m_router->get_net_ptr()->getNumRows();
- int num_cols = m_router->get_net_ptr()->getNumCols();
- assert(num_rows > 0 && num_cols > 0);
-
- int my_id = m_router->get_id();
- int my_x = my_id % num_cols;
- int my_y = my_id / num_cols;
-
- int dest_id = route.dest_router;
- int dest_x = dest_id % num_cols;
- int dest_y = dest_id / num_cols;
-
- int x_hops = abs(dest_x - my_x);
- int y_hops = abs(dest_y - my_y);
-
- bool x_dirn = (dest_x >= my_x);
- bool y_dirn = (dest_y >= my_y);
-
- // already checked that in outportCompute() function
- assert(!(x_hops == 0 && y_hops == 0));
-
- if (x_hops > 0) {
- if (x_dirn) {
- assert(inport_dirn == "Local" || inport_dirn == "West");
- outport_dirn = "East";
- } else {
- assert(inport_dirn == "Local" || inport_dirn == "East");
- outport_dirn = "West";
- }
- } else if (y_hops > 0) {
- if (y_dirn) {
- // "Local" or "South" or "West" or "East"
- assert(inport_dirn != "North");
- outport_dirn = "North";
- } else {
- // "Local" or "North" or "West" or "East"
- assert(inport_dirn != "South");
- outport_dirn = "South";
- }
- } else {
- // x_hops == 0 and y_hops == 0
- // this is not possible
- // already checked that in outportCompute() function
- panic("x_hops == y_hops == 0");
- }
-
- return m_outports_dirn2idx[outport_dirn];
-}
-
-// Template for implementing custom routing algorithm
-// using port directions. (Example adaptive)
-int
-RoutingUnit::outportComputeCustom(RouteInfo route,
- int inport,
- PortDirection inport_dirn)
-{
- panic("%s placeholder executed", __FUNCTION__);
-}
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_ROUTINGUNIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_ROUTINGUNIT_HH__
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-class InputUnit;
-class Router;
-
-class RoutingUnit
-{
- public:
- RoutingUnit(Router *router);
- int outportCompute(RouteInfo route,
- int inport,
- PortDirection inport_dirn);
-
- // Topology-agnostic Routing Table based routing (default)
- void addRoute(std::vector<NetDest>& routing_table_entry);
- void addWeight(int link_weight);
-
- // get output port from routing table
- int lookupRoutingTable(int vnet, NetDest net_dest);
-
- // Topology-specific direction based routing
- void addInDirection(PortDirection inport_dirn, int inport);
- void addOutDirection(PortDirection outport_dirn, int outport);
-
- // Routing for Mesh
- int outportComputeXY(RouteInfo route,
- int inport,
- PortDirection inport_dirn);
-
- // Custom Routing Algorithm using Port Directions
- int outportComputeCustom(RouteInfo route,
- int inport,
- PortDirection inport_dirn);
-
- // Returns true if vnet is present in the vector
- // of vnets or if the vector supports all vnets.
- bool supportsVnet(int vnet, std::vector<int> sVnets);
-
-
- private:
- Router *m_router;
-
- // Routing Table
- std::vector<std::vector<NetDest>> m_routing_table;
- std::vector<int> m_weight_table;
-
- // Inport and Outport direction to idx maps
- std::map<PortDirection, int> m_inports_dirn2idx;
- std::map<int, PortDirection> m_inports_idx2dirn;
- std::map<int, PortDirection> m_outports_idx2dirn;
- std::map<PortDirection, int> m_outports_dirn2idx;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_ROUTINGUNIT_HH__
+++ /dev/null
-# -*- mode:python -*-
-
-# Copyright (c) 2016 Georgia Institute of Technology
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Import('*')
-
-if env['PROTOCOL'] == 'None':
- Return()
-
-SimObject('GarnetLink.py')
-SimObject('GarnetNetwork.py')
-
-Source('GarnetLink.cc')
-Source('GarnetNetwork.cc')
-Source('InputUnit.cc')
-Source('NetworkInterface.cc')
-Source('NetworkLink.cc')
-Source('OutVcState.cc')
-Source('OutputUnit.cc')
-Source('Router.cc')
-Source('RoutingUnit.cc')
-Source('SwitchAllocator.cc')
-Source('CrossbarSwitch.cc')
-Source('VirtualChannel.cc')
-Source('flitBuffer.cc')
-Source('flit.cc')
-Source('Credit.cc')
-Source('NetworkBridge.cc')
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
-
-#include "debug/RubyNetwork.hh"
-#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
-#include "mem/ruby/network/garnet2.0/InputUnit.hh"
-#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
-#include "mem/ruby/network/garnet2.0/Router.hh"
-
-SwitchAllocator::SwitchAllocator(Router *router)
- : Consumer(router)
-{
- m_router = router;
- m_num_vcs = m_router->get_num_vcs();
- m_vc_per_vnet = m_router->get_vc_per_vnet();
-
- m_input_arbiter_activity = 0;
- m_output_arbiter_activity = 0;
-}
-
-void
-SwitchAllocator::init()
-{
- m_num_inports = m_router->get_num_inports();
- m_num_outports = m_router->get_num_outports();
- m_round_robin_inport.resize(m_num_outports);
- m_round_robin_invc.resize(m_num_inports);
- m_port_requests.resize(m_num_outports);
- m_vc_winners.resize(m_num_outports);
-
- for (int i = 0; i < m_num_inports; i++) {
- m_round_robin_invc[i] = 0;
- }
-
- for (int i = 0; i < m_num_outports; i++) {
- m_port_requests[i].resize(m_num_inports);
- m_vc_winners[i].resize(m_num_inports);
-
- m_round_robin_inport[i] = 0;
-
- for (int j = 0; j < m_num_inports; j++) {
- m_port_requests[i][j] = false; // [outport][inport]
- }
- }
-}
-
-/*
- * The wakeup function of the SwitchAllocator performs a 2-stage
- * seperable switch allocation. At the end of the 2nd stage, a free
- * output VC is assigned to the winning flits of each output port.
- * There is no separate VCAllocator stage like the one in garnet1.0.
- * At the end of this function, the router is rescheduled to wakeup
- * next cycle for peforming SA for any flits ready next cycle.
- */
-
-void
-SwitchAllocator::wakeup()
-{
- arbitrate_inports(); // First stage of allocation
- arbitrate_outports(); // Second stage of allocation
-
- clear_request_vector();
- check_for_wakeup();
-}
-
-/*
- * SA-I (or SA-i) loops through all input VCs at every input port,
- * and selects one in a round robin manner.
- * - For HEAD/HEAD_TAIL flits only selects an input VC whose output port
- * has at least one free output VC.
- * - For BODY/TAIL flits, only selects an input VC that has credits
- * in its output VC.
- * Places a request for the output port from this input VC.
- */
-
-void
-SwitchAllocator::arbitrate_inports()
-{
- // Select a VC from each input in a round robin manner
- // Independent arbiter at each input port
- for (int inport = 0; inport < m_num_inports; inport++) {
- int invc = m_round_robin_invc[inport];
-
- for (int invc_iter = 0; invc_iter < m_num_vcs; invc_iter++) {
- auto input_unit = m_router->getInputUnit(inport);
-
- if (input_unit->need_stage(invc, SA_, curTick())) {
- // This flit is in SA stage
-
- int outport = input_unit->get_outport(invc);
- int outvc = input_unit->get_outvc(invc);
-
- // check if the flit in this InputVC is allowed to be sent
- // send_allowed conditions described in that function.
- bool make_request =
- send_allowed(inport, invc, outport, outvc);
-
- if (make_request) {
- m_input_arbiter_activity++;
- m_port_requests[outport][inport] = true;
- m_vc_winners[outport][inport]= invc;
-
- break; // got one vc winner for this port
- }
- }
-
- invc++;
- if (invc >= m_num_vcs)
- invc = 0;
- }
- }
-}
-
-/*
- * SA-II (or SA-o) loops through all output ports,
- * and selects one input VC (that placed a request during SA-I)
- * as the winner for this output port in a round robin manner.
- * - For HEAD/HEAD_TAIL flits, performs simplified outvc allocation.
- * (i.e., select a free VC from the output port).
- * - For BODY/TAIL flits, decrement a credit in the output vc.
- * The winning flit is read out from the input VC and sent to the
- * CrossbarSwitch.
- * An increment_credit signal is sent from the InputUnit
- * to the upstream router. For HEAD_TAIL/TAIL flits, is_free_signal in the
- * credit is set to true.
- */
-
-void
-SwitchAllocator::arbitrate_outports()
-{
- // Now there are a set of input vc requests for output vcs.
- // Again do round robin arbitration on these requests
- // Independent arbiter at each output port
- for (int outport = 0; outport < m_num_outports; outport++) {
- int inport = m_round_robin_inport[outport];
-
- for (int inport_iter = 0; inport_iter < m_num_inports;
- inport_iter++) {
-
- // inport has a request this cycle for outport
- if (m_port_requests[outport][inport]) {
- auto output_unit = m_router->getOutputUnit(outport);
- auto input_unit = m_router->getInputUnit(inport);
-
- // grant this outport to this inport
- int invc = m_vc_winners[outport][inport];
-
- int outvc = input_unit->get_outvc(invc);
- if (outvc == -1) {
- // VC Allocation - select any free VC from outport
- outvc = vc_allocate(outport, inport, invc);
- }
-
- // remove flit from Input VC
- flit *t_flit = input_unit->getTopFlit(invc);
-
- DPRINTF(RubyNetwork, "SwitchAllocator at Router %d "
- "granted outvc %d at outport %d "
- "to invc %d at inport %d to flit %s at "
- "cycle: %lld\n",
- m_router->get_id(), outvc,
- m_router->getPortDirectionName(
- output_unit->get_direction()),
- invc,
- m_router->getPortDirectionName(
- input_unit->get_direction()),
- *t_flit,
- m_router->curCycle());
-
-
- // Update outport field in the flit since this is
- // used by CrossbarSwitch code to send it out of
- // correct outport.
- // Note: post route compute in InputUnit,
- // outport is updated in VC, but not in flit
- t_flit->set_outport(outport);
-
- // set outvc (i.e., invc for next hop) in flit
- // (This was updated in VC by vc_allocate, but not in flit)
- t_flit->set_vc(outvc);
-
- // decrement credit in outvc
- output_unit->decrement_credit(outvc);
-
- // flit ready for Switch Traversal
- t_flit->advance_stage(ST_, curTick());
- m_router->grant_switch(inport, t_flit);
- m_output_arbiter_activity++;
-
- if ((t_flit->get_type() == TAIL_) ||
- t_flit->get_type() == HEAD_TAIL_) {
-
- // This Input VC should now be empty
- assert(!(input_unit->isReady(invc, curTick())));
-
- // Free this VC
- input_unit->set_vc_idle(invc, curTick());
-
- // Send a credit back
- // along with the information that this VC is now idle
- input_unit->increment_credit(invc, true, curTick());
- } else {
- // Send a credit back
- // but do not indicate that the VC is idle
- input_unit->increment_credit(invc, false, curTick());
- }
-
- // remove this request
- m_port_requests[outport][inport] = false;
-
- // Update Round Robin pointer
- m_round_robin_inport[outport] = inport + 1;
- if (m_round_robin_inport[outport] >= m_num_inports)
- m_round_robin_inport[outport] = 0;
-
- // Update Round Robin pointer to the next VC
- // We do it here to keep it fair.
- // Only the VC which got switch traversal
- // is updated.
- m_round_robin_invc[inport] = invc + 1;
- if (m_round_robin_invc[inport] >= m_num_vcs)
- m_round_robin_invc[inport] = 0;
-
-
- break; // got a input winner for this outport
- }
-
- inport++;
- if (inport >= m_num_inports)
- inport = 0;
- }
- }
-}
-
-/*
- * A flit can be sent only if
- * (1) there is at least one free output VC at the
- * output port (for HEAD/HEAD_TAIL),
- * or
- * (2) if there is at least one credit (i.e., buffer slot)
- * within the VC for BODY/TAIL flits of multi-flit packets.
- * and
- * (3) pt-to-pt ordering is not violated in ordered vnets, i.e.,
- * there should be no other flit in this input port
- * within an ordered vnet
- * that arrived before this flit and is requesting the same output port.
- */
-
-bool
-SwitchAllocator::send_allowed(int inport, int invc, int outport, int outvc)
-{
- // Check if outvc needed
- // Check if credit needed (for multi-flit packet)
- // Check if ordering violated (in ordered vnet)
-
- int vnet = get_vnet(invc);
- bool has_outvc = (outvc != -1);
- bool has_credit = false;
-
- auto output_unit = m_router->getOutputUnit(outport);
- if (!has_outvc) {
-
- // needs outvc
- // this is only true for HEAD and HEAD_TAIL flits.
-
- if (output_unit->has_free_vc(vnet)) {
-
- has_outvc = true;
-
- // each VC has at least one buffer,
- // so no need for additional credit check
- has_credit = true;
- }
- } else {
- has_credit = output_unit->has_credit(outvc);
- }
-
- // cannot send if no outvc or no credit.
- if (!has_outvc || !has_credit)
- return false;
-
-
- // protocol ordering check
- if ((m_router->get_net_ptr())->isVNetOrdered(vnet)) {
- auto input_unit = m_router->getInputUnit(inport);
-
- // enqueue time of this flit
- Tick t_enqueue_time = input_unit->get_enqueue_time(invc);
-
- // check if any other flit is ready for SA and for same output port
- // and was enqueued before this flit
- int vc_base = vnet*m_vc_per_vnet;
- for (int vc_offset = 0; vc_offset < m_vc_per_vnet; vc_offset++) {
- int temp_vc = vc_base + vc_offset;
- if (input_unit->need_stage(temp_vc, SA_, curTick()) &&
- (input_unit->get_outport(temp_vc) == outport) &&
- (input_unit->get_enqueue_time(temp_vc) < t_enqueue_time)) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-// Assign a free VC to the winner of the output port.
-int
-SwitchAllocator::vc_allocate(int outport, int inport, int invc)
-{
- // Select a free VC from the output port
- int outvc =
- m_router->getOutputUnit(outport)->select_free_vc(get_vnet(invc));
-
- // has to get a valid VC since it checked before performing SA
- assert(outvc != -1);
- m_router->getInputUnit(inport)->grant_outvc(invc, outvc);
- return outvc;
-}
-
-// Wakeup the router next cycle to perform SA again
-// if there are flits ready.
-void
-SwitchAllocator::check_for_wakeup()
-{
- Tick nextCycle = m_router->clockEdge(Cycles(1));
-
- if (m_router->alreadyScheduled(nextCycle)) {
- return;
- }
-
- for (int i = 0; i < m_num_inports; i++) {
- for (int j = 0; j < m_num_vcs; j++) {
- if (m_router->getInputUnit(i)->need_stage(j, SA_, nextCycle)) {
- m_router->schedule_wakeup(Cycles(1));
- return;
- }
- }
- }
-}
-
-int
-SwitchAllocator::get_vnet(int invc)
-{
- int vnet = invc/m_vc_per_vnet;
- assert(vnet < m_router->get_num_vnets());
- return vnet;
-}
-
-
-// Clear the request vector within the allocator at end of SA-II.
-// Was populated by SA-I.
-void
-SwitchAllocator::clear_request_vector()
-{
- for (int i = 0; i < m_num_outports; i++) {
- for (int j = 0; j < m_num_inports; j++) {
- m_port_requests[i][j] = false;
- }
- }
-}
-
-void
-SwitchAllocator::resetStats()
-{
- m_input_arbiter_activity = 0;
- m_output_arbiter_activity = 0;
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_SWITCHALLOCATOR_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_SWITCHALLOCATOR_HH__
-
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-
-class Router;
-class InputUnit;
-class OutputUnit;
-
-class SwitchAllocator : public Consumer
-{
- public:
- SwitchAllocator(Router *router);
- void wakeup();
- void init();
- void clear_request_vector();
- void check_for_wakeup();
- int get_vnet (int invc);
- void print(std::ostream& out) const {};
- void arbitrate_inports();
- void arbitrate_outports();
- bool send_allowed(int inport, int invc, int outport, int outvc);
- int vc_allocate(int outport, int inport, int invc);
-
- inline double
- get_input_arbiter_activity()
- {
- return m_input_arbiter_activity;
- }
- inline double
- get_output_arbiter_activity()
- {
- return m_output_arbiter_activity;
- }
-
- void resetStats();
-
- private:
- int m_num_inports, m_num_outports;
- int m_num_vcs, m_vc_per_vnet;
-
- double m_input_arbiter_activity, m_output_arbiter_activity;
-
- Router *m_router;
- std::vector<int> m_round_robin_invc;
- std::vector<int> m_round_robin_inport;
- std::vector<std::vector<bool>> m_port_requests;
- std::vector<std::vector<int>> m_vc_winners; // a list for each outport
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_SWITCHALLOCATOR_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
-
-VirtualChannel::VirtualChannel()
- : inputBuffer(), m_vc_state(IDLE_, Tick(0)), m_output_port(-1),
- m_enqueue_time(INFINITE_), m_output_vc(-1)
-{
-}
-
-void
-VirtualChannel::set_idle(Tick curTime)
-{
- m_vc_state.first = IDLE_;
- m_vc_state.second = curTime;
- m_enqueue_time = Tick(INFINITE_);
- m_output_port = -1;
- m_output_vc = -1;
-}
-
-void
-VirtualChannel::set_active(Tick curTime)
-{
- m_vc_state.first = ACTIVE_;
- m_vc_state.second = curTime;
- m_enqueue_time = curTime;
-}
-
-bool
-VirtualChannel::need_stage(flit_stage stage, Tick time)
-{
- if (inputBuffer.isReady(time)) {
- assert(m_vc_state.first == ACTIVE_ && m_vc_state.second <= time);
- flit *t_flit = inputBuffer.peekTopFlit();
- return(t_flit->is_stage(stage, time));
- }
- return false;
-}
-
-uint32_t
-VirtualChannel::functionalWrite(Packet *pkt)
-{
- return inputBuffer.functionalWrite(pkt);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Inria
- * Copyright (c) 2016 Georgia Institute of Technology
- * Copyright (c) 2008 Princeton University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_VIRTUALCHANNEL_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_VIRTUALCHANNEL_HH__
-
-#include <utility>
-
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-class VirtualChannel
-{
- public:
- VirtualChannel();
- ~VirtualChannel() = default;
-
- bool need_stage(flit_stage stage, Tick time);
- void set_idle(Tick curTime);
- void set_active(Tick curTime);
- void set_outvc(int outvc) { m_output_vc = outvc; }
- inline int get_outvc() { return m_output_vc; }
- void set_outport(int outport) { m_output_port = outport; };
- inline int get_outport() { return m_output_port; }
-
- inline Tick get_enqueue_time() { return m_enqueue_time; }
- inline void set_enqueue_time(Tick time) { m_enqueue_time = time; }
- inline VC_state_type get_state() { return m_vc_state.first; }
-
- inline bool
- isReady(Tick curTime)
- {
- return inputBuffer.isReady(curTime);
- }
-
- inline void
- insertFlit(flit *t_flit)
- {
- inputBuffer.insert(t_flit);
- }
-
- inline void
- set_state(VC_state_type m_state, Tick curTime)
- {
- m_vc_state.first = m_state;
- m_vc_state.second = curTime;
- }
-
- inline flit*
- peekTopFlit()
- {
- return inputBuffer.peekTopFlit();
- }
-
- inline flit*
- getTopFlit()
- {
- return inputBuffer.getTopFlit();
- }
-
- uint32_t functionalWrite(Packet *pkt);
-
- private:
- flitBuffer inputBuffer;
- std::pair<VC_state_type, Tick> m_vc_state;
- int m_output_port;
- Tick m_enqueue_time;
- int m_output_vc;
-};
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_VIRTUALCHANNEL_HH__
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-#include "base/intmath.hh"
-#include "debug/RubyNetwork.hh"
-
-// Constructor for the flit
-flit::flit(int id, int vc, int vnet, RouteInfo route, int size,
- MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime)
-{
- m_size = size;
- m_msg_ptr = msg_ptr;
- m_enqueue_time = curTime;
- m_dequeue_time = curTime;
- m_time = curTime;
- m_id = id;
- m_vnet = vnet;
- m_vc = vc;
- m_route = route;
- m_stage.first = I_;
- m_stage.second = curTime;
- m_width = bWidth;
- msgSize = MsgSize;
-
- if (size == 1) {
- m_type = HEAD_TAIL_;
- return;
- }
- if (id == 0)
- m_type = HEAD_;
- else if (id == (size - 1))
- m_type = TAIL_;
- else
- m_type = BODY_;
-}
-
-flit *
-flit::serialize(int ser_id, int parts, uint32_t bWidth)
-{
- assert(m_width > bWidth);
-
- int ratio = (int)divCeil(m_width, bWidth);
- int new_id = (m_id*ratio) + ser_id;
- int new_size = (int)divCeil((float)msgSize, (float)bWidth);
- assert(new_id < new_size);
-
- flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
- new_size, m_msg_ptr, msgSize, bWidth, m_time);
- fl->set_enqueue_time(m_enqueue_time);
- fl->set_src_delay(src_delay);
- return fl;
-}
-
-flit *
-flit::deserialize(int des_id, int num_flits, uint32_t bWidth)
-{
- int ratio = (int)divCeil((float)bWidth, (float)m_width);
- int new_id = ((int)divCeil((float)(m_id+1), (float)ratio)) - 1;
- int new_size = (int)divCeil((float)msgSize, (float)bWidth);
- assert(new_id < new_size);
-
- flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
- new_size, m_msg_ptr, msgSize, bWidth, m_time);
- fl->set_enqueue_time(m_enqueue_time);
- fl->set_src_delay(src_delay);
- return fl;
-}
-
-// Flit can be printed out for debugging purposes
-void
-flit::print(std::ostream& out) const
-{
- out << "[flit:: ";
- out << "Id=" << m_id << " ";
- out << "Type=" << m_type << " ";
- out << "Size=" << m_size << " ";
- out << "Vnet=" << m_vnet << " ";
- out << "VC=" << m_vc << " ";
- out << "Src NI=" << m_route.src_ni << " ";
- out << "Src Router=" << m_route.src_router << " ";
- out << "Dest NI=" << m_route.dest_ni << " ";
- out << "Dest Router=" << m_route.dest_router << " ";
- out << "Set Time=" << m_time << " ";
- out << "Width=" << m_width<< " ";
- out << "]";
-}
-
-bool
-flit::functionalWrite(Packet *pkt)
-{
- Message *msg = m_msg_ptr.get();
- return msg->functionalWrite(pkt);
-}
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_FLIT_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_FLIT_HH__
-
-#include <cassert>
-#include <iostream>
-
-#include "base/types.hh"
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/slicc_interface/Message.hh"
-
-class flit
-{
- public:
- flit() {}
- flit(int id, int vc, int vnet, RouteInfo route, int size,
- MsgPtr msg_ptr, int MsgSize, uint32_t bWidth, Tick curTime);
-
- virtual ~flit(){};
-
- int get_outport() {return m_outport; }
- int get_size() { return m_size; }
- Tick get_enqueue_time() { return m_enqueue_time; }
- Tick get_dequeue_time() { return m_dequeue_time; }
- int get_id() { return m_id; }
- Tick get_time() { return m_time; }
- int get_vnet() { return m_vnet; }
- int get_vc() { return m_vc; }
- RouteInfo get_route() { return m_route; }
- MsgPtr& get_msg_ptr() { return m_msg_ptr; }
- flit_type get_type() { return m_type; }
- std::pair<flit_stage, Tick> get_stage() { return m_stage; }
- Tick get_src_delay() { return src_delay; }
-
- void set_outport(int port) { m_outport = port; }
- void set_time(Tick time) { m_time = time; }
- void set_vc(int vc) { m_vc = vc; }
- void set_route(RouteInfo route) { m_route = route; }
- void set_src_delay(Tick delay) { src_delay = delay; }
- void set_dequeue_time(Tick time) { m_dequeue_time = time; }
- void set_enqueue_time(Tick time) { m_enqueue_time = time; }
-
- void increment_hops() { m_route.hops_traversed++; }
- virtual void print(std::ostream& out) const;
-
- bool
- is_stage(flit_stage stage, Tick time)
- {
- return (stage == m_stage.first &&
- time >= m_stage.second);
- }
-
- void
- advance_stage(flit_stage t_stage, Tick newTime)
- {
- m_stage.first = t_stage;
- m_stage.second = newTime;
- }
-
- static bool
- greater(flit* n1, flit* n2)
- {
- if (n1->get_time() == n2->get_time()) {
- //assert(n1->flit_id != n2->flit_id);
- return (n1->get_id() > n2->get_id());
- } else {
- return (n1->get_time() > n2->get_time());
- }
- }
-
- bool functionalWrite(Packet *pkt);
-
- virtual flit* serialize(int ser_id, int parts, uint32_t bWidth);
- virtual flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
-
- uint32_t m_width;
- int msgSize;
- protected:
- int m_id;
- int m_vnet;
- int m_vc;
- RouteInfo m_route;
- int m_size;
- Tick m_enqueue_time, m_dequeue_time;
- Tick m_time;
- flit_type m_type;
- MsgPtr m_msg_ptr;
- int m_outport;
- Tick src_delay;
- std::pair<flit_stage, Tick> m_stage;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const flit& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_FLIT_HH__
+++ /dev/null
-/*
- * Copyright (c) 2020 Advanced Micro Devices, Inc.
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
-
-flitBuffer::flitBuffer()
-{
- max_size = INFINITE_;
-}
-
-flitBuffer::flitBuffer(int maximum_size)
-{
- max_size = maximum_size;
-}
-
-bool
-flitBuffer::isEmpty()
-{
- return (m_buffer.size() == 0);
-}
-
-bool
-flitBuffer::isReady(Tick curTime)
-{
- if (m_buffer.size() != 0 ) {
- flit *t_flit = peekTopFlit();
- if (t_flit->get_time() <= curTime)
- return true;
- }
- return false;
-}
-
-void
-flitBuffer::print(std::ostream& out) const
-{
- out << "[flitBuffer: " << m_buffer.size() << "] " << std::endl;
-}
-
-bool
-flitBuffer::isFull()
-{
- return (m_buffer.size() >= max_size);
-}
-
-void
-flitBuffer::setMaxSize(int maximum)
-{
- max_size = maximum;
-}
-
-uint32_t
-flitBuffer::functionalWrite(Packet *pkt)
-{
- uint32_t num_functional_writes = 0;
-
- for (unsigned int i = 0; i < m_buffer.size(); ++i) {
- if (m_buffer[i]->functionalWrite(pkt)) {
- num_functional_writes++;
- }
- }
-
- return num_functional_writes;
-}
+++ /dev/null
-/*
- * Copyright (c) 2008 Princeton University
- * Copyright (c) 2016 Georgia Institute of Technology
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef __MEM_RUBY_NETWORK_GARNET2_0_FLITBUFFER_HH__
-#define __MEM_RUBY_NETWORK_GARNET2_0_FLITBUFFER_HH__
-
-#include <algorithm>
-#include <iostream>
-#include <vector>
-
-#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
-#include "mem/ruby/network/garnet2.0/flit.hh"
-
-class flitBuffer
-{
- public:
- flitBuffer();
- flitBuffer(int maximum_size);
-
- bool isReady(Tick curTime);
- bool isEmpty();
- void print(std::ostream& out) const;
- bool isFull();
- void setMaxSize(int maximum);
- int getSize() const { return m_buffer.size(); }
-
- flit *
- getTopFlit()
- {
- flit *f = m_buffer.front();
- std::pop_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
- m_buffer.pop_back();
- return f;
- }
-
- flit *
- peekTopFlit()
- {
- return m_buffer.front();
- }
-
- void
- insert(flit *flt)
- {
- m_buffer.push_back(flt);
- std::push_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
- }
-
- uint32_t functionalWrite(Packet *pkt);
-
- private:
- std::vector<flit *> m_buffer;
- int max_size;
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, const flitBuffer& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif // __MEM_RUBY_NETWORK_GARNET2_0_FLITBUFFER_HH__