From 15382b3b13ff8293c868b7cbee0c9e0fa716af88 Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Sun, 25 Feb 2024 23:07:39 +0100 Subject: [PATCH] Add simulation script --- configs/pim_config.py | 12 +++ .../arm-baremetal.py => pim_simulation.py} | 56 ++++++++++++-- simulation_script.py | 76 +++++++++++++++++++ 3 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 configs/pim_config.py rename configs/{example/gem5_library/arm-baremetal.py => pim_simulation.py} (57%) create mode 100644 simulation_script.py diff --git a/configs/pim_config.py b/configs/pim_config.py new file mode 100644 index 0000000000..e3c78e535e --- /dev/null +++ b/configs/pim_config.py @@ -0,0 +1,12 @@ +from dataclasses import dataclass +from pathlib import Path + +@dataclass(frozen=True) +class Configuration: + name: str + workload: Path + frequency: str = "3GHz" + +@dataclass(frozen=True) +class Statistics: + ticks: int diff --git a/configs/example/gem5_library/arm-baremetal.py b/configs/pim_simulation.py similarity index 57% rename from configs/example/gem5_library/arm-baremetal.py rename to configs/pim_simulation.py index 945d5e0ebe..84201c925b 100644 --- a/configs/example/gem5_library/arm-baremetal.py +++ b/configs/pim_simulation.py @@ -1,3 +1,8 @@ +import m5 +import json +import dataclasses +import sys + from gem5.isas import ISA from m5.objects import ( ArmDefaultRelease, @@ -11,6 +16,10 @@ from gem5.components.boards.arm_baremetal_board import ArmBareMetalBoard from gem5.components.memory import DRAMSysHBM2 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.exit_event import ExitEvent +from dataclasses import dataclass + +from pim_config import Configuration, Statistics requires(isa_required=ISA.ARM) @@ -19,16 +28,19 @@ from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierar ) from gem5.components.cachehierarchies.classic.no_cache import NoCache +configuration = Configuration(**json.loads(sys.argv[1])) + cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( l1d_size="16kB", l1i_size="16kB", l2_size="256kB" ) -memory = DRAMSysHBM2(recordable=True) + +memory = DRAMSysHBM2(recordable=False) processor = SimpleProcessor(cpu_type=CPUTypes.O3, num_cores=1, isa=ISA.ARM) release = ArmDefaultRelease() platform = VExpress_GEM5_Foundation() board = ArmBareMetalBoard( - clk_freq="3GHz", + clk_freq=configuration.frequency, processor=processor, memory=memory, cache_hierarchy=cache_hierarchy, @@ -42,16 +54,46 @@ board.cache_line_size = 32 for core in processor.get_cores(): core.core.fetchBufferSize = 32 -# Address of memory-mapped m5ops -board.m5ops_base = 0x10010000 - workload = CustomWorkload( "set_baremetal_workload", { - "kernel": BinaryResource("kernels/gemv"), + "kernel": BinaryResource(configuration.workload), }, ) board.set_workload(workload) -simulator = Simulator(board=board) + +@dataclass +class WorkloadTime: + start: int + end: int + + +workload_time = WorkloadTime(0, 0) + + +def exit_event(): + print(f"Workload begin @{m5.curTick()}") + workload_time.start = m5.curTick() + m5.stats.reset() + yield False + + print(f"Workload end @{m5.curTick()}") + workload_time.end = m5.curTick() + m5.stats.dump() + yield False + + print(f"Exit simulation @{m5.curTick()}...") + yield True + + +simulator = Simulator( + board=board, on_exit_event={ExitEvent.EXIT: exit_event()} +) + simulator.run() + +print(f"Workload took {workload_time.end - workload_time.start}") + +statistics = Statistics(workload_time.end - workload_time.start) +print(json.dumps(dataclasses.asdict(statistics))) diff --git a/simulation_script.py b/simulation_script.py new file mode 100644 index 0000000000..8364b5ac37 --- /dev/null +++ b/simulation_script.py @@ -0,0 +1,76 @@ +import subprocess +import csv +import copy +import dataclasses +import json + +from threading import Thread +from pathlib import Path +from typing import Dict +from configs.pim_config import Configuration, Statistics + +gem5 = Path("build/ARM/gem5.opt") +out_dir_base = Path("pim_out") +pim_simulation = Path("configs/pim_simulation.py") + + +class Gem5Thread(Thread): + def __init__(self, configuration: Configuration) -> None: + super().__init__() + self.configuration = configuration + + def run(self): + serialized_configuration = json.dumps( + dataclasses.asdict(self.configuration) + ) + + out_dir = out_dir_base / configuration.name + + out = subprocess.run( + [ + gem5, + "-d" + out_dir.as_posix(), + pim_simulation, + serialized_configuration, + ], + capture_output=True, + ) + # print(out.stderr) + # print(out.stdout) + output = out.stdout.splitlines()[-1] + self.statistics = Statistics(**json.loads(output)) + + +workload_directory = Path("kernels") + +workloads = [ + "classic_vadd", + "classic_vmul", + "classic_haxpy", + "classic_gemv", + # "classic_gemv_layers", + "vadd", + "vmul", + "haxpy", + "gemv", + # "gemv_layers", +] + +configurations: list[Configuration] = [] + +for frequency in ["3GHz", "100GHz"]: + for workload in workloads: + configurations.append( + Configuration(workload + "_" + frequency, (workload_directory / workload).as_posix(), frequency) + ) + +threads: list[Gem5Thread] = [] + +for configuration in configurations: + thread = Gem5Thread(configuration) + thread.start() + threads.append(thread) + +for thread in threads: + thread.join() + print(thread.configuration, thread.statistics)