ruby: garnet2.0

Revamped version of garnet with more optimized single-cycle routers,
more configurability, and cleaner code.
This commit is contained in:
Tushar Krishna 2016-10-06 14:35:22 -04:00
parent b512f4bf71
commit dbe8892b76
44 changed files with 4982 additions and 40 deletions

View file

@ -38,25 +38,44 @@ def define_options(parser):
parser.add_option("--topology", type="string", default="Crossbar",
help="check configs/topologies for complete set")
parser.add_option("--mesh-rows", type="int", default=1,
parser.add_option("--mesh-rows", type="int", default=0,
help="the number of rows in the mesh topology")
parser.add_option("--garnet-network", type="choice",
choices=['fixed', 'flexible'], help="'fixed'|'flexible'")
parser.add_option("--network-fault-model", action="store_true", default=False,
help="enable network fault model: see src/mem/ruby/network/fault_model/")
parser.add_option("--network", type="choice", default="simple",
choices=['simple', 'garnet2.0'],
help="'simple'|'garnet2.0'")
parser.add_option("--router-latency", action="store", type="int",
default=1,
help="""number of pipeline stages in the garnet router.
Has to be >= 1.
Can be over-ridden on a per router basis
in the topology file.""")
parser.add_option("--link-latency", action="store", type="int", default=1,
help="""latency of each link the simple/garnet networks.
Has to be >= 1.
Can be over-ridden on a per link basis
in the topology file.""")
parser.add_option("--link-width-bits", action="store", type="int",
default=128,
help="width in bits for all links inside garnet.")
parser.add_option("--vcs-per-vnet", action="store", type="int", default=4,
help="""number of virtual channels per virtual network
inside garnet network.""")
parser.add_option("--routing-algorithm", action="store", type="int",
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""")
parser.add_option("--network-fault-model", action="store_true",
default=False,
help="""enable network fault model:
see src/mem/ruby/network/fault_model/""")
def create_network(options, ruby):
# Set the network classes based on the command line options
if options.garnet_network == "fixed":
NetworkClass = GarnetNetwork_d
IntLinkClass = GarnetIntLink_d
ExtLinkClass = GarnetExtLink_d
RouterClass = GarnetRouter_d
InterfaceClass = GarnetNetworkInterface_d
elif options.garnet_network == "flexible":
if options.network == "garnet2.0":
NetworkClass = GarnetNetwork
IntLinkClass = GarnetIntLink
ExtLinkClass = GarnetExtLink
@ -79,7 +98,13 @@ def create_network(options, ruby):
def init_network(options, network, InterfaceClass):
if options.garnet_network is None:
if options.network == "garnet2.0":
network.num_rows = options.mesh_rows
network.vcs_per_vnet = options.vcs_per_vnet
network.ni_flit_size = options.link_width_bits / 8
network.routing_algorithm = options.routing_algorithm
if options.network == "simple":
network.setup_buffers()
if InterfaceClass != None:
@ -88,6 +113,6 @@ def init_network(options, network, InterfaceClass):
network.netifs = netifs
if options.network_fault_model:
assert(options.garnet_network == "fixed")
assert(options.network == "garnet2.0")
network.enable_fault_model = True
network.fault_model = FaultModel()

View file

@ -35,6 +35,12 @@ class Crossbar(SimpleTopology):
description='Crossbar'
def makeTopology(self, options, network, IntLink, ExtLink, Router):
# default values for link latency and router latency.
# Can be over-ridden on a per link/router basis
link_latency = options.link_latency # used by simple and garnet
router_latency = options.router_latency # only used by garnet
# Create an individual router for each controller plus one more for
# the centralized crossbar. The large numbers of routers are needed
# because external links do not model outgoing bandwidth in the
@ -45,7 +51,8 @@ class Crossbar(SimpleTopology):
xbar = routers[len(self.nodes)] # the crossbar router is the last router created
network.routers = routers
ext_links = [ExtLink(link_id=i, ext_node=n, int_node=routers[i])
ext_links = [ExtLink(link_id=i, ext_node=n, int_node=routers[i],
latency = link_latency)
for (i, n) in enumerate(self.nodes)]
network.ext_links = ext_links
@ -55,13 +62,15 @@ class Crossbar(SimpleTopology):
for i in range(len(self.nodes)):
int_links.append(IntLink(link_id=(link_count+i),
src_node=routers[i],
dst_node=xbar))
dst_node=xbar,
latency = link_latency))
link_count += len(self.nodes)
for i in range(len(self.nodes)):
int_links.append(IntLink(link_id=(link_count+i),
src_node=xbar,
dst_node=routers[i]))
dst_node=routers[i],
latency = link_latency))
network.int_links = int_links

View file

@ -47,6 +47,12 @@ class MeshDirCorners_XY(SimpleTopology):
num_routers = options.num_cpus
num_rows = options.mesh_rows
# default values for link latency and router latency.
# Can be over-ridden on a per link/router basis
link_latency = options.link_latency # used by simple and garnet
router_latency = options.router_latency # only used by garnet
# First determine which nodes are cache cntrls vs. dirs vs. dma
cache_nodes = []
dir_nodes = []
@ -64,7 +70,7 @@ class MeshDirCorners_XY(SimpleTopology):
# and evenly divisible. Also the number of caches must be a
# multiple of the number of routers and the number of directories
# must be four.
assert(num_rows <= num_routers)
assert(num_rows > 0 and num_rows <= num_routers)
num_columns = int(num_routers / num_rows)
assert(num_columns * num_rows == num_routers)
caches_per_router, remainder = divmod(len(cache_nodes), num_routers)
@ -72,7 +78,8 @@ class MeshDirCorners_XY(SimpleTopology):
assert(len(dir_nodes) == 4)
# Create the routers in the mesh
routers = [Router(router_id=i) for i in range(num_routers)]
routers = [Router(router_id=i, latency = router_latency) \
for i in range(num_routers)]
network.routers = routers
# link counter to set unique link ids
@ -84,28 +91,34 @@ class MeshDirCorners_XY(SimpleTopology):
cntrl_level, router_id = divmod(i, num_routers)
assert(cntrl_level < caches_per_router)
ext_links.append(ExtLink(link_id=link_count, ext_node=n,
int_node=routers[router_id]))
int_node=routers[router_id],
latency = link_latency))
link_count += 1
# Connect the dir nodes to the corners.
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[0],
int_node=routers[0]))
int_node=routers[0],
latency = link_latency))
link_count += 1
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[1],
int_node=routers[num_columns - 1]))
int_node=routers[num_columns - 1],
latency = link_latency))
link_count += 1
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[2],
int_node=routers[num_routers - num_columns]))
int_node=routers[num_routers - num_columns],
latency = link_latency))
link_count += 1
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[3],
int_node=routers[num_routers - 1]))
int_node=routers[num_routers - 1],
latency = link_latency))
link_count += 1
# Connect the dma nodes to router 0. These should only be DMA nodes.
for (i, node) in enumerate(dma_nodes):
assert(node.type == 'DMA_Controller')
ext_links.append(ExtLink(link_id=link_count, ext_node=node,
int_node=routers[0]))
int_node=routers[0],
latency = link_latency))
network.ext_links = ext_links
@ -121,6 +134,9 @@ class MeshDirCorners_XY(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[east_out],
dst_node=routers[west_in],
src_outport="East",
dst_inport="West",
latency = link_latency,
weight=1))
link_count += 1
@ -133,6 +149,9 @@ class MeshDirCorners_XY(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[west_out],
dst_node=routers[east_in],
src_outport="West",
dst_inport="East",
latency = link_latency,
weight=1))
link_count += 1
@ -145,6 +164,9 @@ class MeshDirCorners_XY(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[north_out],
dst_node=routers[south_in],
src_outport="North",
dst_inport="South",
latency = link_latency,
weight=2))
link_count += 1
@ -157,6 +179,9 @@ class MeshDirCorners_XY(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[south_out],
dst_node=routers[north_in],
src_outport="South",
dst_inport="North",
latency = link_latency,
weight=2))
link_count += 1

View file

@ -53,15 +53,22 @@ class Mesh_XY(SimpleTopology):
num_routers = options.num_cpus
num_rows = options.mesh_rows
# default values for link latency and router latency.
# Can be over-ridden on a per link/router basis
link_latency = options.link_latency # used by simple and garnet
router_latency = options.router_latency # only used by garnet
# There must be an evenly divisible number of cntrls to routers
# Also, obviously the number or rows must be <= the number of routers
cntrls_per_router, remainder = divmod(len(nodes), num_routers)
assert(num_rows <= num_routers)
assert(num_rows > 0 and num_rows <= num_routers)
num_columns = int(num_routers / num_rows)
assert(num_columns * num_rows == num_routers)
# Create the routers in the mesh
routers = [Router(router_id=i) for i in range(num_routers)]
routers = [Router(router_id=i, latency = router_latency) \
for i in range(num_routers)]
network.routers = routers
# link counter to set unique link ids
@ -83,7 +90,8 @@ class Mesh_XY(SimpleTopology):
cntrl_level, router_id = divmod(i, num_routers)
assert(cntrl_level < cntrls_per_router)
ext_links.append(ExtLink(link_id=link_count, ext_node=n,
int_node=routers[router_id]))
int_node=routers[router_id],
latency = link_latency))
link_count += 1
# Connect the remainding nodes to router 0. These should only be
@ -92,7 +100,8 @@ class Mesh_XY(SimpleTopology):
assert(node.type == 'DMA_Controller')
assert(i < remainder)
ext_links.append(ExtLink(link_id=link_count, ext_node=node,
int_node=routers[0]))
int_node=routers[0],
latency = link_latency))
link_count += 1
network.ext_links = ext_links
@ -111,6 +120,7 @@ class Mesh_XY(SimpleTopology):
dst_node=routers[west_in],
src_outport="East",
dst_inport="West",
latency = link_latency,
weight=1))
link_count += 1
@ -125,6 +135,7 @@ class Mesh_XY(SimpleTopology):
dst_node=routers[east_in],
src_outport="West",
dst_inport="East",
latency = link_latency,
weight=1))
link_count += 1
@ -139,6 +150,7 @@ class Mesh_XY(SimpleTopology):
dst_node=routers[south_in],
src_outport="North",
dst_inport="South",
latency = link_latency,
weight=2))
link_count += 1
@ -153,6 +165,7 @@ class Mesh_XY(SimpleTopology):
dst_node=routers[north_in],
src_outport="South",
dst_inport="North",
latency = link_latency,
weight=2))
link_count += 1

View file

@ -58,15 +58,21 @@ class Mesh_westfirst(SimpleTopology):
num_routers = options.num_cpus
num_rows = options.mesh_rows
# default values for link latency and router latency.
# Can be over-ridden on a per link/router basis
link_latency = options.link_latency # used by simple and garnet
router_latency = options.router_latency # only used by garnet
# There must be an evenly divisible number of cntrls to routers
# Also, obviously the number or rows must be <= the number of routers
cntrls_per_router, remainder = divmod(len(nodes), num_routers)
assert(num_rows <= num_routers)
assert(num_rows > 0 and num_rows <= num_routers)
num_columns = int(num_routers / num_rows)
assert(num_columns * num_rows == num_routers)
# Create the routers in the mesh
routers = [Router(router_id=i) for i in range(num_routers)]
routers = [Router(router_id=i, latency=router_latency) \
for i in range(num_routers)]
network.routers = routers
# link counter to set unique link ids
@ -88,7 +94,8 @@ class Mesh_westfirst(SimpleTopology):
cntrl_level, router_id = divmod(i, num_routers)
assert(cntrl_level < cntrls_per_router)
ext_links.append(ExtLink(link_id=link_count, ext_node=n,
int_node=routers[router_id]))
int_node=routers[router_id],
latency = link_latency))
link_count += 1
# Connect the remainding nodes to router 0. These should only be
@ -97,7 +104,8 @@ class Mesh_westfirst(SimpleTopology):
assert(node.type == 'DMA_Controller')
assert(i < remainder)
ext_links.append(ExtLink(link_id=link_count, ext_node=node,
int_node=routers[0]))
int_node=routers[0],
latency = link_latency))
link_count += 1
network.ext_links = ext_links
@ -114,6 +122,7 @@ class Mesh_westfirst(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[east_out],
dst_node=routers[west_in],
latency = link_latency,
weight=2))
link_count += 1
@ -126,6 +135,7 @@ class Mesh_westfirst(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[west_out],
dst_node=routers[east_in],
latency = link_latency,
weight=1))
link_count += 1
@ -139,6 +149,7 @@ class Mesh_westfirst(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[north_out],
dst_node=routers[south_in],
latency = link_latency,
weight=2))
link_count += 1
@ -151,6 +162,7 @@ class Mesh_westfirst(SimpleTopology):
int_links.append(IntLink(link_id=link_count,
src_node=routers[south_out],
dst_node=routers[north_in],
latency = link_latency,
weight=2))
link_count += 1

View file

@ -42,11 +42,22 @@ class Pt2Pt(SimpleTopology):
def makeTopology(self, options, network, IntLink, ExtLink, Router):
nodes = self.nodes
# Create an individual router for each controller, and connect all to all.
routers = [Router(router_id=i) for i in range(len(nodes))]
# default values for link latency and router latency.
# Can be over-ridden on a per link/router basis
link_latency = options.link_latency # used by simple and garnet
router_latency = options.router_latency # only used by garnet
# Create an individual router for each controller,
# and connect all to all.
# Since this is a high-radix router, router_latency should
# accordingly be set to a higher value than the default
# (which is 1 for mesh routers)
routers = [Router(router_id=i, latency = router_latency) \
for i in range(len(nodes))]
network.routers = routers
ext_links = [ExtLink(link_id=i, ext_node=n, int_node=routers[i])
ext_links = [ExtLink(link_id=i, ext_node=n, int_node=routers[i],
latency = link_latency)
for (i, n) in enumerate(nodes)]
network.ext_links = ext_links
@ -58,6 +69,7 @@ class Pt2Pt(SimpleTopology):
link_count += 1
int_links.append(IntLink(link_id=link_count,
src_node=routers[i],
dst_node=routers[j]))
dst_node=routers[j],
latency = link_latency))
network.int_links = int_links

View file

@ -180,8 +180,8 @@ Info::setName(const string &name)
bool result = p.second;
if (!result) {
// using other->name instead of just name to avoid a compiler
// warning. They should be the same.
// using other->name instead of just name to avoid a compiler
// warning. They should be the same.
panic("same statistic name used twice! name=%s\n", other->name);
}

View file

@ -34,4 +34,6 @@ class BasicRouter(ClockedObject):
type = 'BasicRouter'
cxx_header = "mem/ruby/network/BasicRouter.hh"
router_id = Param.Int("ID in relation to other routers")
# only used by garnet
latency = Param.Cycles(1, "number of cycles inside router")

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_COMMONTYPES_HH__
#define __MEM_RUBY_NETWORK_GARNET_COMMONTYPES_HH__
#include "mem/ruby/common/NetDest.hh"
// All common enums and typedefs go here
enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_, NUM_FLIT_TYPE_};
enum VC_state_type {IDLE_, VC_AB_, ACTIVE_, NUM_VC_STATE_TYPE_};
enum VNET_type {CTRL_VNET_, DATA_VNET_, NULL_VNET_, NUM_VNET_TYPE_};
enum flit_stage {I_, VA_, SA_, ST_, LT_, NUM_FLIT_STAGE_};
enum link_type { EXT_IN_, EXT_OUT_, INT_, NUM_LINK_TYPES_ };
enum RoutingAlgorithm { TABLE_ = 0, XY_ = 1, CUSTOM_ = 2,
NUM_ROUTING_ALGORITHM_};
struct RouteInfo
{
// destination format for table-based routing
int vnet;
NetDest net_dest;
// src and dest format for topology-specific routing
int src_ni;
int src_router;
int dest_ni;
int dest_router;
int hops_traversed;
};
#define INFINITE_ 10000
#endif // __MEM_RUBY_NETWORK_GARNET_COMMONTYPES_HH__

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/Credit.hh"
// Credit Signal for buffers inside VC
// Carries m_vc (inherits from flit.hh)
// and m_is_free_signal (whether VC is free or not)
Credit::Credit(int vc, bool is_free_signal, Cycles curTime)
{
m_id = 0;
m_vc = vc;
m_is_free_signal = is_free_signal;
m_time = curTime;
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_CREDIT_HH__
#define __MEM_RUBY_NETWORK_GARNET_CREDIT_HH__
#include <cassert>
#include <iostream>
#include "base/types.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/flit.hh"
// Credit Signal for buffers inside VC
// Carries m_vc (inherits from flit.hh)
// and m_is_free_signal (whether VC is free or not)
class Credit : public flit
{
public:
Credit() {};
Credit(int vc, bool is_free_signal, Cycles curTime);
bool is_free_signal() { return m_is_free_signal; }
private:
bool m_is_free_signal;
};
#endif // __MEM_RUBY_NETWORK_GARNET_CREDIT_HH__

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_CREDIT_LINK_HH__
#define __MEM_RUBY_NETWORK_GARNET_CREDIT_LINK_HH__
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "params/CreditLink.hh"
class CreditLink : public NetworkLink
{
public:
typedef CreditLinkParams Params;
CreditLink(const Params *p) : NetworkLink(p) {}
};
#endif // __MEM_RUBY_NETWORK_GARNET_CREDIT_LINK_HH__

View file

@ -0,0 +1,112 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
#include "base/stl_helpers.hh"
#include "debug/RubyNetwork.hh"
#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
using m5::stl_helpers::deletePointers;
CrossbarSwitch::CrossbarSwitch(Router *router)
: Consumer(router)
{
m_router = router;
m_num_vcs = m_router->get_num_vcs();
m_crossbar_activity = 0;
}
CrossbarSwitch::~CrossbarSwitch()
{
deletePointers(m_switch_buffer);
}
void
CrossbarSwitch::init()
{
m_output_unit = m_router->get_outputUnit_ref();
m_num_inports = m_router->get_num_inports();
m_switch_buffer.resize(m_num_inports);
for (int i = 0; i < m_num_inports; i++) {
m_switch_buffer[i] = new flitBuffer();
}
}
/*
* The wakeup function of the CrossbarSwitch loops through all input ports,
* and sends the winning flit (from SA) out of its output port on to the
* output link. The output link is scheduled for wakeup in the next cycle.
*/
void
CrossbarSwitch::wakeup()
{
DPRINTF(RubyNetwork, "CrossbarSwitch at Router %d woke up "
"at time: %lld\n",
m_router->get_id(), m_router->curCycle());
for (int inport = 0; inport < m_num_inports; inport++) {
if (!m_switch_buffer[inport]->isReady(m_router->curCycle()))
continue;
flit *t_flit = m_switch_buffer[inport]->peekTopFlit();
if (t_flit->is_stage(ST_, m_router->curCycle())) {
int outport = t_flit->get_outport();
// flit performs LT_ in the next cycle
t_flit->advance_stage(LT_, m_router->curCycle() + Cycles(1));
t_flit->set_time(m_router->curCycle() + Cycles(1));
// This will take care of waking up the Network Link
// in the next cycle
m_output_unit[outport]->insert_flit(t_flit);
m_switch_buffer[inport]->getTopFlit();
m_crossbar_activity++;
}
}
}
uint32_t
CrossbarSwitch::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
for (uint32_t i = 0; i < m_switch_buffer.size(); ++i) {
num_functional_writes += m_switch_buffer[i]->functionalWrite(pkt);
}
return num_functional_writes;
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_CROSSBAR_SWITCH_HH__
#define __MEM_RUBY_NETWORK_GARNET_CROSSBAR_SWITCH_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
class Router;
class OutputUnit;
class CrossbarSwitch : public Consumer
{
public:
CrossbarSwitch(Router *router);
~CrossbarSwitch();
void wakeup();
void init();
void print(std::ostream& out) const {};
inline void update_sw_winner(int inport, flit *t_flit)
{ m_switch_buffer[inport]->insert(t_flit); }
inline double get_crossbar_activity() { return m_crossbar_activity; }
uint32_t functionalWrite(Packet *pkt);
private:
int m_num_vcs;
int m_num_inports;
double m_crossbar_activity;
Router *m_router;
std::vector<flitBuffer *> m_switch_buffer;
std::vector<OutputUnit *> m_output_unit;
};
#endif // __MEM_RUBY_NETWORK_GARNET_CROSSBAR_SWITCH_HH__

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
GarnetIntLink::GarnetIntLink(const Params *p)
: BasicLink(p)
{
// Uni-directional
m_network_link = p->network_link;
m_credit_link = p->credit_link;
}
void
GarnetIntLink::init()
{
}
void
GarnetIntLink::print(std::ostream& out) const
{
out << name();
}
GarnetIntLink *
GarnetIntLinkParams::create()
{
return new GarnetIntLink(this);
}
GarnetExtLink::GarnetExtLink(const Params *p)
: BasicLink(p)
{
// Bi-directional
// In
m_network_links[0] = p->network_links[0];
m_credit_links[0] = p->credit_links[0];
// Out
m_network_links[1] = p->network_links[1];
m_credit_links[1] = p->credit_links[1];
}
void
GarnetExtLink::init()
{
}
void
GarnetExtLink::print(std::ostream& out) const
{
out << name();
}
GarnetExtLink *
GarnetExtLinkParams::create()
{
return new GarnetExtLink(this);
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_LINK_HH__
#define __MEM_RUBY_NETWORK_GARNET_LINK_HH__
#include <iostream>
#include <string>
#include <vector>
#include "mem/ruby/network/BasicLink.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "params/GarnetExtLink.hh"
#include "params/GarnetIntLink.hh"
class GarnetIntLink : public BasicLink
{
public:
typedef GarnetIntLinkParams Params;
GarnetIntLink(const Params *p);
void init();
void print(std::ostream& out) const;
friend class GarnetNetwork;
protected:
NetworkLink* m_network_link;
CreditLink* m_credit_link;
};
inline std::ostream&
operator<<(std::ostream& out, const GarnetIntLink& obj)
{
obj.print(out);
out << std::flush;
return out;
}
class GarnetExtLink : public BasicLink
{
public:
typedef GarnetExtLinkParams Params;
GarnetExtLink(const Params *p);
void init();
void print(std::ostream& out) const;
friend class GarnetNetwork;
protected:
NetworkLink* m_network_links[2];
CreditLink* m_credit_links[2];
};
inline std::ostream&
operator<<(std::ostream& out, const GarnetExtLink& obj)
{
obj.print(out);
out << std::flush;
return out;
}
#endif // __MEM_RUBY_NETWORK_GARNET_LINK_HH__

View file

@ -0,0 +1,79 @@
# Copyright (c) 2008 Princeton University
# Copyright (c) 2009 Advanced Micro Devices, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Steve Reinhardt
# Brad Beckmann
from m5.params import *
from m5.proxy import *
from ClockedObject import ClockedObject
from BasicLink import BasicIntLink, BasicExtLink
class NetworkLink(ClockedObject):
type = 'NetworkLink'
cxx_header = "mem/ruby/network/garnet2.0/NetworkLink.hh"
link_id = Param.Int(Parent.link_id, "link id")
link_latency = Param.Cycles(Parent.latency, "link latency")
vcs_per_vnet = Param.Int(Parent.vcs_per_vnet,
"virtual channels per virtual network")
virt_nets = Param.Int(Parent.number_of_virtual_networks,
"number of virtual networks")
class CreditLink(NetworkLink):
type = 'CreditLink'
cxx_header = "mem/ruby/network/garnet2.0/CreditLink.hh"
# Interior fixed pipeline links between routers
class GarnetIntLink(BasicIntLink):
type = 'GarnetIntLink'
cxx_header = "mem/ruby/network/garnet2.0/GarnetLink.hh"
# The internal link includes one forward link (for flit)
# and one backward flow-control link (for credit)
network_link = Param.NetworkLink(NetworkLink(), "forward link")
credit_link = Param.CreditLink(CreditLink(), "backward flow-control link")
# Exterior fixed pipeline links between a router and a controller
class GarnetExtLink(BasicExtLink):
type = 'GarnetExtLink'
cxx_header = "mem/ruby/network/garnet2.0/GarnetLink.hh"
# The external link is bi-directional.
# It includes two forward links (for flits)
# and two backward flow-control links (for credits),
# one per direction
_nls = []
# In uni-directional link
_nls.append(NetworkLink());
# Out uni-directional link
_nls.append(NetworkLink());
network_links = VectorParam.NetworkLink(_nls, "forward links")
_cls = []
# In uni-directional link
_cls.append(CreditLink());
# Out uni-directional link
_cls.append(CreditLink());
credit_links = VectorParam.CreditLink(_cls, "backward flow-control links")

View file

@ -0,0 +1,460 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
#include <cassert>
#include "base/cast.hh"
#include "base/stl_helpers.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/network/MessageBuffer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/GarnetLink.hh"
#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
#include "mem/ruby/system/RubySystem.hh"
using namespace std;
using m5::stl_helpers::deletePointers;
/*
* GarnetNetwork sets up the routers and links and collects stats.
* Default parameters (GarnetNetwork.py) can be overwritten from command line
* (see configs/network/Network.py)
*/
GarnetNetwork::GarnetNetwork(const Params *p)
: Network(p)
{
m_num_rows = p->num_rows;
m_ni_flit_size = p->ni_flit_size;
m_vcs_per_vnet = p->vcs_per_vnet;
m_buffers_per_data_vc = p->buffers_per_data_vc;
m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
m_routing_algorithm = p->routing_algorithm;
m_enable_fault_model = p->enable_fault_model;
if (m_enable_fault_model)
fault_model = p->fault_model;
m_vnet_type.resize(m_virtual_networks);
for (int i = 0 ; i < m_virtual_networks ; i++) {
if (m_vnet_type_names[i] == "response")
m_vnet_type[i] = DATA_VNET_; // carries data (and ctrl) packets
else
m_vnet_type[i] = CTRL_VNET_; // carries only ctrl packets
}
// record the routers
for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
i != p->routers.end(); ++i) {
Router* router = safe_cast<Router*>(*i);
m_routers.push_back(router);
// initialize the router's network pointers
router->init_net_ptr(this);
}
// record the network interfaces
for (vector<ClockedObject*>::const_iterator i = p->netifs.begin();
i != p->netifs.end(); ++i) {
NetworkInterface *ni = safe_cast<NetworkInterface *>(*i);
m_nis.push_back(ni);
ni->init_net_ptr(this);
}
}
void
GarnetNetwork::init()
{
Network::init();
for (int i=0; i < m_nodes; i++) {
m_nis[i]->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
}
// The topology pointer should have already been initialized in the
// parent network constructor
assert(m_topology_ptr != NULL);
m_topology_ptr->createLinks(this);
// Initialize topology specific parameters
if (getNumRows() > 0) {
// Only for Mesh topology
// m_num_rows and m_num_cols are only used for
// implementing XY or custom routing in RoutingUnit.cc
m_num_rows = getNumRows();
m_num_cols = m_routers.size() / m_num_rows;
assert(m_num_rows * m_num_cols == m_routers.size());
} else {
m_num_rows = -1;
m_num_cols = -1;
}
// FaultModel: declare each router to the fault model
if (isFaultModelEnabled()) {
for (vector<Router*>::const_iterator i= m_routers.begin();
i != m_routers.end(); ++i) {
Router* router = safe_cast<Router*>(*i);
int router_id M5_VAR_USED =
fault_model->declare_router(router->get_num_inports(),
router->get_num_outports(),
router->get_vc_per_vnet(),
getBuffersPerDataVC(),
getBuffersPerCtrlVC());
assert(router_id == router->get_id());
router->printAggregateFaultProbability(cout);
router->printFaultVector(cout);
}
}
}
GarnetNetwork::~GarnetNetwork()
{
deletePointers(m_routers);
deletePointers(m_nis);
deletePointers(m_networklinks);
deletePointers(m_creditlinks);
}
/*
* This function creates a link from the Network Interface (NI)
* into the Network.
* It creates a Network Link from the NI to a Router and a Credit Link from
* the Router to the NI
*/
void
GarnetNetwork::makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
const NetDest& routing_table_entry)
{
assert(src < m_nodes);
GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
// GarnetExtLink is bi-directional
NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_In];
net_link->setType(EXT_IN_);
CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_In];
m_networklinks.push_back(net_link);
m_creditlinks.push_back(credit_link);
PortDirection dst_inport_dirn = "Local";
m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
m_nis[src]->addOutPort(net_link, credit_link, dest);
}
/*
* This function creates a link from the Network to a NI.
* It creates a Network Link from a Router to the NI and
* a Credit Link from NI to the Router
*/
void
GarnetNetwork::makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
const NetDest& routing_table_entry)
{
assert(dest < m_nodes);
assert(src < m_routers.size());
assert(m_routers[src] != NULL);
GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
// GarnetExtLink is bi-directional
NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_Out];
net_link->setType(EXT_OUT_);
CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_Out];
m_networklinks.push_back(net_link);
m_creditlinks.push_back(credit_link);
PortDirection src_outport_dirn = "Local";
m_routers[src]->addOutPort(src_outport_dirn, net_link,
routing_table_entry,
link->m_weight, credit_link);
m_nis[dest]->addInPort(net_link, credit_link);
}
/*
* This function creates an internal network link between two routers.
* It adds both the network link and an opposite credit link.
*/
void
GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
const NetDest& routing_table_entry,
PortDirection src_outport_dirn,
PortDirection dst_inport_dirn)
{
GarnetIntLink* garnet_link = safe_cast<GarnetIntLink*>(link);
// GarnetIntLink is unidirectional
NetworkLink* net_link = garnet_link->m_network_link;
net_link->setType(INT_);
CreditLink* credit_link = garnet_link->m_credit_link;
m_networklinks.push_back(net_link);
m_creditlinks.push_back(credit_link);
m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
m_routers[src]->addOutPort(src_outport_dirn, net_link,
routing_table_entry,
link->m_weight, credit_link);
}
// Total routers in the network
int
GarnetNetwork::getNumRouters()
{
return m_routers.size();
}
// Get ID of router connected to a NI.
int
GarnetNetwork::get_router_id(int ni)
{
return m_nis[ni]->get_router_id();
}
void
GarnetNetwork::regStats()
{
Network::regStats();
// Packets
m_packets_received
.init(m_virtual_networks)
.name(name() + ".packets_received")
.flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
;
m_packets_injected
.init(m_virtual_networks)
.name(name() + ".packets_injected")
.flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
;
m_packet_network_latency
.init(m_virtual_networks)
.name(name() + ".packet_network_latency")
.flags(Stats::oneline)
;
m_packet_queueing_latency
.init(m_virtual_networks)
.name(name() + ".packet_queueing_latency")
.flags(Stats::oneline)
;
for (int i = 0; i < m_virtual_networks; i++) {
m_packets_received.subname(i, csprintf("vnet-%i", i));
m_packets_injected.subname(i, csprintf("vnet-%i", i));
m_packet_network_latency.subname(i, csprintf("vnet-%i", i));
m_packet_queueing_latency.subname(i, csprintf("vnet-%i", i));
}
m_avg_packet_vnet_latency
.name(name() + ".average_packet_vnet_latency")
.flags(Stats::oneline);
m_avg_packet_vnet_latency =
m_packet_network_latency / m_packets_received;
m_avg_packet_vqueue_latency
.name(name() + ".average_packet_vqueue_latency")
.flags(Stats::oneline);
m_avg_packet_vqueue_latency =
m_packet_queueing_latency / m_packets_received;
m_avg_packet_network_latency
.name(name() + ".average_packet_network_latency");
m_avg_packet_network_latency =
sum(m_packet_network_latency) / sum(m_packets_received);
m_avg_packet_queueing_latency
.name(name() + ".average_packet_queueing_latency");
m_avg_packet_queueing_latency
= sum(m_packet_queueing_latency) / sum(m_packets_received);
m_avg_packet_latency
.name(name() + ".average_packet_latency");
m_avg_packet_latency
= m_avg_packet_network_latency + m_avg_packet_queueing_latency;
// Flits
m_flits_received
.init(m_virtual_networks)
.name(name() + ".flits_received")
.flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
;
m_flits_injected
.init(m_virtual_networks)
.name(name() + ".flits_injected")
.flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
;
m_flit_network_latency
.init(m_virtual_networks)
.name(name() + ".flit_network_latency")
.flags(Stats::oneline)
;
m_flit_queueing_latency
.init(m_virtual_networks)
.name(name() + ".flit_queueing_latency")
.flags(Stats::oneline)
;
for (int i = 0; i < m_virtual_networks; i++) {
m_flits_received.subname(i, csprintf("vnet-%i", i));
m_flits_injected.subname(i, csprintf("vnet-%i", i));
m_flit_network_latency.subname(i, csprintf("vnet-%i", i));
m_flit_queueing_latency.subname(i, csprintf("vnet-%i", i));
}
m_avg_flit_vnet_latency
.name(name() + ".average_flit_vnet_latency")
.flags(Stats::oneline);
m_avg_flit_vnet_latency = m_flit_network_latency / m_flits_received;
m_avg_flit_vqueue_latency
.name(name() + ".average_flit_vqueue_latency")
.flags(Stats::oneline);
m_avg_flit_vqueue_latency =
m_flit_queueing_latency / m_flits_received;
m_avg_flit_network_latency
.name(name() + ".average_flit_network_latency");
m_avg_flit_network_latency =
sum(m_flit_network_latency) / sum(m_flits_received);
m_avg_flit_queueing_latency
.name(name() + ".average_flit_queueing_latency");
m_avg_flit_queueing_latency =
sum(m_flit_queueing_latency) / sum(m_flits_received);
m_avg_flit_latency
.name(name() + ".average_flit_latency");
m_avg_flit_latency =
m_avg_flit_network_latency + m_avg_flit_queueing_latency;
// Hops
m_avg_hops.name(name() + ".average_hops");
m_avg_hops = m_total_hops / sum(m_flits_received);
// Links
m_total_ext_in_link_utilization
.name(name() + ".ext_in_link_utilization");
m_total_ext_out_link_utilization
.name(name() + ".ext_out_link_utilization");
m_total_int_link_utilization
.name(name() + ".int_link_utilization");
m_average_link_utilization
.name(name() + ".avg_link_utilization");
m_average_vc_load
.init(m_virtual_networks * m_vcs_per_vnet)
.name(name() + ".avg_vc_load")
.flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
;
}
void
GarnetNetwork::collateStats()
{
RubySystem *rs = params()->ruby_system;
double time_delta = double(curCycle() - rs->getStartCycle());
for (int i = 0; i < m_networklinks.size(); i++) {
link_type type = m_networklinks[i]->getType();
int activity = m_networklinks[i]->getLinkUtilization();
if (type == EXT_IN_)
m_total_ext_in_link_utilization += activity;
else if (type == EXT_OUT_)
m_total_ext_out_link_utilization += activity;
else if (type == INT_)
m_total_int_link_utilization += activity;
m_average_link_utilization +=
(double(activity) / time_delta);
vector<unsigned int> vc_load = m_networklinks[i]->getVcLoad();
for (int j = 0; j < vc_load.size(); j++) {
m_average_vc_load[j] += ((double)vc_load[j] / time_delta);
}
}
// Ask the routers to collate their statistics
for (int i = 0; i < m_routers.size(); i++) {
m_routers[i]->collateStats();
}
}
void
GarnetNetwork::print(ostream& out) const
{
out << "[GarnetNetwork]";
}
GarnetNetwork *
GarnetNetworkParams::create()
{
return new GarnetNetwork(this);
}
uint32_t
GarnetNetwork::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
for (unsigned int i = 0; i < m_routers.size(); i++) {
num_functional_writes += m_routers[i]->functionalWrite(pkt);
}
for (unsigned int i = 0; i < m_nis.size(); ++i) {
num_functional_writes += m_nis[i]->functionalWrite(pkt);
}
for (unsigned int i = 0; i < m_networklinks.size(); ++i) {
num_functional_writes += m_networklinks[i]->functionalWrite(pkt);
}
return num_functional_writes;
}

View file

@ -0,0 +1,208 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_NETWORK_HH__
#define __MEM_RUBY_NETWORK_GARNET_NETWORK_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/network/fault_model/FaultModel.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "params/GarnetNetwork.hh"
class FaultModel;
class NetworkInterface;
class Router;
class NetDest;
class NetworkLink;
class CreditLink;
class GarnetNetwork : public Network
{
public:
typedef GarnetNetworkParams Params;
GarnetNetwork(const Params *p);
~GarnetNetwork();
void init();
// Configuration (set externally)
// for 2D topology
int getNumRows() const { return m_num_rows; }
int getNumCols() { return m_num_cols; }
// for network
uint32_t getNiFlitSize() const { return m_ni_flit_size; }
uint32_t getVCsPerVnet() const { return m_vcs_per_vnet; }
uint32_t getBuffersPerDataVC() { return m_buffers_per_data_vc; }
uint32_t getBuffersPerCtrlVC() { return m_buffers_per_ctrl_vc; }
int getRoutingAlgorithm() const { return m_routing_algorithm; }
bool isFaultModelEnabled() const { return m_enable_fault_model; }
FaultModel* fault_model;
// Internal configuration
bool isVNetOrdered(int vnet) const { return m_ordered[vnet]; }
VNET_type
get_vnet_type(int vc)
{
int vnet = vc/getVCsPerVnet();
return m_vnet_type[vnet];
}
int getNumRouters();
int get_router_id(int ni);
// Methods used by Topology to setup the network
void makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
const NetDest& routing_table_entry);
void makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
const NetDest& routing_table_entry);
void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
const NetDest& routing_table_entry,
PortDirection src_outport_dirn,
PortDirection dest_inport_dirn);
//! Function for performing a functional write. The return value
//! indicates the number of messages that were written.
uint32_t functionalWrite(Packet *pkt);
// Stats
void collateStats();
void regStats();
void print(std::ostream& out) const;
// increment counters
void increment_injected_packets(int vnet) { m_packets_injected[vnet]++; }
void increment_received_packets(int vnet) { m_packets_received[vnet]++; }
void
increment_packet_network_latency(Cycles latency, int vnet)
{
m_packet_network_latency[vnet] += latency;
}
void
increment_packet_queueing_latency(Cycles latency, int vnet)
{
m_packet_queueing_latency[vnet] += latency;
}
void increment_injected_flits(int vnet) { m_flits_injected[vnet]++; }
void increment_received_flits(int vnet) { m_flits_received[vnet]++; }
void
increment_flit_network_latency(Cycles latency, int vnet)
{
m_flit_network_latency[vnet] += latency;
}
void
increment_flit_queueing_latency(Cycles latency, int vnet)
{
m_flit_queueing_latency[vnet] += latency;
}
void
increment_total_hops(int hops)
{
m_total_hops += hops;
}
protected:
// Configuration
int m_num_rows;
int m_num_cols;
uint32_t m_ni_flit_size;
uint32_t m_vcs_per_vnet;
uint32_t m_buffers_per_ctrl_vc;
uint32_t m_buffers_per_data_vc;
int m_routing_algorithm;
bool m_enable_fault_model;
// Statistical variables
Stats::Vector m_packets_received;
Stats::Vector m_packets_injected;
Stats::Vector m_packet_network_latency;
Stats::Vector m_packet_queueing_latency;
Stats::Formula m_avg_packet_vnet_latency;
Stats::Formula m_avg_packet_vqueue_latency;
Stats::Formula m_avg_packet_network_latency;
Stats::Formula m_avg_packet_queueing_latency;
Stats::Formula m_avg_packet_latency;
Stats::Vector m_flits_received;
Stats::Vector m_flits_injected;
Stats::Vector m_flit_network_latency;
Stats::Vector m_flit_queueing_latency;
Stats::Formula m_avg_flit_vnet_latency;
Stats::Formula m_avg_flit_vqueue_latency;
Stats::Formula m_avg_flit_network_latency;
Stats::Formula m_avg_flit_queueing_latency;
Stats::Formula m_avg_flit_latency;
Stats::Scalar m_total_ext_in_link_utilization;
Stats::Scalar m_total_ext_out_link_utilization;
Stats::Scalar m_total_int_link_utilization;
Stats::Scalar m_average_link_utilization;
Stats::Vector m_average_vc_load;
Stats::Scalar m_total_hops;
Stats::Formula m_avg_hops;
private:
GarnetNetwork(const GarnetNetwork& obj);
GarnetNetwork& operator=(const GarnetNetwork& obj);
std::vector<VNET_type > m_vnet_type;
std::vector<Router *> m_routers; // All Routers in Network
std::vector<NetworkLink *> m_networklinks; // All flit links in the network
std::vector<CreditLink *> m_creditlinks; // All credit links in the network
std::vector<NetworkInterface *> m_nis; // All NI's in Network
};
inline std::ostream&
operator<<(std::ostream& out, const GarnetNetwork& obj)
{
obj.print(out);
out << std::flush;
return out;
}
#endif // __MEM_RUBY_NETWORK_GARNET_NETWORK_HH__

View file

@ -0,0 +1,68 @@
# Copyright (c) 2008 Princeton University
# Copyright (c) 2009 Advanced Micro Devices, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Tushar Krishna
#
from m5.params import *
from m5.proxy import *
from Network import RubyNetwork
from BasicRouter import BasicRouter
from ClockedObject import ClockedObject
class GarnetNetwork(RubyNetwork):
type = 'GarnetNetwork'
cxx_header = "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
num_rows = Param.Int(0, "number of rows if 2D (mesh/torus/..) topology");
ni_flit_size = Param.UInt32(16, "network interface flit size in bytes")
vcs_per_vnet = Param.UInt32(4, "virtual channels per virtual network");
buffers_per_data_vc = Param.UInt32(4, "buffers per data virtual channel");
buffers_per_ctrl_vc = Param.UInt32(1, "buffers per ctrl virtual channel");
routing_algorithm = Param.Int(0,
"0: Weight-based Table, 1: XY, 2: Custom");
enable_fault_model = Param.Bool(False, "enable network fault model");
fault_model = Param.FaultModel(NULL, "network fault model");
class GarnetNetworkInterface(ClockedObject):
type = 'GarnetNetworkInterface'
cxx_class = 'NetworkInterface'
cxx_header = "mem/ruby/network/garnet2.0/NetworkInterface.hh"
id = Param.UInt32("ID in relation to other network interfaces")
vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
"virtual channels per virtual network")
virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
"number of virtual networks")
class GarnetRouter(BasicRouter):
type = 'GarnetRouter'
cxx_class = 'Router'
cxx_header = "mem/ruby/network/garnet2.0/Router.hh"
vcs_per_vnet = Param.UInt32(Parent.vcs_per_vnet,
"virtual channels per virtual network")
virt_nets = Param.UInt32(Parent.number_of_virtual_networks,
"number of virtual networks")

View file

@ -0,0 +1,171 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/InputUnit.hh"
#include "base/stl_helpers.hh"
#include "debug/RubyNetwork.hh"
#include "mem/ruby/network/garnet2.0/Credit.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
using namespace std;
using m5::stl_helpers::deletePointers;
InputUnit::InputUnit(int id, PortDirection direction, Router *router)
: Consumer(router)
{
m_id = id;
m_direction = direction;
m_router = router;
m_num_vcs = m_router->get_num_vcs();
m_vc_per_vnet = m_router->get_vc_per_vnet();
m_num_buffer_reads.resize(m_num_vcs/m_vc_per_vnet);
m_num_buffer_writes.resize(m_num_vcs/m_vc_per_vnet);
for (int i = 0; i < m_num_buffer_reads.size(); i++) {
m_num_buffer_reads[i] = 0;
m_num_buffer_writes[i] = 0;
}
creditQueue = new flitBuffer();
// Instantiating the virtual channels
m_vcs.resize(m_num_vcs);
for (int i=0; i < m_num_vcs; i++) {
m_vcs[i] = new VirtualChannel(i);
}
}
InputUnit::~InputUnit()
{
delete creditQueue;
deletePointers(m_vcs);
}
/*
* The InputUnit wakeup function reads the input flit from its input link.
* Each flit arrives with an input VC.
* For HEAD/HEAD_TAIL flits, performs route computation,
* and updates route in the input VC.
* The flit is buffered for (m_latency - 1) cycles in the input VC
* and marked as valid for SwitchAllocation starting that cycle.
*
*/
void
InputUnit::wakeup()
{
flit *t_flit;
if (m_in_link->isReady(m_router->curCycle())) {
t_flit = m_in_link->consumeLink();
int vc = t_flit->get_vc();
t_flit->increment_hops(); // for stats
if ((t_flit->get_type() == HEAD_) ||
(t_flit->get_type() == HEAD_TAIL_)) {
assert(m_vcs[vc]->get_state() == IDLE_);
set_vc_active(vc, m_router->curCycle());
// Route computation for this vc
int outport = m_router->route_compute(t_flit->get_route(),
m_id, m_direction);
// Update output port in VC
// All flits in this packet will use this output port
// The output port field in the flit is updated after it wins SA
grant_outport(vc, outport);
} else {
assert(m_vcs[vc]->get_state() == ACTIVE_);
}
// Buffer the flit
m_vcs[vc]->insertFlit(t_flit);
int vnet = vc/m_vc_per_vnet;
// number of writes same as reads
// any flit that is written will be read only once
m_num_buffer_writes[vnet]++;
m_num_buffer_reads[vnet]++;
Cycles pipe_stages = m_router->get_pipe_stages();
if (pipe_stages == 1) {
// 1-cycle router
// Flit goes for SA directly
t_flit->advance_stage(SA_, m_router->curCycle());
} else {
assert(pipe_stages > 1);
// Router delay is modeled by making flit wait in buffer for
// (pipe_stages cycles - 1) cycles before going for SA
Cycles wait_time = pipe_stages - Cycles(1);
t_flit->advance_stage(SA_, m_router->curCycle() + wait_time);
// Wakeup the router in that cycle to perform SA
m_router->schedule_wakeup(Cycles(wait_time));
}
}
}
// Send a credit back to upstream router for this VC.
// Called by SwitchAllocator when the flit in this VC wins the Switch.
void
InputUnit::increment_credit(int in_vc, bool free_signal, Cycles curTime)
{
Credit *t_credit = new Credit(in_vc, free_signal, curTime);
creditQueue->insert(t_credit);
m_credit_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
}
uint32_t
InputUnit::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
for (int i=0; i < m_num_vcs; i++) {
num_functional_writes += m_vcs[i]->functionalWrite(pkt);
}
return num_functional_writes;
}
void
InputUnit::resetStats()
{
for (int j = 0; j < m_num_buffer_reads.size(); j++) {
m_num_buffer_reads[j] = 0;
m_num_buffer_writes[j] = 0;
}
}

View file

@ -0,0 +1,170 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_INPUT_UNIT_HH__
#define __MEM_RUBY_NETWORK_GARNET_INPUT_UNIT_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
class InputUnit : public Consumer
{
public:
InputUnit(int id, PortDirection direction, Router *router);
~InputUnit();
void wakeup();
void print(std::ostream& out) const {};
inline PortDirection get_direction() { return m_direction; }
inline void
set_vc_idle(int vc, Cycles curTime)
{
m_vcs[vc]->set_idle(curTime);
}
inline void
set_vc_active(int vc, Cycles curTime)
{
m_vcs[vc]->set_active(curTime);
}
inline void
grant_outport(int vc, int outport)
{
m_vcs[vc]->set_outport(outport);
}
inline void
grant_outvc(int vc, int outvc)
{
m_vcs[vc]->set_outvc(outvc);
}
inline int
get_outport(int invc)
{
return m_vcs[invc]->get_outport();
}
inline int
get_outvc(int invc)
{
return m_vcs[invc]->get_outvc();
}
inline Cycles
get_enqueue_time(int invc)
{
return m_vcs[invc]->get_enqueue_time();
}
void increment_credit(int in_vc, bool free_signal, Cycles curTime);
inline flit*
peekTopFlit(int vc)
{
return m_vcs[vc]->peekTopFlit();
}
inline flit*
getTopFlit(int vc)
{
return m_vcs[vc]->getTopFlit();
}
inline bool
need_stage(int vc, flit_stage stage, Cycles time)
{
return m_vcs[vc]->need_stage(stage, time);
}
inline bool
isReady(int invc, Cycles curTime)
{
return m_vcs[invc]->isReady(curTime);
}
flitBuffer* getCreditQueue() { return creditQueue; }
inline void
set_in_link(NetworkLink *link)
{
m_in_link = link;
}
inline int get_inlink_id() { return m_in_link->get_id(); }
inline void
set_credit_link(CreditLink *credit_link)
{
m_credit_link = credit_link;
}
double get_buf_read_activity(unsigned int vnet) const
{ return m_num_buffer_reads[vnet]; }
double get_buf_write_activity(unsigned int vnet) const
{ return m_num_buffer_writes[vnet]; }
uint32_t functionalWrite(Packet *pkt);
void resetStats();
private:
int m_id;
PortDirection m_direction;
int m_num_vcs;
int m_vc_per_vnet;
Router *m_router;
NetworkLink *m_in_link;
CreditLink *m_credit_link;
flitBuffer *creditQueue;
// Input Virtual channels
std::vector<VirtualChannel *> m_vcs;
// Statistical variables
std::vector<double> m_num_buffer_writes;
std::vector<double> m_num_buffer_reads;
};
#endif // __MEM_RUBY_NETWORK_GARNET_INPUT_UNIT_HH__

View file

@ -0,0 +1,443 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
#include <cassert>
#include <cmath>
#include "base/cast.hh"
#include "base/stl_helpers.hh"
#include "debug/RubyNetwork.hh"
#include "mem/ruby/network/MessageBuffer.hh"
#include "mem/ruby/network/garnet2.0/Credit.hh"
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
#include "mem/ruby/slicc_interface/Message.hh"
using namespace std;
using m5::stl_helpers::deletePointers;
NetworkInterface::NetworkInterface(const Params *p)
: ClockedObject(p), Consumer(this), m_id(p->id),
m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
m_num_vcs(m_vc_per_vnet * m_virtual_networks)
{
m_router_id = -1;
m_vc_round_robin = 0;
m_ni_out_vcs.resize(m_num_vcs);
m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
outCreditQueue = new flitBuffer();
// instantiating the NI flit buffers
for (int i = 0; i < m_num_vcs; i++) {
m_ni_out_vcs[i] = new flitBuffer();
m_ni_out_vcs_enqueue_time[i] = Cycles(INFINITE_);
}
m_vc_allocator.resize(m_virtual_networks); // 1 allocator per vnet
for (int i = 0; i < m_virtual_networks; i++) {
m_vc_allocator[i] = 0;
}
}
void
NetworkInterface::init()
{
for (int i = 0; i < m_num_vcs; i++) {
m_out_vc_state.push_back(new OutVcState(i, m_net_ptr));
}
}
NetworkInterface::~NetworkInterface()
{
deletePointers(m_out_vc_state);
deletePointers(m_ni_out_vcs);
delete outCreditQueue;
delete outFlitQueue;
}
void
NetworkInterface::addInPort(NetworkLink *in_link,
CreditLink *credit_link)
{
inNetLink = in_link;
in_link->setLinkConsumer(this);
outCreditLink = credit_link;
credit_link->setSourceQueue(outCreditQueue);
}
void
NetworkInterface::addOutPort(NetworkLink *out_link,
CreditLink *credit_link,
SwitchID router_id)
{
inCreditLink = credit_link;
credit_link->setLinkConsumer(this);
outNetLink = out_link;
outFlitQueue = new flitBuffer();
out_link->setSourceQueue(outFlitQueue);
m_router_id = router_id;
}
void
NetworkInterface::addNode(vector<MessageBuffer *>& in,
vector<MessageBuffer *>& out)
{
inNode_ptr = in;
outNode_ptr = out;
for (auto& it : in) {
if (it != nullptr) {
it->setConsumer(this);
}
}
}
/*
* The NI wakeup checks whether there are any ready messages in the protocol
* buffer. If yes, it picks that up, flitisizes it into a number of flits and
* puts it into an output buffer and schedules the output link. On a wakeup
* it also checks whether there are flits in the input link. If yes, it picks
* them up and if the flit is a tail, the NI inserts the corresponding message
* into the protocol buffer. It also checks for credits being sent by the
* downstream router.
*/
void
NetworkInterface::wakeup()
{
DPRINTF(RubyNetwork, "Network Interface %d connected to router %d "
"woke up at time: %lld\n", m_id, m_router_id, curCycle());
MsgPtr msg_ptr;
Tick curTime = clockEdge();
// Checking for messages coming from the protocol
// can pick up a message/cycle for each virtual net
for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
MessageBuffer *b = inNode_ptr[vnet];
if (b == nullptr) {
continue;
}
if (b->isReady(curTime)) { // Is there a message waiting
msg_ptr = b->peekMsgPtr();
if (flitisizeMessage(msg_ptr, vnet)) {
b->dequeue(curTime);
} else {
break;
}
}
}
scheduleOutputLink();
checkReschedule();
/*********** Check the incoming flit link **********/
if (inNetLink->isReady(curCycle())) {
flit *t_flit = inNetLink->consumeLink();
bool free_signal = false;
if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
free_signal = true;
// enqueue into the protocol buffers
outNode_ptr[t_flit->get_vnet()]->enqueue(
t_flit->get_msg_ptr(), curTime, cyclesToTicks(Cycles(1)));
}
// Simply send a credit back since we are not buffering
// this flit in the NI
Credit *t_credit = new Credit(t_flit->get_vc(), free_signal,
curCycle());
outCreditQueue->insert(t_credit);
outCreditLink->
scheduleEventAbsolute(clockEdge(Cycles(1)));
int vnet = t_flit->get_vnet();
// Update Stats
// Latency
m_net_ptr->increment_received_flits(vnet);
Cycles network_delay = curCycle() - t_flit->get_enqueue_time();
Cycles queueing_delay = t_flit->get_src_delay();
m_net_ptr->increment_flit_network_latency(network_delay, vnet);
m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
m_net_ptr->increment_received_packets(vnet);
m_net_ptr->increment_packet_network_latency(network_delay, vnet);
m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
}
// Hops
m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
delete t_flit;
}
/****************** Check the incoming credit link *******/
if (inCreditLink->isReady(curCycle())) {
Credit *t_credit = (Credit*) inCreditLink->consumeLink();
m_out_vc_state[t_credit->get_vc()]->increment_credit();
if (t_credit->is_free_signal()) {
m_out_vc_state[t_credit->get_vc()]->setState(IDLE_, curCycle());
}
delete t_credit;
}
}
// Embed the protocol message into flits
bool
NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
{
Message *net_msg_ptr = msg_ptr.get();
NetDest net_msg_dest = net_msg_ptr->getDestination();
// gets all the destinations associated with this message.
vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
// Number of flits is dependent on the link bandwidth available.
// This is expressed in terms of bytes/cycle or the flit size
int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(
net_msg_ptr->getMessageSize())/m_net_ptr->getNiFlitSize());
// loop to convert all multicast messages into unicast messages
for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
// this will return a free output virtual channel
int vc = calculateVC(vnet);
if (vc == -1) {
return false ;
}
MsgPtr new_msg_ptr = msg_ptr->clone();
NodeID destID = dest_nodes[ctr];
Message *new_net_msg_ptr = new_msg_ptr.get();
if (dest_nodes.size() > 1) {
NetDest personal_dest;
for (int m = 0; m < (int) MachineType_NUM; m++) {
if ((destID >= MachineType_base_number((MachineType) m)) &&
destID < MachineType_base_number((MachineType) (m+1))) {
// calculating the NetDest associated with this destID
personal_dest.clear();
personal_dest.add((MachineID) {(MachineType) m, (destID -
MachineType_base_number((MachineType) m))});
new_net_msg_ptr->getDestination() = personal_dest;
break;
}
}
net_msg_dest.removeNetDest(personal_dest);
// removing the destination from the original message to reflect
// that a message with this particular destination has been
// flitisized and an output vc is acquired
net_msg_ptr->getDestination().removeNetDest(personal_dest);
}
// Embed Route into the flits
// NetDest format is used by the routing table
// Custom routing algorithms just need destID
RouteInfo route;
route.vnet = vnet;
route.net_dest = new_net_msg_ptr->getDestination();
route.src_ni = m_id;
route.src_router = m_router_id;
route.dest_ni = destID;
route.dest_router = m_net_ptr->get_router_id(destID);
// initialize hops_traversed to -1
// so that the first router increments it to 0
route.hops_traversed = -1;
m_net_ptr->increment_injected_packets(vnet);
for (int i = 0; i < num_flits; i++) {
m_net_ptr->increment_injected_flits(vnet);
flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
curCycle());
fl->set_src_delay(curCycle() - ticksToCycles(msg_ptr->getTime()));
m_ni_out_vcs[vc]->insert(fl);
}
m_ni_out_vcs_enqueue_time[vc] = curCycle();
m_out_vc_state[vc]->setState(ACTIVE_, curCycle());
}
return true ;
}
// Looking for a free output vc
int
NetworkInterface::calculateVC(int vnet)
{
for (int i = 0; i < m_vc_per_vnet; i++) {
int delta = m_vc_allocator[vnet];
m_vc_allocator[vnet]++;
if (m_vc_allocator[vnet] == m_vc_per_vnet)
m_vc_allocator[vnet] = 0;
if (m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(
IDLE_, curCycle())) {
return ((vnet*m_vc_per_vnet) + delta);
}
}
return -1;
}
/** This function looks at the NI buffers
* if some buffer has flits which are ready to traverse the link in the next
* cycle, and the downstream output vc associated with this flit has buffers
* left, the link is scheduled for the next cycle
*/
void
NetworkInterface::scheduleOutputLink()
{
int vc = m_vc_round_robin;
m_vc_round_robin++;
if (m_vc_round_robin == m_num_vcs)
m_vc_round_robin = 0;
for (int i = 0; i < m_num_vcs; i++) {
vc++;
if (vc == m_num_vcs)
vc = 0;
// model buffer backpressure
if (m_ni_out_vcs[vc]->isReady(curCycle()) &&
m_out_vc_state[vc]->has_credit()) {
bool is_candidate_vc = true;
int t_vnet = get_vnet(vc);
int vc_base = t_vnet * m_vc_per_vnet;
if (m_net_ptr->isVNetOrdered(t_vnet)) {
for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
vc_offset++) {
int t_vc = vc_base + vc_offset;
if (m_ni_out_vcs[t_vc]->isReady(curCycle())) {
if (m_ni_out_vcs_enqueue_time[t_vc] <
m_ni_out_vcs_enqueue_time[vc]) {
is_candidate_vc = false;
break;
}
}
}
}
if (!is_candidate_vc)
continue;
m_out_vc_state[vc]->decrement_credit();
// Just removing the flit
flit *t_flit = m_ni_out_vcs[vc]->getTopFlit();
t_flit->set_time(curCycle() + Cycles(1));
outFlitQueue->insert(t_flit);
// schedule the out link
outNetLink->scheduleEventAbsolute(clockEdge(Cycles(1)));
if (t_flit->get_type() == TAIL_ ||
t_flit->get_type() == HEAD_TAIL_) {
m_ni_out_vcs_enqueue_time[vc] = Cycles(INFINITE_);
}
return;
}
}
}
int
NetworkInterface::get_vnet(int vc)
{
for (int i = 0; i < m_virtual_networks; i++) {
if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
return i;
}
}
fatal("Could not determine vc");
}
// Wakeup the NI in the next cycle if there are waiting
// messages in the protocol buffer, or waiting flits in the
// output VC buffer
void
NetworkInterface::checkReschedule()
{
for (const auto& it : inNode_ptr) {
if (it == nullptr) {
continue;
}
while (it->isReady(clockEdge())) { // Is there a message waiting
scheduleEvent(Cycles(1));
return;
}
}
for (int vc = 0; vc < m_num_vcs; vc++) {
if (m_ni_out_vcs[vc]->isReady(curCycle() + Cycles(1))) {
scheduleEvent(Cycles(1));
return;
}
}
}
void
NetworkInterface::print(std::ostream& out) const
{
out << "[Network Interface]";
}
uint32_t
NetworkInterface::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
for (unsigned int i = 0; i < m_num_vcs; ++i) {
num_functional_writes += m_ni_out_vcs[i]->functionalWrite(pkt);
}
num_functional_writes += outFlitQueue->functionalWrite(pkt);
return num_functional_writes;
}
NetworkInterface *
GarnetNetworkInterfaceParams::create()
{
return new NetworkInterface(this);
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_NETWORK_INTERFACE_HH__
#define __MEM_RUBY_NETWORK_GARNET_NETWORK_INTERFACE_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "mem/ruby/network/garnet2.0/OutVcState.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "params/GarnetNetworkInterface.hh"
class MessageBuffer;
class flitBuffer;
class NetworkInterface : public ClockedObject, public Consumer
{
public:
typedef GarnetNetworkInterfaceParams Params;
NetworkInterface(const Params *p);
~NetworkInterface();
void init();
void addInPort(NetworkLink *in_link, CreditLink *credit_link);
void addOutPort(NetworkLink *out_link, CreditLink *credit_link,
SwitchID router_id);
void wakeup();
void addNode(std::vector<MessageBuffer *> &inNode,
std::vector<MessageBuffer *> &outNode);
void print(std::ostream& out) const;
int get_vnet(int vc);
int get_router_id() { return m_router_id; }
void init_net_ptr(GarnetNetwork *net_ptr) { m_net_ptr = net_ptr; }
uint32_t functionalWrite(Packet *);
private:
GarnetNetwork *m_net_ptr;
const NodeID m_id;
const int m_virtual_networks, m_vc_per_vnet, m_num_vcs;
int m_router_id; // id of my router
std::vector<OutVcState *> m_out_vc_state;
std::vector<int> m_vc_allocator;
int m_vc_round_robin; // For round robin scheduling
flitBuffer *outFlitQueue; // For modeling link contention
flitBuffer *outCreditQueue;
NetworkLink *inNetLink;
NetworkLink *outNetLink;
CreditLink *inCreditLink;
CreditLink *outCreditLink;
// Input Flit Buffers
// The flit buffers which will serve the Consumer
std::vector<flitBuffer *> m_ni_out_vcs;
std::vector<Cycles> m_ni_out_vcs_enqueue_time;
// The Message buffers that takes messages from the protocol
std::vector<MessageBuffer *> inNode_ptr;
// The Message buffers that provides messages to the protocol
std::vector<MessageBuffer *> outNode_ptr;
bool flitisizeMessage(MsgPtr msg_ptr, int vnet);
int calculateVC(int vnet);
void scheduleOutputLink();
void checkReschedule();
};
#endif // __MEM_RUBY_NETWORK_GARNET_NETWORK_INTERFACE_HH__

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
NetworkLink::NetworkLink(const Params *p)
: ClockedObject(p), Consumer(this), m_id(p->link_id),
m_type(NUM_LINK_TYPES_),
m_latency(p->link_latency),
linkBuffer(new flitBuffer()), link_consumer(nullptr),
link_srcQueue(nullptr), m_link_utilized(0),
m_vc_load(p->vcs_per_vnet * p->virt_nets)
{
}
NetworkLink::~NetworkLink()
{
delete linkBuffer;
}
void
NetworkLink::setLinkConsumer(Consumer *consumer)
{
link_consumer = consumer;
}
void
NetworkLink::setSourceQueue(flitBuffer *srcQueue)
{
link_srcQueue = srcQueue;
}
void
NetworkLink::wakeup()
{
if (link_srcQueue->isReady(curCycle())) {
flit *t_flit = link_srcQueue->getTopFlit();
t_flit->set_time(curCycle() + m_latency);
linkBuffer->insert(t_flit);
link_consumer->scheduleEventAbsolute(clockEdge(m_latency));
m_link_utilized++;
m_vc_load[t_flit->get_vc()]++;
}
}
NetworkLink *
NetworkLinkParams::create()
{
return new NetworkLink(this);
}
CreditLink *
CreditLinkParams::create()
{
return new CreditLink(this);
}
uint32_t
NetworkLink::functionalWrite(Packet *pkt)
{
return linkBuffer->functionalWrite(pkt);
}

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_NETWORK_LINK_HH__
#define __MEM_RUBY_NETWORK_GARNET_NETWORK_LINK_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
#include "params/NetworkLink.hh"
#include "sim/clocked_object.hh"
class GarnetNetwork;
class NetworkLink : public ClockedObject, public Consumer
{
public:
typedef NetworkLinkParams Params;
NetworkLink(const Params *p);
~NetworkLink();
void setLinkConsumer(Consumer *consumer);
void setSourceQueue(flitBuffer *srcQueue);
void setType(link_type type) { m_type = type; }
link_type getType() { return m_type; }
void print(std::ostream& out) const {}
int get_id() const { return m_id; }
void wakeup();
unsigned int getLinkUtilization() const { return m_link_utilized; }
const std::vector<unsigned int> & getVcLoad() const { return m_vc_load; }
inline bool isReady(Cycles curTime)
{ return linkBuffer->isReady(curTime); }
inline flit* peekLink() { return linkBuffer->peekTopFlit(); }
inline flit* consumeLink() { return linkBuffer->getTopFlit(); }
uint32_t functionalWrite(Packet *);
private:
const int m_id;
link_type m_type;
const Cycles m_latency;
flitBuffer *linkBuffer;
Consumer *link_consumer;
flitBuffer *link_srcQueue;
// Statistical variables
unsigned int m_link_utilized;
std::vector<unsigned int> m_vc_load;
};
#endif // __MEM_RUBY_NETWORK_GARNET_NETWORK_LINK_HH__

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/OutVcState.hh"
#include "mem/ruby/system/RubySystem.hh"
OutVcState::OutVcState(int id, GarnetNetwork *network_ptr)
: m_time(0)
{
m_id = id;
m_vc_state = IDLE_;
if (network_ptr->get_vnet_type(id) == DATA_VNET_)
m_max_credit_count = network_ptr->getBuffersPerDataVC();
else
m_max_credit_count = network_ptr->getBuffersPerCtrlVC();
m_credit_count = m_max_credit_count;
assert(m_credit_count >= 1);
}
void
OutVcState::increment_credit()
{
m_credit_count++;
assert(m_credit_count <= m_max_credit_count);
}
void
OutVcState::decrement_credit()
{
m_credit_count--;
assert(m_credit_count >= 0);
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_OUTVC_STATE_HH__
#define __MEM_RUBY_NETWORK_GARNET_OUTVC_STATE_HH__
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
class OutVcState
{
public:
OutVcState(int id, GarnetNetwork *network_ptr);
int get_credit_count() { return m_credit_count; }
inline bool has_credit() { return (m_credit_count > 0); }
void increment_credit();
void decrement_credit();
inline bool
isInState(VC_state_type state, Cycles request_time)
{
return ((m_vc_state == state) && (request_time >= m_time) );
}
inline void
setState(VC_state_type state, Cycles time)
{
m_vc_state = state;
m_time = time;
}
private:
int m_id ;
Cycles m_time;
VC_state_type m_vc_state;
int m_credit_count;
int m_max_credit_count;
};
#endif // __MEM_RUBY_NETWORK_GARNET_OUTVC_STATE_HH__

View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
#include "base/stl_helpers.hh"
#include "debug/RubyNetwork.hh"
#include "mem/ruby/network/garnet2.0/Credit.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
using namespace std;
using m5::stl_helpers::deletePointers;
OutputUnit::OutputUnit(int id, PortDirection direction, Router *router)
: Consumer(router)
{
m_id = id;
m_direction = direction;
m_router = router;
m_num_vcs = m_router->get_num_vcs();
m_vc_per_vnet = m_router->get_vc_per_vnet();
m_out_buffer = new flitBuffer();
for (int i = 0; i < m_num_vcs; i++) {
m_outvc_state.push_back(new OutVcState(i, m_router->get_net_ptr()));
}
}
OutputUnit::~OutputUnit()
{
delete m_out_buffer;
deletePointers(m_outvc_state);
}
void
OutputUnit::decrement_credit(int out_vc)
{
DPRINTF(RubyNetwork, "Router %d OutputUnit %d decrementing credit for "
"outvc %d at time: %lld\n",
m_router->get_id(), m_id, out_vc, m_router->curCycle());
m_outvc_state[out_vc]->decrement_credit();
}
void
OutputUnit::increment_credit(int out_vc)
{
DPRINTF(RubyNetwork, "Router %d OutputUnit %d incrementing credit for "
"outvc %d at time: %lld\n",
m_router->get_id(), m_id, out_vc, m_router->curCycle());
m_outvc_state[out_vc]->increment_credit();
}
// Check if the output VC (i.e., input VC at next router)
// has free credits (i..e, buffer slots).
// This is tracked by OutVcState
bool
OutputUnit::has_credit(int out_vc)
{
assert(m_outvc_state[out_vc]->isInState(ACTIVE_, m_router->curCycle()));
return m_outvc_state[out_vc]->has_credit();
}
// Check if the output port (i.e., input port at next router) has free VCs.
bool
OutputUnit::has_free_vc(int vnet)
{
int vc_base = vnet*m_vc_per_vnet;
for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
if (is_vc_idle(vc, m_router->curCycle()))
return true;
}
return false;
}
// Assign a free output VC to the winner of Switch Allocation
int
OutputUnit::select_free_vc(int vnet)
{
int vc_base = vnet*m_vc_per_vnet;
for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) {
if (is_vc_idle(vc, m_router->curCycle())) {
m_outvc_state[vc]->setState(ACTIVE_, m_router->curCycle());
return vc;
}
}
return -1;
}
/*
* The wakeup function of the OutputUnit reads the credit signal from the
* downstream router for the output VC (i.e., input VC at downstream router).
* It increments the credit count in the appropriate output VC state.
* If the credit carries is_free_signal as true,
* the output VC is marked IDLE.
*/
void
OutputUnit::wakeup()
{
if (m_credit_link->isReady(m_router->curCycle())) {
Credit *t_credit = (Credit*) m_credit_link->consumeLink();
increment_credit(t_credit->get_vc());
if (t_credit->is_free_signal())
set_vc_state(IDLE_, t_credit->get_vc(), m_router->curCycle());
delete t_credit;
}
}
flitBuffer*
OutputUnit::getOutQueue()
{
return m_out_buffer;
}
void
OutputUnit::set_out_link(NetworkLink *link)
{
m_out_link = link;
}
void
OutputUnit::set_credit_link(CreditLink *credit_link)
{
m_credit_link = credit_link;
}
uint32_t
OutputUnit::functionalWrite(Packet *pkt)
{
return m_out_buffer->functionalWrite(pkt);
}

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_OUTPUT_UNIT_HH__
#define __MEM_RUBY_NETWORK_GARNET_OUTPUT_UNIT_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "mem/ruby/network/garnet2.0/OutVcState.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
class OutputUnit : public Consumer
{
public:
OutputUnit(int id, PortDirection direction, Router *router);
~OutputUnit();
void set_out_link(NetworkLink *link);
void set_credit_link(CreditLink *credit_link);
void wakeup();
flitBuffer* getOutQueue();
void print(std::ostream& out) const {};
void decrement_credit(int out_vc);
void increment_credit(int out_vc);
bool has_credit(int out_vc);
bool has_free_vc(int vnet);
int select_free_vc(int vnet);
inline PortDirection get_direction() { return m_direction; }
int
get_credit_count(int vc)
{
return m_outvc_state[vc]->get_credit_count();
}
inline int
get_outlink_id()
{
return m_out_link->get_id();
}
inline void
set_vc_state(VC_state_type state, int vc, Cycles curTime)
{
m_outvc_state[vc]->setState(state, curTime);
}
inline bool
is_vc_idle(int vc, Cycles curTime)
{
return (m_outvc_state[vc]->isInState(IDLE_, curTime));
}
inline void
insert_flit(flit *t_flit)
{
m_out_buffer->insert(t_flit);
m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1)));
}
uint32_t functionalWrite(Packet *pkt);
private:
int m_id;
PortDirection m_direction;
int m_num_vcs;
int m_vc_per_vnet;
Router *m_router;
NetworkLink *m_out_link;
CreditLink *m_credit_link;
flitBuffer *m_out_buffer; // This is for the network link to consume
std::vector<OutVcState *> m_outvc_state; // vc state of downstream router
};
#endif // __MEM_RUBY_NETWORK_GARNET_OUTPUT_UNIT_HH__

View file

@ -0,0 +1,71 @@
README for Garnet2.0
Written By: Tushar Krishna (tushar@ece.gatech.edu)
Last Updated: Jul 9, 2016
-------------------------------------------------------
Garnet Network Parameters and Setup:
- GarnetNetwork.py
* defaults can be overwritten from command line (see configs/network/Network.py)
- GarnetNetwork.hh/cc
* sets up the routers and links
* collects stats
CODE FLOW
- NetworkInterface.cc::wakeup()
* Every NI connected to one coherence protocol controller on one end, and one router on the other.
* receives messages from coherence protocol buffer in appropriate vnet and converts them into network packets and sends them into the network.
* garnet2.0 adds the ability to capture a network trace at this point.
* receives flits from the network, extracts the protocol message and sends it to the coherence protocol buffer in appropriate vnet.
* manages flow-control (i.e., credits) with its attached router.
* The consuming flit/credit output link of the NI is put in the global event queue with a timestamp set to next cycle.
The eventqueue calls the wakeup function in the consumer.
- NetworkLink.cc::wakeup()
* receives flits from NI/router and sends it to NI/router after m_latency cycles delay
* Default latency value for every link can be set from command line (see configs/network/Network.py)
* Per link latency can be overwritten in the topology file
* The consumer of the link (NI/router) is put in the global event queue with a timestamp set after m_latency cycles.
The eventqueue calls the wakeup function in the consumer.
- Router.cc::wakeup()
* Loop through all InputUnits and call their wakeup()
* Loop through all OutputUnits and call their wakeup()
* Call SwitchAllocator's wakeup()
* Call CrossbarSwitch's wakeup()
* The router's wakeup function is called whenever any of its modules (InputUnit, OutputUnit, SwitchAllocator, CrossbarSwitch) have
a ready flit/credit to act upon this cycle.
- InputUnit.cc::wakeup()
* Read input flit from upstream router if it is ready for this cycle
* For HEAD/HEAD_TAIL flits, perform route computation, and update route in the VC.
* Buffer the flit for (m_latency - 1) cycles and mark it valid for SwitchAllocation starting that cycle.
* Default latency for every router can be set from command line (see configs/network/Network.py)
* Per router latency (i.e., num pipeline stages) can be set in the topology file
- OutputUnit.cc::wakeup()
* Read input credit from downstream router if it is ready for this cycle
* Increment the credit in the appropriate output VC state.
* Mark output VC as free if the credit carries is_free_signal as true
- SwitchAllocator.cc::wakeup()
* Note: SwitchAllocator performs VC arbitration and selection within it.
* SA-I (or SA-i): Loop through all input VCs at every input port, and select one in a round robin manner.
* For HEAD/HEAD_TAIL flits only select an input VC whose output port has at least one free output VC.
* For BODY/TAIL flits, only select an input VC that has credits in its output VC.
* Place a request for the output port from this VC.
* SA-II (or SA-o): Loop through all output ports, and select one input VC (that placed a request during SA-I) as the winner for this output port in a round robin manner.
* For HEAD/HEAD_TAIL flits, perform outvc allocation (i.e., select a free VC from the output port).
* For BODY/TAIL flits, decrement a credit in the output vc.
* Read the flit out from the input VC, and send it to the CrossbarSwitch
* Send a increment_credit signal to the upstream router for this input VC.
* for HEAD_TAIL/TAIL flits, mark is_free_signal as true in the credit.
* The input unit sends the credit out on the credit link to the upstream router.
* Reschedule the Router to wakeup next cycle for any flits ready for SA next cycle.
- CrossbarSwitch.cc::wakeup()
* Loop through all input ports, and send the winning flit out of its output port onto the output link.
* The consuming flit output link of the router is put in the global event queue with a timestamp set to next cycle.
The eventqueue calls the wakeup function in the consumer.

View file

@ -0,0 +1,296 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/Router.hh"
#include "base/stl_helpers.hh"
#include "debug/RubyNetwork.hh"
#include "mem/ruby/network/garnet2.0/CreditLink.hh"
#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh"
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
#include "mem/ruby/network/garnet2.0/InputUnit.hh"
#include "mem/ruby/network/garnet2.0/NetworkLink.hh"
#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
using namespace std;
using m5::stl_helpers::deletePointers;
Router::Router(const Params *p)
: BasicRouter(p), Consumer(this)
{
m_latency = p->latency;
m_virtual_networks = p->virt_nets;
m_vc_per_vnet = p->vcs_per_vnet;
m_num_vcs = m_virtual_networks * m_vc_per_vnet;
m_routing_unit = new RoutingUnit(this);
m_sw_alloc = new SwitchAllocator(this);
m_switch = new CrossbarSwitch(this);
m_input_unit.clear();
m_output_unit.clear();
}
Router::~Router()
{
deletePointers(m_input_unit);
deletePointers(m_output_unit);
delete m_routing_unit;
delete m_sw_alloc;
delete m_switch;
}
void
Router::init()
{
BasicRouter::init();
m_sw_alloc->init();
m_switch->init();
}
void
Router::wakeup()
{
DPRINTF(RubyNetwork, "Router %d woke up\n", m_id);
// check for incoming flits
for (int inport = 0; inport < m_input_unit.size(); inport++) {
m_input_unit[inport]->wakeup();
}
// check for incoming credits
// Note: the credit update is happening before SA
// buffer turnaround time =
// credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle)
// if we want the credit update to take place after SA, this loop should
// be moved after the SA request
for (int outport = 0; outport < m_output_unit.size(); outport++) {
m_output_unit[outport]->wakeup();
}
// Switch Allocation
m_sw_alloc->wakeup();
// Switch Traversal
m_switch->wakeup();
}
void
Router::addInPort(PortDirection inport_dirn,
NetworkLink *in_link, CreditLink *credit_link)
{
int port_num = m_input_unit.size();
InputUnit *input_unit = new InputUnit(port_num, inport_dirn, this);
input_unit->set_in_link(in_link);
input_unit->set_credit_link(credit_link);
in_link->setLinkConsumer(this);
credit_link->setSourceQueue(input_unit->getCreditQueue());
m_input_unit.push_back(input_unit);
m_routing_unit->addInDirection(inport_dirn, port_num);
}
void
Router::addOutPort(PortDirection outport_dirn,
NetworkLink *out_link,
const NetDest& routing_table_entry, int link_weight,
CreditLink *credit_link)
{
int port_num = m_output_unit.size();
OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this);
output_unit->set_out_link(out_link);
output_unit->set_credit_link(credit_link);
credit_link->setLinkConsumer(this);
out_link->setSourceQueue(output_unit->getOutQueue());
m_output_unit.push_back(output_unit);
m_routing_unit->addRoute(routing_table_entry);
m_routing_unit->addWeight(link_weight);
m_routing_unit->addOutDirection(outport_dirn, port_num);
}
PortDirection
Router::getOutportDirection(int outport)
{
return m_output_unit[outport]->get_direction();
}
PortDirection
Router::getInportDirection(int inport)
{
return m_input_unit[inport]->get_direction();
}
int
Router::route_compute(RouteInfo route, int inport, PortDirection inport_dirn)
{
return m_routing_unit->outportCompute(route, inport, inport_dirn);
}
void
Router::grant_switch(int inport, flit *t_flit)
{
m_switch->update_sw_winner(inport, t_flit);
}
void
Router::schedule_wakeup(Cycles time)
{
// wake up after time cycles
scheduleEvent(time);
}
std::string
Router::getPortDirectionName(PortDirection direction)
{
// PortDirection is actually a string
// If not, then this function should add a switch
// statement to convert direction to a string
// that can be printed out
return direction;
}
void
Router::regStats()
{
BasicRouter::regStats();
m_buffer_reads
.name(name() + ".buffer_reads")
.flags(Stats::nozero)
;
m_buffer_writes
.name(name() + ".buffer_writes")
.flags(Stats::nozero)
;
m_crossbar_activity
.name(name() + ".crossbar_activity")
.flags(Stats::nozero)
;
m_sw_input_arbiter_activity
.name(name() + ".sw_input_arbiter_activity")
.flags(Stats::nozero)
;
m_sw_output_arbiter_activity
.name(name() + ".sw_output_arbiter_activity")
.flags(Stats::nozero)
;
}
void
Router::collateStats()
{
for (int j = 0; j < m_virtual_networks; j++) {
for (int i = 0; i < m_input_unit.size(); i++) {
m_buffer_reads += m_input_unit[i]->get_buf_read_activity(j);
m_buffer_writes += m_input_unit[i]->get_buf_write_activity(j);
}
}
m_sw_input_arbiter_activity = m_sw_alloc->get_input_arbiter_activity();
m_sw_output_arbiter_activity = m_sw_alloc->get_output_arbiter_activity();
m_crossbar_activity = m_switch->get_crossbar_activity();
}
void
Router::resetStats()
{
for (int j = 0; j < m_virtual_networks; j++) {
for (int i = 0; i < m_input_unit.size(); i++) {
m_input_unit[i]->resetStats();
}
}
}
void
Router::printFaultVector(ostream& out)
{
int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
int num_fault_types = m_network_ptr->fault_model->number_of_fault_types;
float fault_vector[num_fault_types];
get_fault_vector(temperature_celcius, fault_vector);
out << "Router-" << m_id << " fault vector: " << endl;
for (int fault_type_index = 0; fault_type_index < num_fault_types;
fault_type_index++) {
out << " - probability of (";
out <<
m_network_ptr->fault_model->fault_type_to_string(fault_type_index);
out << ") = ";
out << fault_vector[fault_type_index] << endl;
}
}
void
Router::printAggregateFaultProbability(std::ostream& out)
{
int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS;
float aggregate_fault_prob;
get_aggregate_fault_probability(temperature_celcius,
&aggregate_fault_prob);
out << "Router-" << m_id << " fault probability: ";
out << aggregate_fault_prob << endl;
}
uint32_t
Router::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
num_functional_writes += m_switch->functionalWrite(pkt);
for (uint32_t i = 0; i < m_input_unit.size(); i++) {
num_functional_writes += m_input_unit[i]->functionalWrite(pkt);
}
for (uint32_t i = 0; i < m_output_unit.size(); i++) {
num_functional_writes += m_output_unit[i]->functionalWrite(pkt);
}
return num_functional_writes;
}
Router *
GarnetRouterParams::create()
{
return new Router(this);
}

View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_ROUTER_HH__
#define __MEM_RUBY_NETWORK_GARNET_ROUTER_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/network/BasicRouter.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
#include "mem/ruby/network/garnet2.0/flit.hh"
#include "params/GarnetRouter.hh"
class NetworkLink;
class CreditLink;
class InputUnit;
class OutputUnit;
class RoutingUnit;
class SwitchAllocator;
class CrossbarSwitch;
class FaultModel;
class Router : public BasicRouter, public Consumer
{
public:
typedef GarnetRouterParams Params;
Router(const Params *p);
~Router();
void wakeup();
void print(std::ostream& out) const {};
void init();
void addInPort(PortDirection inport_dirn, NetworkLink *link,
CreditLink *credit_link);
void addOutPort(PortDirection outport_dirn, NetworkLink *link,
const NetDest& routing_table_entry,
int link_weight, CreditLink *credit_link);
Cycles get_pipe_stages(){ return m_latency; }
int get_num_vcs() { return m_num_vcs; }
int get_num_vnets() { return m_virtual_networks; }
int get_vc_per_vnet() { return m_vc_per_vnet; }
int get_num_inports() { return m_input_unit.size(); }
int get_num_outports() { return m_output_unit.size(); }
int get_id() { return m_id; }
void init_net_ptr(GarnetNetwork* net_ptr)
{
m_network_ptr = net_ptr;
}
GarnetNetwork* get_net_ptr() { return m_network_ptr; }
std::vector<InputUnit *>& get_inputUnit_ref() { return m_input_unit; }
std::vector<OutputUnit *>& get_outputUnit_ref() { return m_output_unit; }
PortDirection getOutportDirection(int outport);
PortDirection getInportDirection(int inport);
int route_compute(RouteInfo route, int inport, PortDirection direction);
void grant_switch(int inport, flit *t_flit);
void schedule_wakeup(Cycles time);
std::string getPortDirectionName(PortDirection direction);
void printFaultVector(std::ostream& out);
void printAggregateFaultProbability(std::ostream& out);
void regStats();
void collateStats();
void resetStats();
// For Fault Model:
bool get_fault_vector(int temperature, float fault_vector[]) {
return m_network_ptr->fault_model->fault_vector(m_id, temperature,
fault_vector);
}
bool get_aggregate_fault_probability(int temperature,
float *aggregate_fault_prob) {
return m_network_ptr->fault_model->fault_prob(m_id, temperature,
aggregate_fault_prob);
}
uint32_t functionalWrite(Packet *);
private:
Cycles m_latency;
int m_virtual_networks, m_num_vcs, m_vc_per_vnet;
GarnetNetwork *m_network_ptr;
std::vector<InputUnit *> m_input_unit;
std::vector<OutputUnit *> m_output_unit;
RoutingUnit *m_routing_unit;
SwitchAllocator *m_sw_alloc;
CrossbarSwitch *m_switch;
// Statistical variables required for power computations
Stats::Scalar m_buffer_reads;
Stats::Scalar m_buffer_writes;
Stats::Scalar m_sw_input_arbiter_activity;
Stats::Scalar m_sw_output_arbiter_activity;
Stats::Scalar m_crossbar_activity;
};
#endif // __MEM_RUBY_NETWORK_GARNET_ROUTER_HH__

View file

@ -0,0 +1,241 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/RoutingUnit.hh"
#include "base/cast.hh"
#include "mem/ruby/network/garnet2.0/InputUnit.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
#include "mem/ruby/slicc_interface/Message.hh"
RoutingUnit::RoutingUnit(Router *router)
{
m_router = router;
m_routing_table.clear();
m_weight_table.clear();
}
void
RoutingUnit::addRoute(const NetDest& routing_table_entry)
{
m_routing_table.push_back(routing_table_entry);
}
void
RoutingUnit::addWeight(int link_weight)
{
m_weight_table.push_back(link_weight);
}
/*
* This is the default routing algorithm in garnet.
* The routing table is populated during topology creation.
* Routes can be biased via weight assignments in the topology file.
* Correct weight assignments are critical to provide deadlock avoidance.
*/
int
RoutingUnit::lookupRoutingTable(int vnet, NetDest msg_destination)
{
// First find all possible output link candidates
// For ordered vnet, just choose the first
// (to make sure different packets don't choose different routes)
// For unordered vnet, randomly choose any of the links
// To have a strict ordering between links, they should be given
// different weights in the topology file
int output_link = -1;
int min_weight = INFINITE_;
std::vector<int> output_link_candidates;
int num_candidates = 0;
// Identify the minimum weight among the candidate output links
for (int link = 0; link < m_routing_table.size(); link++) {
if (msg_destination.intersectionIsNotEmpty(m_routing_table[link])) {
if (m_weight_table[link] <= min_weight)
min_weight = m_weight_table[link];
}
}
// Collect all candidate output links with this minimum weight
for (int link = 0; link < m_routing_table.size(); link++) {
if (msg_destination.intersectionIsNotEmpty(m_routing_table[link])) {
if (m_weight_table[link] == min_weight) {
num_candidates++;
output_link_candidates.push_back(link);
}
}
}
if (output_link_candidates.size() == 0) {
fatal("Fatal Error:: No Route exists from this Router.");
exit(0);
}
// Randomly select any candidate output link
int candidate = 0;
if (!(m_router->get_net_ptr())->isVNetOrdered(vnet))
candidate = rand() % num_candidates;
output_link = output_link_candidates.at(candidate);
return output_link;
}
void
RoutingUnit::addInDirection(PortDirection inport_dirn, int inport_idx)
{
m_inports_dirn2idx[inport_dirn] = inport_idx;
m_inports_idx2dirn[inport_idx] = inport_dirn;
}
void
RoutingUnit::addOutDirection(PortDirection outport_dirn, int outport_idx)
{
m_outports_dirn2idx[outport_dirn] = outport_idx;
m_outports_idx2dirn[outport_idx] = outport_dirn;
}
// outportCompute() is called by the InputUnit
// It calls the routing table by default.
// A template for adaptive topology-specific routing algorithm
// implementations using port directions rather than a static routing
// table is provided here.
int
RoutingUnit::outportCompute(RouteInfo route, int inport,
PortDirection inport_dirn)
{
int outport = -1;
if (route.dest_router == m_router->get_id()) {
// Multiple NIs may be connected to this router,
// all with output port direction = "Local"
// Get exact outport id from table
outport = lookupRoutingTable(route.vnet, route.net_dest);
return outport;
}
// Routing Algorithm set in GarnetNetwork.py
// Can be over-ridden from command line using --routing-algorithm = 1
RoutingAlgorithm routing_algorithm =
(RoutingAlgorithm) m_router->get_net_ptr()->getRoutingAlgorithm();
switch (routing_algorithm) {
case TABLE_: outport =
lookupRoutingTable(route.vnet, route.net_dest); break;
case XY_: outport =
outportComputeXY(route, inport, inport_dirn); break;
// any custom algorithm
case CUSTOM_: outport =
outportComputeCustom(route, inport, inport_dirn); break;
default: outport =
lookupRoutingTable(route.vnet, route.net_dest); break;
}
assert(outport != -1);
return outport;
}
// XY routing implemented using port directions
// Only for reference purpose in a Mesh
// By default Garnet uses the routing table
int
RoutingUnit::outportComputeXY(RouteInfo route,
int inport,
PortDirection inport_dirn)
{
PortDirection outport_dirn = "Unknown";
int num_rows = m_router->get_net_ptr()->getNumRows();
int num_cols = m_router->get_net_ptr()->getNumCols();
assert(num_rows > 0 && num_cols > 0);
int my_id = m_router->get_id();
int my_x = my_id % num_cols;
int my_y = my_id / num_cols;
int dest_id = route.dest_router;
int dest_x = dest_id % num_cols;
int dest_y = dest_id / num_cols;
int x_hops = abs(dest_x - my_x);
int y_hops = abs(dest_y - my_y);
bool x_dirn = (dest_x >= my_x);
bool y_dirn = (dest_y >= my_y);
// already checked that in outportCompute() function
assert(!(x_hops == 0 && y_hops == 0));
if (x_hops > 0) {
if (x_dirn) {
assert(inport_dirn == "Local" || inport_dirn == "West");
outport_dirn = "East";
} else {
assert(inport_dirn == "Local" || inport_dirn == "East");
outport_dirn = "West";
}
} else if (y_hops > 0) {
if (y_dirn) {
// "Local" or "South" or "West" or "East"
assert(inport_dirn != "North");
outport_dirn = "North";
} else {
// "Local" or "North" or "West" or "East"
assert(inport_dirn != "South");
outport_dirn = "South";
}
} else {
// x_hops == 0 and y_hops == 0
// this is not possible
// already checked that in outportCompute() function
assert(0);
}
return m_outports_dirn2idx[outport_dirn];
}
// Template for implementing custom routing algorithm
// using port directions. (Example adaptive)
int
RoutingUnit::outportComputeCustom(RouteInfo route,
int inport,
PortDirection inport_dirn)
{
assert(0);
}

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_ROUTING_UNIT_HH__
#define __MEM_RUBY_NETWORK_GARNET_ROUTING_UNIT_HH__
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
#include "mem/ruby/network/garnet2.0/flit.hh"
class InputUnit;
class Router;
class RoutingUnit
{
public:
RoutingUnit(Router *router);
int outportCompute(RouteInfo route,
int inport,
PortDirection inport_dirn);
// Topology-agnostic Routing Table based routing (default)
void addRoute(const NetDest& routing_table_entry);
void addWeight(int link_weight);
// get output port from routing table
int lookupRoutingTable(int vnet, NetDest net_dest);
// Topology-specific direction based routing
void addInDirection(PortDirection inport_dirn, int inport);
void addOutDirection(PortDirection outport_dirn, int outport);
// Routing for Mesh
int outportComputeXY(RouteInfo route,
int inport,
PortDirection inport_dirn);
// Custom Routing Algorithm using Port Directions
int outportComputeCustom(RouteInfo route,
int inport,
PortDirection inport_dirn);
private:
Router *m_router;
// Routing Table
std::vector<NetDest> m_routing_table;
std::vector<int> m_weight_table;
// Inport and Outport direction to idx maps
std::map<PortDirection, int> m_inports_dirn2idx;
std::map<int, PortDirection> m_inports_idx2dirn;
std::map<int, PortDirection> m_outports_idx2dirn;
std::map<PortDirection, int> m_outports_dirn2idx;
};
#endif // __MEM_RUBY_NETWORK_GARNET_ROUTING_UNIT_HH__

View file

@ -0,0 +1,53 @@
# -*- mode:python -*-
# Copyright (c) 2016 Georgia Institute of Technology
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Tushar Krishna
Import('*')
if env['PROTOCOL'] == 'None':
Return()
SimObject('GarnetLink.py')
SimObject('GarnetNetwork.py')
Source('GarnetLink.cc')
Source('GarnetNetwork.cc')
Source('InputUnit.cc')
Source('NetworkInterface.cc')
Source('NetworkLink.cc')
Source('OutVcState.cc')
Source('OutputUnit.cc')
Source('Router.cc')
Source('RoutingUnit.cc')
Source('SwitchAllocator.cc')
Source('CrossbarSwitch.cc')
Source('VirtualChannel.cc')
Source('flitBuffer.cc')
Source('flit.cc')
Source('Credit.cc')

View file

@ -0,0 +1,389 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh"
#include "debug/RubyNetwork.hh"
#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
#include "mem/ruby/network/garnet2.0/InputUnit.hh"
#include "mem/ruby/network/garnet2.0/OutputUnit.hh"
#include "mem/ruby/network/garnet2.0/Router.hh"
SwitchAllocator::SwitchAllocator(Router *router)
: Consumer(router)
{
m_router = router;
m_num_vcs = m_router->get_num_vcs();
m_vc_per_vnet = m_router->get_vc_per_vnet();
m_input_arbiter_activity = 0;
m_output_arbiter_activity = 0;
}
void
SwitchAllocator::init()
{
m_input_unit = m_router->get_inputUnit_ref();
m_output_unit = m_router->get_outputUnit_ref();
m_num_inports = m_router->get_num_inports();
m_num_outports = m_router->get_num_outports();
m_round_robin_inport.resize(m_num_outports);
m_round_robin_invc.resize(m_num_inports);
m_port_requests.resize(m_num_outports);
m_vc_winners.resize(m_num_outports);
for (int i = 0; i < m_num_inports; i++) {
m_round_robin_invc[i] = 0;
}
for (int i = 0; i < m_num_outports; i++) {
m_port_requests[i].resize(m_num_inports);
m_vc_winners[i].resize(m_num_inports);
m_round_robin_inport[i] = 0;
for (int j = 0; j < m_num_inports; j++) {
m_port_requests[i][j] = false; // [outport][inport]
}
}
}
/*
* The wakeup function of the SwitchAllocator performs a 2-stage
* seperable switch allocation. At the end of the 2nd stage, a free
* output VC is assigned to the winning flits of each output port.
* There is no separate VCAllocator stage like the one in garnet1.0.
* At the end of this function, the router is rescheduled to wakeup
* next cycle for peforming SA for any flits ready next cycle.
*/
void
SwitchAllocator::wakeup()
{
arbitrate_inports(); // First stage of allocation
arbitrate_outports(); // Second stage of allocation
clear_request_vector();
check_for_wakeup();
}
/*
* SA-I (or SA-i) loops through all input VCs at every input port,
* and selects one in a round robin manner.
* - For HEAD/HEAD_TAIL flits only selects an input VC whose output port
* has at least one free output VC.
* - For BODY/TAIL flits, only selects an input VC that has credits
* in its output VC.
* Places a request for the output port from this input VC.
*/
void
SwitchAllocator::arbitrate_inports()
{
// Select a VC from each input in a round robin manner
// Independent arbiter at each input port
for (int inport = 0; inport < m_num_inports; inport++) {
int invc = m_round_robin_invc[inport];
// Select next round robin vc candidate within valid vnet
int next_round_robin_invc = invc;
next_round_robin_invc++;
if (next_round_robin_invc >= m_num_vcs)
next_round_robin_invc = 0;
m_round_robin_invc[inport] = next_round_robin_invc;
for (int invc_iter = 0; invc_iter < m_num_vcs; invc_iter++) {
if (m_input_unit[inport]->need_stage(invc, SA_,
m_router->curCycle())) {
// This flit is in SA stage
int outport = m_input_unit[inport]->get_outport(invc);
int outvc = m_input_unit[inport]->get_outvc(invc);
// check if the flit in this InputVC is allowed to be sent
// send_allowed conditions described in that function.
bool make_request =
send_allowed(inport, invc, outport, outvc);
if (make_request) {
m_input_arbiter_activity++;
m_port_requests[outport][inport] = true;
m_vc_winners[outport][inport]= invc;
break; // got one vc winner for this port
}
}
invc++;
if (invc >= m_num_vcs)
invc = 0;
}
}
}
/*
* SA-II (or SA-o) loops through all output ports,
* and selects one input VC (that placed a request during SA-I)
* as the winner for this output port in a round robin manner.
* - For HEAD/HEAD_TAIL flits, performs simplified outvc allocation.
* (i.e., select a free VC from the output port).
* - For BODY/TAIL flits, decrement a credit in the output vc.
* The winning flit is read out from the input VC and sent to the
* CrossbarSwitch.
* An increment_credit signal is sent from the InputUnit
* to the upstream router. For HEAD_TAIL/TAIL flits, is_free_signal in the
* credit is set to true.
*/
void
SwitchAllocator::arbitrate_outports()
{
// Now there are a set of input vc requests for output vcs.
// Again do round robin arbitration on these requests
// Independent arbiter at each output port
for (int outport = 0; outport < m_num_outports; outport++) {
int inport = m_round_robin_inport[outport];
m_round_robin_inport[outport]++;
if (m_round_robin_inport[outport] >= m_num_inports)
m_round_robin_inport[outport] = 0;
for (int inport_iter = 0; inport_iter < m_num_inports;
inport_iter++) {
// inport has a request this cycle for outport
if (m_port_requests[outport][inport]) {
// grant this outport to this inport
int invc = m_vc_winners[outport][inport];
int outvc = m_input_unit[inport]->get_outvc(invc);
if (outvc == -1) {
// VC Allocation - select any free VC from outport
outvc = vc_allocate(outport, inport, invc);
}
// remove flit from Input VC
flit *t_flit = m_input_unit[inport]->getTopFlit(invc);
DPRINTF(RubyNetwork, "SwitchAllocator at Router %d "
"granted outvc %d at outport %d "
"to invc %d at inport %d to flit %s at "
"time: %lld\n",
m_router->get_id(), outvc,
m_router->getPortDirectionName(
m_output_unit[outport]->get_direction()),
invc,
m_router->getPortDirectionName(
m_input_unit[inport]->get_direction()),
*t_flit,
m_router->curCycle());
// Update outport field in the flit since this is
// used by CrossbarSwitch code to send it out of
// correct outport.
// Note: post route compute in InputUnit,
// outport is updated in VC, but not in flit
t_flit->set_outport(outport);
// set outvc (i.e., invc for next hop) in flit
// (This was updated in VC by vc_allocate, but not in flit)
t_flit->set_vc(outvc);
// decrement credit in outvc
m_output_unit[outport]->decrement_credit(outvc);
// flit ready for Switch Traversal
t_flit->advance_stage(ST_, m_router->curCycle());
m_router->grant_switch(inport, t_flit);
m_output_arbiter_activity++;
if ((t_flit->get_type() == TAIL_) ||
t_flit->get_type() == HEAD_TAIL_) {
// This Input VC should now be empty
assert(!(m_input_unit[inport]->isReady(invc,
m_router->curCycle())));
// Free this VC
m_input_unit[inport]->set_vc_idle(invc,
m_router->curCycle());
// Send a credit back
// along with the information that this VC is now idle
m_input_unit[inport]->increment_credit(invc, true,
m_router->curCycle());
} else {
// Send a credit back
// but do not indicate that the VC is idle
m_input_unit[inport]->increment_credit(invc, false,
m_router->curCycle());
}
// remove this request
m_port_requests[outport][inport] = false;
break; // got a input winner for this outport
}
inport++;
if (inport >= m_num_inports)
inport = 0;
}
}
}
/*
* A flit can be sent only if
* (1) there is at least one free output VC at the
* output port (for HEAD/HEAD_TAIL),
* or
* (2) if there is at least one credit (i.e., buffer slot)
* within the VC for BODY/TAIL flits of multi-flit packets.
* and
* (3) pt-to-pt ordering is not violated in ordered vnets, i.e.,
* there should be no other flit in this input port
* within an ordered vnet
* that arrived before this flit and is requesting the same output port.
*/
bool
SwitchAllocator::send_allowed(int inport, int invc, int outport, int outvc)
{
// Check if outvc needed
// Check if credit needed (for multi-flit packet)
// Check if ordering violated (in ordered vnet)
int vnet = get_vnet(invc);
bool has_outvc = (outvc != -1);
bool has_credit = false;
if (!has_outvc) {
// needs outvc
// this is only true for HEAD and HEAD_TAIL flits.
if (m_output_unit[outport]->has_free_vc(vnet)) {
has_outvc = true;
// each VC has at least one buffer,
// so no need for additional credit check
has_credit = true;
}
} else {
has_credit = m_output_unit[outport]->has_credit(outvc);
}
// cannot send if no outvc or no credit.
if (!has_outvc || !has_credit)
return false;
// protocol ordering check
if ((m_router->get_net_ptr())->isVNetOrdered(vnet)) {
// enqueue time of this flit
Cycles t_enqueue_time = m_input_unit[inport]->get_enqueue_time(invc);
// check if any other flit is ready for SA and for same output port
// and was enqueued before this flit
int vc_base = vnet*m_vc_per_vnet;
for (int vc_offset = 0; vc_offset < m_vc_per_vnet; vc_offset++) {
int temp_vc = vc_base + vc_offset;
if (m_input_unit[inport]->need_stage(temp_vc, SA_,
m_router->curCycle()) &&
(m_input_unit[inport]->get_outport(temp_vc) == outport) &&
(m_input_unit[inport]->get_enqueue_time(temp_vc) <
t_enqueue_time)) {
return false;
}
}
}
return true;
}
// Assign a free VC to the winner of the output port.
int
SwitchAllocator::vc_allocate(int outport, int inport, int invc)
{
// Select a free VC from the output port
int outvc = m_output_unit[outport]->select_free_vc(get_vnet(invc));
// has to get a valid VC since it checked before performing SA
assert(outvc != -1);
m_input_unit[inport]->grant_outvc(invc, outvc);
return outvc;
}
// Wakeup the router next cycle to perform SA again
// if there are flits ready.
void
SwitchAllocator::check_for_wakeup()
{
Cycles nextCycle = m_router->curCycle() + Cycles(1);
for (int i = 0; i < m_num_inports; i++) {
for (int j = 0; j < m_num_vcs; j++) {
if (m_input_unit[i]->need_stage(j, SA_, nextCycle)) {
m_router->schedule_wakeup(Cycles(1));
return;
}
}
}
}
int
SwitchAllocator::get_vnet(int invc)
{
int vnet = invc/m_vc_per_vnet;
assert(vnet < m_router->get_num_vnets());
return vnet;
}
// Clear the request vector within the allocator at end of SA-II.
// Was populated by SA-I.
void
SwitchAllocator::clear_request_vector()
{
for (int i = 0; i < m_num_outports; i++) {
for (int j = 0; j < m_num_inports; j++) {
m_port_requests[i][j] = false;
}
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_SWITCH_ALLOCATOR_HH__
#define __MEM_RUBY_NETWORK_GARNET_SWITCH_ALLOCATOR_HH__
#include <iostream>
#include <vector>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
class Router;
class InputUnit;
class OutputUnit;
class SwitchAllocator : public Consumer
{
public:
SwitchAllocator(Router *router);
void wakeup();
void init();
void clear_request_vector();
void check_for_wakeup();
int get_vnet (int invc);
void print(std::ostream& out) const {};
void arbitrate_inports();
void arbitrate_outports();
bool send_allowed(int inport, int invc, int outport, int outvc);
int vc_allocate(int outport, int inport, int invc);
inline double
get_input_arbiter_activity()
{
return m_input_arbiter_activity;
}
inline double
get_output_arbiter_activity()
{
return m_output_arbiter_activity;
}
private:
int m_num_inports, m_num_outports;
int m_num_vcs, m_vc_per_vnet;
double m_input_arbiter_activity, m_output_arbiter_activity;
Router *m_router;
std::vector<int> m_round_robin_invc;
std::vector<int> m_round_robin_inport;
std::vector<std::vector<bool>> m_port_requests;
std::vector<std::vector<int>> m_vc_winners; // a list for each outport
std::vector<InputUnit *> m_input_unit;
std::vector<OutputUnit *> m_output_unit;
};
#endif // __MEM_RUBY_NETWORK_GARNET_SWITCH_ALLOCATOR_HH__

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/VirtualChannel.hh"
VirtualChannel::VirtualChannel(int id)
: m_enqueue_time(INFINITE_)
{
m_id = id;
m_input_buffer = new flitBuffer();
m_vc_state.first = IDLE_;
m_vc_state.second = Cycles(0);
m_output_vc = -1;
m_output_port = -1;
}
VirtualChannel::~VirtualChannel()
{
delete m_input_buffer;
}
void
VirtualChannel::set_idle(Cycles curTime)
{
m_vc_state.first = IDLE_;
m_vc_state.second = curTime;
m_enqueue_time = Cycles(INFINITE_);
m_output_port = -1;
m_output_vc = -1;
}
void
VirtualChannel::set_active(Cycles curTime)
{
m_vc_state.first = ACTIVE_;
m_vc_state.second = curTime;
m_enqueue_time = curTime;
}
bool
VirtualChannel::need_stage(flit_stage stage, Cycles time)
{
if (m_input_buffer->isReady(time)) {
assert(m_vc_state.first == ACTIVE_ && m_vc_state.second <= time);
flit *t_flit = m_input_buffer->peekTopFlit();
return(t_flit->is_stage(stage, time));
}
return false;
}
uint32_t
VirtualChannel::functionalWrite(Packet *pkt)
{
return m_input_buffer->functionalWrite(pkt);
}

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_VIRTUAL_CHANNEL_HH__
#define __MEM_RUBY_NETWORK_GARNET_VIRTUAL_CHANNEL_HH__
#include <utility>
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
class VirtualChannel
{
public:
VirtualChannel(int id);
~VirtualChannel();
bool need_stage(flit_stage stage, Cycles time);
void set_idle(Cycles curTime);
void set_active(Cycles curTime);
void set_outvc(int outvc) { m_output_vc = outvc; }
inline int get_outvc() { return m_output_vc; }
void set_outport(int outport) { m_output_port = outport; };
inline int get_outport() { return m_output_port; }
inline Cycles get_enqueue_time() { return m_enqueue_time; }
inline void set_enqueue_time(Cycles time) { m_enqueue_time = time; }
inline VC_state_type get_state() { return m_vc_state.first; }
inline bool isReady(Cycles curTime)
{
return m_input_buffer->isReady(curTime);
}
inline void
insertFlit(flit *t_flit)
{
m_input_buffer->insert(t_flit);
}
inline void
set_state(VC_state_type m_state, Cycles curTime)
{
m_vc_state.first = m_state;
m_vc_state.second = curTime;
}
inline flit*
peekTopFlit()
{
return m_input_buffer->peekTopFlit();
}
inline flit*
getTopFlit()
{
return m_input_buffer->getTopFlit();
}
uint32_t functionalWrite(Packet *pkt);
private:
int m_id;
flitBuffer *m_input_buffer;
std::pair<VC_state_type, Cycles> m_vc_state;
int m_output_port;
Cycles m_enqueue_time;
int m_output_vc;
};
#endif // __MEM_RUBY_NETWORK_GARNET_VIRTUAL_CHANNEL_HH__

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/flit.hh"
// Constructor for the flit
flit::flit(int id, int vc, int vnet, RouteInfo route, int size,
MsgPtr msg_ptr, Cycles curTime)
{
m_size = size;
m_msg_ptr = msg_ptr;
m_enqueue_time = curTime;
m_time = curTime;
m_id = id;
m_vnet = vnet;
m_vc = vc;
m_route = route;
m_stage.first = I_;
m_stage.second = m_time;
if (size == 1) {
m_type = HEAD_TAIL_;
return;
}
if (id == 0)
m_type = HEAD_;
else if (id == (size - 1))
m_type = TAIL_;
else
m_type = BODY_;
}
// Flit can be printed out for debugging purposes
void
flit::print(std::ostream& out) const
{
out << "[flit:: ";
out << "Id=" << m_id << " ";
out << "Type=" << m_type << " ";
out << "Vnet=" << m_vnet << " ";
out << "VC=" << m_vc << " ";
out << "Src NI=" << m_route.src_ni << " ";
out << "Src Router=" << m_route.src_router << " ";
out << "Dest NI=" << m_route.dest_ni << " ";
out << "Dest Router=" << m_route.dest_router << " ";
out << "Enqueue Time=" << m_enqueue_time << " ";
out << "]";
}
bool
flit::functionalWrite(Packet *pkt)
{
Message *msg = m_msg_ptr.get();
return msg->functionalWrite(pkt);
}

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_FLIT_HH__
#define __MEM_RUBY_NETWORK_GARNET_FLIT_HH__
#include <cassert>
#include <iostream>
#include "base/types.hh"
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/slicc_interface/Message.hh"
class flit
{
public:
flit() {}
flit(int id, int vc, int vnet, RouteInfo route, int size,
MsgPtr msg_ptr, Cycles curTime);
int get_outport() {return m_outport; }
int get_size() { return m_size; }
Cycles get_enqueue_time() { return m_enqueue_time; }
int get_id() { return m_id; }
Cycles get_time() { return m_time; }
int get_vnet() { return m_vnet; }
int get_vc() { return m_vc; }
RouteInfo get_route() { return m_route; }
MsgPtr& get_msg_ptr() { return m_msg_ptr; }
flit_type get_type() { return m_type; }
std::pair<flit_stage, Cycles> get_stage() { return m_stage; }
Cycles get_src_delay() { return src_delay; }
void set_outport(int port) { m_outport = port; }
void set_time(Cycles time) { m_time = time; }
void set_vc(int vc) { m_vc = vc; }
void set_route(RouteInfo route) { m_route = route; }
void set_src_delay(Cycles delay) { src_delay = delay; }
void increment_hops() { m_route.hops_traversed++; }
void print(std::ostream& out) const;
bool
is_stage(flit_stage stage, Cycles time)
{
return (stage == m_stage.first &&
time >= m_stage.second);
}
void
advance_stage(flit_stage t_stage, Cycles newTime)
{
m_stage.first = t_stage;
m_stage.second = newTime;
}
static bool
greater(flit* n1, flit* n2)
{
if (n1->get_time() == n2->get_time()) {
//assert(n1->flit_id != n2->flit_id);
return (n1->get_id() > n2->get_id());
} else {
return (n1->get_time() > n2->get_time());
}
}
bool functionalWrite(Packet *pkt);
protected:
int m_id;
int m_vnet;
int m_vc;
RouteInfo m_route;
int m_size;
Cycles m_enqueue_time, m_time;
flit_type m_type;
MsgPtr m_msg_ptr;
int m_outport;
Cycles src_delay;
std::pair<flit_stage, Cycles> m_stage;
};
inline std::ostream&
operator<<(std::ostream& out, const flit& obj)
{
obj.print(out);
out << std::flush;
return out;
}
#endif // __MEM_RUBY_NETWORK_GARNET_FLIT_HH__

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
flitBuffer::flitBuffer()
{
max_size = INFINITE_;
}
flitBuffer::flitBuffer(int maximum_size)
{
max_size = maximum_size;
}
bool
flitBuffer::isEmpty()
{
return (m_buffer.size() == 0);
}
bool
flitBuffer::isReady(Cycles curTime)
{
if (m_buffer.size() != 0 ) {
flit *t_flit = peekTopFlit();
if (t_flit->get_time() <= curTime)
return true;
}
return false;
}
void
flitBuffer::print(std::ostream& out) const
{
out << "[flitBuffer: " << m_buffer.size() << "] " << std::endl;
}
bool
flitBuffer::isFull()
{
return (m_buffer.size() >= max_size);
}
void
flitBuffer::setMaxSize(int maximum)
{
max_size = maximum;
}
uint32_t
flitBuffer::functionalWrite(Packet *pkt)
{
uint32_t num_functional_writes = 0;
for (unsigned int i = 0; i < m_buffer.size(); ++i) {
if (m_buffer[i]->functionalWrite(pkt)) {
num_functional_writes++;
}
}
return num_functional_writes;
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2008 Princeton University
* Copyright (c) 2016 Georgia Institute of Technology
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Niket Agarwal
* Tushar Krishna
*/
#ifndef __MEM_RUBY_NETWORK_GARNET_FLIT_BUFFER_HH__
#define __MEM_RUBY_NETWORK_GARNET_FLIT_BUFFER_HH__
#include <algorithm>
#include <iostream>
#include <vector>
#include "mem/ruby/network/garnet2.0/CommonTypes.hh"
#include "mem/ruby/network/garnet2.0/flit.hh"
class flitBuffer
{
public:
flitBuffer();
flitBuffer(int maximum_size);
bool isReady(Cycles curTime);
bool isEmpty();
void print(std::ostream& out) const;
bool isFull();
void setMaxSize(int maximum);
flit *
getTopFlit()
{
flit *f = m_buffer.front();
std::pop_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
m_buffer.pop_back();
return f;
}
flit *
peekTopFlit()
{
return m_buffer.front();
}
void
insert(flit *flt)
{
m_buffer.push_back(flt);
std::push_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
}
uint32_t functionalWrite(Packet *pkt);
private:
std::vector<flit *> m_buffer;
int max_size;
};
inline std::ostream&
operator<<(std::ostream& out, const flitBuffer& obj)
{
obj.print(out);
out << std::flush;
return out;
}
#endif // __MEM_RUBY_NETWORK_GARNET_FLIT_BUFFER_HH__