Jason Lowe-Power has submitted this change. (
https://gem5-review.googlesource.com/c/public/gem5/+/52463 )
Change subject: stdlib,mem-ruby: CHI support in components
......................................................................
stdlib,mem-ruby: CHI support in components
This changeset adds CHI support in the components library. Currently,
only a very simple one level protocol is implemented, but hopefully this
design will be able to scale to other more complex hierarchies.
I've tested this with RISC-V with 1 and 4 cores and with x86 with 1
core. Since we don't have an Arm-compatible board, I haven't tested with
ARM. Note that x86 with more than 1 core boots most of the way, but it
hangs during systemd (the kernel comes up completely).
Change-Id: I56953238c6b0ca5ac754b103a1b6ec05a85a0af5
Signed-off-by: Jason Lowe-Power <ja...@lowepower.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52463
Reviewed-by: Tiago Mück <tiago.m...@arm.com>
Reviewed-by: Bobby R. Bruce <bbr...@ucdavis.edu>
Maintainer: Jason Lowe-Power <power...@gmail.com>
Maintainer: Bobby R. Bruce <bbr...@ucdavis.edu>
Tested-by: kokoro <noreply+kok...@google.com>
---
A src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py
A src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py
A
src/python/gem5/components/cachehierarchies/chi/nodes/private_l1_moesi_cache.py
M src/python/SConscript
A src/python/gem5/components/cachehierarchies/chi/nodes/__init__.py
A src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py
A src/python/gem5/components/cachehierarchies/chi/__init__.py
A src/python/gem5/components/cachehierarchies/chi/nodes/directory.py
A
src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py
9 files changed, 759 insertions(+), 0 deletions(-)
Approvals:
Tiago Mück: Looks good to me, approved
Bobby R. Bruce: Looks good to me, approved; Looks good to me, approved
Jason Lowe-Power: Looks good to me, approved
kokoro: Regressions pass
diff --git a/src/python/SConscript b/src/python/SConscript
index d210960..f9b74c0 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -50,6 +50,22 @@
'gem5/components/cachehierarchies/abstract_cache_hierarchy.py')
PySource('gem5.components.cachehierarchies',
'gem5/components/cachehierarchies/abstract_two_level_cache_hierarchy.py')
+PySource('gem5.components.cachehierarchies.chi',
+ 'gem5/components/cachehierarchies/chi/__init__.py')
+PySource('gem5.components.cachehierarchies.chi',
+ 'gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py')
+PySource('gem5.components.cachehierarchies.chi.nodes',
+ 'gem5/components/cachehierarchies/chi/nodes/__init__.py')
+PySource('gem5.components.cachehierarchies.chi.nodes',
+ 'gem5/components/cachehierarchies/chi/nodes/abstract_node.py')
+PySource('gem5.components.cachehierarchies.chi.nodes',
+ 'gem5/components/cachehierarchies/chi/nodes/directory.py')
+PySource('gem5.components.cachehierarchies.chi.nodes',
+ 'gem5/components/cachehierarchies/chi/nodes/dma_requestor.py')
+PySource('gem5.components.cachehierarchies.chi.nodes',
+ 'gem5/components/cachehierarchies/chi/nodes/private_l1_moesi_cache.py')
+PySource('gem5.components.cachehierarchies.chi.nodes',
+ 'gem5/components/cachehierarchies/chi/nodes/memory_controller.py')
PySource('gem5.components.cachehierarchies.classic',
'gem5/components/cachehierarchies/classic/__init__.py')
PySource('gem5.components.cachehierarchies.classic',
diff --git a/src/python/gem5/components/cachehierarchies/chi/__init__.py
b/src/python/gem5/components/cachehierarchies/chi/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/chi/__init__.py
diff --git
a/src/python/gem5/components/cachehierarchies/chi/nodes/__init__.py
b/src/python/gem5/components/cachehierarchies/chi/nodes/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/chi/nodes/__init__.py
diff --git
a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py
b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py
new file mode 100644
index 0000000..e8797b6
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py
@@ -0,0 +1,132 @@
+# Copyright (c) 2021 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 abc import abstractmethod
+from gem5.isas import ISA
+from gem5.components.processors.cpu_types import CPUTypes
+from gem5.components.processors.abstract_core import AbstractCore
+
+from m5.objects import Cache_Controller, MessageBuffer, RubyNetwork
+
+import math
+
+class TriggerMessageBuffer(MessageBuffer):
+ '''
+ MessageBuffer for triggering internal controller events.
+ These buffers should not be affected by the Ruby tester randomization
+ and allow poping messages enqueued in the same cycle.
+ '''
+ randomization = 'disabled'
+ allow_zero_latency = True
+
+class OrderedTriggerMessageBuffer(TriggerMessageBuffer):
+ ordered = True
+
+class AbstractNode(Cache_Controller):
+ """A node is the abstract unit for caches in the CHI protocol.
+
+ You can extend the AbstractNode to create caches (private or shared)
and
+ directories with or without data caches.
+ """
+ _version = 0
+
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ # TODO: I don't love that we have to pass in the cache line size.
+ # However, we need some way to set the index bits
+ def __init__(self, network: RubyNetwork, cache_line_size: int):
+ super(AbstractNode, self).__init__()
+
+ # Note: Need to call versionCount method on *this* class, not the
+ # potentially derived class
+ self.version = AbstractNode.versionCount()
+ self._cache_line_size = cache_line_size
+
+ # Set somewhat large number since we really a lot on internal
+ # triggers. To limit the controller performance, tweak other
+ # params such as: input port buffer size, cache banks, and output
+ # port latency
+ self.transitions_per_cycle = 128
+ # This should be set to true in the data cache controller to enable
+ # timeouts on unique lines when a store conditional fails
+ self.sc_lock_enabled = False
+
+ # Use 32-byte channels (two flits per message)
+ self.data_channel_size = 32
+
+ self.connectQueues(network)
+
+ def getBlockSizeBits(self):
+ bits = int(math.log(self._cache_line_size, 2))
+ if 2 ** bits != self._cache_line_size.value:
+ raise Exception("Cache line size not a power of 2!")
+ return bits
+
+ def sendEvicts(self, core: AbstractCore, target_isa: ISA):
+ """True if the CPU model or ISA requires sending evictions from
caches
+ to the CPU. Scenarios warrant forwarding evictions to the CPU:
+ 1. The O3 model must keep the LSQ coherent with the caches
+ 2. The x86 mwait instruction is built on top of coherence
+ 3. The local exclusive monitor in ARM systems
+ """
+ if core.get_type() is CPUTypes.O3 or target_isa in (ISA.X86,
ISA.ARM):
+ return True
+ return False
+
+ def connectQueues(self, network: RubyNetwork):
+ """Connect all of the queues for this controller.
+ This may be extended in subclasses.
+ """
+ self.mandatoryQueue = MessageBuffer()
+ self.prefetchQueue = MessageBuffer()
+
+ self.triggerQueue = TriggerMessageBuffer()
+ self.retryTriggerQueue = OrderedTriggerMessageBuffer()
+ self.replTriggerQueue = OrderedTriggerMessageBuffer()
+ self.reqRdy = TriggerMessageBuffer()
+ self.snpRdy = TriggerMessageBuffer()
+
+ self.reqOut = MessageBuffer()
+ self.rspOut = MessageBuffer()
+ self.snpOut = MessageBuffer()
+ self.datOut = MessageBuffer()
+ self.reqIn = MessageBuffer()
+ self.rspIn = MessageBuffer()
+ self.snpIn = MessageBuffer()
+ self.datIn = MessageBuffer()
+ self.reqOut.out_port = network.in_port
+ self.rspOut.out_port = network.in_port
+ self.snpOut.out_port = network.in_port
+ self.datOut.out_port = network.in_port
+ self.reqIn.in_port = network.out_port
+ self.rspIn.in_port = network.out_port
+ self.snpIn.in_port = network.out_port
+ self.datIn.in_port = network.out_port
+
+
diff --git
a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py
b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py
new file mode 100644
index 0000000..8f1275c
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2021 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_node import AbstractNode
+
+from m5.objects import (
+ ClockDomain,
+ NULL,
+ RubyCache,
+ RubyNetwork,
+)
+
+class SimpleDirectory(AbstractNode):
+ """A directory or home node (HNF)
+
+ This simple directory has no cache. It forwards all requests as
directly
+ as possible.
+ """
+ def __init__(
+ self,
+ network: RubyNetwork,
+ cache_line_size: int,
+ clk_domain: ClockDomain,
+ ):
+ super().__init__(network, cache_line_size)
+
+ # Dummy cache
+ self.cache = RubyCache(
+ dataAccessLatency = 0,
+ tagAccessLatency = 1,
+ size = "128",
+ assoc = 1
+ )
+
+ self.clk_domain = clk_domain
+
+ # Only used for L1 controllers
+ self.send_evictions = False
+ self.sequencer = NULL
+
+ self.use_prefetcher = False
+
+ # Set up home node that allows three hop protocols
+ self.is_HN = True
+ self.enable_DMT = True
+ self.enable_DCT = True
+
+ # "Owned state"
+ self.allow_SD = True
+
+ # No cache
+ self.alloc_on_seq_acc = False
+ self.alloc_on_seq_line_write = False
+ self.alloc_on_readshared = False
+ self.alloc_on_readunique = False
+ self.alloc_on_readonce = False
+ self.alloc_on_writeback = False
+ self.dealloc_on_unique = False
+ self.dealloc_on_shared = False
+ self.dealloc_backinv_unique = False
+ self.dealloc_backinv_shared = False
+
+ # Some reasonable default TBE params
+ self.number_of_TBEs = 32
+ self.number_of_repl_TBEs = 32
+ self.number_of_snoop_TBEs = 1
+ self.unify_repl_TBEs = False
diff --git
a/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py
b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py
new file mode 100644
index 0000000..7543e06
--- /dev/null
+++ b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2021 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 gem5.components.processors.abstract_core import AbstractCore
+from gem5.isas import ISA
+
+from .abstract_node import AbstractNode
+
+from m5.objects import (
+ ClockDomain,
+ RubyCache,
+)
+
+class DMARequestor(AbstractNode):
+ def __init__(
+ self,
+ network,
+ cache_line_size,
+ clk_domain: ClockDomain,
+ ):
+ super().__init__(network, cache_line_size)
+
+ # Dummy cache
+ self.cache = RubyCache(
+ dataAccessLatency = 0,
+ tagAccessLatency = 1,
+ size = "128",
+ assoc = 1
+ )
+
+ self.clk_domain = clk_domain
+
+ # Only applies to home nodes
+ self.is_HN = False
+ self.enable_DMT = False
+ self.enable_DCT = False
+
+ # No cache
+ self.allow_SD = False
+ self.alloc_on_seq_acc = False
+ self.alloc_on_seq_line_write = False
+ self.alloc_on_readshared = False
+ self.alloc_on_readunique = False
+ self.alloc_on_readonce = False
+ self.alloc_on_writeback = False
+ self.dealloc_on_unique = False
+ self.dealloc_on_shared = False
+ self.dealloc_backinv_unique = True
+ self.dealloc_backinv_shared = True
+
+ self.send_evictions = False
+ self.use_prefetcher = False
+ # Some reasonable default TBE params
+ self.number_of_TBEs = 16
+ self.number_of_repl_TBEs = 1
+ self.number_of_snoop_TBEs = 1 # Should never receive snoops
+ self.unify_repl_TBEs = False
diff --git
a/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py
b/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py
new file mode 100644
index 0000000..cf7d660
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py
@@ -0,0 +1,86 @@
+# Copyright (c) 2021 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
+
+from m5.objects import (
+ AddrRange,
+ Memory_Controller,
+ MessageBuffer,
+ Port,
+ RubyNetwork,
+)
+
+from .abstract_node import TriggerMessageBuffer
+
+class MemoryController(Memory_Controller):
+ """A controller that connects to memory
+ """
+ _version = 0
+
+ @classmethod
+ def versionCount(cls):
+ cls._version += 1 # Use count for this particular type
+ return cls._version - 1
+
+ def __init__(
+ self,
+ network: RubyNetwork,
+ ranges: List[AddrRange],
+ port: Port
+ ):
+ super().__init__()
+
+ self.version = self.versionCount()
+
+ self.addr_ranges = ranges
+ self.memory_out_port = port
+ self.data_channel_size = 32
+
+ self.connectQueues(network)
+
+ def connectQueues(self, network):
+ self.triggerQueue = TriggerMessageBuffer()
+ self.responseFromMemory = MessageBuffer()
+ self.requestToMemory = MessageBuffer(ordered = True)
+ self.reqRdy = TriggerMessageBuffer()
+
+ self.reqOut = MessageBuffer()
+ self.rspOut = MessageBuffer()
+ self.snpOut = MessageBuffer()
+ self.datOut = MessageBuffer()
+ self.reqIn = MessageBuffer()
+ self.rspIn = MessageBuffer()
+ self.snpIn = MessageBuffer()
+ self.datIn = MessageBuffer()
+ self.reqOut.out_port = network.in_port
+ self.rspOut.out_port = network.in_port
+ self.snpOut.out_port = network.in_port
+ self.datOut.out_port = network.in_port
+ self.reqIn.in_port = network.out_port
+ self.rspIn.in_port = network.out_port
+ self.snpIn.in_port = network.out_port
+ self.datIn.in_port = network.out_port
diff --git
a/src/python/gem5/components/cachehierarchies/chi/nodes/private_l1_moesi_cache.py
b/src/python/gem5/components/cachehierarchies/chi/nodes/private_l1_moesi_cache.py
new file mode 100644
index 0000000..664522e
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/chi/nodes/private_l1_moesi_cache.py
@@ -0,0 +1,81 @@
+# Copyright (c) 2021 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 gem5.components.processors.abstract_core import AbstractCore
+from gem5.isas import ISA
+
+from .abstract_node import AbstractNode
+
+from m5.objects import (
+ ClockDomain,
+ RubyCache,
+ RubyNetwork,
+)
+
+
+class PrivateL1MOESICache(AbstractNode):
+ def __init__(
+ self,
+ size: str,
+ assoc: int,
+ network: RubyNetwork,
+ core: AbstractCore,
+ cache_line_size,
+ target_isa: ISA,
+ clk_domain: ClockDomain,
+ ):
+ super().__init__(network, cache_line_size)
+
+ self.cache = RubyCache(
+ size=size, assoc=assoc, start_index_bit=self.getBlockSizeBits()
+ )
+
+ self.clk_domain = clk_domain
+ self.send_evictions = self.sendEvicts(core=core,
target_isa=target_isa)
+ self.use_prefetcher = False
+
+ # Only applies to home nodes
+ self.is_HN = False
+ self.enable_DMT = False
+ self.enable_DCT = False
+
+ # MOESI states for a 1 level cache
+ self.allow_SD = True
+ self.alloc_on_seq_acc = True
+ self.alloc_on_seq_line_write = False
+ self.alloc_on_readshared = True
+ self.alloc_on_readunique = True
+ self.alloc_on_readonce = True
+ self.alloc_on_writeback = False # Should never happen in an
L1
+ self.dealloc_on_unique = False
+ self.dealloc_on_shared = False
+ self.dealloc_backinv_unique = True
+ self.dealloc_backinv_shared = True
+ # Some reasonable default TBE params
+ self.number_of_TBEs = 16
+ self.number_of_repl_TBEs = 16
+ self.number_of_snoop_TBEs = 4
+ self.unify_repl_TBEs = False
diff --git
a/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py
b/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py
new file mode 100644
index 0000000..d692710
--- /dev/null
+++
b/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py
@@ -0,0 +1,249 @@
+# Copyright (c) 2021 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 itertools import chain
+from typing import List
+
+from m5.objects.SubSystem import SubSystem
+from gem5.components.cachehierarchies.ruby.abstract_ruby_cache_hierarchy \
+ import AbstractRubyCacheHierarchy
+from gem5.components.cachehierarchies.abstract_cache_hierarchy import (
+ AbstractCacheHierarchy,
+)
+from gem5.coherence_protocol import CoherenceProtocol
+from gem5.isas import ISA
+from gem5.runtime import get_runtime_isa
+from gem5.utils.requires import requires
+from gem5.utils.override import overrides
+from gem5.components.boards.abstract_board import AbstractBoard
+from gem5.components.processors.abstract_core import AbstractCore
+
+from gem5.components.cachehierarchies.ruby.topologies.simple_pt2pt import (
+ SimplePt2Pt,
+)
+
+from .nodes.private_l1_moesi_cache import PrivateL1MOESICache
+from .nodes.dma_requestor import DMARequestor
+from .nodes.directory import SimpleDirectory
+from .nodes.memory_controller import MemoryController
+
+from m5.objects import (
+ NULL,
+ RubySystem,
+ RubySequencer,
+ RubyPortProxy,
+)
+
+
+class PrivateL1CacheHierarchy(AbstractRubyCacheHierarchy):
+ """A single level cache based on CHI for RISC-V
+
+ This hierarchy has a split I/D L1 caches per CPU, a single directory
(HNF),
+ and as many memory controllers (SNF) as memory channels. The directory
does
+ not have an associated cache.
+
+ The network is a simple point-to-point between all of the controllers.
+ """
+
+ def __init__(self, size: str, assoc: int) -> None:
+ """
+ :param size: The size of the priavte I/D caches in the hierarchy.
+ :param assoc: The associativity of each cache.
+ """
+ super().__init__()
+
+ self._size = size
+ self._assoc = assoc
+
+ @overrides(AbstractCacheHierarchy)
+ def incorporate_cache(self, board: AbstractBoard) -> None:
+
+ requires(coherence_protocol_required=CoherenceProtocol.CHI)
+
+ self.ruby_system = RubySystem()
+
+ # Ruby's global network.
+ self.ruby_system.network = SimplePt2Pt(self.ruby_system)
+
+ # Network configurations
+ # virtual networks: 0=request, 1=snoop, 2=response, 3=data
+ self.ruby_system.number_of_virtual_networks = 4
+ self.ruby_system.network.number_of_virtual_networks = 4
+
+ # Create a single centralized directory
+ self.directory = SimpleDirectory(
+ self.ruby_system.network,
+ cache_line_size=board.get_cache_line_size(),
+ clk_domain=board.get_clock_domain(),
+ )
+ self.directory.ruby_system = self.ruby_system
+
+ # Create one core cluster with a split I/D cache for each core
+ self.core_clusters = [
+ self._create_core_cluster(core, i, board)
+ for i, core in enumerate(board.get_processor().get_cores())
+ ]
+
+ # Create the coherent side of the memory controllers
+ self.memory_controllers = self._create_memory_controllers(board)
+ self.directory.downstream_destinations = self.memory_controllers
+
+ # Create the DMA Controllers, if required.
+ if board.has_dma_ports():
+ self.dma_controllers = self._create_dma_controllers(board)
+ self.ruby_system.num_of_sequencers = len(self.core_clusters) *
2 \
+ + len(self.dma_controllers)
+ else:
+ self.ruby_system.num_of_sequencers = len(self.core_clusters) *
2
+
+ self.ruby_system.network.connectControllers(
+ list(
+ chain.from_iterable( # Grab the controllers from each
cluster
+ [
+ (cluster.dcache, cluster.icache)
+ for cluster in self.core_clusters
+ ]
+ )
+ )
+ + self.memory_controllers
+ + [self.directory]
+ + (self.dma_controllers if board.has_dma_ports() else [])
+ )
+
+ 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_core_cluster(self,
+ core: AbstractCore,
+ core_num: int,
+ board: AbstractBoard
+ ) -> SubSystem:
+ """Given the core and the core number this function creates a
cluster
+ for the core with a split I/D cache
+ """
+ cluster = SubSystem()
+ cluster.dcache = PrivateL1MOESICache(
+ size=self._size,
+ assoc=self._assoc,
+ network=self.ruby_system.network,
+ core=core,
+ cache_line_size=board.get_cache_line_size(),
+ target_isa=get_runtime_isa(),
+ clk_domain=board.get_clock_domain(),
+ )
+ cluster.icache = PrivateL1MOESICache(
+ size=self._size,
+ assoc=self._assoc,
+ network=self.ruby_system.network,
+ core=core,
+ cache_line_size=board.get_cache_line_size(),
+ target_isa=get_runtime_isa(),
+ clk_domain=board.get_clock_domain(),
+ )
+
+ cluster.icache.sequencer = RubySequencer(
+ version=core_num,
+ dcache=NULL,
+ clk_domain=cluster.icache.clk_domain,
+ )
+ cluster.dcache.sequencer = RubySequencer(
+ version=core_num,
+ dcache=cluster.dcache.cache,
+ clk_domain=cluster.dcache.clk_domain,
+ )
+
+ if board.has_io_bus():
+ cluster.dcache.sequencer.connectIOPorts(board.get_io_bus())
+
+ cluster.dcache.ruby_system = self.ruby_system
+ cluster.icache.ruby_system = self.ruby_system
+
+ core.connect_icache(cluster.icache.sequencer.in_ports)
+ core.connect_dcache(cluster.dcache.sequencer.in_ports)
+
+ core.connect_walker_ports(
+ cluster.dcache.sequencer.in_ports,
+ cluster.icache.sequencer.in_ports,
+ )
+
+ # Connect the interrupt ports
+ if get_runtime_isa() == ISA.X86:
+ int_req_port = cluster.dcache.sequencer.interrupt_out_port
+ int_resp_port = cluster.dcache.sequencer.in_ports
+ core.connect_interrupt(int_req_port, int_resp_port)
+ else:
+ core.connect_interrupt()
+
+ cluster.dcache.downstream_destinations = [self.directory]
+ cluster.icache.downstream_destinations = [self.directory]
+
+ return cluster
+
+ def _create_memory_controllers(
+ self,
+ board: AbstractBoard
+ ) -> List[MemoryController]:
+ memory_controllers = []
+ for rng, port in board.get_memory().get_mem_ports():
+ mc = MemoryController(
+ self.ruby_system.network,
+ rng,
+ port,
+ )
+ mc.ruby_system = self.ruby_system
+ memory_controllers.append(mc)
+ return memory_controllers
+
+ def _create_dma_controllers(
+ self,
+ board: AbstractBoard
+ ) -> List[DMARequestor]:
+ dma_controllers = []
+ for i, port in enumerate(board.get_dma_ports()):
+ ctrl = DMARequestor(
+ self.ruby_system.network,
+ board.get_cache_line_size(),
+ board.get_clock_domain(),
+ )
+ version = len(board.get_processor().get_cores()) + i
+ ctrl.sequencer = RubySequencer(
+ version=version,
+ in_ports=port
+ )
+ ctrl.sequencer.dcache = NULL
+
+ ctrl.ruby_system = self.ruby_system
+ ctrl.sequencer.ruby_system = self.ruby_system
+
+ ctrl.downstream_destinations = [self.directory]
+
+ dma_controllers.append(ctrl)
+
+ return dma_controllers
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/52463
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I56953238c6b0ca5ac754b103a1b6ec05a85a0af5
Gerrit-Change-Number: 52463
Gerrit-PatchSet: 5
Gerrit-Owner: Jason Lowe-Power <power...@gmail.com>
Gerrit-Reviewer: Bobby R. Bruce <bbr...@ucdavis.edu>
Gerrit-Reviewer: Jason Lowe-Power <ja...@lowepower.com>
Gerrit-Reviewer: Jason Lowe-Power <power...@gmail.com>
Gerrit-Reviewer: Tiago Mück <tiago.m...@arm.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s