From d32a438913def1d36e8f9beeccbd768214a07629 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 14 Mar 2024 14:42:25 +0000 Subject: [PATCH 1/2] stdlib: Add a new private_l1_private_l2_walk_cache_hierarchy.py module From [1] The PrivateL1PrivateL2Cache hierarchy has been amended with an MMUCache, which is basically a small cache in front of the page table walker. Not every ISA makes use of it. Arm for example already implements caching of page table walks, via the partial_levels parameter in the ArmTLB. With this patch we define a new module which explicitly makes use of the WalkCache. Configurations that do not require another cache in the first level of the memsys (for the ptw) can use the PrivateL1PrivateL2CacheHierarchy [1]: https://gem5-review.googlesource.com/c/public/gem5/+/49364 Change-Id: I17f7e68940ee947ca5b30e6ab3a01dafeed0f338 Signed-off-by: Giacomo Travaglini --- src/python/SConscript | 3 + .../private_l1_private_l2_cache_hierarchy.py | 35 ++++---- ...vate_l1_private_l2_walk_cache_hierarchy.py | 81 +++++++++++++++++++ 3 files changed, 103 insertions(+), 16 deletions(-) create mode 100644 src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_walk_cache_hierarchy.py diff --git a/src/python/SConscript b/src/python/SConscript index ec3b03cdcf..49bc616ae2 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -91,6 +91,9 @@ PySource('gem5.components.cachehierarchies.classic', PySource('gem5.components.cachehierarchies.classic', 'gem5/components/cachehierarchies/classic/' 'private_l1_private_l2_cache_hierarchy.py') +PySource('gem5.components.cachehierarchies.classic', + 'gem5/components/cachehierarchies/classic/' + 'private_l1_private_l2_walk_cache_hierarchy.py') PySource('gem5.components.cachehierarchies.classic', 'gem5/components/cachehierarchies/classic/' 'private_l1_shared_l2_cache_hierarchy.py') diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_cache_hierarchy.py index d1d43ec0c8..e0f918a7d5 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_cache_hierarchy.py @@ -1,3 +1,15 @@ +# Copyright (c) 2024 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2021 The Regents of the University of California # All rights reserved. # @@ -26,6 +38,7 @@ from m5.objects import ( BadAddr, + BaseCPU, BaseXBar, Cache, L2XBar, @@ -42,7 +55,6 @@ from .abstract_classic_cache_hierarchy import AbstractClassicCacheHierarchy from .caches.l1dcache import L1DCache from .caches.l1icache import L1ICache from .caches.l2cache import L2Cache -from .caches.mmu_cache import MMUCache class PrivateL1PrivateL2CacheHierarchy( @@ -130,16 +142,6 @@ class PrivateL1PrivateL2CacheHierarchy( L2Cache(size=self._l2_size) for i in range(board.get_processor().get_num_cores()) ] - # ITLB Page walk caches - self.iptw_caches = [ - MMUCache(size="8KiB") - for _ in range(board.get_processor().get_num_cores()) - ] - # DTLB Page walk caches - self.dptw_caches = [ - MMUCache(size="8KiB") - for _ in range(board.get_processor().get_num_cores()) - ] if board.has_coherent_io(): self._setup_io_cache(board) @@ -150,16 +152,12 @@ class PrivateL1PrivateL2CacheHierarchy( self.l1icaches[i].mem_side = self.l2buses[i].cpu_side_ports self.l1dcaches[i].mem_side = self.l2buses[i].cpu_side_ports - self.iptw_caches[i].mem_side = self.l2buses[i].cpu_side_ports - self.dptw_caches[i].mem_side = self.l2buses[i].cpu_side_ports self.l2buses[i].mem_side_ports = self.l2caches[i].cpu_side self.membus.cpu_side_ports = self.l2caches[i].mem_side - cpu.connect_walker_ports( - self.iptw_caches[i].cpu_side, self.dptw_caches[i].cpu_side - ) + self._connect_table_walker(i, cpu) if board.get_processor().get_isa() == ISA.X86: int_req_port = self.membus.mem_side_ports @@ -168,6 +166,11 @@ class PrivateL1PrivateL2CacheHierarchy( else: cpu.connect_interrupt() + def _connect_table_walker(self, cpu_id: int, cpu: BaseCPU) -> None: + cpu.connect_walker_ports( + self.membus.cpu_side_ports, self.membus.cpu_side_ports + ) + def _setup_io_cache(self, board: AbstractBoard) -> None: """Create a cache for coherent I/O connections""" self.iocache = Cache( diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_walk_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_walk_cache_hierarchy.py new file mode 100644 index 0000000000..3f5999f0f5 --- /dev/null +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_walk_cache_hierarchy.py @@ -0,0 +1,81 @@ +# Copyright (c) 2024 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# 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 m5.objects import BaseCPU + +from ....utils.override import * +from ...boards.abstract_board import AbstractBoard +from .caches.mmu_cache import MMUCache +from .private_l1_private_l2_cache_hierarchy import ( + PrivateL1PrivateL2CacheHierarchy, +) + + +class PrivateL1PrivateL2WalkCacheHierarchy(PrivateL1PrivateL2CacheHierarchy): + """ + A cache setup where each core has a private L1 Data and Instruction Cache, + and a private L2 cache and a Walk Cache for the Table Walker + """ + + def __init__(self, *args, **kwargs) -> None: + PrivateL1PrivateL2CacheHierarchy.__init__(self, *args, **kwargs) + + @overrides(PrivateL1PrivateL2CacheHierarchy) + def incorporate_cache(self, board: AbstractBoard) -> None: + # ITLB Page walk caches + self.iptw_caches = [ + MMUCache(size="8KiB") + for _ in range(board.get_processor().get_num_cores()) + ] + # DTLB Page walk caches + self.dptw_caches = [ + MMUCache(size="8KiB") + for _ in range(board.get_processor().get_num_cores()) + ] + + super().incorporate_cache(board) + + for i, cpu in enumerate(board.get_processor().get_cores()): + self.iptw_caches[i].mem_side = self.l2buses[i].cpu_side_ports + self.dptw_caches[i].mem_side = self.l2buses[i].cpu_side_ports + + def _connect_table_walker(self, cpu_id: int, cpu: BaseCPU) -> None: + cpu.connect_walker_ports( + self.iptw_caches[cpu_id].cpu_side, + self.dptw_caches[cpu_id].cpu_side, + ) From 058dd7e195b8e0875d5ad1aaaebdbd4d7838f633 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 14 Mar 2024 15:15:46 +0000 Subject: [PATCH 2/2] configs, tests: Amend stdlib configs to use WalkCache hierarchy As X86 and RISCV are relying on a Table Walker cache, we change their stdlib configs to use the newly defined PrivateL1PrivateL2WalkCacheHierarchy Change-Id: I63c3f70a9daa3b2c7a8306e51af8065bf1bea92b Signed-off-by: Giacomo Travaglini --- .../gem5_library/checkpoints/simpoints-se-restore.py | 6 +++--- .../gem5_library/looppoints/restore-looppoint-checkpoint.py | 6 +++--- configs/example/gem5_library/riscv-fs.py | 6 +++--- configs/example/gem5_library/riscv-ubuntu-run.py | 6 +++--- configs/example/lupv/run_lupv.py | 6 +++--- .../checkpoint_tests/configs/x86-fs-restore-checkpoint.py | 6 +++--- .../gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py | 6 +++--- tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py | 6 +++--- tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py | 6 +++--- tests/gem5/suite_tests/configs/suite_run_workload.py | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/configs/example/gem5_library/checkpoints/simpoints-se-restore.py b/configs/example/gem5_library/checkpoints/simpoints-se-restore.py index a3639a63bb..ac3d8c9e23 100644 --- a/configs/example/gem5_library/checkpoints/simpoints-se-restore.py +++ b/configs/example/gem5_library/checkpoints/simpoints-se-restore.py @@ -60,8 +60,8 @@ from m5.stats import ( ) from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) from gem5.components.memory import DualChannelDDR4_2400 from gem5.components.processors.cpu_types import CPUTypes @@ -80,7 +80,7 @@ requires(isa_required=ISA.X86) # The cache hierarchy can be different from the cache hierarchy used in taking # the checkpoints -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32kB", l1i_size="32kB", l2_size="256kB", diff --git a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py index 781b2f7281..a97ea39d17 100644 --- a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py +++ b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py @@ -48,8 +48,8 @@ from m5.stats import ( ) from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) from gem5.components.memory import DualChannelDDR4_2400 from gem5.components.processors.cpu_types import CPUTypes @@ -90,7 +90,7 @@ args = parser.parse_args() # The cache hierarchy can be different from the cache hierarchy used in taking # the checkpoints -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32kB", l1i_size="32kB", l2_size="256kB", diff --git a/configs/example/gem5_library/riscv-fs.py b/configs/example/gem5_library/riscv-fs.py index 914d9a7023..1d1b01e560 100644 --- a/configs/example/gem5_library/riscv-fs.py +++ b/configs/example/gem5_library/riscv-fs.py @@ -40,8 +40,8 @@ Characteristics """ from gem5.components.boards.riscv_board import RiscvBoard -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes @@ -57,7 +57,7 @@ requires(isa_required=ISA.RISCV) # Setup the cache hierarchy. # For classic, PrivateL1PrivateL2 and NoCache have been tested. # For Ruby, MESI_Two_Level and MI_example have been tested. -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32KiB", l1i_size="32KiB", l2_size="512KiB" ) diff --git a/configs/example/gem5_library/riscv-ubuntu-run.py b/configs/example/gem5_library/riscv-ubuntu-run.py index 1d31b055de..3ec51bd3a4 100644 --- a/configs/example/gem5_library/riscv-ubuntu-run.py +++ b/configs/example/gem5_library/riscv-ubuntu-run.py @@ -57,12 +57,12 @@ from gem5.utils.requires import requires requires(isa_required=ISA.RISCV) # With RISCV, we use simple caches. -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) # Here we setup the parameters of the l1 and l2 caches. -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="16kB", l1i_size="16kB", l2_size="256kB" ) diff --git a/configs/example/lupv/run_lupv.py b/configs/example/lupv/run_lupv.py index 4be6b924a5..44a4b2dd31 100644 --- a/configs/example/lupv/run_lupv.py +++ b/configs/example/lupv/run_lupv.py @@ -49,8 +49,8 @@ from gem5.utils.requires import requires # Run a check to ensure the right version of gem5 is being used. requires(isa_required=ISA.RISCV) -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) parser = argparse.ArgumentParser(description="Runs Linux fs test with RISCV.") @@ -72,7 +72,7 @@ parser.add_argument( args = parser.parse_args() -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32KiB", l1i_size="32KiB", l2_size="512KiB" ) diff --git a/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py index 6286fc0544..7fb9a483ff 100644 --- a/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py @@ -34,8 +34,8 @@ This configuration serves as a test of restoring a checkpoint with X86 ISA in fs """ from gem5.components.boards.x86_board import X86Board -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes @@ -54,7 +54,7 @@ requires(isa_required=ISA.X86) # Setup the cache hierarchy. # For classic, PrivateL1PrivateL2 and NoCache have been tested. # For Ruby, MESI_Two_Level and MI_example have been tested. -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32kB", l1i_size="32kB", l2_size="512kB" ) diff --git a/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py index fb800209e0..e206cb39b8 100644 --- a/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py @@ -34,8 +34,8 @@ with X86 ISA in fs mode. import argparse from gem5.components.boards.x86_board import X86Board -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes @@ -63,7 +63,7 @@ requires(isa_required=ISA.X86) # Setup the cache hierarchy. # For classic, PrivateL1PrivateL2 and NoCache have been tested. # For Ruby, MESI_Two_Level and MI_example have been tested. -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32kB", l1i_size="32kB", l2_size="512kB" ) diff --git a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py index 606205f103..5a9d5e6e47 100644 --- a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py +++ b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py @@ -146,11 +146,11 @@ args = parser.parse_args() # Setup the cachie hierarchy. if args.mem_system == "classic": - from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, + from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) - cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( + cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32kB", l1i_size="32kB", l2_size="256kB" ) elif args.mem_system == "mesi_two_level": diff --git a/tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py b/tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py index 0192d3dbff..5dfc082e66 100644 --- a/tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py +++ b/tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py @@ -104,12 +104,12 @@ args = parser.parse_args() requires(isa_required=ISA.RISCV) if args.mem_system == "classic": - from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, + from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) # Setup the cache hierarchy. - cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( + cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32KiB", l1i_size="32KiB", l2_size="512KiB" ) elif args.mem_system == "mesi_two_level": diff --git a/tests/gem5/suite_tests/configs/suite_run_workload.py b/tests/gem5/suite_tests/configs/suite_run_workload.py index a9f980d53f..ebf86b5eb0 100644 --- a/tests/gem5/suite_tests/configs/suite_run_workload.py +++ b/tests/gem5/suite_tests/configs/suite_run_workload.py @@ -35,8 +35,8 @@ import argparse from m5.util import panic -from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( - PrivateL1PrivateL2CacheHierarchy, +from gem5.components.cachehierarchies.classic.private_l1_private_l2_walk_cache_hierarchy import ( + PrivateL1PrivateL2WalkCacheHierarchy, ) from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes @@ -92,7 +92,7 @@ parser.add_argument( args = parser.parse_args() # Setup the cache hierarchy. -cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( +cache_hierarchy = PrivateL1PrivateL2WalkCacheHierarchy( l1d_size="32KiB", l1i_size="32KiB", l2_size="512KiB" )