gem5-dev@gem5.org

The gem5 Developer List

View all threads

[L] Change in gem5/gem5[develop]: stdlib: Add a prebuilt MESI_Three_Level cache

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

  •    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

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>