mem-ruby: refactored SimpleNetwork routing

The routing algorithm is encapsulated in a separate SimObject to allow
user to implement different routing strategies. The default
implementation (WeightBased) maintains the original behavior.

JIRA: https://gem5.atlassian.net/browse/GEM5-920

Change-Id: I5c8927f358b8b04b2da55e59679c2f629c7cd2f9
Signed-off-by: Tiago Mück <tiago.muck@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/41858
Reviewed-by: Meatboy 106 <garbage2collector@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Tiago Mück
2019-06-11 15:37:06 -05:00
committed by Tiago Muck
parent 528d184ac7
commit c3880c2c46
13 changed files with 397 additions and 105 deletions

View File

@@ -30,6 +30,8 @@
#ifndef __MEM_RUBY_COMMON_TYPEDEFINES_HH__
#define __MEM_RUBY_COMMON_TYPEDEFINES_HH__
#include <string>
namespace gem5
{
@@ -39,6 +41,7 @@ namespace ruby
typedef unsigned int LinkID;
typedef unsigned int NodeID;
typedef unsigned int SwitchID;
typedef std::string PortDirection;
} // namespace ruby
} // namespace gem5

View File

@@ -42,7 +42,6 @@
#define __MEM_RUBY_NETWORK_TOPOLOGY_HH__
#include <iostream>
#include <string>
#include <vector>
#include "mem/ruby/common/TypeDefines.hh"
@@ -65,7 +64,6 @@ class Network;
* represent the source ID, destination ID, and vnet number.
*/
typedef std::vector<std::vector<std::vector<int>>> Matrix;
typedef std::string PortDirection;
struct LinkEntry
{

View File

@@ -59,13 +59,6 @@ namespace ruby
const int PRIORITY_SWITCH_LIMIT = 128;
// Operator for helper class
bool
operator<(const LinkOrder& l1, const LinkOrder& l2)
{
return (l1.m_value < l2.m_value);
}
PerfectSwitch::PerfectSwitch(SwitchID sid, Switch *sw, uint32_t virt_nets)
: Consumer(sw, Switch::PERFECTSWITCH_EV_PRI),
m_switch_id(sid), m_switch(sw)
@@ -101,17 +94,15 @@ PerfectSwitch::addInPort(const std::vector<MessageBuffer*>& in)
void
PerfectSwitch::addOutPort(const std::vector<MessageBuffer*>& out,
const NetDest& routing_table_entry)
const NetDest& routing_table_entry,
const PortDirection &dst_inport)
{
// Setup link order
LinkOrder l;
l.m_value = 0;
l.m_link = m_out.size();
m_link_order.push_back(l);
// Add to routing table
// Add to routing unit
m_switch->getRoutingUnit().addOutPort(m_out.size(),
out,
routing_table_entry,
dst_inport);
m_out.push_back(out);
m_routing_table.push_back(routing_table_entry);
}
PerfectSwitch::~PerfectSwitch()
@@ -167,8 +158,8 @@ PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
Message *net_msg_ptr = NULL;
// temporary vectors to store the routing results
std::vector<LinkID> output_links;
std::vector<NetDest> output_link_destinations;
static thread_local std::vector<BaseRoutingUnit::RouteInfo> output_links;
Tick current_time = m_switch->clockEdge();
while (buffer->isReady(current_time)) {
@@ -179,72 +170,16 @@ PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
net_msg_ptr = msg_ptr.get();
DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
output_links.clear();
output_link_destinations.clear();
NetDest msg_dsts = net_msg_ptr->getDestination();
// Unfortunately, the token-protocol sends some
// zero-destination messages, so this assert isn't valid
// assert(msg_dsts.count() > 0);
assert(m_link_order.size() == m_routing_table.size());
assert(m_link_order.size() == m_out.size());
if (m_network_ptr->getAdaptiveRouting()) {
if (m_network_ptr->isVNetOrdered(vnet)) {
// Don't adaptively route
for (int out = 0; out < m_out.size(); out++) {
m_link_order[out].m_link = out;
m_link_order[out].m_value = 0;
}
} else {
// Find how clogged each link is
for (int out = 0; out < m_out.size(); out++) {
int out_queue_length = 0;
for (int v = 0; v < m_virtual_networks; v++) {
out_queue_length += m_out[out][v]->getSize(current_time);
}
int value =
(out_queue_length << 8) |
random_mt.random(0, 0xff);
m_link_order[out].m_link = out;
m_link_order[out].m_value = value;
}
// Look at the most empty link first
sort(m_link_order.begin(), m_link_order.end());
}
}
for (int i = 0; i < m_routing_table.size(); i++) {
// pick the next link to look at
int link = m_link_order[i].m_link;
NetDest dst = m_routing_table[link];
DPRINTF(RubyNetwork, "dst: %s\n", dst);
if (!msg_dsts.intersectionIsNotEmpty(dst))
continue;
// Remember what link we're using
output_links.push_back(link);
// Need to remember which destinations need this message in
// another vector. This Set is the intersection of the
// routing_table entry and the current destination set. The
// intersection must not be empty, since we are inside "if"
output_link_destinations.push_back(msg_dsts.AND(dst));
// Next, we update the msg_destination not to include
// those nodes that were already handled by this link
msg_dsts.removeNetDest(dst);
}
assert(msg_dsts.count() == 0);
m_switch->getRoutingUnit().route(*net_msg_ptr, vnet,
m_network_ptr->isVNetOrdered(vnet),
output_links);
// Check for resources - for all outgoing queues
bool enough = true;
for (int i = 0; i < output_links.size(); i++) {
int outgoing = output_links[i];
int outgoing = output_links[i].m_link_id;
if (!m_out[outgoing][vnet]->areNSlotsAvailable(1, current_time))
enough = false;
@@ -282,7 +217,7 @@ PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
// Enqueue it - for all outgoing queues
for (int i=0; i<output_links.size(); i++) {
int outgoing = output_links[i];
int outgoing = output_links[i].m_link_id;
if (i > 0) {
// create a private copy of the unmodified message
@@ -292,7 +227,7 @@ PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
// Change the internal destination set of the message so it
// knows which destinations this link is responsible for.
net_msg_ptr = msg_ptr.get();
net_msg_ptr->getDestination() = output_link_destinations[i];
net_msg_ptr->getDestination() = output_links[i].m_destinations;
// Enqeue msg
DPRINTF(RubyNetwork, "Enqueuing net msg from "

View File

@@ -66,14 +66,6 @@ class NetDest;
class SimpleNetwork;
class Switch;
struct LinkOrder
{
int m_link;
int m_value;
};
bool operator<(const LinkOrder& l1, const LinkOrder& l2);
class PerfectSwitch : public Consumer
{
public:
@@ -86,7 +78,8 @@ class PerfectSwitch : public Consumer
void init(SimpleNetwork *);
void addInPort(const std::vector<MessageBuffer*>& in);
void addOutPort(const std::vector<MessageBuffer*>& out,
const NetDest& routing_table_entry);
const NetDest& routing_table_entry,
const PortDirection &dst_inport);
int getInLinks() const { return m_in.size(); }
int getOutLinks() const { return m_out.size(); }
@@ -113,9 +106,6 @@ class PerfectSwitch : public Consumer
std::vector<std::vector<MessageBuffer*> > m_in;
std::vector<std::vector<MessageBuffer*> > m_out;
std::vector<NetDest> m_routing_table;
std::vector<LinkOrder> m_link_order;
uint32_t m_virtual_networks;
int m_wakeups_wo_switch;

View File

@@ -1,5 +1,17 @@
# -*- mode:python -*-
# Copyright (c) 2021 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2009 The Hewlett-Packard Development Company
# All rights reserved.
#
@@ -32,10 +44,13 @@ if env['PROTOCOL'] == 'None':
Return()
SimObject('SimpleLink.py', sim_objects=['SimpleExtLink', 'SimpleIntLink'])
SimObject('SimpleNetwork.py', sim_objects=['SimpleNetwork', 'Switch'])
SimObject('SimpleNetwork.py', sim_objects=['SimpleNetwork', 'BaseRoutingUnit',
'WeightBased', 'Switch'])
Source('PerfectSwitch.cc')
Source('SimpleLink.cc')
Source('SimpleNetwork.cc')
Source('Switch.cc')
Source('Throttle.cc')
Source('routing/WeightBased.cc')

View File

@@ -61,7 +61,6 @@ namespace ruby
SimpleNetwork::SimpleNetwork(const Params &p)
: Network(p), m_buffer_size(p.buffer_size),
m_endpoint_bandwidth(p.endpoint_bandwidth),
m_adaptive_routing(p.adaptive_routing),
networkStats(this)
{
// record the routers
@@ -162,7 +161,8 @@ SimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
m_switches[dest]->addInPort(queues);
m_switches[src]->addOutPort(queues, routing_table_entry[0],
simple_link->m_latency,
simple_link->m_bw_multiplier);
simple_link->m_bw_multiplier,
dst_inport);
}
void

View File

@@ -70,7 +70,6 @@ class SimpleNetwork : public Network
int getBufferSize() { return m_buffer_size; }
int getEndpointBandwidth() { return m_endpoint_bandwidth; }
bool getAdaptiveRouting() {return m_adaptive_routing; }
void collateStats();
void regStats();
@@ -108,7 +107,6 @@ class SimpleNetwork : public Network
int m_num_connected_buffers;
const int m_buffer_size;
const int m_endpoint_bandwidth;
const bool m_adaptive_routing;
struct NetworkStats : public statistics::Group

View File

@@ -39,6 +39,7 @@
from m5.params import *
from m5.proxy import *
from m5.SimObject import SimObject
from m5.objects.Network import RubyNetwork
from m5.objects.BasicRouter import BasicRouter
from m5.objects.MessageBuffer import MessageBuffer
@@ -51,7 +52,6 @@ class SimpleNetwork(RubyNetwork):
buffer_size = Param.Int(0,
"default buffer size; 0 indicates infinite buffering")
endpoint_bandwidth = Param.Int(1000, "bandwidth adjustment factor")
adaptive_routing = Param.Bool(False, "enable adaptive routing")
int_link_buffers = VectorParam.MessageBuffer("Buffers for int_links")
physical_vnets_channels = VectorParam.Int([],
@@ -110,6 +110,22 @@ class SimpleNetwork(RubyNetwork):
buffer_size = self.vnet_buffer_size(i)))
router.port_buffers = router_buffers
class BaseRoutingUnit(SimObject):
type = 'BaseRoutingUnit'
abstract = True
cxx_header = 'mem/ruby/network/simple/routing/BaseRoutingUnit.hh'
cxx_class = 'gem5::ruby::BaseRoutingUnit'
class WeightBased(BaseRoutingUnit):
type = 'WeightBased'
cxx_header = 'mem/ruby/network/simple/routing/WeightBased.hh'
cxx_class = 'gem5::ruby::WeightBased'
adaptive_routing = Param.Bool(False, "enable adaptive routing")
class Switch(BasicRouter):
type = 'Switch'
cxx_header = 'mem/ruby/network/simple/Switch.hh'
@@ -118,3 +134,7 @@ class Switch(BasicRouter):
virt_nets = Param.Int(Parent.number_of_virtual_networks,
"number of virtual networks")
port_buffers = VectorParam.MessageBuffer("Port buffers")
routing_unit = Param.BaseRoutingUnit(
WeightBased(adaptive_routing = False),
"Routing strategy to be used")

View File

@@ -59,7 +59,8 @@ using stl_helpers::operator<<;
Switch::Switch(const Params &p)
: BasicRouter(p),
perfectSwitch(m_id, this, p.virt_nets), m_latency(p.latency),
m_num_connected_buffers(0), switchStats(this)
m_routing_unit(*p.routing_unit), m_num_connected_buffers(0),
switchStats(this)
{
m_port_buffers.reserve(p.port_buffers.size());
for (auto& buffer : p.port_buffers) {
@@ -72,6 +73,7 @@ Switch::init()
{
BasicRouter::init();
perfectSwitch.init(m_network_ptr);
m_routing_unit.init_parent(this);
}
void
@@ -83,7 +85,8 @@ Switch::addInPort(const std::vector<MessageBuffer*>& in)
void
Switch::addOutPort(const std::vector<MessageBuffer*>& out,
const NetDest& routing_table_entry,
Cycles link_latency, int bw_multiplier)
Cycles link_latency, int bw_multiplier,
PortDirection dst_inport)
{
const std::vector<int> &physical_vnets_channels =
m_network_ptr->params().physical_vnets_channels;
@@ -118,7 +121,8 @@ Switch::addOutPort(const std::vector<MessageBuffer*>& out,
}
// Hook the queues to the PerfectSwitch
perfectSwitch.addOutPort(intermediateBuffers, routing_table_entry);
perfectSwitch.addOutPort(intermediateBuffers, routing_table_entry,
dst_inport);
// Hook the queues to the Throttle
throttles.back().addLinks(intermediateBuffers, out);

View File

@@ -61,6 +61,7 @@
#include "mem/ruby/network/BasicRouter.hh"
#include "mem/ruby/network/simple/PerfectSwitch.hh"
#include "mem/ruby/network/simple/Throttle.hh"
#include "mem/ruby/network/simple/routing/BaseRoutingUnit.hh"
#include "mem/ruby/protocol/MessageSizeType.hh"
#include "params/Switch.hh"
@@ -91,7 +92,8 @@ class Switch : public BasicRouter
void addInPort(const std::vector<MessageBuffer*>& in);
void addOutPort(const std::vector<MessageBuffer*>& out,
const NetDest& routing_table_entry,
Cycles link_latency, int bw_multiplier);
Cycles link_latency, int bw_multiplier,
PortDirection dst_inport = "");
void resetStats();
void collateStats();
@@ -110,6 +112,8 @@ class Switch : public BasicRouter
Tick latencyTicks() const { return cyclesToTicks(m_latency); }
BaseRoutingUnit& getRoutingUnit() { return m_routing_unit; }
private:
// Private copy constructor and assignment operator
Switch(const Switch& obj);
@@ -121,6 +125,8 @@ class Switch : public BasicRouter
const Cycles m_latency;
BaseRoutingUnit &m_routing_unit;
unsigned m_num_connected_buffers;
std::vector<MessageBuffer*> m_port_buffers;

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2021 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* 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_SIMPLE_BASEROUTINGUNIT_HH__
#define __MEM_RUBY_NETWORK_SIMPLE_BASEROUTINGUNIT_HH__
#include <vector>
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "params/BaseRoutingUnit.hh"
#include "sim/sim_object.hh"
namespace gem5
{
namespace ruby
{
class Switch;
class BaseRoutingUnit : public SimObject
{
public:
PARAMS(BaseRoutingUnit);
BaseRoutingUnit(const Params &p)
:SimObject(p)
{
}
virtual void addOutPort(LinkID link_id,
const std::vector<MessageBuffer*>& m_out_buffer,
const NetDest& routing_table_entry,
const PortDirection &direction) = 0;
struct RouteInfo
{
RouteInfo(const NetDest &dests, const LinkID link_id)
:m_destinations(dests), m_link_id(link_id)
{}
const NetDest m_destinations;
const LinkID m_link_id;
};
virtual void route(const Message &msg,
int vnet,
bool deterministic,
std::vector<RouteInfo> &out_links) = 0;
void init_parent(Switch *parent_switch)
{ m_parent_switch = parent_switch; }
protected:
Switch *m_parent_switch;
};
} // namespace ruby
} // namespace gem5
#endif // __MEM_RUBY_NETWORK_SIMPLE_BASEROUTINGUNIT_HH__

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2021 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* 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/simple/routing/WeightBased.hh"
#include <algorithm>
#include "base/random.hh"
#include "mem/ruby/network/simple/Switch.hh"
namespace gem5
{
namespace ruby
{
WeightBased::WeightBased(const Params &p)
:BaseRoutingUnit(p)
{
}
void
WeightBased::addOutPort(LinkID link_id,
const std::vector<MessageBuffer*>& m_out_buffer,
const NetDest& routing_table_entry,
const PortDirection &direction)
{
gem5_assert(link_id == m_links.size());
m_links.emplace_back(new LinkInfo{link_id,
routing_table_entry,
m_out_buffer,
static_cast<int>(link_id)});
}
void
WeightBased::route(const Message &msg,
int vnet,
bool deterministic,
std::vector<RouteInfo> &out_links)
{
// Makes sure ordering was reset adaptive option was set
if (params().adaptive_routing) {
if (deterministic) {
// Don't adaptively route
// Makes sure ordering is reset
for (auto &link : m_links)
link->m_order = static_cast<int>(link->m_link_id);
} else {
// Find how clogged each link is
for (auto &link : m_links) {
int out_queue_length = 0;
Tick current_time = m_parent_switch->clockEdge();
for (auto buffer : link->m_out_buffers) {
out_queue_length += buffer->getSize(current_time);
}
// improve load distribution by randomizing order of links
// with the same queue length
link->m_order =
(out_queue_length << 8) | random_mt.random(0, 0xff);
}
}
std::sort(m_links.begin(), m_links.end(),
[](const std::unique_ptr<LinkInfo> &a,
const std::unique_ptr<LinkInfo> &b) {
return a->m_order < b->m_order;
});
}
findRoute(msg, out_links);
}
void
WeightBased::findRoute(const Message &msg,
std::vector<RouteInfo> &out_links) const
{
NetDest msg_dsts = msg.getDestination();
assert(out_links.size() == 0);
for (auto &link : m_links) {
const NetDest &dst = link->m_routing_entry;
if (msg_dsts.intersectionIsNotEmpty(dst)) {
// Need to remember which destinations need this message in
// another vector. This Set is the intersection of the
// routing_table entry and the current destination set.
out_links.emplace_back(msg_dsts.AND(dst), link->m_link_id);
// Next, we update the msg_destination not to include
// those nodes that were already handled by this link
msg_dsts.removeNetDest(dst);
}
}
gem5_assert(msg_dsts.count() == 0);
}
} // namespace ruby
} // namespace gem5

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2021 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* 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_SIMPLE_WEIGHTBASEDROUTINGUNIT_HH__
#define __MEM_RUBY_NETWORK_SIMPLE_WEIGHTBASEDROUTINGUNIT_HH__
#include "mem/ruby/network/simple/routing/BaseRoutingUnit.hh"
#include "params/WeightBased.hh"
namespace gem5
{
namespace ruby
{
class WeightBased : public BaseRoutingUnit
{
public:
PARAMS(WeightBased);
WeightBased(const Params &p);
void addOutPort(LinkID link_id,
const std::vector<MessageBuffer*>& m_out_buffer,
const NetDest& routing_table_entry,
const PortDirection &direction) override;
void route(const Message &msg,
int vnet,
bool deterministic,
std::vector<RouteInfo> &out_links) override;
private:
struct LinkInfo {
const LinkID m_link_id;
const NetDest m_routing_entry;
const std::vector<MessageBuffer*> m_out_buffers;
int m_order;
};
std::vector<std::unique_ptr<LinkInfo>> m_links;
void findRoute(const Message &msg,
std::vector<RouteInfo> &out_links) const;
};
} // namespace ruby
} // namespace gem5
#endif // __MEM_RUBY_NETWORK_SIMPLE_WEIGHTBASEDROUTINGUNIT_HH__