ruby: garnet2.0
Revamped version of garnet with more optimized single-cycle routers, more configurability, and cleaner code.
This commit is contained in:
parent
b512f4bf71
commit
dbe8892b76
44 changed files with 4982 additions and 40 deletions
|
@ -38,25 +38,44 @@ def define_options(parser):
|
||||||
|
|
||||||
parser.add_option("--topology", type="string", default="Crossbar",
|
parser.add_option("--topology", type="string", default="Crossbar",
|
||||||
help="check configs/topologies for complete set")
|
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")
|
help="the number of rows in the mesh topology")
|
||||||
parser.add_option("--garnet-network", type="choice",
|
parser.add_option("--network", type="choice", default="simple",
|
||||||
choices=['fixed', 'flexible'], help="'fixed'|'flexible'")
|
choices=['simple', 'garnet2.0'],
|
||||||
parser.add_option("--network-fault-model", action="store_true", default=False,
|
help="'simple'|'garnet2.0'")
|
||||||
help="enable network fault model: see src/mem/ruby/network/fault_model/")
|
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):
|
def create_network(options, ruby):
|
||||||
|
|
||||||
# Set the network classes based on the command line options
|
# Set the network classes based on the command line options
|
||||||
if options.garnet_network == "fixed":
|
if options.network == "garnet2.0":
|
||||||
NetworkClass = GarnetNetwork_d
|
|
||||||
IntLinkClass = GarnetIntLink_d
|
|
||||||
ExtLinkClass = GarnetExtLink_d
|
|
||||||
RouterClass = GarnetRouter_d
|
|
||||||
InterfaceClass = GarnetNetworkInterface_d
|
|
||||||
|
|
||||||
elif options.garnet_network == "flexible":
|
|
||||||
NetworkClass = GarnetNetwork
|
NetworkClass = GarnetNetwork
|
||||||
IntLinkClass = GarnetIntLink
|
IntLinkClass = GarnetIntLink
|
||||||
ExtLinkClass = GarnetExtLink
|
ExtLinkClass = GarnetExtLink
|
||||||
|
@ -79,7 +98,13 @@ def create_network(options, ruby):
|
||||||
|
|
||||||
def init_network(options, network, InterfaceClass):
|
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()
|
network.setup_buffers()
|
||||||
|
|
||||||
if InterfaceClass != None:
|
if InterfaceClass != None:
|
||||||
|
@ -88,6 +113,6 @@ def init_network(options, network, InterfaceClass):
|
||||||
network.netifs = netifs
|
network.netifs = netifs
|
||||||
|
|
||||||
if options.network_fault_model:
|
if options.network_fault_model:
|
||||||
assert(options.garnet_network == "fixed")
|
assert(options.network == "garnet2.0")
|
||||||
network.enable_fault_model = True
|
network.enable_fault_model = True
|
||||||
network.fault_model = FaultModel()
|
network.fault_model = FaultModel()
|
||||||
|
|
|
@ -35,6 +35,12 @@ class Crossbar(SimpleTopology):
|
||||||
description='Crossbar'
|
description='Crossbar'
|
||||||
|
|
||||||
def makeTopology(self, options, network, IntLink, ExtLink, Router):
|
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
|
# Create an individual router for each controller plus one more for
|
||||||
# the centralized crossbar. The large numbers of routers are needed
|
# the centralized crossbar. The large numbers of routers are needed
|
||||||
# because external links do not model outgoing bandwidth in the
|
# 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
|
xbar = routers[len(self.nodes)] # the crossbar router is the last router created
|
||||||
network.routers = routers
|
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)]
|
for (i, n) in enumerate(self.nodes)]
|
||||||
network.ext_links = ext_links
|
network.ext_links = ext_links
|
||||||
|
|
||||||
|
@ -55,13 +62,15 @@ class Crossbar(SimpleTopology):
|
||||||
for i in range(len(self.nodes)):
|
for i in range(len(self.nodes)):
|
||||||
int_links.append(IntLink(link_id=(link_count+i),
|
int_links.append(IntLink(link_id=(link_count+i),
|
||||||
src_node=routers[i],
|
src_node=routers[i],
|
||||||
dst_node=xbar))
|
dst_node=xbar,
|
||||||
|
latency = link_latency))
|
||||||
|
|
||||||
link_count += len(self.nodes)
|
link_count += len(self.nodes)
|
||||||
|
|
||||||
for i in range(len(self.nodes)):
|
for i in range(len(self.nodes)):
|
||||||
int_links.append(IntLink(link_id=(link_count+i),
|
int_links.append(IntLink(link_id=(link_count+i),
|
||||||
src_node=xbar,
|
src_node=xbar,
|
||||||
dst_node=routers[i]))
|
dst_node=routers[i],
|
||||||
|
latency = link_latency))
|
||||||
|
|
||||||
network.int_links = int_links
|
network.int_links = int_links
|
||||||
|
|
|
@ -47,6 +47,12 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
num_routers = options.num_cpus
|
num_routers = options.num_cpus
|
||||||
num_rows = options.mesh_rows
|
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
|
# First determine which nodes are cache cntrls vs. dirs vs. dma
|
||||||
cache_nodes = []
|
cache_nodes = []
|
||||||
dir_nodes = []
|
dir_nodes = []
|
||||||
|
@ -64,7 +70,7 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
# and evenly divisible. Also the number of caches must be a
|
# and evenly divisible. Also the number of caches must be a
|
||||||
# multiple of the number of routers and the number of directories
|
# multiple of the number of routers and the number of directories
|
||||||
# must be four.
|
# must be four.
|
||||||
assert(num_rows <= num_routers)
|
assert(num_rows > 0 and num_rows <= num_routers)
|
||||||
num_columns = int(num_routers / num_rows)
|
num_columns = int(num_routers / num_rows)
|
||||||
assert(num_columns * num_rows == num_routers)
|
assert(num_columns * num_rows == num_routers)
|
||||||
caches_per_router, remainder = divmod(len(cache_nodes), 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)
|
assert(len(dir_nodes) == 4)
|
||||||
|
|
||||||
# Create the routers in the mesh
|
# 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
|
network.routers = routers
|
||||||
|
|
||||||
# link counter to set unique link ids
|
# link counter to set unique link ids
|
||||||
|
@ -84,28 +91,34 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
cntrl_level, router_id = divmod(i, num_routers)
|
cntrl_level, router_id = divmod(i, num_routers)
|
||||||
assert(cntrl_level < caches_per_router)
|
assert(cntrl_level < caches_per_router)
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=n,
|
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
|
link_count += 1
|
||||||
|
|
||||||
# Connect the dir nodes to the corners.
|
# Connect the dir nodes to the corners.
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[0],
|
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
|
link_count += 1
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[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
|
link_count += 1
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[2],
|
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
|
link_count += 1
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=dir_nodes[3],
|
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
|
link_count += 1
|
||||||
|
|
||||||
# Connect the dma nodes to router 0. These should only be DMA nodes.
|
# Connect the dma nodes to router 0. These should only be DMA nodes.
|
||||||
for (i, node) in enumerate(dma_nodes):
|
for (i, node) in enumerate(dma_nodes):
|
||||||
assert(node.type == 'DMA_Controller')
|
assert(node.type == 'DMA_Controller')
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=node,
|
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
|
network.ext_links = ext_links
|
||||||
|
|
||||||
|
@ -121,6 +134,9 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[east_out],
|
src_node=routers[east_out],
|
||||||
dst_node=routers[west_in],
|
dst_node=routers[west_in],
|
||||||
|
src_outport="East",
|
||||||
|
dst_inport="West",
|
||||||
|
latency = link_latency,
|
||||||
weight=1))
|
weight=1))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -133,6 +149,9 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[west_out],
|
src_node=routers[west_out],
|
||||||
dst_node=routers[east_in],
|
dst_node=routers[east_in],
|
||||||
|
src_outport="West",
|
||||||
|
dst_inport="East",
|
||||||
|
latency = link_latency,
|
||||||
weight=1))
|
weight=1))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -145,6 +164,9 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[north_out],
|
src_node=routers[north_out],
|
||||||
dst_node=routers[south_in],
|
dst_node=routers[south_in],
|
||||||
|
src_outport="North",
|
||||||
|
dst_inport="South",
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -157,6 +179,9 @@ class MeshDirCorners_XY(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[south_out],
|
src_node=routers[south_out],
|
||||||
dst_node=routers[north_in],
|
dst_node=routers[north_in],
|
||||||
|
src_outport="South",
|
||||||
|
dst_inport="North",
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
|
|
@ -53,15 +53,22 @@ class Mesh_XY(SimpleTopology):
|
||||||
num_routers = options.num_cpus
|
num_routers = options.num_cpus
|
||||||
num_rows = options.mesh_rows
|
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
|
# There must be an evenly divisible number of cntrls to routers
|
||||||
# Also, obviously the number or rows must be <= the number of routers
|
# Also, obviously the number or rows must be <= the number of routers
|
||||||
cntrls_per_router, remainder = divmod(len(nodes), num_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)
|
num_columns = int(num_routers / num_rows)
|
||||||
assert(num_columns * num_rows == num_routers)
|
assert(num_columns * num_rows == num_routers)
|
||||||
|
|
||||||
# Create the routers in the mesh
|
# 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
|
network.routers = routers
|
||||||
|
|
||||||
# link counter to set unique link ids
|
# link counter to set unique link ids
|
||||||
|
@ -83,7 +90,8 @@ class Mesh_XY(SimpleTopology):
|
||||||
cntrl_level, router_id = divmod(i, num_routers)
|
cntrl_level, router_id = divmod(i, num_routers)
|
||||||
assert(cntrl_level < cntrls_per_router)
|
assert(cntrl_level < cntrls_per_router)
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=n,
|
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
|
link_count += 1
|
||||||
|
|
||||||
# Connect the remainding nodes to router 0. These should only be
|
# 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(node.type == 'DMA_Controller')
|
||||||
assert(i < remainder)
|
assert(i < remainder)
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=node,
|
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
|
link_count += 1
|
||||||
|
|
||||||
network.ext_links = ext_links
|
network.ext_links = ext_links
|
||||||
|
@ -111,6 +120,7 @@ class Mesh_XY(SimpleTopology):
|
||||||
dst_node=routers[west_in],
|
dst_node=routers[west_in],
|
||||||
src_outport="East",
|
src_outport="East",
|
||||||
dst_inport="West",
|
dst_inport="West",
|
||||||
|
latency = link_latency,
|
||||||
weight=1))
|
weight=1))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -125,6 +135,7 @@ class Mesh_XY(SimpleTopology):
|
||||||
dst_node=routers[east_in],
|
dst_node=routers[east_in],
|
||||||
src_outport="West",
|
src_outport="West",
|
||||||
dst_inport="East",
|
dst_inport="East",
|
||||||
|
latency = link_latency,
|
||||||
weight=1))
|
weight=1))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -139,6 +150,7 @@ class Mesh_XY(SimpleTopology):
|
||||||
dst_node=routers[south_in],
|
dst_node=routers[south_in],
|
||||||
src_outport="North",
|
src_outport="North",
|
||||||
dst_inport="South",
|
dst_inport="South",
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -153,6 +165,7 @@ class Mesh_XY(SimpleTopology):
|
||||||
dst_node=routers[north_in],
|
dst_node=routers[north_in],
|
||||||
src_outport="South",
|
src_outport="South",
|
||||||
dst_inport="North",
|
dst_inport="North",
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
|
|
@ -58,15 +58,21 @@ class Mesh_westfirst(SimpleTopology):
|
||||||
num_routers = options.num_cpus
|
num_routers = options.num_cpus
|
||||||
num_rows = options.mesh_rows
|
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
|
# There must be an evenly divisible number of cntrls to routers
|
||||||
# Also, obviously the number or rows must be <= the number of routers
|
# Also, obviously the number or rows must be <= the number of routers
|
||||||
cntrls_per_router, remainder = divmod(len(nodes), num_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)
|
num_columns = int(num_routers / num_rows)
|
||||||
assert(num_columns * num_rows == num_routers)
|
assert(num_columns * num_rows == num_routers)
|
||||||
|
|
||||||
# Create the routers in the mesh
|
# 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
|
network.routers = routers
|
||||||
|
|
||||||
# link counter to set unique link ids
|
# link counter to set unique link ids
|
||||||
|
@ -88,7 +94,8 @@ class Mesh_westfirst(SimpleTopology):
|
||||||
cntrl_level, router_id = divmod(i, num_routers)
|
cntrl_level, router_id = divmod(i, num_routers)
|
||||||
assert(cntrl_level < cntrls_per_router)
|
assert(cntrl_level < cntrls_per_router)
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=n,
|
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
|
link_count += 1
|
||||||
|
|
||||||
# Connect the remainding nodes to router 0. These should only be
|
# 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(node.type == 'DMA_Controller')
|
||||||
assert(i < remainder)
|
assert(i < remainder)
|
||||||
ext_links.append(ExtLink(link_id=link_count, ext_node=node,
|
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
|
link_count += 1
|
||||||
|
|
||||||
network.ext_links = ext_links
|
network.ext_links = ext_links
|
||||||
|
@ -114,6 +122,7 @@ class Mesh_westfirst(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[east_out],
|
src_node=routers[east_out],
|
||||||
dst_node=routers[west_in],
|
dst_node=routers[west_in],
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -126,6 +135,7 @@ class Mesh_westfirst(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[west_out],
|
src_node=routers[west_out],
|
||||||
dst_node=routers[east_in],
|
dst_node=routers[east_in],
|
||||||
|
latency = link_latency,
|
||||||
weight=1))
|
weight=1))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -139,6 +149,7 @@ class Mesh_westfirst(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[north_out],
|
src_node=routers[north_out],
|
||||||
dst_node=routers[south_in],
|
dst_node=routers[south_in],
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
@ -151,6 +162,7 @@ class Mesh_westfirst(SimpleTopology):
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[south_out],
|
src_node=routers[south_out],
|
||||||
dst_node=routers[north_in],
|
dst_node=routers[north_in],
|
||||||
|
latency = link_latency,
|
||||||
weight=2))
|
weight=2))
|
||||||
link_count += 1
|
link_count += 1
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,22 @@ class Pt2Pt(SimpleTopology):
|
||||||
def makeTopology(self, options, network, IntLink, ExtLink, Router):
|
def makeTopology(self, options, network, IntLink, ExtLink, Router):
|
||||||
nodes = self.nodes
|
nodes = self.nodes
|
||||||
|
|
||||||
# Create an individual router for each controller, and connect all to all.
|
# default values for link latency and router latency.
|
||||||
routers = [Router(router_id=i) for i in range(len(nodes))]
|
# 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
|
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)]
|
for (i, n) in enumerate(nodes)]
|
||||||
network.ext_links = ext_links
|
network.ext_links = ext_links
|
||||||
|
|
||||||
|
@ -58,6 +69,7 @@ class Pt2Pt(SimpleTopology):
|
||||||
link_count += 1
|
link_count += 1
|
||||||
int_links.append(IntLink(link_id=link_count,
|
int_links.append(IntLink(link_id=link_count,
|
||||||
src_node=routers[i],
|
src_node=routers[i],
|
||||||
dst_node=routers[j]))
|
dst_node=routers[j],
|
||||||
|
latency = link_latency))
|
||||||
|
|
||||||
network.int_links = int_links
|
network.int_links = int_links
|
||||||
|
|
|
@ -34,4 +34,6 @@ class BasicRouter(ClockedObject):
|
||||||
type = 'BasicRouter'
|
type = 'BasicRouter'
|
||||||
cxx_header = "mem/ruby/network/BasicRouter.hh"
|
cxx_header = "mem/ruby/network/BasicRouter.hh"
|
||||||
router_id = Param.Int("ID in relation to other routers")
|
router_id = Param.Int("ID in relation to other routers")
|
||||||
|
|
||||||
|
# only used by garnet
|
||||||
latency = Param.Cycles(1, "number of cycles inside router")
|
latency = Param.Cycles(1, "number of cycles inside router")
|
||||||
|
|
65
src/mem/ruby/network/garnet2.0/CommonTypes.hh
Normal file
65
src/mem/ruby/network/garnet2.0/CommonTypes.hh
Normal 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__
|
46
src/mem/ruby/network/garnet2.0/Credit.cc
Normal file
46
src/mem/ruby/network/garnet2.0/Credit.cc
Normal 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;
|
||||||
|
}
|
60
src/mem/ruby/network/garnet2.0/Credit.hh
Normal file
60
src/mem/ruby/network/garnet2.0/Credit.hh
Normal 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__
|
47
src/mem/ruby/network/garnet2.0/CreditLink.hh
Normal file
47
src/mem/ruby/network/garnet2.0/CreditLink.hh
Normal 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__
|
112
src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc
Normal file
112
src/mem/ruby/network/garnet2.0/CrossbarSwitch.cc
Normal 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;
|
||||||
|
}
|
72
src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh
Normal file
72
src/mem/ruby/network/garnet2.0/CrossbarSwitch.hh
Normal 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__
|
94
src/mem/ruby/network/garnet2.0/GarnetLink.cc
Normal file
94
src/mem/ruby/network/garnet2.0/GarnetLink.cc
Normal 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);
|
||||||
|
}
|
97
src/mem/ruby/network/garnet2.0/GarnetLink.hh
Normal file
97
src/mem/ruby/network/garnet2.0/GarnetLink.hh
Normal 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__
|
79
src/mem/ruby/network/garnet2.0/GarnetLink.py
Normal file
79
src/mem/ruby/network/garnet2.0/GarnetLink.py
Normal 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")
|
460
src/mem/ruby/network/garnet2.0/GarnetNetwork.cc
Normal file
460
src/mem/ruby/network/garnet2.0/GarnetNetwork.cc
Normal 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;
|
||||||
|
}
|
208
src/mem/ruby/network/garnet2.0/GarnetNetwork.hh
Normal file
208
src/mem/ruby/network/garnet2.0/GarnetNetwork.hh
Normal 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__
|
68
src/mem/ruby/network/garnet2.0/GarnetNetwork.py
Normal file
68
src/mem/ruby/network/garnet2.0/GarnetNetwork.py
Normal 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")
|
171
src/mem/ruby/network/garnet2.0/InputUnit.cc
Normal file
171
src/mem/ruby/network/garnet2.0/InputUnit.cc
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
170
src/mem/ruby/network/garnet2.0/InputUnit.hh
Normal file
170
src/mem/ruby/network/garnet2.0/InputUnit.hh
Normal 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__
|
443
src/mem/ruby/network/garnet2.0/NetworkInterface.cc
Normal file
443
src/mem/ruby/network/garnet2.0/NetworkInterface.cc
Normal 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);
|
||||||
|
}
|
108
src/mem/ruby/network/garnet2.0/NetworkInterface.hh
Normal file
108
src/mem/ruby/network/garnet2.0/NetworkInterface.hh
Normal 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__
|
94
src/mem/ruby/network/garnet2.0/NetworkLink.cc
Normal file
94
src/mem/ruby/network/garnet2.0/NetworkLink.cc
Normal 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);
|
||||||
|
}
|
88
src/mem/ruby/network/garnet2.0/NetworkLink.hh
Normal file
88
src/mem/ruby/network/garnet2.0/NetworkLink.hh
Normal 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__
|
65
src/mem/ruby/network/garnet2.0/OutVcState.cc
Normal file
65
src/mem/ruby/network/garnet2.0/OutVcState.cc
Normal 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);
|
||||||
|
}
|
70
src/mem/ruby/network/garnet2.0/OutVcState.hh
Normal file
70
src/mem/ruby/network/garnet2.0/OutVcState.hh
Normal 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__
|
168
src/mem/ruby/network/garnet2.0/OutputUnit.cc
Normal file
168
src/mem/ruby/network/garnet2.0/OutputUnit.cc
Normal 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);
|
||||||
|
}
|
113
src/mem/ruby/network/garnet2.0/OutputUnit.hh
Normal file
113
src/mem/ruby/network/garnet2.0/OutputUnit.hh
Normal 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__
|
71
src/mem/ruby/network/garnet2.0/README.txt
Normal file
71
src/mem/ruby/network/garnet2.0/README.txt
Normal 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.
|
||||||
|
|
||||||
|
|
296
src/mem/ruby/network/garnet2.0/Router.cc
Normal file
296
src/mem/ruby/network/garnet2.0/Router.cc
Normal 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);
|
||||||
|
}
|
140
src/mem/ruby/network/garnet2.0/Router.hh
Normal file
140
src/mem/ruby/network/garnet2.0/Router.hh
Normal 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__
|
241
src/mem/ruby/network/garnet2.0/RoutingUnit.cc
Normal file
241
src/mem/ruby/network/garnet2.0/RoutingUnit.cc
Normal 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);
|
||||||
|
}
|
89
src/mem/ruby/network/garnet2.0/RoutingUnit.hh
Normal file
89
src/mem/ruby/network/garnet2.0/RoutingUnit.hh
Normal 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__
|
53
src/mem/ruby/network/garnet2.0/SConscript
Normal file
53
src/mem/ruby/network/garnet2.0/SConscript
Normal 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')
|
389
src/mem/ruby/network/garnet2.0/SwitchAllocator.cc
Normal file
389
src/mem/ruby/network/garnet2.0/SwitchAllocator.cc
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
src/mem/ruby/network/garnet2.0/SwitchAllocator.hh
Normal file
88
src/mem/ruby/network/garnet2.0/SwitchAllocator.hh
Normal 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__
|
85
src/mem/ruby/network/garnet2.0/VirtualChannel.cc
Normal file
85
src/mem/ruby/network/garnet2.0/VirtualChannel.cc
Normal 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);
|
||||||
|
}
|
101
src/mem/ruby/network/garnet2.0/VirtualChannel.hh
Normal file
101
src/mem/ruby/network/garnet2.0/VirtualChannel.hh
Normal 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__
|
85
src/mem/ruby/network/garnet2.0/flit.cc
Normal file
85
src/mem/ruby/network/garnet2.0/flit.cc
Normal 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);
|
||||||
|
}
|
122
src/mem/ruby/network/garnet2.0/flit.hh
Normal file
122
src/mem/ruby/network/garnet2.0/flit.hh
Normal 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__
|
93
src/mem/ruby/network/garnet2.0/flitBuffer.cc
Normal file
93
src/mem/ruby/network/garnet2.0/flitBuffer.cc
Normal 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;
|
||||||
|
}
|
93
src/mem/ruby/network/garnet2.0/flitBuffer.hh
Normal file
93
src/mem/ruby/network/garnet2.0/flitBuffer.hh
Normal 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__
|
Loading…
Reference in a new issue