Hoa Nguyen has submitted this change. ( 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 <hoangu...@ucdavis.edu>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71598
Maintainer: Jason Lowe-Power <power...@gmail.com>
Tested-by: kokoro <noreply+kok...@google.com>
Reviewed-by: Jason Lowe-Power <power...@gmail.com>
---
M src/python/SConscript
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.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
6 files changed, 717 insertions(+), 0 deletions(-)

Approvals:
  Jason Lowe-Power: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass




diff --git a/src/python/SConscript b/src/python/SConscript
index f98b570..ea9d3d4 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/__init__.py b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py
new file mode 100644
index 0000000..b08f46b
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py
@@ -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.
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..f056d76
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py
@@ -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)
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..9c8b93d
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi.py
@@ -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)
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..745ef82
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py
@@ -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)
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..8a413ea
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py
@@ -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

--
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: merged
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ib64248bed9155b8e48e5158ffdeebf1f2d770754
Gerrit-Change-Number: 71598
Gerrit-PatchSet: 5
Gerrit-Owner: Hoa Nguyen <hoangu...@ucdavis.edu>
Gerrit-Reviewer: Bobby Bruce <bbr...@ucdavis.edu>
Gerrit-Reviewer: Hoa Nguyen <hoangu...@ucdavis.edu>
Gerrit-Reviewer: Jason Lowe-Power <power...@gmail.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-CC: Matthew Poremba <matthew.pore...@amd.com>
Gerrit-CC: kokoro <noreply+kok...@google.com>
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to