HN
Hoa Nguyen (Gerrit)
Tue, Jun 13, 2023 9:09 PM
Hoa Nguyen has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/71598?usp=email )
Change subject: stdlib: Add a prebuilt MESI_Three_Level cache
......................................................................
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
M src/python/SConscript
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/init.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
M
src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
7 files changed, 616 insertions(+), 1 deletion(-)
diff --git a/src/python/SConscript b/src/python/SConscript
index f98b570..47901fd 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -154,6 +154,18 @@
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',
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
new file mode 100644
index 0000000..96a68da
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
@@ -0,0 +1,237 @@
+from ...abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy
+from ....abstract_three_level_cache_hierarchy import (
- AbstractThreeLevelCacheHierarchy,
+)
+from ......coherence_protocol import CoherenceProtocol
+from ......isas import ISA
+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 (
- RubyNetworkComponent,
- 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
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()
ruby_system=self.ruby_system
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)
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/init.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/init.py
new file mode 100644
index 0000000..4c92ffe
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/init.py
@@ -0,0 +1 @@
+from Octopi import OctopiCache
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
new file mode 100644
index 0000000..7d133ea
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
@@ -0,0 +1,235 @@
+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.abstract_three_level_cache_hierarchy
import (
- AbstractThreeLevelCacheHierarchy,
+)
+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
gem5.components.cachehierarchies.ruby.caches.mesi_three_level.directory
import (
- Directory,
+)
+from m5.objects import (
- SubSystem,
- L2Cache_Controller,
- AddrRange,
- RubySequencer,
- Switch,
- SimpleIntLink,
- SimpleExtLink,
- SubSystem,
- SimObject,
+)
+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)
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
new file mode 100644
index 0000000..e6b9f93
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
@@ -0,0 +1,45 @@
+from .ruby_network_components import (
- RubyNetworkComponent,
- RubyExtLink,
- RubyIntLink,
- RubyRouter,
+)
+from m5.objects import SimpleNetwork
+
+# . 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.
+#
+# Terms: "connect" -> create int links
+# "incorporate" -> copy references of routers and links, create
routers/links if necessary
+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)
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
new file mode 100644
index 0000000..fa07efd
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
@@ -0,0 +1,85 @@
+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):
+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
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
b/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
index 89b6b21..ff572ac 100644
a/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
+++
b/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
@@ -30,7 +30,7 @@
AbstractThreeLevelCacheHierarchy,
)
from ....coherence_protocol import CoherenceProtocol
-from ....isas import ISA
+from ......isas import ISA
from ...boards.abstract_board import AbstractBoard
from ....utils.requires import requires
--
To view, visit
https://gem5-review.googlesource.com/c/public/gem5/+/71598?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ib64248bed9155b8e48e5158ffdeebf1f2d770754
Gerrit-Change-Number: 71598
Gerrit-PatchSet: 1
Gerrit-Owner: Hoa Nguyen hoanguyen@ucdavis.edu
Hoa Nguyen has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/71598?usp=email )
Change subject: stdlib: Add a prebuilt MESI_Three_Level cache
......................................................................
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>
---
M src/python/SConscript
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
A
src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
M
src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
7 files changed, 616 insertions(+), 1 deletion(-)
diff --git a/src/python/SConscript b/src/python/SConscript
index f98b570..47901fd 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -154,6 +154,18 @@
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',
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
new file mode 100644
index 0000000..96a68da
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/Octopi.py
@@ -0,0 +1,237 @@
+from ...abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy
+from ....abstract_three_level_cache_hierarchy import (
+ AbstractThreeLevelCacheHierarchy,
+)
+from ......coherence_protocol import CoherenceProtocol
+from ......isas import ISA
+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 (
+ RubyNetworkComponent,
+ 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)
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py
new file mode 100644
index 0000000..4c92ffe
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py
@@ -0,0 +1 @@
+from Octopi import OctopiCache
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
new file mode 100644
index 0000000..7d133ea
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
@@ -0,0 +1,235 @@
+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.abstract_three_level_cache_hierarchy
import (
+ AbstractThreeLevelCacheHierarchy,
+)
+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
gem5.components.cachehierarchies.ruby.caches.mesi_three_level.directory
import (
+ Directory,
+)
+
+from m5.objects import (
+ SubSystem,
+ L2Cache_Controller,
+ AddrRange,
+ RubySequencer,
+ Switch,
+ SimpleIntLink,
+ SimpleExtLink,
+ SubSystem,
+ SimObject,
+)
+
+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)
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
new file mode 100644
index 0000000..e6b9f93
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
@@ -0,0 +1,45 @@
+from .ruby_network_components import (
+ RubyNetworkComponent,
+ RubyExtLink,
+ RubyIntLink,
+ RubyRouter,
+)
+
+from m5.objects import SimpleNetwork
+
+# . 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.
+#
+# Terms: "connect" -> create int links
+# "incorporate" -> copy references of routers and links, create
routers/links if necessary
+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)
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
new file mode 100644
index 0000000..fa07efd
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
@@ -0,0 +1,85 @@
+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
diff --git
a/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
b/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
index 89b6b21..ff572ac 100644
---
a/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
+++
b/src/python/gem5/components/cachehierarchies/ruby/mesi_three_level_cache_hierarchy.py
@@ -30,7 +30,7 @@
AbstractThreeLevelCacheHierarchy,
)
from ....coherence_protocol import CoherenceProtocol
-from ....isas import ISA
+from ......isas import ISA
from ...boards.abstract_board import AbstractBoard
from ....utils.requires import requires
--
To view, visit
https://gem5-review.googlesource.com/c/public/gem5/+/71598?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ib64248bed9155b8e48e5158ffdeebf1f2d770754
Gerrit-Change-Number: 71598
Gerrit-PatchSet: 1
Gerrit-Owner: Hoa Nguyen <hoanguyen@ucdavis.edu>