stdlib: Add a prebuilt MESI_Three_Level cache
The cache is modeled after an AMD EPYC cache, but not exactly like AMD EPYC cache. - K cores per core complex (CCD), each core has one private split L1, and one private L2. - K cores in the same CCD share 1 slice of L3 cache, which is not a victim cache. - There can be multiple CCDs, which communicate with each other via Cross-CCD router. The Cross-CCD rounter is also connected to directory controllers and dma controllers. - All links latency are set to 1. Change-Id: Ib64248bed9155b8e48e5158ffdeebf1f2d770754 Signed-off-by: Hoa Nguyen <hoanguyen@ucdavis.edu> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71598 Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
committed by
Bobby R. Bruce
parent
872dc8bf59
commit
b9db0976ca
@@ -154,6 +154,18 @@ PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level',
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level',
|
||||
'gem5/components/cachehierarchies/ruby/caches/mesi_three_level/'
|
||||
'l3_cache.py')
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level',
|
||||
'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/'
|
||||
'octopi.py')
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level',
|
||||
'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/'
|
||||
'core_complex.py')
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level',
|
||||
'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/'
|
||||
'octopi_network.py')
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level',
|
||||
'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/'
|
||||
'ruby_network_components.py')
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mi_example',
|
||||
'gem5/components/cachehierarchies/ruby/caches/mi_example/__init__.py')
|
||||
PySource('gem5.components.cachehierarchies.ruby.caches.mi_example',
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2022-2023 The Regents of the University of California
|
||||
# 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.
|
||||
@@ -0,0 +1,245 @@
|
||||
# Copyright (c) 2022-2023 The Regents of the University of California
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from typing import List, Tuple
|
||||
|
||||
from gem5.isas import ISA
|
||||
from gem5.components.boards.abstract_board import AbstractBoard
|
||||
from gem5.components.processors.abstract_core import AbstractCore
|
||||
from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l1_cache import (
|
||||
L1Cache,
|
||||
)
|
||||
from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l2_cache import (
|
||||
L2Cache,
|
||||
)
|
||||
from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l3_cache import (
|
||||
L3Cache,
|
||||
)
|
||||
|
||||
from m5.objects import SubSystem, RubySequencer
|
||||
|
||||
from .ruby_network_components import (
|
||||
RubyRouter,
|
||||
RubyExtLink,
|
||||
RubyIntLink,
|
||||
RubyNetworkComponent,
|
||||
)
|
||||
|
||||
|
||||
class CoreComplex(SubSystem, RubyNetworkComponent):
|
||||
_core_id = 0
|
||||
_core_complex_id = 0
|
||||
|
||||
@classmethod
|
||||
def _get_core_id(cls):
|
||||
cls._core_id += 1
|
||||
return cls._core_id - 1
|
||||
|
||||
@classmethod
|
||||
def _get_core_complex_id(cls):
|
||||
cls._core_complex_id += 1
|
||||
return cls._core_complex_id - 1
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
board: AbstractBoard,
|
||||
cores: List[AbstractCore],
|
||||
ruby_system,
|
||||
l1i_size: str,
|
||||
l1i_assoc: int,
|
||||
l1d_size: str,
|
||||
l1d_assoc: int,
|
||||
l2_size: str,
|
||||
l2_assoc: int,
|
||||
l3_size: str,
|
||||
l3_assoc: int,
|
||||
):
|
||||
SubSystem.__init__(self=self)
|
||||
RubyNetworkComponent.__init__(self=self)
|
||||
|
||||
self._l1i_size = l1i_size
|
||||
self._l1i_assoc = l1i_assoc
|
||||
self._l1d_size = l1d_size
|
||||
self._l1d_assoc = l1d_assoc
|
||||
self._l2_size = l2_size
|
||||
self._l2_assoc = l2_assoc
|
||||
self._l3_size = l3_size
|
||||
self._l3_assoc = l3_assoc
|
||||
|
||||
self._board = board
|
||||
self._cores = cores
|
||||
self._ruby_system = ruby_system
|
||||
self._cache_line_size = 64
|
||||
|
||||
self._directory_controllers = []
|
||||
|
||||
self._core_complex_id = self._get_core_complex_id()
|
||||
self.main_router = RubyRouter(
|
||||
self._ruby_system
|
||||
) # this will be connect to component outside the core complex
|
||||
self._add_router(self.main_router)
|
||||
self._create_core_complex()
|
||||
|
||||
def get_main_router(self):
|
||||
return self.main_router
|
||||
|
||||
def _create_core_complex(self):
|
||||
# Create L1 caches, L2 cache, and corresponding controllers per core
|
||||
self.core_clusters = [
|
||||
self._create_core_cluster(core) for core in self._cores
|
||||
]
|
||||
# Create L3 cache and its corresponding controller
|
||||
self._create_shared_cache()
|
||||
# Setting up one router and one external link per controller
|
||||
self._create_external_links()
|
||||
# Setting up L1/L2 links, L2/main links, L3/main link
|
||||
self._create_internal_links()
|
||||
|
||||
def _create_core_cluster(self, core: AbstractCore):
|
||||
cluster = SubSystem()
|
||||
core_id = self._get_core_id()
|
||||
|
||||
cluster.l1_cache = L1Cache(
|
||||
l1i_size=self._l1i_size,
|
||||
l1i_assoc=self._l1i_assoc,
|
||||
l1d_size=self._l1d_size,
|
||||
l1d_assoc=self._l1d_assoc,
|
||||
network=self._ruby_system.network,
|
||||
core=core,
|
||||
cache_line_size=self._cache_line_size,
|
||||
target_isa=self._board.processor.get_isa(),
|
||||
clk_domain=self._board.get_clock_domain(),
|
||||
)
|
||||
cluster.l1_cache.sequencer = RubySequencer(
|
||||
version=core_id,
|
||||
dcache=cluster.l1_cache.Dcache,
|
||||
clk_domain=cluster.l1_cache.clk_domain,
|
||||
)
|
||||
|
||||
if self._board.has_io_bus():
|
||||
cluster.l1_cache.sequencer.connectIOPorts(self._board.get_io_bus())
|
||||
cluster.l1_cache.ruby_system = self._ruby_system
|
||||
core.connect_icache(cluster.l1_cache.sequencer.in_ports)
|
||||
core.connect_dcache(cluster.l1_cache.sequencer.in_ports)
|
||||
core.connect_walker_ports(
|
||||
cluster.l1_cache.sequencer.in_ports,
|
||||
cluster.l1_cache.sequencer.in_ports,
|
||||
)
|
||||
if self._board.get_processor().get_isa() == ISA.X86:
|
||||
core.connect_interrupt(
|
||||
cluster.l1_cache.sequencer.interrupt_out_port,
|
||||
cluster.l1_cache.sequencer.in_ports,
|
||||
)
|
||||
else:
|
||||
core.connect_interrupt()
|
||||
|
||||
cluster.l2_cache = L2Cache(
|
||||
l2_size=self._l2_size,
|
||||
l2_assoc=self._l2_assoc,
|
||||
network=self._ruby_system.network,
|
||||
core=core,
|
||||
num_l3Caches=1, # each core complex has 1 slice of L3 Cache
|
||||
cache_line_size=self._cache_line_size,
|
||||
cluster_id=self._core_complex_id,
|
||||
target_isa=self._board.processor.get_isa(),
|
||||
clk_domain=self._board.get_clock_domain(),
|
||||
)
|
||||
cluster.l2_cache.ruby_system = self._ruby_system
|
||||
# L0Cache in the ruby backend is l1 cache in stdlib
|
||||
# L1Cache in the ruby backend is l2 cache in stdlib
|
||||
cluster.l2_cache.bufferFromL0 = cluster.l1_cache.bufferToL1
|
||||
cluster.l2_cache.bufferToL0 = cluster.l1_cache.bufferFromL1
|
||||
|
||||
return cluster
|
||||
|
||||
def _create_shared_cache(self):
|
||||
self.l3_cache = L3Cache(
|
||||
l3_size=self._l3_size,
|
||||
l3_assoc=self._l3_assoc,
|
||||
network=self._ruby_system.network,
|
||||
num_l3Caches=1,
|
||||
cache_line_size=self._cache_line_size,
|
||||
cluster_id=self._core_complex_id,
|
||||
)
|
||||
self.l3_cache.ruby_system = self._ruby_system
|
||||
|
||||
# This is where all routers and links are created
|
||||
def _create_external_links(self):
|
||||
# create a router per cache controller
|
||||
# - there is one L3 per ccd
|
||||
self.l3_router = RubyRouter(self._ruby_system)
|
||||
self._add_router(self.l3_router)
|
||||
# - there is one L1 and one L2 per cluster
|
||||
for cluster in self.core_clusters:
|
||||
cluster.l1_router = RubyRouter(self._ruby_system)
|
||||
self._add_router(cluster.l1_router)
|
||||
cluster.l2_router = RubyRouter(self._ruby_system)
|
||||
self._add_router(cluster.l2_router)
|
||||
|
||||
# create an ext link from a controller to a router
|
||||
self.l3_router_link = RubyExtLink(
|
||||
ext_node=self.l3_cache,
|
||||
int_node=self.l3_router,
|
||||
bandwidth_factor=64,
|
||||
)
|
||||
self._add_ext_link(self.l3_router_link)
|
||||
for cluster in self.core_clusters:
|
||||
cluster.l1_router_link = RubyExtLink(
|
||||
ext_node=cluster.l1_cache, int_node=cluster.l1_router
|
||||
)
|
||||
self._add_ext_link(cluster.l1_router_link)
|
||||
cluster.l2_router_link = RubyExtLink(
|
||||
ext_node=cluster.l2_cache, int_node=cluster.l2_router
|
||||
)
|
||||
self._add_ext_link(cluster.l2_router_link)
|
||||
|
||||
def _create_internal_links(self):
|
||||
# create L1/L2 links
|
||||
for cluster in self.core_clusters:
|
||||
l1_to_l2, l2_to_l1 = RubyIntLink.create_bidirectional_links(
|
||||
cluster.l1_router, cluster.l2_router
|
||||
)
|
||||
cluster.l1_to_l2_link = l1_to_l2
|
||||
cluster.l2_to_l1_link = l2_to_l1
|
||||
self._add_int_link(l1_to_l2)
|
||||
self._add_int_link(l2_to_l1)
|
||||
# create L2/main_router links
|
||||
for cluster in self.core_clusters:
|
||||
l2_to_main, main_to_l2 = RubyIntLink.create_bidirectional_links(
|
||||
cluster.l2_router, self.main_router
|
||||
)
|
||||
cluster.l2_to_main_link = l2_to_main
|
||||
cluster.main_to_l2_link = main_to_l2
|
||||
self._add_int_link(l2_to_main)
|
||||
self._add_int_link(main_to_l2)
|
||||
# create L3/main_router link
|
||||
l3_to_main, main_to_l3 = RubyIntLink.create_bidirectional_links(
|
||||
self.l3_router, self.main_router, bandwidth_factor=64
|
||||
)
|
||||
self.l3_to_main_link = l3_to_main
|
||||
self.main_to_l3_link = main_to_l3
|
||||
self._add_int_link(l3_to_main)
|
||||
self._add_int_link(main_to_l3)
|
||||
@@ -0,0 +1,257 @@
|
||||
# Copyright (c) 2022-2023 The Regents of the University of California
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from ...abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy
|
||||
from ....abstract_three_level_cache_hierarchy import (
|
||||
AbstractThreeLevelCacheHierarchy,
|
||||
)
|
||||
from ......coherence_protocol import CoherenceProtocol
|
||||
from ......components.boards.abstract_board import AbstractBoard
|
||||
from ......utils.requires import requires
|
||||
|
||||
from ......components.cachehierarchies.ruby.caches.mesi_three_level.directory import (
|
||||
Directory,
|
||||
)
|
||||
from ......components.cachehierarchies.ruby.caches.mesi_three_level.dma_controller import (
|
||||
DMAController,
|
||||
)
|
||||
|
||||
from m5.objects import RubySystem, DMASequencer, RubyPortProxy
|
||||
|
||||
from .core_complex import CoreComplex
|
||||
from .octopi_network import OctopiNetwork
|
||||
from .ruby_network_components import RubyRouter, RubyExtLink, RubyIntLink
|
||||
|
||||
# CoreComplex sub-systems own the L1, L2, L3 controllers
|
||||
# OctopiCache owns the directory controllers
|
||||
# RubySystem owns the DMA Controllers
|
||||
class OctopiCache(
|
||||
AbstractRubyCacheHierarchy, AbstractThreeLevelCacheHierarchy
|
||||
):
|
||||
def __init__(
|
||||
self,
|
||||
l1i_size: str,
|
||||
l1i_assoc: int,
|
||||
l1d_size: str,
|
||||
l1d_assoc: int,
|
||||
l2_size: str,
|
||||
l2_assoc: int,
|
||||
l3_size: str,
|
||||
l3_assoc: int,
|
||||
num_core_complexes: int,
|
||||
is_fullsystem: bool,
|
||||
):
|
||||
AbstractRubyCacheHierarchy.__init__(self=self)
|
||||
AbstractThreeLevelCacheHierarchy.__init__(
|
||||
self=self,
|
||||
l1i_size=l1i_size,
|
||||
l1i_assoc=l1i_assoc,
|
||||
l1d_size=l1d_size,
|
||||
l1d_assoc=l1d_assoc,
|
||||
l2_size=l2_size,
|
||||
l2_assoc=l2_assoc,
|
||||
l3_size=l3_size,
|
||||
l3_assoc=l3_assoc,
|
||||
)
|
||||
|
||||
self._directory_controllers = []
|
||||
self._dma_controllers = []
|
||||
self._io_controllers = []
|
||||
self._core_complexes = []
|
||||
self._num_core_complexes = num_core_complexes
|
||||
self._is_fullsystem = is_fullsystem
|
||||
|
||||
def incorporate_cache(self, board: AbstractBoard) -> None:
|
||||
|
||||
requires(
|
||||
coherence_protocol_required=CoherenceProtocol.MESI_THREE_LEVEL
|
||||
)
|
||||
|
||||
cache_line_size = board.get_cache_line_size()
|
||||
|
||||
self.ruby_system = RubySystem()
|
||||
# MESI_Three_Level needs 3 virtual networks
|
||||
self.ruby_system.number_of_virtual_networks = 3
|
||||
self.ruby_system.network = OctopiNetwork(self.ruby_system)
|
||||
|
||||
# Setting up the core complex
|
||||
all_cores = board.get_processor().get_cores()
|
||||
num_cores_per_core_complex = len(all_cores) // self._num_core_complexes
|
||||
|
||||
self.core_complexes = [
|
||||
CoreComplex(
|
||||
board=board,
|
||||
cores=all_cores[
|
||||
core_complex_idx
|
||||
* num_cores_per_core_complex : (core_complex_idx + 1)
|
||||
* num_cores_per_core_complex
|
||||
],
|
||||
ruby_system=self.ruby_system,
|
||||
l1i_size=self._l1i_size,
|
||||
l1i_assoc=self._l1i_assoc,
|
||||
l1d_size=self._l1d_size,
|
||||
l1d_assoc=self._l1d_assoc,
|
||||
l2_size=self._l2_size,
|
||||
l2_assoc=self._l2_assoc,
|
||||
l3_size=self._l3_size,
|
||||
l3_assoc=self._l3_assoc,
|
||||
)
|
||||
for core_complex_idx in range(self._num_core_complexes)
|
||||
]
|
||||
|
||||
self.ruby_system.network.incorporate_ccds(self.core_complexes)
|
||||
|
||||
self._create_directory_controllers(board)
|
||||
self._create_dma_controllers(board, self.ruby_system)
|
||||
|
||||
self.ruby_system.num_of_sequencers = (
|
||||
len(all_cores)
|
||||
+ len(self._dma_controllers)
|
||||
+ len(self._io_controllers)
|
||||
)
|
||||
# SimpleNetwork requires .int_links and .routers to exist
|
||||
# if we want to call SimpleNetwork.setup_buffers()
|
||||
self.ruby_system.network.int_links = (
|
||||
self.ruby_system.network._int_links
|
||||
)
|
||||
self.ruby_system.network.ext_links = (
|
||||
self.ruby_system.network._ext_links
|
||||
)
|
||||
self.ruby_system.network.routers = self.ruby_system.network._routers
|
||||
self.ruby_system.network.setup_buffers()
|
||||
|
||||
# Set up a proxy port for the system_port. Used for load binaries and
|
||||
# other functional-only things.
|
||||
self.ruby_system.sys_port_proxy = RubyPortProxy()
|
||||
board.connect_system_port(self.ruby_system.sys_port_proxy.in_ports)
|
||||
|
||||
def _create_directory_controllers(self, board):
|
||||
# Adding controllers
|
||||
self.directory_controllers = [
|
||||
Directory(
|
||||
self.ruby_system.network,
|
||||
board.get_cache_line_size(),
|
||||
addr_range,
|
||||
mem_port,
|
||||
)
|
||||
for addr_range, mem_port in board.get_mem_ports()
|
||||
]
|
||||
for ctrl in self.directory_controllers:
|
||||
ctrl.ruby_system = self.ruby_system
|
||||
# Adding controller routers
|
||||
self.directory_controller_routers = [
|
||||
RubyRouter(self.ruby_system.network)
|
||||
for _ in range(len(self.directory_controllers))
|
||||
]
|
||||
for router in self.directory_controller_routers:
|
||||
self.ruby_system.network._add_router(router)
|
||||
# Adding an external link for each controller and its router
|
||||
self.directory_controller_ext_links = [
|
||||
RubyExtLink(ext_node=dir_ctrl, int_node=dir_router)
|
||||
for dir_ctrl, dir_router in zip(
|
||||
self.directory_controllers, self.directory_controller_routers
|
||||
)
|
||||
]
|
||||
for ext_link in self.directory_controller_ext_links:
|
||||
self.ruby_system.network._add_ext_link(ext_link)
|
||||
_directory_controller_int_links = []
|
||||
for router in self.directory_controller_routers:
|
||||
int_link_1, int_link_2 = RubyIntLink.create_bidirectional_links(
|
||||
router, self.ruby_system.network.cross_ccd_router
|
||||
)
|
||||
_directory_controller_int_links.extend([int_link_1, int_link_2])
|
||||
self.ruby_system.network._add_int_link(int_link_1)
|
||||
self.ruby_system.network._add_int_link(int_link_2)
|
||||
self.directory_controller_int_links = _directory_controller_int_links
|
||||
|
||||
def _create_dma_controllers(self, board, ruby_system):
|
||||
# IOController for full system simulation
|
||||
if self._is_fullsystem:
|
||||
self.io_sequencer = DMASequencer(
|
||||
version=0, ruby_system=self.ruby_system
|
||||
)
|
||||
self.io_sequencer.in_ports = board.get_mem_side_coherent_io_port()
|
||||
self.ruby_system.io_controller = DMAController(
|
||||
dma_sequencer=self.io_sequencer, ruby_system=self.ruby_system
|
||||
)
|
||||
self._io_controllers.append(self.ruby_system.io_controller)
|
||||
self.io_controller_router = RubyRouter(self.ruby_system.network)
|
||||
self.ruby_system.network._add_router(self.io_controller_router)
|
||||
self.io_controller_ext_link = RubyExtLink(
|
||||
ext_node=self._io_controllers[0],
|
||||
int_node=self.io_controller_router,
|
||||
)
|
||||
self.ruby_system.network._add_ext_link(self.io_controller_ext_link)
|
||||
self.io_controller_int_links = (
|
||||
RubyIntLink.create_bidirectional_links(
|
||||
self.io_controller_router,
|
||||
self.ruby_system.network.cross_ccd_router,
|
||||
)
|
||||
)
|
||||
self.ruby_system.network._add_int_link(
|
||||
self.io_controller_int_links[0]
|
||||
)
|
||||
self.ruby_system.network._add_int_link(
|
||||
self.io_controller_int_links[1]
|
||||
)
|
||||
|
||||
self._dma_controllers = []
|
||||
if board.has_dma_ports():
|
||||
self.ruby_system.dma_controllers = [
|
||||
DMAController(
|
||||
dma_sequencer=DMASequencer(version=i + 1, in_ports=port),
|
||||
ruby_system=self.ruby_system,
|
||||
)
|
||||
for i, port in enumerate(board.get_dma_ports())
|
||||
]
|
||||
self._dma_controllers = self.ruby_system.dma_controllers
|
||||
self.dma_routers = [
|
||||
RubyRouter(self.ruby_system.network)
|
||||
for dma_controller in self._dma_controllers
|
||||
]
|
||||
for dma_router in self.dma_routers:
|
||||
self.ruby_system.network._add_router(dma_router)
|
||||
self.dma_ext_links = [
|
||||
RubyExtLink(ext_node=dma_controller, int_node=dma_router)
|
||||
for dma_controller, dma_router in zip(
|
||||
self._dma_controllers, self.dma_routers
|
||||
)
|
||||
]
|
||||
for link in self.dma_ext_links:
|
||||
self.ruby_system.network._add_ext_link(link)
|
||||
self.dma_int_links = [
|
||||
RubyIntLink(
|
||||
dma_router, self.ruby_system.network.cross_ccd_router
|
||||
)
|
||||
for dma_router in self.dma_routers
|
||||
] + [
|
||||
RubyIntLink(
|
||||
self.ruby_system.network.cross_ccd_router, dma_router
|
||||
)
|
||||
for dma_router in self.dma_routers
|
||||
]
|
||||
for link in self.dma_int_links:
|
||||
self.ruby_system.network._add_int_link(link)
|
||||
@@ -0,0 +1,67 @@
|
||||
# Copyright (c) 2022-2023 The Regents of the University of California
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from m5.objects import SimpleNetwork
|
||||
|
||||
from .ruby_network_components import (
|
||||
RubyNetworkComponent,
|
||||
RubyRouter,
|
||||
RubyIntLink,
|
||||
)
|
||||
|
||||
# . The Network owns all routers, all int links and all ext links that are not in CCD's.
|
||||
# . The CCD subsystems are not of type RubyNetwork, so we need to copy the references of
|
||||
# routers and links to OctopiNetwork._routers, ._int_links, and ._ext_links; which will
|
||||
# be, in turns, copied to RubyNetwork.routers, .int_links, and .ext_links respectively.
|
||||
class OctopiNetwork(SimpleNetwork, RubyNetworkComponent):
|
||||
def __init__(self, ruby_system):
|
||||
SimpleNetwork.__init__(self=self)
|
||||
RubyNetworkComponent.__init__(self=self)
|
||||
self.netifs = []
|
||||
self.ruby_system = ruby_system
|
||||
self.number_of_virtual_networks = (
|
||||
ruby_system.number_of_virtual_networks
|
||||
)
|
||||
|
||||
self.cross_ccd_router = RubyRouter(self)
|
||||
self._add_router(self.cross_ccd_router)
|
||||
|
||||
def connect_ccd_routers_to_cross_ccd_router(self, ccds):
|
||||
for ccd in ccds:
|
||||
int_link_1, int_link_2 = RubyIntLink.create_bidirectional_links(
|
||||
self.cross_ccd_router,
|
||||
ccd.get_main_router(),
|
||||
bandwidth_factor=64,
|
||||
)
|
||||
ccd.to_cross_ccd_router_link = int_link_1
|
||||
ccd.from_cross_ccd_router_link = int_link_2
|
||||
self._add_int_link(int_link_1)
|
||||
self._add_int_link(int_link_2)
|
||||
|
||||
def incorporate_ccds(self, ccds):
|
||||
for ccd in ccds:
|
||||
self.incorporate_ruby_subsystem(ccd)
|
||||
self.connect_ccd_routers_to_cross_ccd_router(ccds)
|
||||
@@ -0,0 +1,111 @@
|
||||
# Copyright (c) 2022-2023 The Regents of the University of California
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from m5.objects import Switch, SimpleIntLink, SimpleExtLink
|
||||
|
||||
|
||||
class RubyNetworkComponent:
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._routers = []
|
||||
self._ext_links = []
|
||||
self._int_links = []
|
||||
|
||||
def _add_router(self, router):
|
||||
self._routers.append(router)
|
||||
|
||||
def _add_ext_link(self, link):
|
||||
self._ext_links.append(link)
|
||||
|
||||
def _add_int_link(self, link):
|
||||
self._int_links.append(link)
|
||||
|
||||
def get_routers(self):
|
||||
return self._routers
|
||||
|
||||
def get_ext_links(self):
|
||||
return self._ext_links
|
||||
|
||||
def get_int_links(self):
|
||||
return self._int_links
|
||||
|
||||
def incorporate_ruby_subsystem(self, other_ruby_subsystem):
|
||||
self._routers.extend(other_ruby_subsystem.get_routers())
|
||||
self._ext_links.extend(other_ruby_subsystem.get_ext_links())
|
||||
self._int_links.extend(other_ruby_subsystem.get_int_links())
|
||||
|
||||
|
||||
class RubyRouter(Switch):
|
||||
_router_id = 0
|
||||
|
||||
@classmethod
|
||||
def _get_router_id(cls):
|
||||
cls._router_id += 1
|
||||
return cls._router_id - 1
|
||||
|
||||
def __init__(self, network):
|
||||
super().__init__()
|
||||
self.router_id = self._get_router_id()
|
||||
self.virt_nets = network.number_of_virtual_networks
|
||||
|
||||
|
||||
class RubyExtLink(SimpleExtLink):
|
||||
_link_id = 0
|
||||
|
||||
@classmethod
|
||||
def _get_link_id(cls):
|
||||
cls._link_id += 1
|
||||
return cls._link_id - 1
|
||||
|
||||
def __init__(self, ext_node, int_node, bandwidth_factor=16):
|
||||
super().__init__()
|
||||
self.link_id = self._get_link_id()
|
||||
self.ext_node = ext_node
|
||||
self.int_node = int_node
|
||||
self.bandwidth_factor = bandwidth_factor
|
||||
|
||||
|
||||
class RubyIntLink(SimpleIntLink):
|
||||
_link_id = 0
|
||||
|
||||
@classmethod
|
||||
def _get_link_id(cls):
|
||||
cls._link_id += 1
|
||||
return cls._link_id - 1
|
||||
|
||||
@classmethod
|
||||
def create_bidirectional_links(cls, node_1, node_2, bandwidth_factor=16):
|
||||
return [
|
||||
RubyIntLink(node_1, node_2, bandwidth_factor),
|
||||
RubyIntLink(node_2, node_1, bandwidth_factor),
|
||||
]
|
||||
|
||||
def __init__(self, src_node, dst_node, bandwidth_factor=16):
|
||||
super().__init__()
|
||||
self.link_id = self._get_link_id()
|
||||
self.src_node = src_node
|
||||
self.dst_node = dst_node
|
||||
self.bandwidth_factor = bandwidth_factor
|
||||
Reference in New Issue
Block a user