From bd1d72f61e694a198220cec82dd138784f097682 Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Wed, 31 May 2023 11:25:07 +0800 Subject: [PATCH 001/693] fastmodel: add src include path by default We have some customized protocols in gem5 repository and they require the include path from src directory. It causes the users of those protocols need to handle the include path correctly by theirselve. This is tedious and unstable. We should add the default include path in SIMGEN command line to prevent issues. Change-Id: I2a3748646567635d131a8fb4099e02e332691e97 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71118 Reviewed-by: Wei-Han Chen Tested-by: kokoro Maintainer: Jason Lowe-Power --- src/arch/arm/fastmodel/CortexA76/x1/x1.sgproj | 2 -- src/arch/arm/fastmodel/CortexA76/x2/x2.sgproj | 2 -- src/arch/arm/fastmodel/CortexA76/x3/x3.sgproj | 2 -- src/arch/arm/fastmodel/CortexA76/x4/x4.sgproj | 2 -- src/arch/arm/fastmodel/CortexR52/x1/x1.sgproj | 2 -- src/arch/arm/fastmodel/CortexR52/x2/x2.sgproj | 2 -- src/arch/arm/fastmodel/CortexR52/x3/x3.sgproj | 2 -- src/arch/arm/fastmodel/CortexR52/x4/x4.sgproj | 2 -- src/arch/arm/fastmodel/GIC/GIC.sgproj | 2 +- src/arch/arm/fastmodel/PL330_DMAC/PL330.sgproj | 2 +- src/arch/arm/fastmodel/SConscript | 3 ++- 11 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/arch/arm/fastmodel/CortexA76/x1/x1.sgproj b/src/arch/arm/fastmodel/CortexA76/x1/x1.sgproj index f3fd0db70f..7101b499db 100644 --- a/src/arch/arm/fastmodel/CortexA76/x1/x1.sgproj +++ b/src/arch/arm/fastmodel/CortexA76/x1/x1.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexA76/x2/x2.sgproj b/src/arch/arm/fastmodel/CortexA76/x2/x2.sgproj index abec8addca..54327dc723 100644 --- a/src/arch/arm/fastmodel/CortexA76/x2/x2.sgproj +++ b/src/arch/arm/fastmodel/CortexA76/x2/x2.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexA76/x3/x3.sgproj b/src/arch/arm/fastmodel/CortexA76/x3/x3.sgproj index 666b1dc0f4..5809b31f66 100644 --- a/src/arch/arm/fastmodel/CortexA76/x3/x3.sgproj +++ b/src/arch/arm/fastmodel/CortexA76/x3/x3.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexA76/x4/x4.sgproj b/src/arch/arm/fastmodel/CortexA76/x4/x4.sgproj index e3c9063ac7..1866c98be8 100644 --- a/src/arch/arm/fastmodel/CortexA76/x4/x4.sgproj +++ b/src/arch/arm/fastmodel/CortexA76/x4/x4.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexR52/x1/x1.sgproj b/src/arch/arm/fastmodel/CortexR52/x1/x1.sgproj index 9d2a5749f6..83c0584869 100644 --- a/src/arch/arm/fastmodel/CortexR52/x1/x1.sgproj +++ b/src/arch/arm/fastmodel/CortexR52/x1/x1.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexR52/x2/x2.sgproj b/src/arch/arm/fastmodel/CortexR52/x2/x2.sgproj index e103170ed1..ab8399a419 100644 --- a/src/arch/arm/fastmodel/CortexR52/x2/x2.sgproj +++ b/src/arch/arm/fastmodel/CortexR52/x2/x2.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexR52/x3/x3.sgproj b/src/arch/arm/fastmodel/CortexR52/x3/x3.sgproj index 0c92809924..a9bfa3fa08 100644 --- a/src/arch/arm/fastmodel/CortexR52/x3/x3.sgproj +++ b/src/arch/arm/fastmodel/CortexR52/x3/x3.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/CortexR52/x4/x4.sgproj b/src/arch/arm/fastmodel/CortexR52/x4/x4.sgproj index 6a145fd1c1..dc333763cf 100644 --- a/src/arch/arm/fastmodel/CortexR52/x4/x4.sgproj +++ b/src/arch/arm/fastmodel/CortexR52/x4/x4.sgproj @@ -16,8 +16,6 @@ config "gcc" SIMGEN_COMMAND_LINE = "--num-comps-file 50"; TARGET_SYSTEMC = "1"; TARGET_SYSTEMC_AUTO = "1"; - - INCLUDE_DIRS="../../../../../"; } files { diff --git a/src/arch/arm/fastmodel/GIC/GIC.sgproj b/src/arch/arm/fastmodel/GIC/GIC.sgproj index aa5e6aec32..fd5c04a5a5 100644 --- a/src/arch/arm/fastmodel/GIC/GIC.sgproj +++ b/src/arch/arm/fastmodel/GIC/GIC.sgproj @@ -5,7 +5,7 @@ ACTIVE_CONFIG_LINUX = "gcc"; ACTIVE_CONFIG_WINDOWS = "Win64-Release-VC2015"; config "gcc" { - ADDITIONAL_COMPILER_SETTINGS = "-O3 -Wall -std=c++14 -Wno-deprecated -Wno-unused-function -I../../../../../"; + ADDITIONAL_COMPILER_SETTINGS = "-O3 -Wall -std=c++14 -Wno-deprecated -Wno-unused-function"; ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; BUILD_DIR = "./gcc"; COMPILER = "gcc-7.3"; diff --git a/src/arch/arm/fastmodel/PL330_DMAC/PL330.sgproj b/src/arch/arm/fastmodel/PL330_DMAC/PL330.sgproj index d59849c409..c972ad760c 100644 --- a/src/arch/arm/fastmodel/PL330_DMAC/PL330.sgproj +++ b/src/arch/arm/fastmodel/PL330_DMAC/PL330.sgproj @@ -5,7 +5,7 @@ ACTIVE_CONFIG_LINUX = "gcc"; ACTIVE_CONFIG_WINDOWS = "Win64-Release-VC2015"; config "gcc" { - ADDITIONAL_COMPILER_SETTINGS = "-O3 -Wall -std=c++14 -Wno-deprecated -Wno-unused-function -I../../../../../"; + ADDITIONAL_COMPILER_SETTINGS = "-O3 -Wall -std=c++14 -Wno-deprecated -Wno-unused-function"; ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; BUILD_DIR = "./gcc"; COMPILER = "gcc-7.3"; diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript index 9d9d183516..3bc9aa5bad 100644 --- a/src/arch/arm/fastmodel/SConscript +++ b/src/arch/arm/fastmodel/SConscript @@ -377,11 +377,12 @@ class ArmFastModelComponent(object): self.rpaths = [simgen_dir, project_file_dir] self.log = gen_dir.File('build_%s.log' % tlc) self.simgen_cmd = env.subst('${CONF["SIMGEN"]} -p %s ' - '--configuration %s -b --verbose off --num-build-cpus %d %s ' + '--configuration %s -b --verbose off --num-build-cpus %d -I %s %s ' '--build-dir %s >%s') % \ (shlex.quote(project_file.srcnode().abspath), shlex.quote(config_name), GetOption('num_jobs'), + shlex.quote(Dir('#/src').srcnode().abspath), simgen_command_line, shlex.quote(simgen_dir.abspath), shlex.quote(self.log.abspath)) From ebd5b3e4ae49b24dec4efc299d0b0198be9f4df3 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Tue, 30 May 2023 13:57:09 -0500 Subject: [PATCH 002/693] gpu-compute: Gfx version check for FS and SE mode There is no GPU device in SE mode to get version from and no GPU driver in FS mode to get version from, so a conditional needs to be added depending on the mode to get the gfx version. Change-Id: I33fdafb60d351ebc5148e2248244537fb5bebd31 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71078 Tested-by: kokoro Maintainer: Matt Sinclair Reviewed-by: Matt Sinclair --- src/gpu-compute/gpu_command_processor.cc | 4 +++- src/gpu-compute/gpu_compute_driver.hh | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gpu-compute/gpu_command_processor.cc b/src/gpu-compute/gpu_command_processor.cc index 9755180204..8f748bdc31 100644 --- a/src/gpu-compute/gpu_command_processor.cc +++ b/src/gpu-compute/gpu_command_processor.cc @@ -227,9 +227,11 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, DPRINTF(GPUKernelInfo, "Kernel name: %s\n", kernel_name.c_str()); + GfxVersion gfxVersion = FullSystem ? gpuDevice->getGfxVersion() + : driver()->getGfxVersion(); HSAQueueEntry *task = new HSAQueueEntry(kernel_name, queue_id, dynamic_task_id, raw_pkt, &akc, host_pkt_addr, machine_code_addr, - gpuDevice->getGfxVersion()); + gfxVersion); DPRINTF(GPUCommandProc, "Task ID: %i Got AQL: wg size (%dx%dx%d), " "grid size (%dx%dx%d) kernarg addr: %#x, completion " diff --git a/src/gpu-compute/gpu_compute_driver.hh b/src/gpu-compute/gpu_compute_driver.hh index def40f4557..9a3c6479c3 100644 --- a/src/gpu-compute/gpu_compute_driver.hh +++ b/src/gpu-compute/gpu_compute_driver.hh @@ -142,6 +142,8 @@ class GPUComputeDriver final : public EmulatedDriver }; typedef class EventTableEntry ETEntry; + GfxVersion getGfxVersion() const { return gfxVersion; } + private: /** * GPU that is controlled by this driver. From 917ced812c46c63b53adccf51863747178b0fbc2 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 30 May 2023 10:43:52 -0700 Subject: [PATCH 003/693] stdlib: Fix incorrect path and checks for DRAMsim3 There are three bugs fixed in this patch: 1. The `dram_3_dir` was missing the "dramsim3" directory. 2. Missing `not` when checking if configs is a directory. 3. Missing `not` when checking if input file is a file. Change-Id: I185f4832c1c2f1ecc4e138c148ad7969ef9b6fd4 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71038 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/python/gem5/components/memory/dramsim_3.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/python/gem5/components/memory/dramsim_3.py b/src/python/gem5/components/memory/dramsim_3.py index e5c1877fb5..f154ba354f 100644 --- a/src/python/gem5/components/memory/dramsim_3.py +++ b/src/python/gem5/components/memory/dramsim_3.py @@ -32,6 +32,7 @@ def config_ds3(mem_type: str, num_chnls: int) -> Tuple[str, str]: os.pardir, os.pardir, "ext", + "dramsim3", "DRAMsim3", ) @@ -47,11 +48,11 @@ def config_ds3(mem_type: str, num_chnls: int) -> Tuple[str, str]: "Please navigate to `ext` and run:\n" "git clone git@github.com:umd-memsys/DRAMsim3.git" ) - elif os.path.isdir(dramsim_3_mem_configs): + elif not os.path.isdir(dramsim_3_mem_configs): raise Exception( "The `ext/DRAMsim3/configs` directory cannot be found." ) - elif os.path.isfile(input_file): + elif not os.path.isfile(input_file): raise Exception( "The configuration file '" + input_file + "' cannot be found." ) From 5e5e81d1c53ff506e3bbd0498c5fdccb227862ba Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Fri, 2 Jun 2023 17:00:59 +0800 Subject: [PATCH 004/693] arch-riscv: Check FPU status for c.flwsp c.fldsp c.fswsp c.fsdsp The change adds the missing FPU checking for these instructions. Change-Id: I7f2ef89786af0d528f2029f1097cfeac6c7d65f2 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71198 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- src/arch/riscv/isa/decoder.isa | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index c7eefbc79c..2dcd118225 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -307,6 +307,11 @@ decode QUADRANT default Unknown::unknown() { CIMM1 << 5 | CIMM5<2:0> << 6; }}, {{ + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (status.fs == FPUStatus::OFF) + return std::make_shared("FPU is off", + machInst); + Fc1_bits = Mem; }}, {{ EA = rvZext(sp + offset); @@ -330,6 +335,11 @@ decode QUADRANT default Unknown::unknown() { CIMM1 << 5 | CIMM5<1:0> << 6; }}, {{ + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (status.fs == FPUStatus::OFF) + return std::make_shared("FPU is off", + machInst); + freg_t fd; fd = freg(f32(Mem_uw)); Fd_bits = fd.v; @@ -387,6 +397,11 @@ decode QUADRANT default Unknown::unknown() { offset = CIMM6<5:3> << 3 | CIMM6<2:0> << 6; }}, {{ + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (status.fs == FPUStatus::OFF) + return std::make_shared("FPU is off", + machInst); + Mem_ud = Fc2_bits; }}, {{ EA = rvZext(sp + offset); @@ -404,6 +419,11 @@ decode QUADRANT default Unknown::unknown() { offset = CIMM6<5:2> << 2 | CIMM6<1:0> << 6; }}, {{ + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (status.fs == FPUStatus::OFF) + return std::make_shared("FPU is off", + machInst); + Mem_uw = unboxF32(boxF32(Fs2_bits)); }}, {{ EA = (uint32_t)(sp_uw + offset); From 14f919a67efc49dba9d514a43fb4588975ec2591 Mon Sep 17 00:00:00 2001 From: Xuan Hu Date: Tue, 17 Jan 2023 21:08:57 +0800 Subject: [PATCH 005/693] arch-riscv,cpu-minor: Add MinorDefaultVecFU for risc-v v-ext Change-Id: Id5c5ae5fa1901154cadeb0a4958703f3f15d491f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67295 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/cpu/minor/BaseMinorCPU.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/cpu/minor/BaseMinorCPU.py b/src/cpu/minor/BaseMinorCPU.py index bd27b92540..c20a310447 100644 --- a/src/cpu/minor/BaseMinorCPU.py +++ b/src/cpu/minor/BaseMinorCPU.py @@ -250,6 +250,33 @@ class MinorDefaultMiscFU(MinorFU): opLat = 1 +class MinorDefaultVecFU(MinorFU): + opClasses = minorMakeOpClassSet( + [ + "VectorUnitStrideLoad", + "VectorUnitStrideStore", + "VectorUnitStrideMaskLoad", + "VectorUnitStrideMaskStore", + "VectorStridedLoad", + "VectorStridedStore", + "VectorIndexedLoad", + "VectorIndexedStore", + "VectorUnitStrideFaultOnlyFirstLoad", + "VectorWholeRegisterLoad", + "VectorWholeRegisterStore", + "VectorIntegerArith", + "VectorFloatArith", + "VectorFloatConvert", + "VectorIntegerReduce", + "VectorFloatReduce", + "VectorMisc", + "VectorIntegerExtension", + "VectorConfig", + ] + ) + opLat = 1 + + class MinorDefaultFUPool(MinorFUPool): funcUnits = [ MinorDefaultIntFU(), @@ -260,6 +287,7 @@ class MinorDefaultFUPool(MinorFUPool): MinorDefaultPredFU(), MinorDefaultMemFU(), MinorDefaultMiscFU(), + MinorDefaultVecFU(), ] From 942a9ea503e5a053b5fbd56535ef31bd58921177 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Sat, 3 Jun 2023 10:30:38 +0800 Subject: [PATCH 006/693] stdlib: Add U74VecFU to U74CPU This change is to elimilate the warning message from U74CPU. Change-Id: I7a5d0cd0b2955e54ed14fc1ac6f7127bd7f0604b Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71238 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py index 48291bf670..4b8d2c1d32 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py @@ -75,6 +75,10 @@ class U74MiscFU(MinorDefaultMiscFU): pass +class U74VecFU(MinorDefaultVecFU): + pass + + class U74FUPool(MinorFUPool): funcUnits = [ U74IntFU(), @@ -86,6 +90,7 @@ class U74FUPool(MinorFUPool): U74MemReadFU(), U74MemWriteFU(), U74MiscFU(), + U74VecFU(), ] From b355baac939ef7ec7aafec3b707afd577ff923e4 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 31 May 2023 13:57:12 +0100 Subject: [PATCH 007/693] dev-arm: Treat GICv3 reserved addresses as RES0 According to the GIC specification (IHI0069) reserved addresses in the GIC memory map are treated as RES0. We allow to disable this behaviour and panic instead (reserved_res0 = False, which is what we have been doing so far) to catch development bugs (in gem5 and in the guest SW) Change-Id: I23f98519c2f256c092a52425735b8792bae7a2c7 Signed-off-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71138 Reviewed-by: Richard Cooper Tested-by: kokoro --- src/dev/arm/Gic.py | 9 +++++++++ src/dev/arm/gic_v3.hh | 11 +++++++++++ src/dev/arm/gic_v3_distributor.cc | 6 +++--- src/dev/arm/gic_v3_redistributor.cc | 6 +++--- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/dev/arm/Gic.py b/src/dev/arm/Gic.py index 41d602b86a..6fd8eb235f 100644 --- a/src/dev/arm/Gic.py +++ b/src/dev/arm/Gic.py @@ -315,6 +315,15 @@ class Gicv3(BaseGic): gicv4 = Param.Bool(False, "GIC is GICv4 compatible") + reserved_is_res0 = Param.Bool( + True, + "According to the GIC specification (IHI0069) " + "reserved addresses in the GIC memory map are treated as RES0. " + "We allow to disable this behaviour and panic instead " + "(reserved_res0 = False) to catch development bugs " + "(in gem5 and in the guest SW)", + ) + def interruptCells(self, int_type, int_num, int_trigger, partition=None): """ Interupt cells generation helper: diff --git a/src/dev/arm/gic_v3.hh b/src/dev/arm/gic_v3.hh index 2ea6a98b3b..7adb1d0f3f 100644 --- a/src/dev/arm/gic_v3.hh +++ b/src/dev/arm/gic_v3.hh @@ -167,6 +167,17 @@ class Gicv3 : public BaseGic, public Gicv3Registers Tick write(PacketPtr pkt) override; bool supportsVersion(GicVersion version) override; + template + void + reserved(const char* fmt, Args... args) const + { + if (params().reserved_is_res0) { + warn(fmt, args...); + } else { + panic(fmt, args...); + } + } + public: Gicv3(const Params &p); diff --git a/src/dev/arm/gic_v3_distributor.cc b/src/dev/arm/gic_v3_distributor.cc index 1cb485c5f5..af306929ff 100644 --- a/src/dev/arm/gic_v3_distributor.cc +++ b/src/dev/arm/gic_v3_distributor.cc @@ -505,8 +505,8 @@ Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) return 0; // RES0 default: - panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); - break; + gic->reserved("Gicv3Distributor::read(): invalid offset %#x\n", addr); + return 0; // RES0 } } @@ -999,7 +999,7 @@ Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, } default: - panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); + gic->reserved("Gicv3Distributor::write(): invalid offset %#x\n", addr); break; } } diff --git a/src/dev/arm/gic_v3_redistributor.cc b/src/dev/arm/gic_v3_redistributor.cc index e4380ef6f0..67d6e42e6b 100644 --- a/src/dev/arm/gic_v3_redistributor.cc +++ b/src/dev/arm/gic_v3_redistributor.cc @@ -377,8 +377,8 @@ Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) return 0; default: - panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr); - break; + gic->reserved("Gicv3Redistributor::read(): invalid offset %#x\n", addr); + return 0; // RES0 } } @@ -704,7 +704,7 @@ Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size, } default: - panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr); + gic->reserved("Gicv3Redistributor::write(): invalid offset %#x\n", addr); break; } } From ffbf73db1debd264337704b84b4c9db4d4b32c90 Mon Sep 17 00:00:00 2001 From: Kunal Pai <62979320+kunpai@users.noreply.github.com> Date: Sun, 21 May 2023 23:35:40 -0700 Subject: [PATCH 008/693] stdlib, tests, configs: Introduce gem5 Vision to resources This patch makes changes to the stdlib based on the gem5 Vision project. Firstly, a MongoDB database is supported. A JSON database's support is continued. The JSON can either be a local path or a raw GitHub link. The data for these databases is stored in src/python under "gem5-config.json". This will be used by default. However, the configuration can be overridden: - by providing a path using the GEM5_CONFIG env variable. - by placing a gem5-config.json file in the current working directory. An AbstractClient is an abstract class that implements searching and sorting relevant to the databases. Clients is an optional list that can be passed while defining any Resource class and obtain_resource. These databases can be defined in the config JSON. Resources now have versions. This allows for a single version, e.g., 'x86-ubuntu-boot', to have multiple versions. As such, the key of a resource is its ID and Version (e.g., 'x86-ubuntu-boot/v2.1.0'). Different versions of a resource might be compatible with different versions of gem5. By default, it picks the latest version compatible with the gem5 Version of the user. A gem5 resource schema now has additional fields. These are: - source_url: Stores URL of GitHub Source of the resource. - license: License information of the resource. - tags: Words to identify a resource better, like hello for hello-world - example_usage: How to use the resource in a simulation. - gem5_versions: List of gem5 versions that resource is compatible with. - resource_version: The version of the resource itself. - size: The download size of the resource, if it exists. - code_examples: List of objects. These objects contain the path to where a resource is used in gem5 example config scripts, and if the resource itself is used in tests or not. - category: Category of the resource, as defined by classes in src/python/gem5/resources/resource.py. Some fields have been renamed: - "name" is changed to "id" - "documentation" is changed to "description" Besides these, the schema also supports resource specialization. It adds fields relevant to a specific resource as specified in src/python/gem5/resources/resource.py These changes have been made to better present information on the new gem5 Resources website. But, they do not affect the way resources are used by a gem5 user. This patch is also backwards compatible. Existing code doesn't break with this new infrastructure. Also, refs in the tests have been changed to match this new schema. Tests have been changed to work with the two clients. Change-Id: Ia9bf47f7900763827fd5e873bcd663cc3ecdba40 Co-authored-by: Kunal Pai Co-authored-by: Parth Shah Co-authored-by: Harshil Patel Co-authored-by: aarsli Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70858 Tested-by: kokoro Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power --- src/python/SConscript | 12 + src/python/gem5/resources/client.py | 84 +++ .../gem5/resources/client_api/__init__.py | 0 .../resources/client_api/abstract_client.py | 71 +++ .../gem5/resources/client_api/atlasclient.py | 91 ++++ .../resources/client_api/client_wrapper.py | 228 ++++++++ .../gem5/resources/client_api/jsonclient.py | 70 +++ src/python/gem5/resources/downloader.py | 23 +- src/python/gem5/resources/resource.py | 155 ++++-- src/python/gem5/resources/workload.py | 27 +- src/python/gem5/utils/simpoint.py | 12 +- src/python/gem5_default_config.py | 39 ++ tests/gem5/verifier.py | 1 + .../resources/pyunit_client_wrapper_checks.py | 511 ++++++++++++++++++ .../resources/pyunit_downloader_checks.py | 155 ++++-- .../pyunit_obtain_resources_check.py | 192 +++++++ .../pyunit_resource_download_checks.py | 72 +++ .../pyunit_resource_specialization.py | 68 ++- .../resources/pyunit_workload_checks.py | 42 +- .../stdlib/resources/refs/mongo_dup_mock.json | 30 + .../stdlib/resources/refs/mongo_mock.json | 56 ++ .../resources/refs/obtain-resource.json | 59 ++ .../refs/resource-specialization.json | 311 ++++++----- .../stdlib/resources/refs/resources.json | 329 +++++++++++ .../refs/workload-checks-custom-workload.json | 33 +- .../resources/refs/workload-checks.json | 84 +-- 26 files changed, 2413 insertions(+), 342 deletions(-) create mode 100644 src/python/gem5/resources/client.py create mode 100644 src/python/gem5/resources/client_api/__init__.py create mode 100644 src/python/gem5/resources/client_api/abstract_client.py create mode 100644 src/python/gem5/resources/client_api/atlasclient.py create mode 100644 src/python/gem5/resources/client_api/client_wrapper.py create mode 100644 src/python/gem5/resources/client_api/jsonclient.py create mode 100644 src/python/gem5_default_config.py create mode 100644 tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py create mode 100644 tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py create mode 100644 tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py create mode 100644 tests/pyunit/stdlib/resources/refs/mongo_dup_mock.json create mode 100644 tests/pyunit/stdlib/resources/refs/mongo_mock.json create mode 100644 tests/pyunit/stdlib/resources/refs/obtain-resource.json create mode 100644 tests/pyunit/stdlib/resources/refs/resources.json diff --git a/src/python/SConscript b/src/python/SConscript index e261bfa7f2..f98b5700c7 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -264,12 +264,24 @@ PySource('gem5.prebuilt.riscvmatched', PySource('gem5.prebuilt.riscvmatched', 'gem5/prebuilt/riscvmatched/riscvmatched_core.py') PySource('gem5.resources', 'gem5/resources/__init__.py') +PySource('gem5.resources', 'gem5/resources/client.py') PySource('gem5.resources', 'gem5/resources/downloader.py') PySource('gem5.resources', 'gem5/resources/md5_utils.py') PySource('gem5.resources', 'gem5/resources/resource.py') PySource('gem5.resources', 'gem5/resources/workload.py') PySource('gem5.resources', 'gem5/resources/looppoint.py') PySource('gem5.resources', 'gem5/resources/elfie.py') +PySource('gem5.resources.client_api', + 'gem5/resources/client_api/__init__.py') +PySource('gem5.resources.client_api', + 'gem5/resources/client_api/jsonclient.py') +PySource('gem5.resources.client_api', + 'gem5/resources/client_api/atlasclient.py') +PySource('gem5.resources.client_api', + 'gem5/resources/client_api/client_wrapper.py') +PySource('gem5.resources.client_api', + 'gem5/resources/client_api/abstract_client.py') +PySource('gem5', 'gem5_default_config.py') PySource('gem5.utils', 'gem5/utils/__init__.py') PySource('gem5.utils', 'gem5/utils/filelock.py') PySource('gem5.utils', 'gem5/utils/override.py') diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py new file mode 100644 index 0000000000..bd473eb038 --- /dev/null +++ b/src/python/gem5/resources/client.py @@ -0,0 +1,84 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import json +from pathlib import Path +import os +from typing import Optional, Dict, List +from .client_api.client_wrapper import ClientWrapper +from gem5.gem5_default_config import config +from m5.util import inform + + +def getFileContent(file_path: Path) -> Dict: + """ + Get the content of the file at the given path + :param file_path: The path of the file + :return: The content of the file + """ + if file_path.exists(): + with open(file_path, "r") as file: + return json.load(file) + else: + raise Exception(f"File not found at {file_path}") + + +clientwrapper = None + + +def get_resource_json_obj( + resource_id, + resource_version: Optional[str] = None, + clients: Optional[List[str]] = None, +) -> Dict: + """ + Get the resource json object from the clients wrapper + :param resource_id: The resource id + :param resource_version: The resource version + :param clients: The list of clients to query + """ + global clientwrapper + if clientwrapper is None: + # First check if the config file path is provided in the environment variable + if "GEM5_CONFIG" in os.environ: + config_file_path = Path(os.environ["GEM5_CONFIG"]) + gem5_config = getFileContent(config_file_path) + inform("Using config file specified by $GEM5_CONFIG") + inform(f"Using config file at {os.environ['GEM5_CONFIG']}") + # If not, check if the config file is present in the current directory + elif (Path().cwd().resolve() / "gem5-config.json").exists(): + config_file_path = Path().resolve() / "gem5-config.json" + gem5_config = getFileContent(config_file_path) + inform(f"Using config file at {config_file_path}") + # If not, use the default config in the build directory + else: + gem5_config = config + inform("Using default config") + clientwrapper = ClientWrapper(gem5_config) + + return clientwrapper.get_resource_json_obj_from_client( + resource_id, resource_version, clients + ) diff --git a/src/python/gem5/resources/client_api/__init__.py b/src/python/gem5/resources/client_api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/python/gem5/resources/client_api/abstract_client.py b/src/python/gem5/resources/client_api/abstract_client.py new file mode 100644 index 0000000000..74a513fc56 --- /dev/null +++ b/src/python/gem5/resources/client_api/abstract_client.py @@ -0,0 +1,71 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from abc import ABC, abstractmethod +from typing import Any, Dict, List +import urllib.parse + + +class AbstractClient(ABC): + def verify_status_code(self, status_code: int) -> None: + """ + Verifies that the status code is 200. + :param status_code: The status code to verify. + """ + if status_code == 200: + return + if status_code == 429: + raise Exception("Panic: Too many requests") + if status_code == 401: + raise Exception("Panic: Unauthorized") + if status_code == 404: + raise Exception("Panic: Not found") + if status_code == 400: + raise Exception("Panic: Bad request") + if status_code == 500: + raise Exception("Panic: Internal server error") + + raise Exception(f"Panic: Unknown status code {status_code}") + + def _url_validator(self, url: str) -> bool: + """ + Validates the provided URL. + :param url: The URL to be validated. + :return: True if the URL is valid, False otherwise. + """ + try: + result = urllib.parse.urlparse(url) + return all([result.scheme, result.netloc, result.path]) + except: + return False + + @abstractmethod + def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: + """ + :param resource_id: The ID of the Resource. + :return: A list of all the Resources with the given ID. + """ + raise NotImplementedError diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py new file mode 100644 index 0000000000..4a6e5cf691 --- /dev/null +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -0,0 +1,91 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from urllib import request, parse +from urllib.error import HTTPError, URLError +from typing import Optional, Dict, Union, Type, Tuple, List, Any +import json +from .abstract_client import AbstractClient + + +class AtlasClient(AbstractClient): + def __init__(self, config: Dict[str, str]): + """ + Initializes a connection to a MongoDB Atlas database. + :param uri: The URI for connecting to the MongoDB server. + :param db: The name of the database to connect to. + :param collection: The name of the collection within the database. + """ + self.apiKey = config["apiKey"] + self.url = config["url"] + self.collection = config["collection"] + self.database = config["database"] + self.dataSource = config["dataSource"] + self.authUrl = config["authUrl"] + + def get_token(self): + data = {"key": self.apiKey} + data = json.dumps(data).encode("utf-8") + + req = request.Request( + self.authUrl, + data=data, + headers={"Content-Type": "application/json"}, + ) + try: + response = request.urlopen(req) + except HTTPError as e: + self.verify_status_code(e.status) + return None + result = json.loads(response.read().decode("utf-8")) + token = result["access_token"] + return token + + def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: + url = f"{self.url}/action/find" + data = { + "dataSource": self.dataSource, + "collection": self.collection, + "database": self.database, + "filter": {"id": resource_id}, + } + data = json.dumps(data).encode("utf-8") + + headers = { + "Authorization": f"Bearer {self.get_token()}", + "Content-Type": "application/json", + } + + req = request.Request(url, data=data, headers=headers) + try: + response = request.urlopen(req) + except HTTPError as e: + self.verify_status_code(e.status) + return None + result = json.loads(response.read().decode("utf-8")) + resources = result["documents"] + + return resources diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py new file mode 100644 index 0000000000..74ee831c1f --- /dev/null +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -0,0 +1,228 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from .jsonclient import JSONClient +from .atlasclient import AtlasClient +from _m5 import core +from typing import Optional, Dict, List +from distutils.version import StrictVersion +import itertools +from m5.util import warn + + +class ClientWrapper: + def __init__(self, config): + self.clients = self.create_clients(config) + + def create_clients( + self, + config: Dict, + ) -> Dict: + """ + This function creates respective client object for each source in the + config file according to the type of source. + Params: config: config file containing the source information + Returns: clients: dictionary of clients for each source + """ + clients = {} + for client in config["sources"]: + client_source = config["sources"][client] + try: + if client_source["isMongo"]: + clients[client] = AtlasClient(client_source) + else: + clients[client] = JSONClient(client_source["url"]) + except Exception as e: + warn(f"Error creating client {client}: {str(e)}") + return clients + + def get_all_resources_by_id( + self, + resource_id: str, + clients: Optional[List[str]] = None, + ) -> List[Dict]: + """ + This function returns all the resources with the given id from all the + sources. + :param resource_id: The id of the resource to search for. + :param clients: A list of clients to search through. If None, all + clients are searched. + :return: A list of resources as Python dictionaries. + """ + resources = [] + if not clients: + clients = list(self.clients.keys()) + for client in clients: + if client not in self.clients: + raise Exception(f"Client: {client} does not exist") + try: + resources.extend( + self.clients[client].get_resources_by_id(resource_id) + ) + except Exception as e: + warn(f"Error getting resources from client {client}: {str(e)}") + # check if no 2 resources have the same id and version + for res1, res2 in itertools.combinations(resources, 2): + if res1["resource_version"] == res2["resource_version"]: + raise Exception( + f"Resource {resource_id} has multiple resources with " + f"the same version: {res1['resource_version']}" + ) + return resources + + def get_resource_json_obj_from_client( + self, + resource_id: str, + resource_version: Optional[str] = None, + clients: Optional[List[str]] = None, + ) -> Dict: + """ + This function returns the resource object from the client with the + given id and version. + :param resource_id: The id of the resource to search for. + :param resource_version: The version of the resource to search for. + :param clients: A list of clients to search through. If None, all + clients are searched. + :return: The resource object as a Python dictionary if found. + If not found, exception is thrown. + """ + # getting all the resources with the given id from the dictionary + resources = self.get_all_resources_by_id(resource_id, clients) + # if no resource with the given id is found, return None + if len(resources) == 0: + raise Exception(f"Resource with ID '{resource_id}' not found.") + + resource_to_return = None + + if resource_version: + resource_to_return = self._search_version_in_resources( + resources, resource_id, resource_version + ) + + else: + compatible_resources = ( + self._get_resources_compatible_with_gem5_version(resources) + ) + if len(compatible_resources) == 0: + resource_to_return = self._sort_resources(resources)[0] + else: + resource_to_return = self._sort_resources( + compatible_resources + )[0] + + self._check_resource_version_compatibility(resource_to_return) + + return resource_to_return + + def _search_version_in_resources( + self, resources: List, resource_id: str, resource_version: str + ) -> Dict: + """ + Searches for the resource with the given version. If the resource is + not found, an exception is thrown. + :param resources: A list of resources to search through. + :param resource_version: The version of the resource to search for. + :return: The resource object as a Python dictionary if found. + If not found, None is returned. + """ + return_resource = next( + iter( + [ + resource + for resource in resources + if resource["resource_version"] == resource_version + ] + ), + None, + ) + if not return_resource: + raise Exception( + f"Resource {resource_id} with version '{resource_version}'" + " not found.\nResource versions can be found at: " + "https://resources.gem5.org/" + f"resources/{resource_id}/versions" + ) + return return_resource + + def _get_resources_compatible_with_gem5_version( + self, resources: List, gem5_version: str = core.gem5Version + ) -> List: + """ + Returns a list of compatible resources with the current gem5 version. + :param resources: A list of resources to filter. + :return: A list of compatible resources as Python dictionaries. + If no compatible resources are found, the original list of resources + is returned. + """ + compatible_resources = [ + resource + for resource in resources + if gem5_version in resource["gem5_versions"] + ] + return compatible_resources + + def _sort_resources(self, resources: List) -> List: + """ + Sorts the resources by ID. + If the IDs are the same, the resources are sorted by version. + :param resources: A list of resources to sort. + :return: A list of sorted resources. + """ + return sorted( + resources, + key=lambda resource: ( + resource["id"].lower(), + StrictVersion(resource["resource_version"]), + ), + reverse=True, + ) + + def _check_resource_version_compatibility( + self, resource: dict, gem5_version: Optional[str] = core.gem5Version + ) -> bool: + """ + Checks if the resource is compatible with the gem5 version. + Prints a warning if the resource is not compatible. + :param resource: The resource to check. + :optional param gem5_version: The gem5 version to check + compatibility with. + :return: True if the resource is compatible, False otherwise. + """ + if not resource: + return False + if gem5_version not in resource["gem5_versions"]: + warn( + f"Resource {resource['id']} with version " + f"{resource['resource_version']} is not known to be compatible" + f" with gem5 version {gem5_version}. " + "This may cause problems with your simulation. " + "This resource's compatibility " + "with different gem5 versions can be found here: " + "https://resources.gem5.org" + f"/resources/{resource['id']}/versions" + ) + return False + return True diff --git a/src/python/gem5/resources/client_api/jsonclient.py b/src/python/gem5/resources/client_api/jsonclient.py new file mode 100644 index 0000000000..225126e2a8 --- /dev/null +++ b/src/python/gem5/resources/client_api/jsonclient.py @@ -0,0 +1,70 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import json +from pathlib import Path +from urllib import request +from typing import Optional, Dict, Union, Type, Tuple, List, Any +from .abstract_client import AbstractClient +from urllib.error import URLError +from m5.util import warn + + +class JSONClient(AbstractClient): + def __init__(self, path: str): + """ + Initializes a JSON client. + :param path: The path to the Resource, either URL or local. + """ + self.path = path + self.resources = [] + + if Path(self.path).is_file(): + self.resources = json.load(open(self.path)) + elif not self._url_validator(self.path): + raise Exception( + f"Resources location '{self.path}' is not a valid path or URL." + ) + else: + req = request.Request(self.path) + try: + response = request.urlopen(req) + except URLError as e: + raise Exception( + f"Unable to open Resources location '{self.path}': {e}" + ) + self.resources = json.loads(response.read().decode("utf-8")) + + def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: + """ + :param resource_id: The ID of the Resource. + :return: A list of all the Resources with the given ID. + """ + return [ + resource + for resource in self.resources + if resource["id"] == resource_id + ] diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index 16b0147b74..0781d9b15a 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -41,6 +41,7 @@ from tempfile import gettempdir from urllib.error import HTTPError from typing import List, Dict, Set, Optional +from .client import get_resource_json_obj from .md5_utils import md5_file, md5_dir from ..utils.progress_bar import tqdm, progress_hook @@ -398,6 +399,8 @@ def get_resource( unzip: bool = True, untar: bool = True, download_md5_mismatch: bool = True, + resource_version: Optional[str] = None, + clients: Optional[List] = None, ) -> None: """ Obtains a gem5 resource and stored it to a specified location. If the @@ -419,6 +422,13 @@ def get_resource( will delete this local resource and re-download it if this parameter is True. True by default. + :param resource_version: The version of the resource to be obtained. If + None, the latest version of the resource compatible with the working + directory's gem5 version will be obtained. None by default. + + :param clients: A list of clients to use when obtaining the resource. If + None, all clients will be used. None by default. + :raises Exception: An exception is thrown if a file is already present at `to_path` but it does not have the correct md5 sum. An exception will also be thrown is a directory is present at `to_path` @@ -430,11 +440,13 @@ def get_resource( # minutes.Most resources should be downloaded and decompressed in this # timeframe, even on the most constrained of systems. with FileLock(f"{to_path}.lock", timeout=900): - - resource_json = get_resources_json_obj(resource_name) + resource_json = get_resource_json_obj( + resource_name, + resource_version=resource_version, + clients=clients, + ) if os.path.exists(to_path): - if os.path.isfile(to_path): md5 = md5_file(Path(to_path)) else: @@ -495,9 +507,8 @@ def get_resource( ) ) - # Get the URL. The URL may contain '{url_base}' which needs replaced - # with the correct value. - url = resource_json["url"].format(url_base=_get_url_base()) + # Get the URL. + url = resource_json["url"] _download(url=url, download_to=download_dest) print(f"Finished downloading resource '{resource_name}'.") diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 9cba9cf88f..22adf15670 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -29,13 +29,15 @@ import os from pathlib import Path from m5.util import warn, fatal -from .downloader import get_resource, get_resources_json_obj +from .downloader import get_resource from .looppoint import LooppointCsvLoader, LooppointJsonLoader from ..isas import ISA, get_isa_from_str from typing import Optional, Dict, Union, Type, Tuple, List +from .client import get_resource_json_obj + """ Resources are items needed to run a simulation, such as a disk image, kernel, or binary. The gem5 project provides pre-built resources, with sources, at @@ -67,18 +69,20 @@ class AbstractResource: def __init__( self, + resource_version: Optional[str] = None, local_path: Optional[str] = None, - documentation: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, ): """ :param local_path: The path on the host system where this resource is located. - :param documentation: Documentation describing this resource. Not a + :param description: Description describing this resource. Not a required parameter. By default is None. :param source: The source (as in "source code") for this resource. This string should navigate users to where the source for this resource may be found. Not a required parameter. By default is None. + :param resource_version: Version of the resource itself. """ if local_path and not os.path.exists(local_path): @@ -88,16 +92,21 @@ class AbstractResource: ) self._local_path = local_path - self._documentation = documentation + self._description = description self._source = source + self._version = resource_version + + def get_resource_version(self) -> str: + """Returns the version of the resource.""" + return self._version def get_local_path(self) -> Optional[str]: """Returns the local path of the resource.""" return self._local_path - def get_documentation(self) -> Optional[str]: - """Returns documentation associated with this resource.""" - return self._documentation + def get_description(self) -> Optional[str]: + """Returns description associated with this resource.""" + return self._description def get_source(self) -> Optional[str]: """Returns information as to where the source for this resource may be @@ -112,7 +121,8 @@ class FileResource(AbstractResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): @@ -123,8 +133,9 @@ class FileResource(AbstractResource): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) @@ -134,11 +145,11 @@ class DirectoryResource(AbstractResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): - if not os.path.isdir(local_path): raise Exception( f"DirectoryResource path specified, {local_path}, is not a " @@ -147,8 +158,9 @@ class DirectoryResource(AbstractResource): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) @@ -158,15 +170,17 @@ class DiskImageResource(FileResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, root_partition: Optional[str] = None, **kwargs, ): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) self._root_partition = root_partition @@ -181,15 +195,17 @@ class BinaryResource(FileResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, architecture: Optional[Union[ISA, str]] = None, **kwargs, ): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) self._architecture = None @@ -210,16 +226,18 @@ class BootloaderResource(BinaryResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, architecture: Optional[Union[ISA, str]] = None, **kwargs, ): super().__init__( local_path=local_path, - documentation=documentation, + description=description, architecture=architecture, source=source, + resource_version=resource_version, ) @@ -229,14 +247,16 @@ class GitResource(DirectoryResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) @@ -246,16 +266,18 @@ class KernelResource(BinaryResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, architecture: Optional[Union[ISA, str]] = None, **kwargs, ): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, architecture=architecture, + resource_version=resource_version, ) @@ -270,14 +292,16 @@ class CheckpointResource(DirectoryResource): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) @@ -290,12 +314,13 @@ class SimpointResource(AbstractResource): def __init__( self, + resource_version: Optional[str] = None, simpoint_interval: int = None, simpoint_list: List[int] = None, weight_list: List[float] = None, warmup_interval: int = 0, workload_name: Optional[str] = None, - documentation: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, local_path: Optional[str] = None, **kwargs, @@ -314,8 +339,9 @@ class SimpointResource(AbstractResource): super().__init__( local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) self._weight_list = weight_list @@ -402,15 +428,17 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): def __init__( self, local_path: str, - documentation: Optional[str] = None, + resource_version: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): FileResource.__init__( self, local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) LooppointCsvLoader.__init__(self, pinpoints_file=Path(local_path)) @@ -419,16 +447,18 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): def __init__( self, local_path: str, + resource_version: Optional[str] = None, region_id: Optional[Union[str, int]] = None, - documentation: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): FileResource.__init__( self, local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) LooppointJsonLoader.__init__( self, looppoint_file=local_path, region_id=region_id @@ -446,8 +476,9 @@ class SimpointDirectoryResource(SimpointResource): weight_file: str, simpoint_interval: int, warmup_interval: int, + resource_version: Optional[str] = None, workload_name: Optional[str] = None, - documentation: Optional[str] = None, + description: Optional[str] = None, source: Optional[str] = None, **kwargs, ): @@ -478,8 +509,9 @@ class SimpointDirectoryResource(SimpointResource): warmup_interval=warmup_interval, workload_name=workload_name, local_path=local_path, - documentation=documentation, + description=description, source=source, + resource_version=resource_version, ) def get_simpoint_file(self) -> Path: @@ -522,9 +554,11 @@ class SimpointDirectoryResource(SimpointResource): def obtain_resource( - resource_name: str, + resource_id: str, resource_directory: Optional[str] = None, download_md5_mismatch: bool = True, + resource_version: Optional[str] = None, + clients: Optional[List] = None, ) -> AbstractResource: """ This function primarily serves as a factory for resources. It will return @@ -544,10 +578,16 @@ def obtain_resource( have the correct md5 value, the resoruce will be deleted and re-downloaded if this value is True. Otherwise an exception will be thrown. True by default. + :param resource_version: Version of the resource itself. + Not a required parameter. None by default. + :param clients: A list of clients to search for the resource. If this + parameter is not set, it will default search all clients. """ - # Obtain the JSON resource entry for this resource - resource_json = get_resources_json_obj(resource_name) + # Obtain the resource object entry for this resource + resource_json = get_resource_json_obj( + resource_id, resource_version=resource_version, clients=clients + ) to_path = None # If the "url" field is specified, the resoruce must be downloaded. @@ -580,38 +620,37 @@ def obtain_resource( os.makedirs(resource_directory, exist_ok=True) # This is the path to which the resource is to be stored. - to_path = os.path.join(resource_directory, resource_name) + to_path = os.path.join(resource_directory, resource_id) # Download the resource if it does not already exist. get_resource( - resource_name=resource_name, - to_path=os.path.join(resource_directory, resource_name), + resource_name=resource_id, + to_path=os.path.join(resource_directory, resource_id), download_md5_mismatch=download_md5_mismatch, + resource_version=resource_version, + clients=clients, ) # Obtain the type from the JSON. From this we will determine what subclass # of `AbstractResource` we are to create and return. - resources_type = resource_json["type"] + resources_category = resource_json["category"] - if resources_type == "resource": + if resources_category == "resource": # This is a stop-gap measure to ensure to work with older versions of # the "resource.json" file. These should be replaced with their # respective specializations ASAP and this case removed. - if ( - "additional_metadata" in resource_json - and "root_partition" in resource_json["additional_metadata"] - ): + if "root_partition" in resource_json: # In this case we should return a DiskImageResource. - root_partition = resource_json["additional_metadata"][ - "root_partition" - ] + root_partition = resource_json["root_partition"] return DiskImageResource( - local_path=to_path, root_partition=root_partition + local_path=to_path, + root_partition=root_partition, + **resource_json, ) return CustomResource(local_path=to_path) - assert resources_type in _get_resource_json_type_map - resource_class = _get_resource_json_type_map[resources_type] + assert resources_category in _get_resource_json_type_map + resource_class = _get_resource_json_type_map[resources_category] # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the @@ -694,6 +733,7 @@ class CustomDiskImageResource(DiskImageResource): def __init__( self, local_path: str, + resource_version: Optional[str] = None, root_partition: Optional[str] = None, metadata: Dict = {}, ): @@ -702,6 +742,7 @@ class CustomDiskImageResource(DiskImageResource): :param root_partition: The root disk partition to use. :param metadata: Metadata for the resource. **Warning:** As of " "v22.1.1, this parameter is not used. + :param resource_version: Version of the resource itself. """ warn( "The `CustomDiskImageResource` class is deprecated. Please use " @@ -713,13 +754,19 @@ class CustomDiskImageResource(DiskImageResource): "`CustomDiskImageResource` constructor. This parameter is not " "used." ) - super().__init__(local_path=local_path, root_partition=root_partition) + super().__init__( + local_path=local_path, + root_partition=root_partition, + resource_version=resource_version, + ) def Resource( - resource_name: str, + resource_id: str, resource_directory: Optional[str] = None, download_md5_mismatch: bool = True, + resource_version: Optional[str] = None, + clients: Optional[List[str]] = None, ) -> AbstractResource: """ This function was created to maintain backwards compability for v21.1.0 @@ -737,9 +784,11 @@ def Resource( ) return obtain_resource( - resource_name=resource_name, + resource_id=resource_id, resource_directory=resource_directory, download_md5_mismatch=download_md5_mismatch, + resource_version=resource_version, + clients=clients, ) diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index e0a19d0792..148ab3f35a 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -24,10 +24,10 @@ # (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 .downloader import get_workload_json_obj from .resource import obtain_resource +from .client import get_resource_json_obj -from typing import Dict, Any, Optional +from typing import Dict, Any, List, Optional class AbstractWorkload: @@ -155,7 +155,11 @@ class Workload(AbstractWorkload): """ def __init__( - self, workload_name: str, resource_directory: Optional[str] = None + self, + workload_name: str, + resource_directory: Optional[str] = None, + resource_version: Optional[str] = None, + clients: Optional[List] = None, ) -> None: """ This constructor will load the workload details from the workload with @@ -167,13 +171,13 @@ class Workload(AbstractWorkload): ```json { - "type" : "workload", - "name" : "x86-ubuntu-18.04-echo-hello", - "documentation" : "Description of workload here", + "category" : "workload", + "id" : "x86-ubuntu-18.04-echo-hello", + "description" : "Description of workload here", "function" : "set_kernel_disk_workload", "resources" : { "kernel" : "x86-linux-kernel-5.4.49", - "disk_image" : "x86-ubuntu-18.04-img" + "disk-image" : "x86-ubuntu-18.04-img" }, "additional_params" : { "readfile_contents" : "m5_exit; echo 'hello'; m5_exit" @@ -187,7 +191,7 @@ class Workload(AbstractWorkload): ```python board.set_kernel_disk_workload( kernel = Resource("x86-linux-kernel-5.4.49"), - disk_image = Resource("x86-ubuntu-18.04-img"), + disk-image = Resource("x86-ubuntu-18.04-img"), readfile_contents = "m5_exit; echo 'hello'; m5_exit", ) ``` @@ -198,7 +202,12 @@ class Workload(AbstractWorkload): any resources should be download and accessed from. If None, a default location will be used. None by default. """ - workload_json = get_workload_json_obj(workload_name=workload_name) + + workload_json = get_resource_json_obj( + workload_name, + resource_version=resource_version, + clients=clients, + ) func = workload_json["function"] assert isinstance(func, str) diff --git a/src/python/gem5/utils/simpoint.py b/src/python/gem5/utils/simpoint.py index eab92e2291..0d1af4b1cf 100644 --- a/src/python/gem5/utils/simpoint.py +++ b/src/python/gem5/utils/simpoint.py @@ -83,15 +83,11 @@ class SimPoint: simpoint_file_path = simpoint_directory.get_simpoint_file() weight_file_path = simpoint_resource.get_weight_file() - simpoint_interval = ( - simpoint_resource.get_metadata() - .get("additional_metadata") - .get("simpoint_interval") + simpoint_interval = simpoint_resource.get_metadata().get( + "simpoint_interval" ) - warmup_interval = ( - simpoint_resource.get_metadata() - .get("additional_metadata") - .get("warmup_interval") + warmup_interval = simpoint_resource.get_metadata().get( + "warmup_interval" ) self._simpoint_interval = simpoint_interval diff --git a/src/python/gem5_default_config.py b/src/python/gem5_default_config.py new file mode 100644 index 0000000000..980c883109 --- /dev/null +++ b/src/python/gem5_default_config.py @@ -0,0 +1,39 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +config = { + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "versions_test", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": True, + } + } +} diff --git a/tests/gem5/verifier.py b/tests/gem5/verifier.py index 93d47c8d10..c725fc68b9 100644 --- a/tests/gem5/verifier.py +++ b/tests/gem5/verifier.py @@ -172,6 +172,7 @@ class MatchStdout(DerivedGoldStandard): re.compile("^Using GPU kernel code file\(s\) "), re.compile("^.* not found locally\. Downloading"), re.compile("^Finished downloading"), + re.compile("^info: Using default config"), ] diff --git a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py new file mode 100644 index 0000000000..96aadf6879 --- /dev/null +++ b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py @@ -0,0 +1,511 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +from gem5.isas import ISA +from gem5.resources.client import get_resource_json_obj +import gem5.resources.client +from gem5.resources.client_api.client_wrapper import ClientWrapper +from typing import Dict +from unittest.mock import patch +from unittest import mock +import json +from urllib.error import HTTPError +import io +import contextlib +from pathlib import Path + +mock_json_path = Path(__file__).parent / "refs/resources.json" +mock_config_json = { + "sources": { + "baba": { + "url": mock_json_path, + "isMongo": False, + } + }, +} + +mock_config_mongo = { + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "versions_test", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": True, + } + }, +} + +mock_config_combined = { + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "versions_test", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": True, + }, + "baba": { + "url": mock_json_path, + "isMongo": False, + }, + }, +} + +mock_json = {} + +with open(Path(__file__).parent / "refs/mongo_mock.json", "r") as f: + mock_json = json.load(f) + +duplicate_mock_json = {} + +with open(Path(__file__).parent / "refs/mongo_dup_mock.json", "r") as f: + duplicate_mock_json = json.load(f) + + +def mocked_requests_post(*args): + # mokcing urllib.request.urlopen + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status = status_code + + def read(self): + return json.dumps(self.json_data).encode("utf-8") + + data = json.loads(args[0].data) + if "/api-key/login" in args[0].full_url: + return MockResponse({"access_token": "test-token"}, 200) + if "/endpoint/data/v1/action/find" in args[0].full_url: + if data: + if data["filter"]["id"] == "x86-ubuntu-18.04-img": + return MockResponse( + { + "documents": mock_json, + }, + 200, + ) + if data["filter"]["id"] == "test-duplicate": + return MockResponse( + { + "documents": duplicate_mock_json, + }, + 200, + ) + if data["filter"]["id"] == "test-too-many": + error_file = io.BytesIO() + error_file.status = 429 + raise HTTPError( + args[0].full_url, 429, "Too Many Requests", {}, error_file + ) + return MockResponse( + { + "documents": [], + }, + 200, + ) + error_file = io.BytesIO() + error_file.status = 404 + raise HTTPError(args[0].full_url, 404, "Not Found", {}, error_file) + + +class ClientWrapperTestSuite(unittest.TestCase): + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_json), + ) + def test_get_resource_json_obj(self): + # Test that the resource object is correctly returned + resource = "this-is-a-test-resource" + resource = get_resource_json_obj(resource) + self.assertEqual(resource["id"], "this-is-a-test-resource") + self.assertEqual(resource["resource_version"], "2.0.0") + self.assertEqual(resource["category"], "binary") + self.assertEqual( + resource["description"], "This is a test resource but double newer" + ) + self.assertEqual( + resource["source_url"], + "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + ) + self.assertEqual(resource["architecture"], "X86") + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_json), + ) + def test_get_resource_json_obj_invalid_client(self): + # Test that an exception is raised when an invalid client is passed + resource_id = "test-id" + client = "invalid" + with self.assertRaises(Exception) as context: + get_resource_json_obj(resource_id, clients=[client]) + self.assertTrue( + f"Client: {client} does not exist" in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_json), + ) + def test_get_resource_json_obj_with_version(self): + # Test that the resource object is correctly returned + resource_id = "this-is-a-test-resource" + resource_version = "1.0.0" + resource = get_resource_json_obj( + resource_id, resource_version=resource_version + ) + self.assertEqual(resource["id"], "this-is-a-test-resource") + self.assertEqual(resource["resource_version"], "1.0.0") + self.assertEqual(resource["category"], "binary") + self.assertEqual(resource["description"], "This is a test resource") + self.assertEqual( + resource["source_url"], + "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + ) + self.assertEqual(resource["architecture"], "X86") + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_mongo), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_obj_1(self, mock_get): + resource = "x86-ubuntu-18.04-img" + resource = get_resource_json_obj(resource) + self.assertEqual(resource["id"], "x86-ubuntu-18.04-img") + self.assertEqual(resource["resource_version"], "1.1.0") + self.assertEqual(resource["category"], "disk-image") + self.assertEqual( + resource["description"], + "A disk image containing Ubuntu 18.04 for x86. This image will run an `m5 readfile` instruction after booting. If no script file is specified an `m5 exit` instruction will be executed.", + ) + self.assertEqual( + resource["source_url"], + "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + ) + self.assertEqual(resource["architecture"], "X86") + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_mongo), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_obj_with_version_mongodb(self, mock_get): + # Test that the resource object is correctly returned + resource_id = "x86-ubuntu-18.04-img" + resource_version = "1.0.0" + resource = get_resource_json_obj( + resource_id, + resource_version=resource_version, + clients=["gem5-resources"], + ) + self.assertEqual(resource["id"], "x86-ubuntu-18.04-img") + self.assertEqual(resource["resource_version"], "1.0.0") + self.assertEqual(resource["category"], "disk-image") + self.assertEqual(resource["description"], "This is a test resource") + self.assertEqual( + resource["source_url"], + "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + ) + self.assertEqual(resource["architecture"], "X86") + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_mongo), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_obj_with_id_invalid_mongodb(self, mock_get): + resource_id = "invalid-id" + with self.assertRaises(Exception) as context: + get_resource_json_obj(resource_id, clients=["gem5-resources"]) + self.assertTrue( + "Resource with ID 'invalid-id' not found." + in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_mongo), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_obj_with_version_invalid_mongodb( + self, mock_get + ): + resource_id = "x86-ubuntu-18.04-img" + resource_version = "2.5.0" + with self.assertRaises(Exception) as context: + get_resource_json_obj( + resource_id, + resource_version=resource_version, + clients=["gem5-resources"], + ) + self.assertTrue( + f"Resource x86-ubuntu-18.04-img with version '2.5.0'" + " not found.\nResource versions can be found at: " + f"https://resources.gem5.org/resources/x86-ubuntu-18.04-img/versions" + in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_json), + ) + def test_get_resource_json_obj_with_version_invalid_json(self): + resource_id = "this-is-a-test-resource" + resource_version = "2.5.0" + with self.assertRaises(Exception) as context: + get_resource_json_obj( + resource_id, + resource_version=resource_version, + ) + self.assertTrue( + f"Resource this-is-a-test-resource with version '2.5.0'" + " not found.\nResource versions can be found at: " + f"https://resources.gem5.org/resources/this-is-a-test-resource/versions" + in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_combined), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_obj_combine(self, mock_get): + resource_id_mongo = "x86-ubuntu-18.04-img" + resource_version_mongo = "1.0.0" + resource_id_json = "this-is-a-test-resource" + resource_version_json = "1.0.0" + resource_mongo = get_resource_json_obj( + resource_id_mongo, + resource_version=resource_version_mongo, + clients=["gem5-resources"], + ) + resource_json = get_resource_json_obj( + resource_id_json, + resource_version=resource_version_json, + clients=["baba"], + ) + self.assertEqual(resource_mongo["id"], "x86-ubuntu-18.04-img") + self.assertEqual(resource_mongo["resource_version"], "1.0.0") + self.assertEqual(resource_mongo["category"], "disk-image") + self.assertEqual( + resource_mongo["description"], "This is a test resource" + ) + self.assertEqual( + resource_mongo["source_url"], + "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + ) + self.assertEqual(resource_mongo["architecture"], "X86") + + self.assertEqual(resource_json["id"], "this-is-a-test-resource") + self.assertEqual(resource_json["resource_version"], "1.0.0") + self.assertEqual(resource_json["category"], "binary") + self.assertEqual( + resource_json["description"], "This is a test resource" + ) + self.assertEqual( + resource_json["source_url"], + "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + ) + self.assertEqual(resource_json["architecture"], "X86") + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_combined), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_obj_multi_database_second_only(self, mock_get): + resource_id = "simpoint-resource" + resource = get_resource_json_obj( + resource_id, + ) + self.assertEqual(resource["id"], resource_id) + self.assertEqual(resource["resource_version"], "0.2.0") + self.assertEqual(resource["category"], "file") + self.assertEqual( + resource["description"], + ( + "Simpoints for running the 'x86-print-this' resource with" + ' the parameters `"print this" 15000`. This is encapsulated' + " in the 'x86-print-this-15000-with-simpoints' workload." + ), + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_combined), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_json_same_resource_different_versions( + self, mock_get + ): + resource_id = "x86-ubuntu-18.04-img" + resource_json = get_resource_json_obj( + resource_id, + ) + + self.assertEqual(resource_json["id"], "x86-ubuntu-18.04-img") + self.assertEqual(resource_json["resource_version"], "2.0.0") + self.assertEqual(resource_json["category"], "disk-image") + + resource_json = get_resource_json_obj( + resource_id, + resource_version="1.0.0", + ) + + self.assertEqual(resource_json["id"], "x86-ubuntu-18.04-img") + self.assertEqual(resource_json["resource_version"], "1.0.0") + self.assertEqual(resource_json["category"], "disk-image") + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_combined), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_get_resource_same_resource_same_version(self, mock_get): + resource_id = "test-duplicate" + with self.assertRaises(Exception) as context: + get_resource_json_obj( + resource_id, + ) + self.assertTrue( + f"Resource {resource_id} has multiple resources with" + f" the same version: 0.2.0" in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper( + { + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "versions_test", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/logi", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": True, + } + }, + } + ), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_invalid_auth_url(self, mock_get): + resource_id = "test-resource" + f = io.StringIO() + with self.assertRaises(Exception) as context: + with contextlib.redirect_stderr(f): + get_resource_json_obj( + resource_id, + ) + self.assertTrue( + "Error getting resources from client gem5-resources:" + " Panic: Not found" in str(f.getvalue()) + ) + self.assertTrue( + "Resource with ID 'test-resource' not found." + in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper( + { + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "versions_test", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": True, + } + }, + } + ), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_invalid_url(self, mock_get): + resource_id = "test-resource" + f = io.StringIO() + with self.assertRaises(Exception) as context: + with contextlib.redirect_stderr(f): + get_resource_json_obj( + resource_id, + ) + self.assertTrue( + "Error getting resources from client gem5-resources:" + " Panic: Not found" in str(f.getvalue()) + ) + self.assertTrue( + "Resource with ID 'test-resource' not found." + in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper( + { + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "versions_test", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": True, + } + }, + } + ), + ) + @patch("urllib.request.urlopen", side_effect=mocked_requests_post) + def test_invalid_url(self, mock_get): + resource_id = "test-too-many" + f = io.StringIO() + with self.assertRaises(Exception) as context: + with contextlib.redirect_stderr(f): + get_resource_json_obj( + resource_id, + ) + self.assertTrue( + "Error getting resources from client gem5-resources:" + " Panic: Too many requests" in str(f.getvalue()) + ) + self.assertTrue( + "Resource with ID 'test-too-many' not found." + in str(context.exception) + ) diff --git a/tests/pyunit/stdlib/resources/pyunit_downloader_checks.py b/tests/pyunit/stdlib/resources/pyunit_downloader_checks.py index 08736bbc32..19169e480e 100644 --- a/tests/pyunit/stdlib/resources/pyunit_downloader_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_downloader_checks.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ import unittest import tempfile import os from typing import Dict +import json from gem5.resources.downloader import ( _get_resources_json_at_path, @@ -42,48 +43,102 @@ class ResourceDownloaderTestSuite(unittest.TestCase): @classmethod def setUpClass(cls) -> str: """ - This creates a simple resource.json temp file for testing purposes. + This creates a simple resources collection for testing """ - - file_contents = ( - "{" - + f'"version" : "{_resources_json_version_required()}",' - + """ - "url_base" : "http://dist.gem5.org/dist/v21-2", - "previous-versions" : {}, - "resources": [ - { - "type": "resource", - "name" : "riscv-disk-img", - "documentation" : "A simple RISCV disk image based on busybox.", - "architecture": "RISCV", - "is_zipped" : true, - "md5sum" : "d6126db9f6bed7774518ae25aa35f153", - "url": "{url_base}/images/riscv/busybox/riscv-disk.img.gz", - "source" : "src/riscv-fs", - "additional_metadata" : { - "root_partition": null - } - }, - { - "type": "resource", - "name" : "riscv-lupio-busybox-img", - "documentation" : "A RISCV disk image, based on busybox, to ...", - "architecture": "RISCV", - "is_zipped" : true, - "md5sum" : "e5bee8a31f45f4803f87c0d781553ccc", - "url": "{url_base}/images/riscv/busybox/riscv-lupio-busybox.img", - "source" : "src/lupv", - "additional_metadata" : { - "root_partition": "1" - } - } - ] -} - """ - ) + file_contents = [ + { + "category": "binary", + "id": "this-is-a-test-resource", + "description": "This is a test resource", + "architecture": "X86", + "size": 13816, + "tags": ["asmtest", "testing", "riscv", "testing"], + "is_zipped": False, + "md5sum": "4e70a98b6976969deffff91eed17fba1", + "source": "src/asmtest", + "url": "http://dist.gem5.org/dist/develop/test-progs/asmtest/bin/rv64mi-p-sbreak", + "code_examples": [], + "license": " BSD-3-Clause", + "author": [], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + "example_usage": 'get_resource(resource_name="rv64mi-p-sbreak")', + }, + { + "category": "binary", + "id": "this-is-a-test-resource", + "description": "This is a test resource but double newer", + "architecture": "X86", + "size": 13816, + "tags": ["asmtest"], + "is_zipped": False, + "md5sum": "4e70a98b6976969deffff91eed17fba1", + "source": "src/asmtest", + "url": "http://dist.gem5.org/dist/develop/test-progs/asmtest/bin/rv64mi-p-sbreak", + "code_examples": [], + "license": " BSD-3-Clause", + "author": [], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + "resource_version": "2.0.0", + "gem5_versions": ["23.1"], + "example_usage": 'get_resource(resource_name="rv64mi-p-sbreak")', + }, + { + "category": "simpoint", + "id": "test-version", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": False, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": True, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": 'get_resource(resource_name="x86-print-this-1500-simpoints")', + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint", + ], + }, + { + "category": "file", + "id": "test-version", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": False, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": True, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": ["23.0"], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": 'get_resource(resource_name="x86-print-this-1500-simpoints")', + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint", + ], + }, + ] file = tempfile.NamedTemporaryFile(mode="w", delete=False) - file.write(file_contents) + file.write(json.dumps(file_contents)) file.close() cls.file_path = file.name @@ -100,14 +155,16 @@ class ResourceDownloaderTestSuite(unittest.TestCase): "create_temp_resources_json" has been loaded correctly into a Python dictionary. """ - self.assertTrue("resources" in json) - self.assertEquals(2, len(json["resources"])) - self.assertTrue("name" in json["resources"][0]) - self.assertEquals("riscv-disk-img", json["resources"][0]["name"]) - self.assertTrue("name" in json["resources"][1]) - self.assertEquals( - "riscv-lupio-busybox-img", json["resources"][1]["name"] - ) + self.assertEquals(4, len(json)) + self.assertTrue("id" in json[0]) + self.assertEquals("this-is-a-test-resource", json[0]["id"]) + self.assertEquals("binary", json[0]["category"]) + self.assertTrue("id" in json[1]) + self.assertEquals("this-is-a-test-resource", json[1]["id"]) + self.assertTrue("id" in json[2]) + self.assertEquals("test-version", json[2]["id"]) + self.assertTrue("id" in json[3]) + self.assertEquals("test-version", json[3]["id"]) def test_get_resources_json_at_path(self) -> None: # Tests the gem5.resources.downloader._get_resources_json_at_path() diff --git a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py new file mode 100644 index 0000000000..791d96c1f1 --- /dev/null +++ b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py @@ -0,0 +1,192 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +import os +import io +import contextlib +from pathlib import Path + +from gem5.resources.resource import * + +from gem5.resources.looppoint import ( + LooppointCsvLoader, + LooppointJsonLoader, +) + +from gem5.isas import ISA + +from _m5 import core + +from gem5.resources.client_api.client_wrapper import ClientWrapper +from unittest.mock import patch + +mock_json_path = Path(__file__).parent / "refs/obtain-resource.json" + +mock_config_json = { + "sources": { + "baba": { + "url": mock_json_path, + "isMongo": False, + } + }, +} + + +@patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), +) +class TestObtainResourcesCheck(unittest.TestCase): + @classmethod + def setUpClass(cls): + """Prior to running the suite we set the resource directory to + "ref/resource-specialization.json" + """ + os.environ["GEM5_RESOURCE_JSON"] = os.path.join( + os.path.realpath(os.path.dirname(__file__)), + "refs", + "obtain-resource.json", + ) + + @classmethod + def tearDownClass(cls) -> None: + """After running the suite we unset the gem5-resource JSON file, as to + not interfere with others tests. + """ + del os.environ["GEM5_RESOURCE_JSON"] + + def get_resource_dir(cls) -> str: + """To ensure the resources are cached to the same directory as all + other tests, this function returns the location of the testing + directories "resources" directory. + """ + return os.path.join( + os.path.realpath(os.path.dirname(__file__)), + os.pardir, + os.pardir, + os.pardir, + "gem5", + "resources", + ) + + def test_obtain_resources_no_version(self): + """Test that the resource loader returns latest version compatible with that version of gem5 when no version is specified.""" + gem5Version = core.gem5Version + resource = obtain_resource( + resource_id="test-binary-resource", + resource_directory=self.get_resource_dir(), + ) + self.assertEquals("2.5.0", resource.get_resource_version()) + self.assertIsInstance(resource, BinaryResource) + # self.assertIn(gem5Version, resource.get_gem5_versions()) + self.assertEquals("test description", resource.get_description()) + self.assertEquals("src/test-source", resource.get_source()) + self.assertEquals(ISA.ARM, resource.get_architecture()) + + def test_obtain_resources_with_version_compatible(self): + gem5Version = core.gem5Version + resource = obtain_resource( + resource_id="test-binary-resource", + resource_directory=self.get_resource_dir(), + resource_version="1.7.0", + ) + self.assertEquals("1.7.0", resource.get_resource_version()) + self.assertIsInstance(resource, BinaryResource) + # self.assertIn(gem5Version, resource.get_gem5_versions()) + self.assertEquals( + "test description v1.7.0", resource.get_description() + ) + self.assertEquals("src/test-source", resource.get_source()) + self.assertEquals(ISA.ARM, resource.get_architecture()) + + def test_obtain_resources_with_version_incompatible(self): + resource = None + f = io.StringIO() + with contextlib.redirect_stderr(f): + resource = obtain_resource( + resource_id="test-binary-resource", + resource_directory=self.get_resource_dir(), + resource_version="1.5.0", + ) + self.assertTrue( + f"warn: Resource test-binary-resource with version 1.5.0 is not known to be compatible with gem5 version {core.gem5Version}. " + "This may cause problems with your simulation. This resource's compatibility with different gem5 versions can be found here: " + f"https://resources.gem5.org/resources/test-binary-resource/versions" + in f.getvalue() + ) + + resource = obtain_resource( + resource_id="test-binary-resource", + resource_directory=self.get_resource_dir(), + resource_version="1.5.0", + ) + self.assertEquals("1.5.0", resource.get_resource_version()) + self.assertIsInstance(resource, BinaryResource) + self.assertEquals( + "test description for 1.5.0", resource.get_description() + ) + self.assertEquals("src/test-source", resource.get_source()) + self.assertEquals(ISA.ARM, resource.get_architecture()) + + def test_obtain_resources_no_version_invalid_id(self): + with self.assertRaises(Exception) as context: + obtain_resource( + resource_id="invalid-id", + resource_directory=self.get_resource_dir(), + ) + self.assertTrue( + "Resource with ID 'invalid-id' not found." + in str(context.exception) + ) + + def test_obtain_resources_with_version_invalid_id(self): + with self.assertRaises(Exception) as context: + obtain_resource( + resource_id="invalid-id", + resource_directory=self.get_resource_dir(), + resource_version="1.7.0", + ) + self.assertTrue( + "Resource with ID 'invalid-id' not found." + in str(context.exception) + ) + + def test_obtain_resources_with_version_invalid_version(self): + with self.assertRaises(Exception) as context: + obtain_resource( + resource_id="test-binary-resource", + resource_directory=self.get_resource_dir(), + resource_version="3.0.0", + ) + print("context.exception: ", context.exception) + print(str(context.exception)) + self.assertTrue( + f"Resource test-binary-resource with version '3.0.0'" + " not found.\nResource versions can be found at: " + f"https://resources.gem5.org/resources/test-binary-resource/versions" + in str(context.exception) + ) diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py b/tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py new file mode 100644 index 0000000000..8f6674ff0d --- /dev/null +++ b/tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py @@ -0,0 +1,72 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +import tempfile +import os +from typing import Dict + +from gem5.resources.downloader import ( + get_resources_json_obj, +) + + +class ResourceDownloadTestSuite(unittest.TestCase): + """Test cases for gem5.resources.downloader""" + + @classmethod + def setUpClass(cls) -> str: + pass + + def get_resource_json_by_id(self) -> None: + """Get a resource by its id""" + resources = get_resources_json_obj("test-version") + self.assertEqual(resources["id"], "test-version") + self.assertEqual(resources["resource_version"], "2.0.0") + + def get_resource_json_invalid_id(self) -> None: + """Should throw an exception when trying to get a resource that doesn't exist""" + with self.assertRaises(Exception) as context: + get_resources_json_obj("this-resource-doesnt-exist") + self.assertTrue( + f"Error: Resource with name 'this-resource-doesnt-exist' does not exist" + in str(context.exception) + ) + + def get_resource_json_by_id_and_version(self) -> None: + """Get a resource by its id and version""" + resources = get_resources_json_obj("test-version", "1.0.0") + self.assertEqual(resources["id"], "test-version") + self.assertEqual(resources["resource_version"], "1.0.0") + + def get_resource_json_by_id_and_invalid_version(self) -> None: + """Get a resource by its id and an invalid version (does not exist)""" + with self.assertRaises(Exception) as context: + get_resources_json_obj("test-version", "3.0.0") + self.assertTrue( + f"Specified Version 3.0.0 does not exist for the resource 'test-version'." + in str(context.exception) + ) diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py index 660bf5f38f..5c22a7341e 100644 --- a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py +++ b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py @@ -37,7 +37,25 @@ from gem5.resources.looppoint import ( from gem5.isas import ISA +from gem5.resources.client_api.client_wrapper import ClientWrapper +from unittest.mock import patch +mock_json_path = Path(__file__).parent / "refs/resource-specialization.json" + +mock_config_json = { + "sources": { + "baba": { + "url": mock_json_path, + "isMongo": False, + } + }, +} + + +@patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_json), +) class ResourceSpecializationSuite(unittest.TestCase): """This suite tests that `gem5.resource.resource` casts to the correct `AbstractResource` specialization when using the `obtain_resource` @@ -79,14 +97,14 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_binary_resource(self) -> None: """Tests the loading of of a BinaryResource""" resource = obtain_resource( - resource_name="binary-example", + resource_id="binary-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, BinaryResource) self.assertEquals( - "binary-example documentation.", resource.get_documentation() + "binary-example documentation.", resource.get_description() ) self.assertEquals("src/simple", resource.get_source()) self.assertEquals(ISA.ARM, resource.get_architecture()) @@ -94,14 +112,14 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_kernel_resource(self) -> None: """Tests the loading of a KernelResource.""" resource = obtain_resource( - resource_name="kernel-example", + resource_id="kernel-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, KernelResource) self.assertEquals( - "kernel-example documentation.", resource.get_documentation() + "kernel-example documentation.", resource.get_description() ) self.assertEquals("src/linux-kernel", resource.get_source()) self.assertEquals(ISA.RISCV, resource.get_architecture()) @@ -109,14 +127,14 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_bootloader_resource(self) -> None: """Tests the loading of a BootloaderResource.""" resource = obtain_resource( - resource_name="bootloader-example", + resource_id="bootloader-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, BootloaderResource) self.assertEquals( - "bootloader documentation.", resource.get_documentation() + "bootloader documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) self.assertIsNone(resource.get_architecture()) @@ -124,14 +142,14 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_disk_image_resource(self) -> None: """Tests the loading of a DiskImageResource.""" resource = obtain_resource( - resource_name="disk-image-example", + resource_id="disk-image-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, DiskImageResource) self.assertEquals( - "disk-image documentation.", resource.get_documentation() + "disk-image documentation.", resource.get_description() ) self.assertEquals("src/x86-ubuntu", resource.get_source()) self.assertEquals("1", resource.get_root_partition()) @@ -139,40 +157,40 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_checkpoint_resource(self) -> None: """Tests the loading of a CheckpointResource.""" resource = obtain_resource( - resource_name="checkpoint-example", + resource_id="checkpoint-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, CheckpointResource) self.assertEquals( - "checkpoint-example documentation.", resource.get_documentation() + "checkpoint-example documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) def test_git_resource(self) -> None: """Tests the loading of a GitResource.""" resource = obtain_resource( - resource_name="git-example", + resource_id="git-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, GitResource) - self.assertIsNone(resource.get_documentation()) + self.assertIsNone(resource.get_description()) self.assertIsNone(resource.get_source()) def test_simpoint_directory_resource(self) -> None: """Tests the loading of a Simpoint directory resource.""" resource = obtain_resource( - resource_name="simpoint-directory-example", + resource_id="simpoint-directory-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, SimpointDirectoryResource) self.assertEquals( - "simpoint directory documentation.", resource.get_documentation() + "simpoint directory documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -199,14 +217,14 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_simpoint_resource(self) -> None: """Tests the loading of a Simpoint resource.""" resource = obtain_resource( - resource_name="simpoint-example", + resource_id="simpoint-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, SimpointResource) self.assertEquals( - "simpoint documentation.", resource.get_documentation() + "simpoint documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) self.assertIsNone(resource.get_local_path()) @@ -219,26 +237,27 @@ class ResourceSpecializationSuite(unittest.TestCase): def test_file_resource(self) -> None: """Tests the loading of a FileResource.""" resource = obtain_resource( - resource_name="file-example", + resource_id="file-example", resource_directory=self.get_resource_dir(), + resource_version="1.0.0", ) self.assertIsInstance(resource, FileResource) - self.assertIsNone(resource.get_documentation()) + self.assertIsNone(resource.get_description()) self.assertIsNone(resource.get_source()) def test_directory_resource(self) -> None: """Tests the loading of a DirectoryResource.""" resource = obtain_resource( - resource_name="directory-example", + resource_id="directory-example", resource_directory=self.get_resource_dir(), ) self.assertIsInstance(resource, DirectoryResource) self.assertEquals( - "directory-example documentation.", resource.get_documentation() + "directory-example documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -247,7 +266,7 @@ class ResourceSpecializationSuite(unittest.TestCase): pinpoints csv file.""" resource = obtain_resource( - resource_name="looppoint-pinpoint-csv-resource", + resource_id="looppoint-pinpoint-csv-resource", resource_directory=self.get_resource_dir(), ) @@ -258,7 +277,7 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, LooppointCsvLoader) self.assertEquals( - "A looppoint pinpoints csv file.", resource.get_documentation() + "A looppoint pinpoints csv file.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -267,8 +286,9 @@ class ResourceSpecializationSuite(unittest.TestCase): Looppoint JSON file.""" resource = obtain_resource( - resource_name="looppoint-json-restore-resource-region-1", + resource_id="looppoint-json-restore-resource-region-1", resource_directory=self.get_resource_dir(), + resource_version="1.0.0", ) self.assertIsInstance(resource, LooppointJsonResource) @@ -278,6 +298,6 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertTrue("1" in resource.get_regions()) self.assertEquals( - "A looppoint json file resource.", resource.get_documentation() + "A looppoint json file resource.", resource.get_description() ) self.assertIsNone(resource.get_source()) diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index 2bc31f5a3f..b898faeb79 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,6 +36,29 @@ from gem5.resources.resource import ( from typing import Dict +from gem5.resources.client_api.client_wrapper import ClientWrapper +from unittest.mock import patch +from pathlib import Path + +mock_config_json1 = { + "sources": { + "baba": { + "url": Path(__file__).parent + / "refs/workload-checks-custom-workload.json", + "isMongo": False, + } + }, +} + +mock_config_json2 = { + "sources": { + "baba": { + "url": Path(__file__).parent / "refs/workload-checks.json", + "isMongo": False, + } + }, +} + class CustomWorkloadTestSuite(unittest.TestCase): """ @@ -43,8 +66,11 @@ class CustomWorkloadTestSuite(unittest.TestCase): """ @classmethod + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json1), + ) def setUpClass(cls) -> None: - os.environ["GEM5_RESOURCE_JSON"] = os.path.join( os.path.realpath(os.path.dirname(__file__)), "refs", @@ -114,8 +140,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): "test", self.custom_workload.get_parameters()["binary"] ) - # We set the overridden parameter back to it's old value. - self.custom_workload.set_parameter("binary", old_value) + # We set the overridden parameter back to it's old valu self.custom_workload.set_parameter("binary", old_value) class WorkloadTestSuite(unittest.TestCase): @@ -124,8 +149,11 @@ class WorkloadTestSuite(unittest.TestCase): """ @classmethod + @patch( + "gem5.resources.client.clientwrapper", + ClientWrapper(mock_config_json2), + ) def setUpClass(cls): - os.environ["GEM5_RESOURCE_JSON"] = os.path.join( os.path.realpath(os.path.dirname(__file__)), "refs", @@ -157,9 +185,9 @@ class WorkloadTestSuite(unittest.TestCase): self.assertTrue("kernel" in parameters) self.assertTrue(isinstance(parameters["kernel"], BinaryResource)) - self.assertTrue("disk_image" in parameters) + self.assertTrue("disk-image" in parameters) self.assertTrue( - isinstance(parameters["disk_image"], DiskImageResource) + isinstance(parameters["disk-image"], DiskImageResource) ) self.assertTrue("readfile_contents" in parameters) diff --git a/tests/pyunit/stdlib/resources/refs/mongo_dup_mock.json b/tests/pyunit/stdlib/resources/refs/mongo_dup_mock.json new file mode 100644 index 0000000000..fe87cc8c28 --- /dev/null +++ b/tests/pyunit/stdlib/resources/refs/mongo_dup_mock.json @@ -0,0 +1,30 @@ +[ + { + "category": "file", + "id": "test-duplicate", + "description": "test", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + } +] diff --git a/tests/pyunit/stdlib/resources/refs/mongo_mock.json b/tests/pyunit/stdlib/resources/refs/mongo_mock.json new file mode 100644 index 0000000000..b6376cc5e4 --- /dev/null +++ b/tests/pyunit/stdlib/resources/refs/mongo_mock.json @@ -0,0 +1,56 @@ +[ + { + "category": "disk-image", + "id": "x86-ubuntu-18.04-img", + "description": "This is a test resource", + "architecture": "X86", + "size": 688119691, + "tags": [ + "x86", + "fullsystem" + ], + "is_zipped": true, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "source": "src/x86-ubuntu", + "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "root_partition": "1", + "code_examples": [], + "license": "", + "author": [ + "Ayaz Akram" + ], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ], + "example_usage": "get_resource(resource_name=\"x86-ubuntu-18.04-img\")" + }, + { + "category": "disk-image", + "id": "x86-ubuntu-18.04-img", + "description": "A disk image containing Ubuntu 18.04 for x86. This image will run an `m5 readfile` instruction after booting. If no script file is specified an `m5 exit` instruction will be executed.", + "architecture": "X86", + "size": 688119691, + "tags": [ + "x86", + "fullsystem" + ], + "is_zipped": true, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "source": "src/x86-ubuntu", + "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "root_partition": "1", + "code_examples": [], + "license": "", + "author": [ + "Ayaz Akram" + ], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + "resource_version": "1.1.0", + "gem5_versions": [ + "23.0" + ], + "example_usage": "get_resource(resource_name=\"x86-ubuntu-18.04-img\")" + } +] diff --git a/tests/pyunit/stdlib/resources/refs/obtain-resource.json b/tests/pyunit/stdlib/resources/refs/obtain-resource.json new file mode 100644 index 0000000000..fac95e106a --- /dev/null +++ b/tests/pyunit/stdlib/resources/refs/obtain-resource.json @@ -0,0 +1,59 @@ +[ + { + "category": "binary", + "id": "test-binary-resource", + "description": "test description", + "architecture": "ARM", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "source": "src/test-source", + "resource_version": "2.5.0", + "gem5_versions": [ + "25.0" + ] + }, + { + "category": "binary", + "id": "test-binary-resource", + "description": "test description", + "architecture": "ARM", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "source": "src/test-source", + "resource_version": "2.0.0", + "gem5_versions": [ + "develop" + ] + }, + { + "category": "binary", + "id": "test-binary-resource", + "description": "test description v1.7.0", + "architecture": "ARM", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "source": "src/test-source", + "resource_version": "1.7.0", + "gem5_versions": [ + "develop" + ] + }, + { + "category": "binary", + "id": "test-binary-resource", + "description": "test description for 1.5.0", + "architecture": "ARM", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "source": "src/test-source", + "resource_version": "1.5.0", + "gem5_versions": [ + "21.1", + "22.1" + ] + } +] diff --git a/tests/pyunit/stdlib/resources/refs/resource-specialization.json b/tests/pyunit/stdlib/resources/refs/resource-specialization.json index c4d5eb4714..1129f1bd05 100644 --- a/tests/pyunit/stdlib/resources/refs/resource-specialization.json +++ b/tests/pyunit/stdlib/resources/refs/resource-specialization.json @@ -1,132 +1,181 @@ - -{ - "version" : "develop", - "url_base" : "http://dist.gem5.org/dist/v22-1", - "previous-versions" : { - "develop" : "https://gem5.googlesource.com/public/gem5-resources/+/refs/heads/develop/resources.json?format=TEXT", - "21.2" : "http://resources.gem5.org/prev-resources-json/resources-21-2.json" +[ + { + "category": "kernel", + "id": "kernel-example", + "description": "kernel-example documentation.", + "architecture": "RISCV", + "is_zipped": false, + "md5sum": "60a53c7d47d7057436bf4b9df707a841", + "url": "http://dist.gem5.org/dist/develop/kernels/x86/static/vmlinux-5.4.49", + "source": "src/linux-kernel", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] }, - "resources": [ - { - "type" : "kernel", - "name" : "kernel-example", - "documentation" : "kernel-example documentation.", - "architecture" : "RISCV", - "is_zipped" : false, - "md5sum" : "60a53c7d47d7057436bf4b9df707a841", - "url" : "{url_base}/kernels/x86/static/vmlinux-5.4.49", - "source" : "src/linux-kernel" - }, - { - "type" : "disk-image", - "name" : "disk-image-example", - "documentation" : "disk-image documentation.", - "architecture" : "X86", - "is_zipped" : true, - "md5sum" : "90e363abf0ddf22eefa2c7c5c9391c49", - "url" : "{url_base}/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", - "source" : "src/x86-ubuntu", - "root_partition": "1" - }, - { - "type" : "binary", - "name" : "binary-example", - "documentation" : "binary-example documentation.", - "architecture" : "ARM", - "is_zipped" : false, - "md5sum" : "71b2cb004fe2cda4556f0b1a38638af6", - "url" : "{url_base}/test-progs/hello/bin/arm/linux/hello64-static", - "source" : "src/simple" - }, - { - "type" : "bootloader", - "name" : "bootloader-example", - "documentation" : "bootloader documentation.", - "is_zipped" : false, - "md5sum" : "71b2cb004fe2cda4556f0b1a38638af6", - "url" : "{url_base}/test-progs/hello/bin/arm/linux/hello64-static" - }, - { - "type" : "checkpoint", - "name" : "checkpoint-example", - "documentation" : "checkpoint-example documentation.", - "architecture": "RISCV", - "is_zipped" : false, - "md5sum" : "3a57c1bb1077176c4587b8a3bf4f8ace", - "source" : null, - "is_tar_archive" : true, - "url": "{url_base}/checkpoints/riscv-hello-example-checkpoint.tar" - }, - { - "type" : "git", - "name" : "git-example", - "documentation" : null, - "is_zipped" : false, - "is_tar_archive" : true, - "md5sum" : "71b2cb004fe2cda4556f0b1a38638af6", - "url": "{url_base}/checkpoints/riscv-hello-example-checkpoint.tar" - }, - { - "type" : "file", - "name" : "file-example", - "documentation" : null, - "is_zipped" : false, - "md5sum" : "71b2cb004fe2cda4556f0b1a38638af6", - "url": "{url_base}/checkpoints/riscv-hello-example-checkpoint.tar", - "source" : null - }, - { - "type" : "directory", - "name" : "directory-example", - "documentation" : "directory-example documentation.", - "is_zipped" : false, - "md5sum" : "3a57c1bb1077176c4587b8a3bf4f8ace", - "source" : null, - "is_tar_archive" : true, - "url": "{url_base}/checkpoints/riscv-hello-example-checkpoint.tar" - }, - { - "type": "simpoint-directory", - "name": "simpoint-directory-example", - "documentation": "simpoint directory documentation.", - "is_zipped" : false, - "md5sum" : "3fcffe3956c8a95e3fb82e232e2b41fb", - "source" : null, - "is_tar_archive" : true, - "url": "{url_base}/simpoints/x86-print-this-15000-simpoints-20221013.tar", - "simpoint_interval": 1000000, - "warmup_interval": 1000000, - "simpoint_file": "simpoint.simpt", - "weight_file": "simpoint.weight", - "workload_name": "Example Workload" - }, - { - "type": "simpoint", - "name": "simpoint-example", - "documentation": "simpoint documentation.", - "simpoint_interval": 1000000, - "warmup_interval": 23445, - "simpoint_list" : [2,3,4,15], - "weight_list" : [0.1, 0.2, 0.4, 0.3] - }, - { - "type": "looppoint-pinpoint-csv", - "name": "looppoint-pinpoint-csv-resource", - "documentation" : "A looppoint pinpoints csv file.", - "is_zipped" : false, - "md5sum" : "199ab22dd463dc70ee2d034bfe045082", - "url": "http://dist.gem5.org/dist/develop/pinpoints/x86-matrix-multiply-omp-100-8-global-pinpoints-20230127", - "source" : null - }, - { - "type": "looppoint-json", - "name": "looppoint-json-restore-resource-region-1", - "documentation" : "A looppoint json file resource.", - "is_zipped" : false, - "region_id" : "1", - "md5sum" : "a71ed64908b082ea619b26b940a643c1", - "url": "http://dist.gem5.org/dist/develop/looppoints/x86-matrix-multiply-omp-100-8-looppoint-json-20230128", - "source" : null - } - ] -} + { + "category": "disk-image", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": true, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "binary", + "id": "binary-example", + "description": "binary-example documentation.", + "architecture": "ARM", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "bootloader", + "id": "bootloader-example", + "description": "bootloader documentation.", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "checkpoint", + "id": "checkpoint-example", + "description": "checkpoint-example documentation.", + "architecture": "RISCV", + "is_zipped": false, + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", + "source": null, + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "git", + "id": "git-example", + "description": null, + "is_zipped": false, + "is_tar_archive": true, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "file", + "id": "file-example", + "description": null, + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "source": null, + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "directory", + "id": "directory-example", + "description": "directory-example documentation.", + "is_zipped": false, + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", + "source": null, + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "simpoint-directory", + "id": "simpoint-directory-example", + "description": "simpoint directory documentation.", + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "source": null, + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "simpoint_file": "simpoint.simpt", + "weight_file": "simpoint.weight", + "workload_name": "Example Workload", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "simpoint", + "id": "simpoint-example", + "description": "simpoint documentation.", + "simpoint_interval": 1000000, + "warmup_interval": 23445, + "simpoint_list": [ + 2, + 3, + 4, + 15 + ], + "weight_list": [ + 0.1, + 0.2, + 0.4, + 0.3 + ], + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "looppoint-pinpoint-csv", + "id": "looppoint-pinpoint-csv-resource", + "description": "A looppoint pinpoints csv file.", + "is_zipped": false, + "md5sum": "199ab22dd463dc70ee2d034bfe045082", + "url": "http://dist.gem5.org/dist/develop/pinpoints/x86-matrix-multiply-omp-100-8-global-pinpoints-20230127", + "source": null, + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "looppoint-json", + "id": "looppoint-json-restore-resource-region-1", + "description": "A looppoint json file resource.", + "is_zipped": false, + "region_id": "1", + "md5sum": "a71ed64908b082ea619b26b940a643c1", + "url": "http://dist.gem5.org/dist/develop/looppoints/x86-matrix-multiply-omp-100-8-looppoint-json-20230128", + "source": null, + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + } +] diff --git a/tests/pyunit/stdlib/resources/refs/resources.json b/tests/pyunit/stdlib/resources/refs/resources.json new file mode 100644 index 0000000000..812caeff43 --- /dev/null +++ b/tests/pyunit/stdlib/resources/refs/resources.json @@ -0,0 +1,329 @@ +[ + { + "category": "binary", + "id": "this-is-a-test-resource", + "description": "This is a test resource", + "architecture": "X86", + "size": 13816, + "tags": [ + "asmtest", + "testing", + "riscv", + "testing" + ], + "is_zipped": false, + "md5sum": "4e70a98b6976969deffff91eed17fba1", + "source": "src/asmtest", + "url": "http://dist.gem5.org/dist/develop/test-progs/asmtest/bin/rv64mi-p-sbreak", + "code_examples": [], + "license": " BSD-3-Clause", + "author": [], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ], + "example_usage": "get_resource(resource_name=\"rv64mi-p-sbreak\")" + }, + { + "category": "binary", + "id": "this-is-a-test-resource", + "description": "This is a test resource but newer", + "architecture": "X86", + "size": 13816, + "tags": [ + "asmtest", + "testing", + "riscv", + "testing", + "new" + ], + "is_zipped": false, + "md5sum": "4e70a98b6976969deffff91eed17fba1", + "source": "src/asmtest", + "url": "http://dist.gem5.org/dist/develop/test-progs/asmtest/bin/rv64mi-p-sbreak", + "code_examples": [], + "license": " BSD-3-Clause", + "author": [], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + "resource_version": "1.1.0", + "gem5_versions": [ + "23.0" + ], + "example_usage": "get_resource(resource_name=\"rv64mi-p-sbreak\")" + }, + { + "category": "binary", + "id": "this-is-a-test-resource", + "description": "This is a test resource but double newer", + "architecture": "X86", + "size": 13816, + "tags": [ + "asmtest" + ], + "is_zipped": false, + "md5sum": "4e70a98b6976969deffff91eed17fba1", + "source": "src/asmtest", + "url": "http://dist.gem5.org/dist/develop/test-progs/asmtest/bin/rv64mi-p-sbreak", + "code_examples": [], + "license": " BSD-3-Clause", + "author": [], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", + "resource_version": "2.0.0", + "gem5_versions": [ + "23.1" + ], + "example_usage": "get_resource(resource_name=\"rv64mi-p-sbreak\")" + }, + { + "category": "simpoint", + "id": "test-version", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "test-version", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "test-duplicate", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "aa", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "asfsaf", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "simpoint-resource", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "bat43f34fman", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "file", + "id": "adadadas", + "description": "Simpoints for running the 'x86-print-this' resource with the parameters `\"print this\" 15000`. This is encapsulated in the 'x86-print-this-15000-with-simpoints' workload.", + "architecture": "X86", + "size": 10240, + "tags": [], + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "code_examples": [], + "license": "", + "author": [], + "source_url": "", + "resource_version": "0.2.0", + "gem5_versions": [ + "23.0" + ], + "workload_name": "x86-print-this-15000-with-simpoints", + "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", + "workloads": [ + "x86-print-this-15000-with-simpoints", + "x86-print-this-15000-with-simpoints-and-checkpoint" + ] + }, + { + "category": "disk-image", + "id": "x86-ubuntu-18.04-img", + "description": "This is a test resource", + "architecture": "X86", + "size": 688119691, + "tags": [ + "x86", + "fullsystem" + ], + "is_zipped": true, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "source": "src/x86-ubuntu", + "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "root_partition": "1", + "code_examples": [], + "license": "", + "author": [ + "Ayaz Akram" + ], + "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + "resource_version": "2.0.0", + "gem5_versions": [ + "23.0" + ], + "example_usage": "get_resource(resource_name=\"x86-ubuntu-18.04-img\")" + } +] diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json b/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json index a9dd2aaa46..8349b92658 100644 --- a/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json +++ b/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json @@ -1,17 +1,16 @@ -{ - "version" : null, - "url_base" : "http://dist.gem5.org/dist/v22-0", - "previous-versions" : {}, - "resources": [ - { - "type" : "binary", - "name" : "x86-hello64-static", - "documentation" : "A 'Hello World!' binary.", - "architecture" : "X86", - "is_zipped" : false, - "md5sum" : "dbf120338b37153e3334603970cebd8c", - "url" : "{url_base}/test-progs/hello/bin/x86/linux/hello64-static", - "source" : "src/simple" - } - ] -} +[ + { + "category": "binary", + "id": "x86-hello64-static", + "description": "A 'Hello World!' binary.", + "architecture": "X86", + "is_zipped": false, + "md5sum": "dbf120338b37153e3334603970cebd8c", + "url": "{url_base}/test-progs/hello/bin/x86/linux/hello64-static", + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + } +] diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks.json b/tests/pyunit/stdlib/resources/refs/workload-checks.json index 4f7e76bfb5..d19396bf8c 100644 --- a/tests/pyunit/stdlib/resources/refs/workload-checks.json +++ b/tests/pyunit/stdlib/resources/refs/workload-checks.json @@ -1,40 +1,48 @@ -{ - "url_base" : "http://dist.gem5.org/dist/v22-0", - "previous-versions" : {}, - "resources": [ - { - "type" : "kernel", - "name" : "x86-linux-kernel-5.2.3", - "documentation" : "The linux kernel (v5.2.3), compiled to X86.", - "architecture" : "X86", - "is_zipped" : false, - "md5sum" : "4838c99b77d33c8307b939c16624e4ac", - "url" : "{url_base}/kernels/x86/static/vmlinux-5.2.3", - "source" : "src/linux-kernel" +[ + { + "category": "kernel", + "id": "x86-linux-kernel-5.2.3", + "description": "The linux kernel (v5.2.3), compiled to X86.", + "architecture": "X86", + "is_zipped": false, + "md5sum": "4838c99b77d33c8307b939c16624e4ac", + "url": "{url_base}/kernels/x86/static/vmlinux-5.2.3", + "source": "src/linux-kernel", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "disk-image", + "id": "x86-ubuntu-18.04-img", + "description": "A disk image containing Ubuntu 18.04 for x86..", + "architecture": "X86", + "is_zipped": true, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": "{url_base}/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "workload", + "id": "simple-boot", + "description": "Description of workload here", + "function": "set_kernel_disk_workload", + "resources": { + "kernel": "x86-linux-kernel-5.2.3", + "disk-image": "x86-ubuntu-18.04-img" }, - { - "type" : "disk-image", - "name" : "x86-ubuntu-18.04-img", - "documentation" : "A disk image containing Ubuntu 18.04 for x86..", - "architecture" : "X86", - "is_zipped" : true, - "md5sum" : "90e363abf0ddf22eefa2c7c5c9391c49", - "url" : "{url_base}/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", - "source" : "src/x86-ubuntu", - "root_partition": "1" + "additional_params": { + "readfile_contents": "echo 'Boot successful'; m5 exit" }, - { - "type" : "workload", - "name" : "simple-boot", - "documentation" : "Description of workload here", - "function" : "set_kernel_disk_workload", - "resources" : { - "kernel" : "x86-linux-kernel-5.2.3", - "disk_image" : "x86-ubuntu-18.04-img" - }, - "additional_params" : { - "readfile_contents" : "echo 'Boot successful'; m5 exit" - } - } - ] -} + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + } +] From 685a5cd017b1416cfbbfe087252d818fb498a275 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 5 Jun 2023 14:32:18 +0800 Subject: [PATCH 009/693] scons: Fix grpc protobuf actions The change will fix the proto import issue and build issue with --no-duplicate-sources options, more details please reference: https://gem5-review.googlesource.com/c/public/gem5/+/64491. Change-Id: I259413f7739f89598dcd42c3f2e1e865cec3de43 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71318 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- src/SConscript | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SConscript b/src/SConscript index 13f08d2f5a..d26bf49cce 100644 --- a/src/SConscript +++ b/src/SConscript @@ -280,9 +280,9 @@ def protoc_grpc_emitter(target, source, env): root, ext = os.path.splitext(source[0].get_abspath()) return [root + '.grpc.pb.cc', root + '.grpc.pb.h'], source -protoc_grpc_action=MakeAction('${PROTOC} --grpc_out ${BUILDDIR} ' - '--plugin=protoc-gen-grpc=${PROTOC_GRPC} --proto_path ${BUILDDIR} ' - '${SOURCE.get_abspath()}', +protoc_grpc_action=MakeAction('${PROTOC} --grpc_out ${TARGET.dir.abspath} ' + '--plugin=protoc-gen-grpc=${PROTOC_GRPC} ' + '--proto_path ${SOURCE.dir.abspath} ${SOURCE.abspath}', Transform("PROTOC")) env.Append(BUILDERS={'GrpcProtoBufCC' : Builder( From 77ac6eacd93969855e9b76a6213802a210f93c9d Mon Sep 17 00:00:00 2001 From: "Daniel R. Carvalho" Date: Sat, 27 May 2023 09:47:56 -0300 Subject: [PATCH 010/693] mem-cache: De-virtualize forEachBlk() in tags Avoid code duplication by using the anyBlk function with a lambda that always returns false, which forces all blocks to be visited. Change-Id: I25527602535c719f46699677a7f70f3e31157f26 Signed-off-by: Daniel R. Carvalho Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70998 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/mem/cache/tags/base.cc | 9 +++++++++ src/mem/cache/tags/base.hh | 2 +- src/mem/cache/tags/base_set_assoc.hh | 6 ------ src/mem/cache/tags/compressed_tags.cc | 8 -------- src/mem/cache/tags/compressed_tags.hh | 10 ---------- src/mem/cache/tags/fa_lru.hh | 6 ------ src/mem/cache/tags/sector_tags.cc | 8 -------- src/mem/cache/tags/sector_tags.hh | 10 ---------- 8 files changed, 10 insertions(+), 49 deletions(-) diff --git a/src/mem/cache/tags/base.cc b/src/mem/cache/tags/base.cc index 560b041e45..8216f3dfe8 100644 --- a/src/mem/cache/tags/base.cc +++ b/src/mem/cache/tags/base.cc @@ -215,6 +215,15 @@ BaseTags::print() return str; } +void +BaseTags::forEachBlk(std::function visitor) +{ + anyBlk([visitor](CacheBlk &blk) { + visitor(blk); + return false; + }); +} + BaseTags::BaseTagStats::BaseTagStats(BaseTags &_tags) : statistics::Group(&_tags), tags(_tags), diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh index e2702778b8..c49188151c 100644 --- a/src/mem/cache/tags/base.hh +++ b/src/mem/cache/tags/base.hh @@ -336,7 +336,7 @@ class BaseTags : public ClockedObject * * @param visitor Visitor to call on each block. */ - virtual void forEachBlk(std::function visitor) = 0; + void forEachBlk(std::function visitor); /** * Find if any of the blocks satisfies a condition diff --git a/src/mem/cache/tags/base_set_assoc.hh b/src/mem/cache/tags/base_set_assoc.hh index 22695d2010..8ffb7189b7 100644 --- a/src/mem/cache/tags/base_set_assoc.hh +++ b/src/mem/cache/tags/base_set_assoc.hh @@ -233,12 +233,6 @@ class BaseSetAssoc : public BaseTags return indexingPolicy->regenerateAddr(blk->getTag(), blk); } - void forEachBlk(std::function visitor) override { - for (CacheBlk& blk : blks) { - visitor(blk); - } - } - bool anyBlk(std::function visitor) override { for (CacheBlk& blk : blks) { if (visitor(blk)) { diff --git a/src/mem/cache/tags/compressed_tags.cc b/src/mem/cache/tags/compressed_tags.cc index 32d7401550..c84718f5f6 100644 --- a/src/mem/cache/tags/compressed_tags.cc +++ b/src/mem/cache/tags/compressed_tags.cc @@ -163,14 +163,6 @@ CompressedTags::findVictim(Addr addr, const bool is_secure, return victim; } -void -CompressedTags::forEachBlk(std::function visitor) -{ - for (CompressionBlk& blk : blks) { - visitor(blk); - } -} - bool CompressedTags::anyBlk(std::function visitor) { diff --git a/src/mem/cache/tags/compressed_tags.hh b/src/mem/cache/tags/compressed_tags.hh index b54efb05d4..6e5b62d3e8 100644 --- a/src/mem/cache/tags/compressed_tags.hh +++ b/src/mem/cache/tags/compressed_tags.hh @@ -108,16 +108,6 @@ class CompressedTags : public SectorTags const std::size_t compressed_size, std::vector& evict_blks) override; - /** - * Visit each sub-block in the tags and apply a visitor. - * - * The visitor should be a std::function that takes a cache block. - * reference as its parameter. - * - * @param visitor Visitor to call on each block. - */ - void forEachBlk(std::function visitor) override; - /** * Find if any of the sub-blocks satisfies a condition. * diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index deffd72015..cd07817007 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -253,12 +253,6 @@ class FALRU : public BaseTags return blk->getTag(); } - void forEachBlk(std::function visitor) override { - for (int i = 0; i < numBlocks; i++) { - visitor(blks[i]); - } - } - bool anyBlk(std::function visitor) override { for (int i = 0; i < numBlocks; i++) { if (visitor(blks[i])) { diff --git a/src/mem/cache/tags/sector_tags.cc b/src/mem/cache/tags/sector_tags.cc index cb121ebd9a..6a9ffd02ed 100644 --- a/src/mem/cache/tags/sector_tags.cc +++ b/src/mem/cache/tags/sector_tags.cc @@ -359,14 +359,6 @@ SectorTags::SectorTagsStats::regStats() } } -void -SectorTags::forEachBlk(std::function visitor) -{ - for (SectorSubBlk& blk : blks) { - visitor(blk); - } -} - bool SectorTags::anyBlk(std::function visitor) { diff --git a/src/mem/cache/tags/sector_tags.hh b/src/mem/cache/tags/sector_tags.hh index bad132158c..035b085962 100644 --- a/src/mem/cache/tags/sector_tags.hh +++ b/src/mem/cache/tags/sector_tags.hh @@ -193,16 +193,6 @@ class SectorTags : public BaseTags */ Addr regenerateBlkAddr(const CacheBlk* blk) const override; - /** - * Visit each sub-block in the tags and apply a visitor. - * - * The visitor should be a std::function that takes a cache block. - * reference as its parameter. - * - * @param visitor Visitor to call on each block. - */ - void forEachBlk(std::function visitor) override; - /** * Find if any of the sub-blocks satisfies a condition. * From 25d7badcc1fdfa5b40de54011960549f6523eae3 Mon Sep 17 00:00:00 2001 From: KUNAL PAI Date: Wed, 7 Jun 2023 15:30:15 -0700 Subject: [PATCH 011/693] tests: Fix bugs related to gem5 Vision This patch fixes refs under tests/pyunit/stdlib/resources. Removes instances of {url_base} in refs. Also, renames two refs: mongo_mock and mongo_dup_mock to mongo-mock and mongo-dup-mock to follow naming convention of other refs. Change-Id: If115114bc7a89764e7c546b77a93d36d6a3b5f8a Co-authored-by: Parth Shah Co-authored-by: Harshil2107 Co-authored-by: aarsli Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71360 Tested-by: kokoro Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce --- tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py | 4 ++-- .../refs/{mongo_dup_mock.json => mongo-dup-mock.json} | 0 .../resources/refs/{mongo_mock.json => mongo-mock.json} | 0 .../resources/refs/workload-checks-custom-workload.json | 2 +- tests/pyunit/stdlib/resources/refs/workload-checks.json | 4 ++-- 5 files changed, 5 insertions(+), 5 deletions(-) rename tests/pyunit/stdlib/resources/refs/{mongo_dup_mock.json => mongo-dup-mock.json} (100%) rename tests/pyunit/stdlib/resources/refs/{mongo_mock.json => mongo-mock.json} (100%) diff --git a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py index 96aadf6879..344f67b8b0 100644 --- a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py @@ -82,12 +82,12 @@ mock_config_combined = { mock_json = {} -with open(Path(__file__).parent / "refs/mongo_mock.json", "r") as f: +with open(Path(__file__).parent / "refs/mongo-mock.json", "r") as f: mock_json = json.load(f) duplicate_mock_json = {} -with open(Path(__file__).parent / "refs/mongo_dup_mock.json", "r") as f: +with open(Path(__file__).parent / "refs/mongo-dup-mock.json", "r") as f: duplicate_mock_json = json.load(f) diff --git a/tests/pyunit/stdlib/resources/refs/mongo_dup_mock.json b/tests/pyunit/stdlib/resources/refs/mongo-dup-mock.json similarity index 100% rename from tests/pyunit/stdlib/resources/refs/mongo_dup_mock.json rename to tests/pyunit/stdlib/resources/refs/mongo-dup-mock.json diff --git a/tests/pyunit/stdlib/resources/refs/mongo_mock.json b/tests/pyunit/stdlib/resources/refs/mongo-mock.json similarity index 100% rename from tests/pyunit/stdlib/resources/refs/mongo_mock.json rename to tests/pyunit/stdlib/resources/refs/mongo-mock.json diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json b/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json index 8349b92658..a7e9c9d84f 100644 --- a/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json +++ b/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json @@ -6,7 +6,7 @@ "architecture": "X86", "is_zipped": false, "md5sum": "dbf120338b37153e3334603970cebd8c", - "url": "{url_base}/test-progs/hello/bin/x86/linux/hello64-static", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/x86/linux/hello64-static", "source": "src/simple", "resource_version": "1.0.0", "gem5_versions": [ diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks.json b/tests/pyunit/stdlib/resources/refs/workload-checks.json index d19396bf8c..d41001d26c 100644 --- a/tests/pyunit/stdlib/resources/refs/workload-checks.json +++ b/tests/pyunit/stdlib/resources/refs/workload-checks.json @@ -6,7 +6,7 @@ "architecture": "X86", "is_zipped": false, "md5sum": "4838c99b77d33c8307b939c16624e4ac", - "url": "{url_base}/kernels/x86/static/vmlinux-5.2.3", + "url": "http://dist.gem5.org/dist/develop/kernels/x86/static/vmlinux-5.2.3", "source": "src/linux-kernel", "resource_version": "1.0.0", "gem5_versions": [ @@ -20,7 +20,7 @@ "architecture": "X86", "is_zipped": true, "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", - "url": "{url_base}/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", "source": "src/x86-ubuntu", "root_partition": "1", "resource_version": "1.0.0", From c644eae2ddd34cf449a9c4476730bd29703c4dd7 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 8 Jun 2023 10:50:23 -0500 Subject: [PATCH 012/693] configs,gpu-compute: Kernel dispatch-based exit events Add two kernel dispatch-based exit events that are useful for limiting the simulation and enabling debug flags at specific GPU kernels. Since the KVM CPU typically used with GPUFS is not deterministic, this help with enabling debug flags when the Tick number may vary. The exit at GPU kernel option can also limit simulation by only simulating a few hundred kernels, for example, and exit at a determined point. Change-Id: I81bae92a80c25fc38c41e999aa662e1417b7a20d Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71418 Maintainer: Matt Sinclair Tested-by: kokoro Reviewed-by: Matt Sinclair --- configs/example/gpufs/runfs.py | 27 +++++++++++++++++++++++++++ src/gpu-compute/dispatcher.cc | 3 +++ 2 files changed, 30 insertions(+) diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index f8ef70d5a2..01203bbcbb 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -137,6 +137,20 @@ def addRunFSOptions(parser): "MI200 (gfx90a)", ) + parser.add_argument( + "--debug-at-gpu-kernel", + type=int, + default=-1, + help="Turn on debug flags starting with this kernel", + ) + + parser.add_argument( + "--exit-at-gpu-kernel", + type=int, + default=-1, + help="Exit simulation after running this many kernels", + ) + def runGpuFSSystem(args): """ @@ -184,6 +198,9 @@ def runGpuFSSystem(args): print("Running the simulation") sim_ticks = args.abs_max_tick + kernels_launched = 0 + if args.debug_at_gpu_kernel != -1: + m5.trace.disable() exit_event = m5.simulate(sim_ticks) @@ -199,11 +216,21 @@ def runGpuFSSystem(args): assert args.checkpoint_dir is not None m5.checkpoint(args.checkpoint_dir) break + elif "GPU Kernel Completed" in exit_event.getCause(): + kernels_launched += 1 else: print( f"Unknown exit event: {exit_event.getCause()}. Continuing..." ) + if kernels_launched == args.debug_at_gpu_kernel: + m5.trace.enable() + if kernels_launched == args.exit_at_gpu_kernel: + print(f"Exiting @ GPU kernel {kernels_launched}") + break + + exit_event = m5.simulate(sim_ticks - m5.curTick()) + print( "Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause()) ) diff --git a/src/gpu-compute/dispatcher.cc b/src/gpu-compute/dispatcher.cc index a76ba7c0be..b19bccca50 100644 --- a/src/gpu-compute/dispatcher.cc +++ b/src/gpu-compute/dispatcher.cc @@ -40,6 +40,7 @@ #include "gpu-compute/hsa_queue_entry.hh" #include "gpu-compute/shader.hh" #include "gpu-compute/wavefront.hh" +#include "sim/sim_exit.hh" #include "sim/syscall_emul_buf.hh" #include "sim/system.hh" @@ -330,6 +331,8 @@ GPUDispatcher::notifyWgCompl(Wavefront *wf) DPRINTF(GPUWgLatency, "Kernel Complete ticks:%d kernel:%d\n", curTick(), kern_id); DPRINTF(GPUKernelInfo, "Completed kernel %d\n", kern_id); + + exitSimLoop("GPU Kernel Completed"); } if (!tickEvent.scheduled()) { From 90067c6ce47a49ca2c5d6b9d666f7931a3092939 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 8 Jun 2023 10:54:10 -0500 Subject: [PATCH 013/693] configs: GPUFS: Only use parallel eventqs for KVM This is turned on by default with multiple CPUs in the GPUFS configs, which causes other CPU types (e.g., AtomicSimpleCPU) to assert. Only enable parallel event queues for KVM CPUs to avoid this issue. Change-Id: Ic8235437caf0150560e2b360a4544d82dfc26c36 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71419 Maintainer: Matt Sinclair Tested-by: kokoro Reviewed-by: Matt Sinclair --- configs/example/gpufs/runfs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index 01203bbcbb..b045b801c6 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -162,7 +162,8 @@ def runGpuFSSystem(args): # GPUFS is primarily designed to use the X86 KVM CPU. This model needs to # use multiple event queues when more than one CPU is simulated. Force it # on if that is the case. - args.host_parallel = True if args.num_cpus > 1 else False + if ObjectList.is_kvm_cpu(ObjectList.cpu_list.get(args.cpu_type)): + args.host_parallel = True if args.num_cpus > 1 else False # These are used by the protocols. They should not be set by the user. n_cu = args.num_compute_units From f467cf79fda2884f5d6d26ff616269822fac5c48 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Tue, 30 May 2023 16:44:32 -0700 Subject: [PATCH 014/693] util: Add util for GitHub runner configuration This adds files that can be used to configure Vagrant machines that will be used to test running gem5 alongside Github Actions. Change-Id: I52b0f39b6e6044c22481f02163d5fc01eab76788 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71098 Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce Tested-by: kokoro --- util/github-runners-vagrant/README.md | 118 ++++++++++++++++++ .../Vagrantfile-builder | 49 ++++++++ .../github-runners-vagrant/Vagrantfile-runner | 48 +++++++ .../provision_nonroot.sh | 15 +++ util/github-runners-vagrant/provision_root.sh | 43 +++++++ util/github-runners-vagrant/vm_manager.sh | 39 ++++++ 6 files changed, 312 insertions(+) create mode 100644 util/github-runners-vagrant/README.md create mode 100644 util/github-runners-vagrant/Vagrantfile-builder create mode 100644 util/github-runners-vagrant/Vagrantfile-runner create mode 100644 util/github-runners-vagrant/provision_nonroot.sh create mode 100644 util/github-runners-vagrant/provision_root.sh create mode 100755 util/github-runners-vagrant/vm_manager.sh diff --git a/util/github-runners-vagrant/README.md b/util/github-runners-vagrant/README.md new file mode 100644 index 0000000000..86b9e1da87 --- /dev/null +++ b/util/github-runners-vagrant/README.md @@ -0,0 +1,118 @@ +# Setting up a Github Actions Runner with Vagrant + +This directory provides a way to setup a Github Actions runner using Vagrant to host the runner in a Virtual machine. + +This tutorial has been written with the assumption of running on a machine with Ubuntu 22.04. +Setting up a runner on a different OS may require some changes. + +Before anything else, copy this directory, "util/github-runners-vagrant", to the root of the location on your host system you wish to setup the VMs from. +The CWD is assumed to be this directory. + +## Install Dependencies + +```sh +sudo apt install vagrant +sudo apt-get build-dep vagrant ruby-libvirt +sudo apt-get install qemu libvirt-daemon-system libvirt-clients ebtables dnsmasq-base libxslt-dev libxml2-dev libvirt-dev zlib1g-dev ruby-dev + +# Note: The vagrant-libvirt APT package does not work as intended. We must +# remove it from the system otherwise errors will occur (we will install it +# later using the vagrant plugin command). +sudo apt purge vagrant-libvirt +``` + +## Set up the Vagrantfiles for the GitHub repository + +First, generate a Personal Access Token, which you can create [here](https://github.com/settings/tokens) +Make sure to set admin permissions on this token, then replace instances of `` in the Vagrantfiles ("Vagrantfile-builder" and "Vagrant-runner") with your token. + +Next, replace instances of `` with your GitHub account name and the repository name, separated by a forward slash. +For example, if your GitHub account name is `example` and your repository name is `example-repo`, you would replace `` with `example/example-repo`. + +## Install Vagrant Plugins + +Once everything is set properly, set the `VAGRANT_HOME` environment variable to the directory in which the Vagrant files and other scripts are stored (i.e., the CWD). +For example: + +```sh +export VAGRANT_HOME=`pwd` +``` + +After this, install the relevant vagrant plugins: + +``` sh +vagrant plugin install dotenv +vagrant plugin install vagrant-libvirt +vagrant plugin install vagrant-reload +``` + +## The "builder" and "runner" VMs + +The number of CPUs and the memory size differs between the "Vagrantfile-builder" and "Vagrantfile-runner". + +In our work we have two types of machines "runners" and "builders". +Runners are single core machines with 8GB of memory, and builders are 4 core machines with 16GB of memory. +The latter is used for building gem5 binaries while the former is used for running instances of gem5. +You can expect each machine to take up approximately 60GB of disk space though VMs will consume the disk space they require. + +The "Vagrantfile-builder" file is set to create a runner machine and the "Vagrantfile-builder" file is set to create a builder machine. + +Specifying which Vagrantfile to use is done by setting the `VAGRANT_VAGRANTFILE` environment variable. + +## Creating the virtual machine + +Each VM on your host system must have a unique name. +Give the VM to be created a unique name by setting the `` variables in the Vagrantfile you wish to utilize. + +Then run: + +```sh +VAGRANT_VAGRANTFILE= vagrant up --provider=libvirt +``` + +This should automatically create your machine, as well as configure and start up a Github Actions runner. +You can check the status of the runner here: https://github.com///settings/actions/runners + +If the runner ever shows as offline, you can rerun the `vagrant up --provider=libvirt` command to make sure everything is working properly. + +If you wish to create more than one runner you must edit the `` in the Vagrant file. + +## Helper scripts + +The "vm_manager" script can be used to set up multiple builder and runner VMs. +To use this script simply modify the `NUM_RUNNERS`, `NUM_BUILDERS`, `RUNNER_PREFIX`, and `BUILDER_PREFIX` variables to the desired values. +Then run the script with: + +```sh +./vm_manager.sh +``` + +This script will create any VMs that don't already exist and ensure those that do exists are running. + +If you wish to destroy all the VMs you can run: + +```sh +./vm_manager.sh destroy +``` + +**Note:** This script assumes "VAGRANT_HOME" is set to the CWD. + +## Troubleshooting + +### The default libvirt disk image storage pool is on the wrong drive + +By default libvirt will store disk images in "/var/lib/libvirt/images". +This is not ideal as it is on a small root partition. +A solution to this is to change the default storage location. +To do so, do the following: + +```sh +virsh pool-list --all # Confirm here a "default" pool exist. We'll modify this. +virsh pool-dumpxml default >default-pool.xml # We take a dump of the default then removed it. +virsh pool-destroy default +virsh pool-undefine default +vim default-pool.xml # Change the image path to the desired path +virsh pool-define default-pool.xml # From here we re-add the default. +virsh pool-start default +virsh pool-autostart default +``` diff --git a/util/github-runners-vagrant/Vagrantfile-builder b/util/github-runners-vagrant/Vagrantfile-builder new file mode 100644 index 0000000000..242e094d19 --- /dev/null +++ b/util/github-runners-vagrant/Vagrantfile-builder @@ -0,0 +1,49 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure("2") do |config| + config.vm.box = "generic/ubuntu2204" + config.vm.box_check_update = true + config.vm.define "" + config.vm.hostname = "" + # allows us to ssh into the machine, addressing the problem below + # https://www.reddit.com/r/vagrant/comments/sb7hfl/new_to_vagrant_getting_efault_warning/ + config.ssh.username = "vagrant" + config.ssh.password = "vagrant" + + config.vm.provider "libvirt" do |vb| + # Customize the amount of cpus and memory on the VM: + vb.cpus = "4".to_i + vb.memory = "16384".to_i + end + + # sets up vm + config.vm.provision :shell, path: "provision_root.sh" + config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" + # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. + config.vm.provision :reload + config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL + if [ -d ~/actions-runner ]; then + # This will be run everytime the VM is run (once created). + cd actions-runner + nohup ./run.sh & + else + # This will be run the first time the VM is created. + mkdir ~/actions-runner && cd ~/actions-runner + curl -so actions-runner-linux-x64-2.304.0.tar.gz -L \ + https://github.com/actions/runner/releases/download/v2.304.0/actions-runner-linux-x64-2.304.0.tar.gz + tar xzf ./actions-runner-linux-x64-2.304.0.tar.gz + + # configure the runner + # echo automatically sets the name of the runner, and the tags + # create a personal access token with admin permission and copy it into the curl command + echo -ne '\n\nbuild\n\n' | ./config.sh --url https://github.com/ --token $(curl -L \ + -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos//actions/runners/registration-token | jq -r '.token') + # start the runner + nohup ./run.sh & + fi + SHELL + +end diff --git a/util/github-runners-vagrant/Vagrantfile-runner b/util/github-runners-vagrant/Vagrantfile-runner new file mode 100644 index 0000000000..ab601cd9c8 --- /dev/null +++ b/util/github-runners-vagrant/Vagrantfile-runner @@ -0,0 +1,48 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure("2") do |config| + config.vm.box = "generic/ubuntu2204" + config.vm.box_check_update = true + config.vm.define "" + config.vm.hostname = "" + # allows us to ssh into the machine, addressing the problem below + # https://www.reddit.com/r/vagrant/comments/sb7hfl/new_to_vagrant_getting_efault_warning/ + config.ssh.username = "vagrant" + config.ssh.password = "vagrant" + + config.vm.provider "libvirt" do |vb| + # Customize the amount of cpus and memory on the VM: + vb.cpus = "1".to_i + vb.memory = "8192".to_i + end + + # sets up vm + config.vm.provision :shell, path: "provision_root.sh" + config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" + # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. + config.vm.provision :reload + config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL + if [ -d ~/actions-runner ]; then + # This will be run everytime the VM is run (once created). + cd actions-runner + nohup ./run.sh & + else + # This will be run the first time the VM is created. + mkdir ~/actions-runner && cd ~/actions-runner + curl -so actions-runner-linux-x64-2.304.0.tar.gz -L \ + https://github.com/actions/runner/releases/download/v2.304.0/actions-runner-linux-x64-2.304.0.tar.gz + tar xzf ./actions-runner-linux-x64-2.304.0.tar.gz + + # configure the runner + # echo automatically sets the name of the runner, and the tags + # create a personal access token with admin permission and copy it into the curl command + echo -ne '\n\nrun\n\n' | ./config.sh --url https://github.com/ --token $(curl -L \ + -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos//actions/runners/registration-token | jq -r '.token') + # start the runner + nohup ./run.sh & + fi + SHELL +end diff --git a/util/github-runners-vagrant/provision_nonroot.sh b/util/github-runners-vagrant/provision_nonroot.sh new file mode 100644 index 0000000000..4465b5a192 --- /dev/null +++ b/util/github-runners-vagrant/provision_nonroot.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# fail on unset variables and command errors +set -eu -o pipefail # -x: is for debugging + +# Install deno +curl -fsSL https://deno.land/x/install/install.sh | sh +echo "export PATH=\"\${HOME}/.deno/bin:\${PATH}\"" >> ~/.profile +echo "export PATH=\"\${HOME}/.deno/bin:\${PATH}\"" >> ~/.bash_profile + +# Install docker compose +DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r '.tag_name') +mkdir -p "${HOME}/.docker/cli-plugins" +curl -sL "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o "${HOME}/.docker/cli-plugins/docker-compose" +chmod +x "${HOME}/.docker/cli-plugins/docker-compose" diff --git a/util/github-runners-vagrant/provision_root.sh b/util/github-runners-vagrant/provision_root.sh new file mode 100644 index 0000000000..660064f8ca --- /dev/null +++ b/util/github-runners-vagrant/provision_root.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# fail on unset variables and command errors +set -eu -o pipefail # -x: is for debugging + +apt-get update +apt-get upgrade -y +apt-get install -y software-properties-common +add-apt-repository --yes --update ppa:git-core/ppa +apt-get install -y \ + bash \ + build-essential \ + clang-format \ + git \ + git-lfs \ + jq \ + libffi-dev \ + libssl-dev \ + nkf \ + python3 \ + python3-dev \ + python3-pip \ + python3-venv \ + shellcheck \ + tree \ + wget \ + yamllint \ + zstd +snap install jq + +# Install docker +apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg +echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt-get update -y +apt-get install -y docker-ce docker-ce-cli containerd.io +groupadd docker || true +gpasswd -a vagrant docker +newgrp docker +systemctl restart docker + +# Cleanup +apt-get autoremove -y diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh new file mode 100755 index 0000000000..1cae8d2686 --- /dev/null +++ b/util/github-runners-vagrant/vm_manager.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +NUM_RUNNERS=20 +NUM_BUILDERS=3 +RUNNER_PREFIX="$(hostname)-runner-" +BUILDER_PREFIX="$(hostname)-builder-" + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +export VAGRANT_HOME=${SCRIPT_DIR} + +param="up" +if [[ $# -eq 1 ]]; then + param=$1 + if [[ "${param}" != "destroy" ]]; then + echo "Only valid parameter is 'destroy', to destroy all VMs" + exit 1 + fi +fi + + +for (( i=1; i<=NUM_RUNNERS; i++ )); do + sed -i "s/ config.vm.define.*/ config.vm.define \"${RUNNER_PREFIX}${i}\"/g" Vagrantfile-runner + sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${RUNNER_PREFIX}${i}\"/g" Vagrantfile-runner + if [[ "${param}" == "destroy" ]]; then + VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant destroy -f + else + VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant up --provider=libvirt + fi +done + +for (( i=1; i<=NUM_BUILDERS; i++ )); do + sed -i "s/ config.vm.define.*/ config.vm.define \"${BUILDER_PREFIX}${i}\"/g" Vagrantfile-builder + sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${BUILDER_PREFIX}${i}\"/g" Vagrantfile-builder + if [[ "${param}" == "destroy" ]]; then + VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant destroy -f + else + VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant up --provider=libvirt + fi +done From 0fef2300c06af42876889676aade4c264675ca5c Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 12 Jun 2023 14:06:57 +0800 Subject: [PATCH 015/693] arch-riscv: Refactor fmax and fmin instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently fmax and fmin instructions convert source float registers such as Fs1_bits to float64_t(or float32_t and float16_t) many times in the single instruction. It is not efficient for the future maintenance of these instructions. The change adds non-register float_t intermediate variables fs1 and fs2 to keep converted results so that we don’t need to do it repeatedly. It also added an intermediate variable fd for specific float type to assume the upper bits of the packed float register are all one. Change-Id: Ic508d5255db6c4b38ca4df6dd805df440c043fff Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71479 Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power Tested-by: kokoro --- src/arch/riscv/isa/decoder.isa | 121 +++++++++++++++------------------ 1 file changed, 54 insertions(+), 67 deletions(-) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 2dcd118225..a339c11375 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -1615,93 +1615,80 @@ decode QUADRANT default Unknown::unknown() { } 0x14: decode ROUND_MODE { 0x0: fmin_s({{ - bool less = f32_lt_quiet(f32(freg(Fs1_bits)), - f32(freg(Fs2_bits))) || - (f32_eq(f32(freg(Fs1_bits)), - f32(freg(Fs2_bits))) && - bits(f32(freg(Fs1_bits)).v, 31)); + float32_t fs1 = f32(freg(Fs1_bits)); + float32_t fs2 = f32(freg(Fs2_bits)); + float32_t fd; + bool less = f32_lt_quiet(fs1, fs2) || + (f32_eq(fs1, fs2) && bits(fs1.v, 31)); - Fd_bits = less || - isNaNF32UI(f32(freg(Fs2_bits)).v) ? - freg(Fs1_bits).v : freg(Fs2_bits).v; - if (isNaNF32UI(f32(freg(Fs1_bits)).v) && - isNaNF32UI(f32(freg(Fs2_bits)).v)) - Fd_bits = f32(defaultNaNF32UI).v; + fd = less || isNaNF32UI(fs2.v) ? fs1 : fs2; + if (isNaNF32UI(fs1.v) && isNaNF32UI(fs2.v)) + fd = f32(defaultNaNF32UI); + Fd_bits = freg(fd).v; }}, FloatCmpOp); 0x1: fmax_s({{ - bool greater = f32_lt_quiet(f32(freg(Fs2_bits)), - f32(freg(Fs1_bits))) || - (f32_eq(f32(freg(Fs2_bits)), - f32(freg(Fs1_bits))) && - bits(f32(freg(Fs2_bits)).v, 31)); + float32_t fs1 = f32(freg(Fs1_bits)); + float32_t fs2 = f32(freg(Fs2_bits)); + float32_t fd; + bool greater = f32_lt_quiet(fs2, fs1) || + (f32_eq(fs2, fs1) && bits(fs2.v, 31)); - Fd_bits = greater || - isNaNF32UI(f32(freg(Fs2_bits)).v) ? - freg(Fs1_bits).v : freg(Fs2_bits).v; - if (isNaNF32UI(f32(freg(Fs1_bits)).v) && - isNaNF32UI(f32(freg(Fs2_bits)).v)) - Fd_bits = f32(defaultNaNF32UI).v; + fd = greater || isNaNF32UI(fs2.v) ? fs1: fs2; + if (isNaNF32UI(fs1.v) && isNaNF32UI(fs2.v)) + fd = f32(defaultNaNF32UI); + Fd_bits = freg(fd).v; }}, FloatCmpOp); } 0x15: decode ROUND_MODE { 0x0: fmin_d({{ - bool less = f64_lt_quiet(f64(freg(Fs1_bits)), - f64(freg(Fs2_bits))) || - (f64_eq(f64(freg(Fs1_bits)), - f64(freg(Fs2_bits))) && - bits(f64(freg(Fs1_bits)).v, 63)); + float64_t fs1 = f64(freg(Fs1_bits)); + float64_t fs2 = f64(freg(Fs2_bits)); + float64_t fd; + bool less = f64_lt_quiet(fs1, fs2) || + (f64_eq(fs1, fs2) && bits(fs1.v, 63)); - Fd_bits = less || - isNaNF64UI(f64(freg(Fs2_bits)).v) ? - freg(Fs1_bits).v : freg(Fs2_bits).v; - if (isNaNF64UI(f64(freg(Fs1_bits)).v) && - isNaNF64UI(f64(freg(Fs2_bits)).v)) - Fd_bits = f64(defaultNaNF64UI).v; + fd = less || isNaNF64UI(fs2.v) ? fs1 : fs2; + if (isNaNF64UI(fs1.v) && isNaNF64UI(fs2.v)) + fd = f64(defaultNaNF64UI); + Fd_bits = freg(fd).v; }}, FloatCmpOp); 0x1: fmax_d({{ - bool greater = - f64_lt_quiet(f64(freg(Fs2_bits)), - f64(freg(Fs1_bits))) || - (f64_eq(f64(freg(Fs2_bits)), - f64(freg(Fs1_bits))) && - bits(f64(freg(Fs2_bits)).v, 63)); + float64_t fs1 = f64(freg(Fs1_bits)); + float64_t fs2 = f64(freg(Fs2_bits)); + float64_t fd; + bool greater = f64_lt_quiet(fs2, fs1) || + (f64_eq(fs2, fs1) && bits(fs2.v, 63)); - Fd_bits = greater || - isNaNF64UI(f64(freg(Fs2_bits)).v) ? - freg(Fs1_bits).v : freg(Fs2_bits).v; - if (isNaNF64UI(f64(freg(Fs1_bits)).v) && - isNaNF64UI(f64(Fs2_bits).v)) - Fd_bits = f64(defaultNaNF64UI).v; + fd = greater || isNaNF64UI(fs2.v) ? fs1 : fs2; + if (isNaNF64UI(fs1.v) && isNaNF64UI(fs2.v)) + fd = f64(defaultNaNF64UI); + Fd_bits = freg(fd).v; }}, FloatCmpOp); } 0x16: decode ROUND_MODE { 0x0: fmin_h({{ - bool less = f16_lt_quiet(f16(freg(Fs1_bits)), - f16(freg(Fs2_bits))) || - (f16_eq(f16(freg(Fs1_bits)), - f16(freg(Fs2_bits))) && - bits(f16(freg(Fs1_bits)).v, 15)); + float16_t fs1 = f16(freg(Fs1_bits)); + float16_t fs2 = f16(freg(Fs2_bits)); + float16_t fd; + bool less = f16_lt_quiet(fs1, fs2) || + (f16_eq(fs1, fs2) && bits(fs1.v, 15)); - Fd_bits = less || - isNaNF16UI(f16(freg(Fs2_bits)).v) ? - freg(Fs1_bits).v : freg(Fs2_bits).v; - if (isNaNF16UI(f16(freg(Fs1_bits)).v) && - isNaNF16UI(f16(freg(Fs2_bits)).v)) - Fd_bits = f16(defaultNaNF16UI).v; + fd = less || isNaNF16UI(fs2.v) ? fs1 : fs2; + if (isNaNF16UI(fs1.v) && isNaNF16UI(fs2.v)) + fd = f16(defaultNaNF16UI); + Fd_bits = freg(fd).v; }}, FloatCmpOp); 0x1: fmax_h({{ - bool greater = f16_lt_quiet(f16(freg(Fs2_bits)), - f16(freg(Fs1_bits))) || - (f16_eq(f16(freg(Fs2_bits)), - f16(freg(Fs1_bits))) && - bits(f16(freg(Fs2_bits)).v, 15)); + float16_t fs1 = f16(freg(Fs1_bits)); + float16_t fs2 = f16(freg(Fs2_bits)); + float16_t fd; + bool greater = f16_lt_quiet(fs2, fs1) || + (f16_eq(fs2, fs1) && bits(fs2.v, 15)); - Fd_bits = greater || - isNaNF16UI(f16(freg(Fs2_bits)).v) ? - freg(Fs1_bits).v : freg(Fs2_bits).v; - if (isNaNF16UI(f16(freg(Fs1_bits)).v) && - isNaNF16UI(f16(freg(Fs2_bits)).v)) - Fd_bits = f16(defaultNaNF16UI).v; + fd = greater || isNaNF16UI(fs2.v) ? fs1 : fs2; + if (isNaNF16UI(fs1.v) && isNaNF16UI(fs2.v)) + fd = f16(defaultNaNF16UI); + Fd_bits = freg(fd).v; }}, FloatCmpOp); } 0x20: decode CONV_SGN { From 28777e1114e189df7da2191271dca5a38a9de769 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Mon, 12 Jun 2023 15:31:04 -0700 Subject: [PATCH 016/693] python: Ignore -s as gem5 option This enables more compatibility with the normal python binary. This is needed to get multiprocessing to work on some systems. Change-Id: Ibb946136d153979bf54a773060010a0ae479a9d1 Signed-off-by: Jason Lowe-Power Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71502 Maintainer: Bobby Bruce Tested-by: kokoro Reviewed-by: Bobby Bruce --- src/python/m5/main.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/python/m5/main.py b/src/python/m5/main.py index a68279b633..4701dfa5ea 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -193,6 +193,13 @@ def parse_options(): callback=collect_args, ) + option( + "-s", + action="store_true", + help="IGNORED, only for compatibility with python. don't" + "add user site directory to sys.path; also PYTHONNOUSERSITE", + ) + # Statistics options group("Statistics Options") option( From 9a27322c7b0ba8871f10ac66e3b60672175f2cd9 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 13 Jun 2023 17:25:47 +0800 Subject: [PATCH 017/693] arch-riscv: Fix unexpected behavior of float operations in Mac OS The uint_fast16_t is the integer at least 16 bits size, it can be 32, 64 bits and more. Usually most of the simulations are in the x86-64 linux host, the size of uint_fast16_t is 64 bits. Therefore, there is no problem for double precision float operations and it can pass FloatMM test. However, in the Mac OS, the size of uint_fast16_t is 16 bits, it will lose the upper bits when converting float register bits to freg_t and it will generate unexpected results for FloatMM test. The change can guarantee that the size of data in freg_t is at least 64 bits and it will not lose any data from floating point to freg_t. Reference: https://developer.apple.com/documentation/kernel/uint_fast16_t https://codebrowser.dev/glibc/glibc/stdlib/stdint.h.html Change-Id: I3df6610f0903cdee0f56584d6cbdb51ac26c86c8 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71578 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/arch/riscv/regs/float.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/regs/float.hh b/src/arch/riscv/regs/float.hh index 1654bdb627..4809372070 100644 --- a/src/arch/riscv/regs/float.hh +++ b/src/arch/riscv/regs/float.hh @@ -105,7 +105,7 @@ static constexpr float64_t f64(freg_t r) { return r; } static constexpr freg_t freg(float16_t f) { return {boxF16(f.v)}; } static constexpr freg_t freg(float32_t f) { return {boxF32(f.v)}; } static constexpr freg_t freg(float64_t f) { return f; } -static constexpr freg_t freg(uint_fast16_t f) { return {f}; } +static constexpr freg_t freg(uint_fast64_t f) { return {f}; } namespace float_reg { From 23a88d0400f222aec3527975dbc77c7145aca542 Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Tue, 30 May 2023 13:26:18 +0800 Subject: [PATCH 018/693] fastmodel: only support single line literal when paring project file In python3.11, it requires the global specifier should be the first token of regex. However it's not possible when using ply library. In fastmodel case, we actually don't need to support multiline string literal. We fix this issue by just making the string literal single line. Ref: https://github.com/dabeaz/ply/issues/282 Change-Id: I746b628db7ad4c1d7834f1a1b2c1243cef68aa01 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71018 Tested-by: kokoro Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce --- src/arch/arm/fastmodel/SConscript | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript index 3bc9aa5bad..7c6019e2a8 100644 --- a/src/arch/arm/fastmodel/SConscript +++ b/src/arch/arm/fastmodel/SConscript @@ -218,10 +218,9 @@ class ProjectFileParser(Grammar): t_ID = r'[A-Za-z_]\w*' def t_STRLIT(self, t): - r'(?m)"([^"])*"' + r'"([^"])*"' # strip off quotes t.value = t.value[1:-1] - t.lexer.lineno += t.value.count('\n') return t t_EQUALS = r'=' From 694673f1d7981907a6e0695ae1d9cb1bdec136f4 Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Tue, 30 May 2023 13:27:01 +0800 Subject: [PATCH 019/693] arch: set multiline re as default in isa_parser In python3.11, it requires the global specifier should be the first token of regex. However it's not possible when using ply library. Instead, we set the rules are multiline regex by default and modifies those single line rules. Ref: https://github.com/dabeaz/ply/issues/282 Change-Id: I7bdbfeb97a9dd74f45c1890a76f8cc16100e5a42 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71019 Reviewed-by: Richard Cooper Tested-by: kokoro Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power --- src/arch/isa_parser/isa_parser.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/arch/isa_parser/isa_parser.py b/src/arch/isa_parser/isa_parser.py index 0f29840c3b..5be50a11bf 100755 --- a/src/arch/isa_parser/isa_parser.py +++ b/src/arch/isa_parser/isa_parser.py @@ -514,6 +514,7 @@ class InstObjParams(object): class ISAParser(Grammar): def __init__(self, output_dir): super().__init__() + self.lex_kwargs["reflags"] = int(re.MULTILINE) self.output_dir = output_dir self.filename = None # for output file watermarking/scaremongering @@ -851,7 +852,7 @@ class ISAParser(Grammar): # String literal. Note that these use only single quotes, and # can span multiple lines. def t_STRLIT(self, t): - r"(?m)'([^'])+'" + r"'([^'])+'" # strip off quotes t.value = t.value[1:-1] t.lexer.lineno += t.value.count("\n") @@ -860,19 +861,19 @@ class ISAParser(Grammar): # "Code literal"... like a string literal, but delimiters are # '{{' and '}}' so they get formatted nicely under emacs c-mode def t_CODELIT(self, t): - r"(?m)\{\{([^\}]|}(?!\}))+\}\}" + r"\{\{([^\}]|}(?!\}))+\}\}" # strip off {{ & }} t.value = t.value[2:-2] t.lexer.lineno += t.value.count("\n") return t def t_CPPDIRECTIVE(self, t): - r"^\#[^\#].*\n" + r"^\#[^\#][^\n]*\n" t.lexer.lineno += t.value.count("\n") return t def t_NEWFILE(self, t): - r'^\#\#newfile\s+"[^"]*"\n' + r'^\#\#newfile\s+"[^"\n]*"\n' self.fileNameStack.push(t.lexer.lineno) t.lexer.lineno = LineTracker(t.value[11:-2]) @@ -892,7 +893,7 @@ class ISAParser(Grammar): # Comments def t_comment(self, t): - r"//.*" + r"//[^\n]*\n" # Completely ignored characters t_ignore = " \t\x0c" From db903f4fd47bb54827bb2a4c6328fd332a37385f Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 17 May 2023 08:57:09 -0500 Subject: [PATCH 020/693] arch-vega: Helper methods for SDWA/DPP for VOP2 Many of the outstanding issues with the GPU model are related to instructions not having SDWA/DPP implementations and executing by ignoring the special registers leading to incorrect executiong. Adding SDWA/DPP is current very cumbersome as there is a lot of boilerplate code. This changeset adds helper methods for VOP2 with one instruction changed as an example. This review is intended to get feedback before applying this change to all VOP2 instructions that support SDWA/DPP. Change-Id: I1edbc3f3bb166d34f151545aa9f47a94150e1406 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70738 Reviewed-by: Matt Sinclair Maintainer: Matt Sinclair Tested-by: kokoro --- src/arch/amdgpu/vega/insts/instructions.cc | 56 +------------ src/arch/amdgpu/vega/insts/op_encodings.hh | 93 ++++++++++++++++++++++ 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index 6c014bc107..0d3f2dc00b 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -6384,65 +6384,17 @@ namespace VegaISA void Inst_VOP2__V_MUL_U32_U24::execute(GPUDynInstPtr gpuDynInst) { - Wavefront *wf = gpuDynInst->wavefront(); - ConstVecOperandU32 src0(gpuDynInst, instData.SRC0); - VecOperandU32 src1(gpuDynInst, instData.VSRC1); - VecOperandU32 vdst(gpuDynInst, instData.VDST); - - src0.readSrc(); - src1.read(); - - if (isSDWAInst()) { - VecOperandU32 src0_sdwa(gpuDynInst, extData.iFmt_VOP_SDWA.SRC0); - // use copies of original src0, src1, and dest during selecting - VecOperandU32 origSrc0_sdwa(gpuDynInst, - extData.iFmt_VOP_SDWA.SRC0); - VecOperandU32 origSrc1(gpuDynInst, instData.VSRC1); - VecOperandU32 origVdst(gpuDynInst, instData.VDST); - - src0_sdwa.read(); - origSrc0_sdwa.read(); - origSrc1.read(); - - DPRINTF(VEGA, "Handling V_MUL_U32_U24 SRC SDWA. SRC0: register " - "v[%d], DST_SEL: %d, DST_U: %d, CLMP: %d, SRC0_SEL: " - "%d, SRC0_SEXT: %d, SRC0_NEG: %d, SRC0_ABS: %d, SRC1_SEL: " - "%d, SRC1_SEXT: %d, SRC1_NEG: %d, SRC1_ABS: %d\n", - extData.iFmt_VOP_SDWA.SRC0, extData.iFmt_VOP_SDWA.DST_SEL, - extData.iFmt_VOP_SDWA.DST_U, - extData.iFmt_VOP_SDWA.CLMP, - extData.iFmt_VOP_SDWA.SRC0_SEL, - extData.iFmt_VOP_SDWA.SRC0_SEXT, - extData.iFmt_VOP_SDWA.SRC0_NEG, - extData.iFmt_VOP_SDWA.SRC0_ABS, - extData.iFmt_VOP_SDWA.SRC1_SEL, - extData.iFmt_VOP_SDWA.SRC1_SEXT, - extData.iFmt_VOP_SDWA.SRC1_NEG, - extData.iFmt_VOP_SDWA.SRC1_ABS); - - processSDWA_src(extData.iFmt_VOP_SDWA, src0_sdwa, origSrc0_sdwa, - src1, origSrc1); - - for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) { - if (wf->execMask(lane)) { - vdst[lane] = bits(src0_sdwa[lane], 23, 0) * - bits(src1[lane], 23, 0); - origVdst[lane] = vdst[lane]; // keep copy consistent - } - } - - processSDWA_dst(extData.iFmt_VOP_SDWA, vdst, origVdst); - } else { + auto opImpl = [](VecOperandU32& src0, VecOperandU32& src1, + VecOperandU32& vdst, Wavefront* wf) { for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) { if (wf->execMask(lane)) { vdst[lane] = bits(src0[lane], 23, 0) * bits(src1[lane], 23, 0); } } - } + }; - - vdst.write(); + vop2Helper(gpuDynInst, opImpl); } // execute // --- Inst_VOP2__V_MUL_HI_U32_U24 class methods --- diff --git a/src/arch/amdgpu/vega/insts/op_encodings.hh b/src/arch/amdgpu/vega/insts/op_encodings.hh index 1071eada0e..f1954723af 100644 --- a/src/arch/amdgpu/vega/insts/op_encodings.hh +++ b/src/arch/amdgpu/vega/insts/op_encodings.hh @@ -272,6 +272,99 @@ namespace VegaISA InstFormat extData; uint32_t varSize; + template + T sdwaSrcHelper(GPUDynInstPtr gpuDynInst, T & src1) + { + T src0_sdwa(gpuDynInst, extData.iFmt_VOP_SDWA.SRC0); + // use copies of original src0, src1, and dest during selecting + T origSrc0_sdwa(gpuDynInst, extData.iFmt_VOP_SDWA.SRC0); + T origSrc1(gpuDynInst, instData.VSRC1); + + src0_sdwa.read(); + origSrc0_sdwa.read(); + origSrc1.read(); + + DPRINTF(VEGA, "Handling %s SRC SDWA. SRC0: register v[%d], " + "DST_SEL: %d, DST_U: %d, CLMP: %d, SRC0_SEL: %d, SRC0_SEXT: " + "%d, SRC0_NEG: %d, SRC0_ABS: %d, SRC1_SEL: %d, SRC1_SEXT: %d, " + "SRC1_NEG: %d, SRC1_ABS: %d\n", + opcode().c_str(), extData.iFmt_VOP_SDWA.SRC0, + extData.iFmt_VOP_SDWA.DST_SEL, extData.iFmt_VOP_SDWA.DST_U, + extData.iFmt_VOP_SDWA.CLMP, extData.iFmt_VOP_SDWA.SRC0_SEL, + extData.iFmt_VOP_SDWA.SRC0_SEXT, + extData.iFmt_VOP_SDWA.SRC0_NEG, extData.iFmt_VOP_SDWA.SRC0_ABS, + extData.iFmt_VOP_SDWA.SRC1_SEL, + extData.iFmt_VOP_SDWA.SRC1_SEXT, + extData.iFmt_VOP_SDWA.SRC1_NEG, + extData.iFmt_VOP_SDWA.SRC1_ABS); + + processSDWA_src(extData.iFmt_VOP_SDWA, src0_sdwa, origSrc0_sdwa, + src1, origSrc1); + + return src0_sdwa; + } + + template + void sdwaDstHelper(GPUDynInstPtr gpuDynInst, T & vdst) + { + T origVdst(gpuDynInst, instData.VDST); + + Wavefront *wf = gpuDynInst->wavefront(); + for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) { + if (wf->execMask(lane)) { + origVdst[lane] = vdst[lane]; // keep copy consistent + } + } + + processSDWA_dst(extData.iFmt_VOP_SDWA, vdst, origVdst); + } + + template + T dppHelper(GPUDynInstPtr gpuDynInst, T & src1) + { + T src0_dpp(gpuDynInst, extData.iFmt_VOP_DPP.SRC0); + src0_dpp.read(); + + DPRINTF(VEGA, "Handling %s SRC DPP. SRC0: register v[%d], " + "DPP_CTRL: 0x%#x, SRC0_ABS: %d, SRC0_NEG: %d, SRC1_ABS: %d, " + "SRC1_NEG: %d, BC: %d, BANK_MASK: %d, ROW_MASK: %d\n", + opcode().c_str(), extData.iFmt_VOP_DPP.SRC0, + extData.iFmt_VOP_DPP.DPP_CTRL, extData.iFmt_VOP_DPP.SRC0_ABS, + extData.iFmt_VOP_DPP.SRC0_NEG, extData.iFmt_VOP_DPP.SRC1_ABS, + extData.iFmt_VOP_DPP.SRC1_NEG, extData.iFmt_VOP_DPP.BC, + extData.iFmt_VOP_DPP.BANK_MASK, extData.iFmt_VOP_DPP.ROW_MASK); + + processDPP(gpuDynInst, extData.iFmt_VOP_DPP, src0_dpp, src1); + + return src0_dpp; + } + + template + void vop2Helper(GPUDynInstPtr gpuDynInst, + void (*fOpImpl)(T&, T&, T&, Wavefront*)) + { + Wavefront *wf = gpuDynInst->wavefront(); + T src0(gpuDynInst, instData.SRC0); + T src1(gpuDynInst, instData.VSRC1); + T vdst(gpuDynInst, instData.VDST); + + src0.readSrc(); + src1.read(); + + if (isSDWAInst()) { + T src0_sdwa = sdwaSrcHelper(gpuDynInst, src1); + fOpImpl(src0_sdwa, src1, vdst, wf); + sdwaDstHelper(gpuDynInst, vdst); + } else if (isDPPInst()) { + T src0_dpp = dppHelper(gpuDynInst, src1); + fOpImpl(src0_dpp, src1, vdst, wf); + } else { + fOpImpl(src0, src1, vdst, wf); + } + + vdst.write(); + } + private: bool hasSecondDword(InFmt_VOP2 *); }; // Inst_VOP2 From 13e55e849129a276fea1549a24272c5bcf626cde Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Tue, 13 Jun 2023 21:04:30 +0000 Subject: [PATCH 021/693] 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 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71598 Maintainer: Jason Lowe-Power Tested-by: kokoro Reviewed-by: Jason Lowe-Power --- src/python/SConscript | 12 + .../caches/prebuilt/octopi_cache/__init__.py | 25 ++ .../prebuilt/octopi_cache/core_complex.py | 245 +++++++++++++++++ .../caches/prebuilt/octopi_cache/octopi.py | 257 ++++++++++++++++++ .../prebuilt/octopi_cache/octopi_network.py | 67 +++++ .../octopi_cache/ruby_network_components.py | 111 ++++++++ 6 files changed, 717 insertions(+) create mode 100644 src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py create mode 100644 src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py create mode 100644 src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi.py create mode 100644 src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py create mode 100644 src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py diff --git a/src/python/SConscript b/src/python/SConscript index f98b5700c7..ea9d3d4021 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -154,6 +154,18 @@ PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level', PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level', 'gem5/components/cachehierarchies/ruby/caches/mesi_three_level/' 'l3_cache.py') +PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level', + 'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/' + 'octopi.py') +PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level', + 'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/' + 'core_complex.py') +PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level', + 'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/' + 'octopi_network.py') +PySource('gem5.components.cachehierarchies.ruby.caches.mesi_three_level', + 'gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/' + 'ruby_network_components.py') PySource('gem5.components.cachehierarchies.ruby.caches.mi_example', 'gem5/components/cachehierarchies/ruby/caches/mi_example/__init__.py') PySource('gem5.components.cachehierarchies.ruby.caches.mi_example', diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py new file mode 100644 index 0000000000..b08f46b513 --- /dev/null +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/__init__.py @@ -0,0 +1,25 @@ +# Copyright (c) 2022-2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py new file mode 100644 index 0000000000..f056d76f98 --- /dev/null +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/core_complex.py @@ -0,0 +1,245 @@ +# Copyright (c) 2022-2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from typing import List, Tuple + +from gem5.isas import ISA +from gem5.components.boards.abstract_board import AbstractBoard +from gem5.components.processors.abstract_core import AbstractCore +from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l1_cache import ( + L1Cache, +) +from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l2_cache import ( + L2Cache, +) +from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l3_cache import ( + L3Cache, +) + +from m5.objects import SubSystem, RubySequencer + +from .ruby_network_components import ( + RubyRouter, + RubyExtLink, + RubyIntLink, + RubyNetworkComponent, +) + + +class CoreComplex(SubSystem, RubyNetworkComponent): + _core_id = 0 + _core_complex_id = 0 + + @classmethod + def _get_core_id(cls): + cls._core_id += 1 + return cls._core_id - 1 + + @classmethod + def _get_core_complex_id(cls): + cls._core_complex_id += 1 + return cls._core_complex_id - 1 + + def __init__( + self, + board: AbstractBoard, + cores: List[AbstractCore], + ruby_system, + l1i_size: str, + l1i_assoc: int, + l1d_size: str, + l1d_assoc: int, + l2_size: str, + l2_assoc: int, + l3_size: str, + l3_assoc: int, + ): + SubSystem.__init__(self=self) + RubyNetworkComponent.__init__(self=self) + + self._l1i_size = l1i_size + self._l1i_assoc = l1i_assoc + self._l1d_size = l1d_size + self._l1d_assoc = l1d_assoc + self._l2_size = l2_size + self._l2_assoc = l2_assoc + self._l3_size = l3_size + self._l3_assoc = l3_assoc + + self._board = board + self._cores = cores + self._ruby_system = ruby_system + self._cache_line_size = 64 + + self._directory_controllers = [] + + self._core_complex_id = self._get_core_complex_id() + self.main_router = RubyRouter( + self._ruby_system + ) # this will be connect to component outside the core complex + self._add_router(self.main_router) + self._create_core_complex() + + def get_main_router(self): + return self.main_router + + def _create_core_complex(self): + # Create L1 caches, L2 cache, and corresponding controllers per core + self.core_clusters = [ + self._create_core_cluster(core) for core in self._cores + ] + # Create L3 cache and its corresponding controller + self._create_shared_cache() + # Setting up one router and one external link per controller + self._create_external_links() + # Setting up L1/L2 links, L2/main links, L3/main link + self._create_internal_links() + + def _create_core_cluster(self, core: AbstractCore): + cluster = SubSystem() + core_id = self._get_core_id() + + cluster.l1_cache = L1Cache( + l1i_size=self._l1i_size, + l1i_assoc=self._l1i_assoc, + l1d_size=self._l1d_size, + l1d_assoc=self._l1d_assoc, + network=self._ruby_system.network, + core=core, + cache_line_size=self._cache_line_size, + target_isa=self._board.processor.get_isa(), + clk_domain=self._board.get_clock_domain(), + ) + cluster.l1_cache.sequencer = RubySequencer( + version=core_id, + dcache=cluster.l1_cache.Dcache, + clk_domain=cluster.l1_cache.clk_domain, + ) + + if self._board.has_io_bus(): + cluster.l1_cache.sequencer.connectIOPorts(self._board.get_io_bus()) + cluster.l1_cache.ruby_system = self._ruby_system + core.connect_icache(cluster.l1_cache.sequencer.in_ports) + core.connect_dcache(cluster.l1_cache.sequencer.in_ports) + core.connect_walker_ports( + cluster.l1_cache.sequencer.in_ports, + cluster.l1_cache.sequencer.in_ports, + ) + if self._board.get_processor().get_isa() == ISA.X86: + core.connect_interrupt( + cluster.l1_cache.sequencer.interrupt_out_port, + cluster.l1_cache.sequencer.in_ports, + ) + else: + core.connect_interrupt() + + cluster.l2_cache = L2Cache( + l2_size=self._l2_size, + l2_assoc=self._l2_assoc, + network=self._ruby_system.network, + core=core, + num_l3Caches=1, # each core complex has 1 slice of L3 Cache + cache_line_size=self._cache_line_size, + cluster_id=self._core_complex_id, + target_isa=self._board.processor.get_isa(), + clk_domain=self._board.get_clock_domain(), + ) + cluster.l2_cache.ruby_system = self._ruby_system + # L0Cache in the ruby backend is l1 cache in stdlib + # L1Cache in the ruby backend is l2 cache in stdlib + cluster.l2_cache.bufferFromL0 = cluster.l1_cache.bufferToL1 + cluster.l2_cache.bufferToL0 = cluster.l1_cache.bufferFromL1 + + return cluster + + def _create_shared_cache(self): + self.l3_cache = L3Cache( + l3_size=self._l3_size, + l3_assoc=self._l3_assoc, + network=self._ruby_system.network, + num_l3Caches=1, + cache_line_size=self._cache_line_size, + cluster_id=self._core_complex_id, + ) + self.l3_cache.ruby_system = self._ruby_system + + # This is where all routers and links are created + def _create_external_links(self): + # create a router per cache controller + # - there is one L3 per ccd + self.l3_router = RubyRouter(self._ruby_system) + self._add_router(self.l3_router) + # - there is one L1 and one L2 per cluster + for cluster in self.core_clusters: + cluster.l1_router = RubyRouter(self._ruby_system) + self._add_router(cluster.l1_router) + cluster.l2_router = RubyRouter(self._ruby_system) + self._add_router(cluster.l2_router) + + # create an ext link from a controller to a router + self.l3_router_link = RubyExtLink( + ext_node=self.l3_cache, + int_node=self.l3_router, + bandwidth_factor=64, + ) + self._add_ext_link(self.l3_router_link) + for cluster in self.core_clusters: + cluster.l1_router_link = RubyExtLink( + ext_node=cluster.l1_cache, int_node=cluster.l1_router + ) + self._add_ext_link(cluster.l1_router_link) + cluster.l2_router_link = RubyExtLink( + ext_node=cluster.l2_cache, int_node=cluster.l2_router + ) + self._add_ext_link(cluster.l2_router_link) + + def _create_internal_links(self): + # create L1/L2 links + for cluster in self.core_clusters: + l1_to_l2, l2_to_l1 = RubyIntLink.create_bidirectional_links( + cluster.l1_router, cluster.l2_router + ) + cluster.l1_to_l2_link = l1_to_l2 + cluster.l2_to_l1_link = l2_to_l1 + self._add_int_link(l1_to_l2) + self._add_int_link(l2_to_l1) + # create L2/main_router links + for cluster in self.core_clusters: + l2_to_main, main_to_l2 = RubyIntLink.create_bidirectional_links( + cluster.l2_router, self.main_router + ) + cluster.l2_to_main_link = l2_to_main + cluster.main_to_l2_link = main_to_l2 + self._add_int_link(l2_to_main) + self._add_int_link(main_to_l2) + # create L3/main_router link + l3_to_main, main_to_l3 = RubyIntLink.create_bidirectional_links( + self.l3_router, self.main_router, bandwidth_factor=64 + ) + self.l3_to_main_link = l3_to_main + self.main_to_l3_link = main_to_l3 + self._add_int_link(l3_to_main) + self._add_int_link(main_to_l3) diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi.py b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi.py new file mode 100644 index 0000000000..9c8b93d812 --- /dev/null +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi.py @@ -0,0 +1,257 @@ +# Copyright (c) 2022-2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from ...abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy +from ....abstract_three_level_cache_hierarchy import ( + AbstractThreeLevelCacheHierarchy, +) +from ......coherence_protocol import CoherenceProtocol +from ......components.boards.abstract_board import AbstractBoard +from ......utils.requires import requires + +from ......components.cachehierarchies.ruby.caches.mesi_three_level.directory import ( + Directory, +) +from ......components.cachehierarchies.ruby.caches.mesi_three_level.dma_controller import ( + DMAController, +) + +from m5.objects import RubySystem, DMASequencer, RubyPortProxy + +from .core_complex import CoreComplex +from .octopi_network import OctopiNetwork +from .ruby_network_components import RubyRouter, RubyExtLink, RubyIntLink + +# CoreComplex sub-systems own the L1, L2, L3 controllers +# OctopiCache owns the directory controllers +# RubySystem owns the DMA Controllers +class OctopiCache( + AbstractRubyCacheHierarchy, AbstractThreeLevelCacheHierarchy +): + def __init__( + self, + l1i_size: str, + l1i_assoc: int, + l1d_size: str, + l1d_assoc: int, + l2_size: str, + l2_assoc: int, + l3_size: str, + l3_assoc: int, + num_core_complexes: int, + is_fullsystem: bool, + ): + AbstractRubyCacheHierarchy.__init__(self=self) + AbstractThreeLevelCacheHierarchy.__init__( + self=self, + l1i_size=l1i_size, + l1i_assoc=l1i_assoc, + l1d_size=l1d_size, + l1d_assoc=l1d_assoc, + l2_size=l2_size, + l2_assoc=l2_assoc, + l3_size=l3_size, + l3_assoc=l3_assoc, + ) + + self._directory_controllers = [] + self._dma_controllers = [] + self._io_controllers = [] + self._core_complexes = [] + self._num_core_complexes = num_core_complexes + self._is_fullsystem = is_fullsystem + + def incorporate_cache(self, board: AbstractBoard) -> None: + + requires( + coherence_protocol_required=CoherenceProtocol.MESI_THREE_LEVEL + ) + + cache_line_size = board.get_cache_line_size() + + self.ruby_system = RubySystem() + # MESI_Three_Level needs 3 virtual networks + self.ruby_system.number_of_virtual_networks = 3 + self.ruby_system.network = OctopiNetwork(self.ruby_system) + + # Setting up the core complex + all_cores = board.get_processor().get_cores() + num_cores_per_core_complex = len(all_cores) // self._num_core_complexes + + self.core_complexes = [ + CoreComplex( + board=board, + cores=all_cores[ + core_complex_idx + * num_cores_per_core_complex : (core_complex_idx + 1) + * num_cores_per_core_complex + ], + ruby_system=self.ruby_system, + l1i_size=self._l1i_size, + l1i_assoc=self._l1i_assoc, + l1d_size=self._l1d_size, + l1d_assoc=self._l1d_assoc, + l2_size=self._l2_size, + l2_assoc=self._l2_assoc, + l3_size=self._l3_size, + l3_assoc=self._l3_assoc, + ) + for core_complex_idx in range(self._num_core_complexes) + ] + + self.ruby_system.network.incorporate_ccds(self.core_complexes) + + self._create_directory_controllers(board) + self._create_dma_controllers(board, self.ruby_system) + + self.ruby_system.num_of_sequencers = ( + len(all_cores) + + len(self._dma_controllers) + + len(self._io_controllers) + ) + # SimpleNetwork requires .int_links and .routers to exist + # if we want to call SimpleNetwork.setup_buffers() + self.ruby_system.network.int_links = ( + self.ruby_system.network._int_links + ) + self.ruby_system.network.ext_links = ( + self.ruby_system.network._ext_links + ) + self.ruby_system.network.routers = self.ruby_system.network._routers + self.ruby_system.network.setup_buffers() + + # Set up a proxy port for the system_port. Used for load binaries and + # other functional-only things. + self.ruby_system.sys_port_proxy = RubyPortProxy() + board.connect_system_port(self.ruby_system.sys_port_proxy.in_ports) + + def _create_directory_controllers(self, board): + # Adding controllers + self.directory_controllers = [ + Directory( + self.ruby_system.network, + board.get_cache_line_size(), + addr_range, + mem_port, + ) + for addr_range, mem_port in board.get_mem_ports() + ] + for ctrl in self.directory_controllers: + ctrl.ruby_system = self.ruby_system + # Adding controller routers + self.directory_controller_routers = [ + RubyRouter(self.ruby_system.network) + for _ in range(len(self.directory_controllers)) + ] + for router in self.directory_controller_routers: + self.ruby_system.network._add_router(router) + # Adding an external link for each controller and its router + self.directory_controller_ext_links = [ + RubyExtLink(ext_node=dir_ctrl, int_node=dir_router) + for dir_ctrl, dir_router in zip( + self.directory_controllers, self.directory_controller_routers + ) + ] + for ext_link in self.directory_controller_ext_links: + self.ruby_system.network._add_ext_link(ext_link) + _directory_controller_int_links = [] + for router in self.directory_controller_routers: + int_link_1, int_link_2 = RubyIntLink.create_bidirectional_links( + router, self.ruby_system.network.cross_ccd_router + ) + _directory_controller_int_links.extend([int_link_1, int_link_2]) + self.ruby_system.network._add_int_link(int_link_1) + self.ruby_system.network._add_int_link(int_link_2) + self.directory_controller_int_links = _directory_controller_int_links + + def _create_dma_controllers(self, board, ruby_system): + # IOController for full system simulation + if self._is_fullsystem: + self.io_sequencer = DMASequencer( + version=0, ruby_system=self.ruby_system + ) + self.io_sequencer.in_ports = board.get_mem_side_coherent_io_port() + self.ruby_system.io_controller = DMAController( + dma_sequencer=self.io_sequencer, ruby_system=self.ruby_system + ) + self._io_controllers.append(self.ruby_system.io_controller) + self.io_controller_router = RubyRouter(self.ruby_system.network) + self.ruby_system.network._add_router(self.io_controller_router) + self.io_controller_ext_link = RubyExtLink( + ext_node=self._io_controllers[0], + int_node=self.io_controller_router, + ) + self.ruby_system.network._add_ext_link(self.io_controller_ext_link) + self.io_controller_int_links = ( + RubyIntLink.create_bidirectional_links( + self.io_controller_router, + self.ruby_system.network.cross_ccd_router, + ) + ) + self.ruby_system.network._add_int_link( + self.io_controller_int_links[0] + ) + self.ruby_system.network._add_int_link( + self.io_controller_int_links[1] + ) + + self._dma_controllers = [] + if board.has_dma_ports(): + self.ruby_system.dma_controllers = [ + DMAController( + dma_sequencer=DMASequencer(version=i + 1, in_ports=port), + ruby_system=self.ruby_system, + ) + for i, port in enumerate(board.get_dma_ports()) + ] + self._dma_controllers = self.ruby_system.dma_controllers + self.dma_routers = [ + RubyRouter(self.ruby_system.network) + for dma_controller in self._dma_controllers + ] + for dma_router in self.dma_routers: + self.ruby_system.network._add_router(dma_router) + self.dma_ext_links = [ + RubyExtLink(ext_node=dma_controller, int_node=dma_router) + for dma_controller, dma_router in zip( + self._dma_controllers, self.dma_routers + ) + ] + for link in self.dma_ext_links: + self.ruby_system.network._add_ext_link(link) + self.dma_int_links = [ + RubyIntLink( + dma_router, self.ruby_system.network.cross_ccd_router + ) + for dma_router in self.dma_routers + ] + [ + RubyIntLink( + self.ruby_system.network.cross_ccd_router, dma_router + ) + for dma_router in self.dma_routers + ] + for link in self.dma_int_links: + self.ruby_system.network._add_int_link(link) diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py new file mode 100644 index 0000000000..745ef826c7 --- /dev/null +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/octopi_network.py @@ -0,0 +1,67 @@ +# Copyright (c) 2022-2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.objects import SimpleNetwork + +from .ruby_network_components import ( + RubyNetworkComponent, + RubyRouter, + RubyIntLink, +) + +# . The Network owns all routers, all int links and all ext links that are not in CCD's. +# . The CCD subsystems are not of type RubyNetwork, so we need to copy the references of +# routers and links to OctopiNetwork._routers, ._int_links, and ._ext_links; which will +# be, in turns, copied to RubyNetwork.routers, .int_links, and .ext_links respectively. +class OctopiNetwork(SimpleNetwork, RubyNetworkComponent): + def __init__(self, ruby_system): + SimpleNetwork.__init__(self=self) + RubyNetworkComponent.__init__(self=self) + self.netifs = [] + self.ruby_system = ruby_system + self.number_of_virtual_networks = ( + ruby_system.number_of_virtual_networks + ) + + self.cross_ccd_router = RubyRouter(self) + self._add_router(self.cross_ccd_router) + + def connect_ccd_routers_to_cross_ccd_router(self, ccds): + for ccd in ccds: + int_link_1, int_link_2 = RubyIntLink.create_bidirectional_links( + self.cross_ccd_router, + ccd.get_main_router(), + bandwidth_factor=64, + ) + ccd.to_cross_ccd_router_link = int_link_1 + ccd.from_cross_ccd_router_link = int_link_2 + self._add_int_link(int_link_1) + self._add_int_link(int_link_2) + + def incorporate_ccds(self, ccds): + for ccd in ccds: + self.incorporate_ruby_subsystem(ccd) + self.connect_ccd_routers_to_cross_ccd_router(ccds) diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py new file mode 100644 index 0000000000..8a413ea59d --- /dev/null +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/prebuilt/octopi_cache/ruby_network_components.py @@ -0,0 +1,111 @@ +# Copyright (c) 2022-2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.objects import Switch, SimpleIntLink, SimpleExtLink + + +class RubyNetworkComponent: + def __init__(self): + super().__init__() + self._routers = [] + self._ext_links = [] + self._int_links = [] + + def _add_router(self, router): + self._routers.append(router) + + def _add_ext_link(self, link): + self._ext_links.append(link) + + def _add_int_link(self, link): + self._int_links.append(link) + + def get_routers(self): + return self._routers + + def get_ext_links(self): + return self._ext_links + + def get_int_links(self): + return self._int_links + + def incorporate_ruby_subsystem(self, other_ruby_subsystem): + self._routers.extend(other_ruby_subsystem.get_routers()) + self._ext_links.extend(other_ruby_subsystem.get_ext_links()) + self._int_links.extend(other_ruby_subsystem.get_int_links()) + + +class RubyRouter(Switch): + _router_id = 0 + + @classmethod + def _get_router_id(cls): + cls._router_id += 1 + return cls._router_id - 1 + + def __init__(self, network): + super().__init__() + self.router_id = self._get_router_id() + self.virt_nets = network.number_of_virtual_networks + + +class RubyExtLink(SimpleExtLink): + _link_id = 0 + + @classmethod + def _get_link_id(cls): + cls._link_id += 1 + return cls._link_id - 1 + + def __init__(self, ext_node, int_node, bandwidth_factor=16): + super().__init__() + self.link_id = self._get_link_id() + self.ext_node = ext_node + self.int_node = int_node + self.bandwidth_factor = bandwidth_factor + + +class RubyIntLink(SimpleIntLink): + _link_id = 0 + + @classmethod + def _get_link_id(cls): + cls._link_id += 1 + return cls._link_id - 1 + + @classmethod + def create_bidirectional_links(cls, node_1, node_2, bandwidth_factor=16): + return [ + RubyIntLink(node_1, node_2, bandwidth_factor), + RubyIntLink(node_2, node_1, bandwidth_factor), + ] + + def __init__(self, src_node, dst_node, bandwidth_factor=16): + super().__init__() + self.link_id = self._get_link_id() + self.src_node = src_node + self.dst_node = dst_node + self.bandwidth_factor = bandwidth_factor From 307ec86f05c2c70522c1a2cb1aa5f701660459a2 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Tue, 13 Jun 2023 21:43:39 +0000 Subject: [PATCH 022/693] configs: Add example configuration for OctopiCache Change-Id: Ia78dd63e63808ebad40052d2a7cdb67cc7179e44 Signed-off-by: Hoa Nguyen Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71618 Tested-by: kokoro Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power --- .../caches/octopi-cache-example.py | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 configs/example/gem5_library/caches/octopi-cache-example.py diff --git a/configs/example/gem5_library/caches/octopi-cache-example.py b/configs/example/gem5_library/caches/octopi-cache-example.py new file mode 100644 index 0000000000..1b39a8bee5 --- /dev/null +++ b/configs/example/gem5_library/caches/octopi-cache-example.py @@ -0,0 +1,100 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +This script boots Ubuntu 20.04 with 8 timing cores in 1 CCD. + +Usage +----- + +``` +scons build/ARM_MESI_Three_Level/gem5.opt -j `nproc` +./build/ARM_MESI_Three_Level/gem5.opt \ + configs/example/gem5_library/caches/octopi-cache-example.py +``` +""" + + +from m5.objects import ArmDefaultRelease, VExpress_GEM5_Foundation + +from gem5.utils.requires import requires +from gem5.components.boards.arm_board import ArmBoard +from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.octopi import ( + OctopiCache, +) +from gem5.isas import ISA +from gem5.coherence_protocol import CoherenceProtocol +from gem5.simulate.simulator import Simulator +from gem5.resources.workload import Workload + +num_ccds = 1 # CCDs +num_cores_per_ccd = 8 # 8 cores/CCD + +# OctopiCache is built on top of gem5's MESI_Three_Level cache coherence +# protocol +requires(coherence_protocol_required=CoherenceProtocol.MESI_THREE_LEVEL) +cache_hierarchy = OctopiCache( + l1i_size="32KiB", + l1i_assoc=8, + l1d_size="32KiB", + l1d_assoc=8, + l2_size="512KiB", + l2_assoc=8, + l3_size="32MiB", + l3_assoc=16, + num_core_complexes=num_ccds, + is_fullsystem=True, +) + +memory = DualChannelDDR4_2400(size="16GB") + +# The number of cores must be consistent with +# num_core_complexes and num_cores_per_core_complexes +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, + isa=ISA.ARM, + num_cores=num_ccds * num_cores_per_ccd, +) + +release = ArmDefaultRelease() +platform = VExpress_GEM5_Foundation() + +board = ArmBoard( + clk_freq="4GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, + release=release, + platform=platform, +) + +board.set_workload(Workload("arm64-ubuntu-20.04-boot")) + +simulator = Simulator(board=board) +simulator.run() From 8a6ee4cab35f03d924396c839da55e87ad5e737e Mon Sep 17 00:00:00 2001 From: Mahyar Samani Date: Thu, 8 Jun 2023 14:56:50 -0700 Subject: [PATCH 023/693] tests: Reducing json stat dump size. This change reduces the number of stats dumped as json in traffic_gen tests. Change-Id: I94becb2e6d5da6096271cf7893ff2b380314da06 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71402 Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce Tested-by: kokoro (cherry picked from commit f78471fb81db40c836b89a015a61b8311b4b98fd) Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71438 --- tests/gem5/traffic_gen/simple_traffic_run.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/gem5/traffic_gen/simple_traffic_run.py b/tests/gem5/traffic_gen/simple_traffic_run.py index 7c0f18865a..3766d7314f 100644 --- a/tests/gem5/traffic_gen/simple_traffic_run.py +++ b/tests/gem5/traffic_gen/simple_traffic_run.py @@ -209,7 +209,9 @@ print("Beginning simulation!") exit_event = m5.simulate() print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}.") -simstats = get_simstat(root, prepare_stats=True) +simstats = get_simstat( + [core.generator for core in generator.get_cores()], prepare_stats=True +) json_output = Path(m5.options.outdir) / "output.json" with open(json_output, "w") as stats_file: simstats.dump(stats_file, indent=2) From 7398e1e401a085b7bae4e336c8d9b6e57202457a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= Date: Wed, 7 Jun 2023 17:01:03 +0200 Subject: [PATCH 024/693] arch-riscv: fix load reserved store conditional * According to the manual, load reservations must be cleared on a failed or a successful SC attempt. * A load reservation can be arbitrarily large. The current implementation was reserving something different than cacheBlockSize which could lead to problems if snoop addresses are cache block aligned. This patch implementation assumes a cacheBlock granularity. * Load reservations should also be cleared on faults Change-Id: I64513534710b5f269260fcb204f717801913e2f5 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71558 Reviewed-by: Jason Lowe-Power Reviewed-by: Roger Chang Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/arch/generic/isa.hh | 1 + src/arch/riscv/faults.cc | 3 +++ src/arch/riscv/isa.cc | 29 ++++++++++++++++++----------- src/arch/riscv/isa.hh | 12 ++++++++++++ 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/arch/generic/isa.hh b/src/arch/generic/isa.hh index e9e4d95d7b..58f66fc99b 100644 --- a/src/arch/generic/isa.hh +++ b/src/arch/generic/isa.hh @@ -70,6 +70,7 @@ class BaseISA : public SimObject public: virtual PCStateBase *newPCState(Addr new_inst_addr=0) const = 0; virtual void clear() {} + virtual void clearLoadReservation(ContextID cid) {} virtual RegVal readMiscRegNoEffect(RegIndex idx) const = 0; virtual RegVal readMiscReg(RegIndex idx) = 0; diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 940f7107ba..8fb8f81261 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -153,6 +153,9 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) tc->setMiscReg(MISCREG_NMIE, 0); } + // Clear load reservation address + tc->getIsaPtr()->clearLoadReservation(tc->contextId()); + // Set PC to fault handler address Addr addr = mbits(tc->readMiscReg(tvec), 63, 2); if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1) diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index d744fe369b..94a8239bac 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -672,11 +672,6 @@ ISA::unserialize(CheckpointIn &cp) UNSERIALIZE_CONTAINER(miscRegFile); } -const int WARN_FAILURE = 10000; - -const Addr INVALID_RESERVATION_ADDR = (Addr) -1; -std::unordered_map load_reservation_addrs; - void ISA::handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) { @@ -696,9 +691,9 @@ ISA::handleLockedRead(const RequestPtr &req) { Addr& load_reservation_addr = load_reservation_addrs[tc->contextId()]; - load_reservation_addr = req->getPaddr() & ~0xF; + load_reservation_addr = req->getPaddr(); DPRINTF(LLSC, "[cid:%d]: Reserved address %x.\n", - req->contextId(), req->getPaddr() & ~0xF); + req->contextId(), req->getPaddr()); } bool @@ -717,12 +712,13 @@ ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask) lr_addr_empty ? "yes" : "no"); if (!lr_addr_empty) { DPRINTF(LLSC, "[cid:%d]: addr = %x.\n", req->contextId(), - req->getPaddr() & ~0xF); + req->getPaddr() & cacheBlockMask); DPRINTF(LLSC, "[cid:%d]: last locked addr = %x.\n", req->contextId(), - load_reservation_addr); + load_reservation_addr & cacheBlockMask); } - if (lr_addr_empty - || load_reservation_addr != ((req->getPaddr() & ~0xF))) { + if (lr_addr_empty || + (load_reservation_addr & cacheBlockMask) + != ((req->getPaddr() & cacheBlockMask))) { req->setExtraData(0); int stCondFailures = tc->readStCondFailures(); tc->setStCondFailures(++stCondFailures); @@ -730,12 +726,21 @@ ISA::handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask) warn("%i: context %d: %d consecutive SC failures.\n", curTick(), tc->contextId(), stCondFailures); } + + // Must clear any reservations + load_reservation_addr = INVALID_RESERVATION_ADDR; + return false; } if (req->isUncacheable()) { req->setExtraData(2); } + // Must clear any reservations + load_reservation_addr = INVALID_RESERVATION_ADDR; + + DPRINTF(LLSC, "[cid:%d]: SC success! Current locked addr = %x.\n", + req->contextId(), load_reservation_addr & cacheBlockMask); return true; } @@ -743,6 +748,8 @@ void ISA::globalClearExclusive() { tc->getCpuPtr()->wakeup(tc->threadId()); + Addr& load_reservation_addr = load_reservation_addrs[tc->contextId()]; + load_reservation_addr = INVALID_RESERVATION_ADDR; } void diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 5a2a610479..7ef5c526f5 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -76,6 +76,11 @@ class ISA : public BaseISA bool hpmCounterEnabled(int counter) const; + // Load reserve - store conditional monitor + const int WARN_FAILURE = 10000; + const Addr INVALID_RESERVATION_ADDR = (Addr)-1; + std::unordered_map load_reservation_addrs; + public: using Params = RiscvISAParams; @@ -87,6 +92,13 @@ class ISA : public BaseISA return new PCState(new_inst_addr, rv_type); } + void + clearLoadReservation(ContextID cid) override + { + Addr& load_reservation_addr = load_reservation_addrs[cid]; + load_reservation_addr = INVALID_RESERVATION_ADDR; + } + public: RegVal readMiscRegNoEffect(RegIndex idx) const override; RegVal readMiscReg(RegIndex idx) override; From 29055a0a6a1e4421053749d50a13b6884ab2b2f1 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 13 Jun 2023 18:14:38 -0700 Subject: [PATCH 025/693] scons,stdlib: Remove deprecated 'distutils' module The Python module 'distutils' will be removed in Python 3.12: https://docs.python.org/3/library/distutils.html This patch removed usage of 'distutils' in the gem5 code base. Change-Id: I1e3a944446149f3cd6cbf4211a1565b5f74c85a0 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71679 Tested-by: kokoro Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power (cherry picked from commit b182b15f93621206c87c6c760cdfc1f5df1877cf) Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71741 Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce --- src/SConscript | 4 +-- .../resources/client_api/client_wrapper.py | 26 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/SConscript b/src/SConscript index d26bf49cce..1b4430327c 100644 --- a/src/SConscript +++ b/src/SConscript @@ -39,7 +39,7 @@ import collections import copy -import distutils.spawn +from shutil import which import itertools import os import os.path @@ -269,7 +269,7 @@ def ProtoBuf(source, tags=None, add_tags=None): '''Add a Protocol Buffer to build''' Source(source, tags, add_tags, append={'CXXFLAGS': '-Wno-array-bounds'}) -env['PROTOC_GRPC'] = distutils.spawn.find_executable('grpc_cpp_plugin') +env['PROTOC_GRPC'] = which('grpc_cpp_plugin') if env['PROTOC_GRPC']: with Configure(env) as conf: if (not env['HAVE_PKG_CONFIG'] or diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index 74ee831c1f..69787a0441 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -27,8 +27,7 @@ from .jsonclient import JSONClient from .atlasclient import AtlasClient from _m5 import core -from typing import Optional, Dict, List -from distutils.version import StrictVersion +from typing import Optional, Dict, List, Tuple import itertools from m5.util import warn @@ -191,12 +190,27 @@ class ClientWrapper: :param resources: A list of resources to sort. :return: A list of sorted resources. """ + + def sort_tuple(resource: Dict) -> Tuple: + """This is used for sorting resources by ID and version. First + the ID is sorted, then the version. In cases where the version + contains periods, it's assumed this is to separate a + "major.minor.hotfix" style versioning system. In which case, the + value separated in the most-significant position is sorted before + those less significant. If the value is a digit it is cast as an + int, otherwise, it is cast as a string, to lower-case. + """ + to_return = (resource["id"].lower(),) + for val in resource["resource_version"].split("."): + if val.isdigit(): + to_return += (int(val),) + else: + to_return += (str(val).lower(),) + return to_return + return sorted( resources, - key=lambda resource: ( - resource["id"].lower(), - StrictVersion(resource["resource_version"]), - ), + key=lambda resource: sort_tuple(resource), reverse=True, ) From b22afde3be8e790e807897239c84637d1ff04317 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 13 Jun 2023 17:42:23 -0700 Subject: [PATCH 026/693] python: Remove Python 'pipes' module This is scheduled for removal from Python in 3.13: https://docs.python.org/3/library/pipes.html. The 'shlex.quote' function can replace the 'pipes.quote' function used in "main.py". A special wrapper has been made to account for the Windows case which 'shlex.quote' doesn't handle. Change-Id: I9c84605f0ccd8468b9cab6cece6248ef8c2107f0 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71678 Maintainer: Jason Lowe-Power Tested-by: kokoro Reviewed-by: Jason Lowe-Power (cherry picked from commit a63d376ecd4debd60f89fa2e0592dac6f9addae2) Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71740 Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce --- src/python/m5/main.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 4701dfa5ea..ddcb024f8b 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -496,10 +496,23 @@ def main(): % (socket.gethostname(), os.getpid()) ) - # in Python 3 pipes.quote() is moved to shlex.quote() - import pipes + def quote(arg: str) -> str: + """Quotes a string for printing in a shell. In addition to Unix, + this is designed to handle the problematic Windows cases where + 'shlex.quote' doesn't work""" - print("command line:", " ".join(map(pipes.quote, sys.argv))) + if os.name == "nt" and os.sep == "\\": + # If a Windows machine, we manually quote the string. + arg = arg.replace('"', '\\"') + if re.search("\s", args): + # We quote args which have whitespace. + arg = '"' + arg + '"' + return arg + import shlex + + return shlex.quote(arg) + + print("command line:", " ".join(map(quote, sys.argv))) print() # check to make sure we can find the listed script From aff1e7b64c6c6e647f6d23dc79c2b3630bb91da4 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 12 Jun 2023 14:09:15 -0700 Subject: [PATCH 027/693] stdlib: Refactor gem5 Vision/gem5-resources code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch includes several changes to the gem5 tools interface to the gem5-resources infrastructure. These are: * The old download and JSON query functions have been removed from the downloader module. These functions were used for directly downloading and inspecting the resource JSON file, hosted at https://resources.gem5.org/resources. This information is now obtained via `gem5.client`. If a resources JSON file is specified as a client, it should conform to the new schema: https//resources.gem5.org/gem5-resources-schema.json. The old schema (pre-v23.0) is no longer valid. Tests have been updated to reflect this change. Those which tested these old functions have been removed. * Unused imports have been removed. * For the resource query functions, and those tasked with obtaining the resources, the parameter `gem5_version` has been added. In all cases it does the same thing: * It will filter results based on compatibility to the `gem5_version` specified. If no resources are compatible the latest version of that resource is chosen (though a warning is thrown). * By default it is set to the current gem5 version. * It is optional. If `None`, this filtering functionality is not carried out. * Tests have been updated to fix the version to “develop” so the they do not break between versions. * The `gem5_version` parameters will filter using a logic which will base compatibility on the specificity of the gem5-version specified in a resource’s data. If a resource has a compatible gem5-version of “v18.4” it will be compatible with any minor/hotfix version within the v18.4 release (this can be seen as matching on “v18.4.*.*”.) Likewise, if a resource has a compatible gem5-version of “v18.4.1” then it’s only compatible with the v18.4.1 release but any of it’s hot fix releases (“v18.4.1.*”). * The ‘list_resources’ function has been updated to use the “gem5.client” APIs to get resource information from the clients (MongoDB or a JSON file). This has been designed to remain backwards compatible to as much as is possible, though, due to schema changes, the function does search across all versions of gem5. * `get_resources` function was added to the `AbstractClient`. This is a more general function than `get_resource_by_id`. It was primarily created to handle the `list_resources` update but is a useful update to the API. The `get_resource_by_id` function has been altered to function as a wrapped to the `get_resources` function. * Removed “GEM5_RESOURCE_JSON” code has been removed. This is no longer used. * Tests have been cleaned up a little bit to be easier to read. * Some docstrings have been updated. Things that are left TODO with this code: * The client_wrapper/client/abstract_client abstractions are rather pointless. In particular the client_wrapper and client classes could be merged. * The downloader module no longer does much and should have its functions merged into other modules. * With the addition of the `get_resources` function, much of the code in the `AbstractClient` could be simplified. Change-Id: I0ce48e88b93a2b9db53d4749861fa0b5f9472053 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71506 Reviewed-by: Kunal Pai Maintainer: Jason Lowe-Power Tested-by: kokoro (cherry picked from commit 82587ce71bbbdc80d3ef6386e07c892f309697a3) Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71739 Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce --- src/python/gem5/resources/client.py | 52 +++- .../resources/client_api/abstract_client.py | 56 +++- .../gem5/resources/client_api/atlasclient.py | 22 +- .../resources/client_api/client_wrapper.py | 81 +++++- .../gem5/resources/client_api/jsonclient.py | 38 ++- src/python/gem5/resources/downloader.py | 271 ++---------------- src/python/gem5/resources/resource.py | 18 +- src/python/gem5/resources/workload.py | 12 +- tests/gem5/configs/download_check.py | 66 +++-- .../resources/pyunit_client_wrapper_checks.py | 109 +++---- ...checks.py => pyunit_json_client_checks.py} | 37 +-- .../pyunit_obtain_resources_check.py | 47 +-- .../pyunit_resource_download_checks.py | 72 ----- .../pyunit_resource_specialization.py | 29 +- .../resources/pyunit_workload_checks.py | 48 +--- .../stdlib/resources/refs/mongo-mock.json | 4 +- .../resources/refs/obtain-resource.json | 8 +- .../refs/resource-specialization.json | 18 +- .../stdlib/resources/refs/resources.json | 24 +- .../refs/workload-checks-custom-workload.json | 16 -- .../resources/refs/workload-checks.json | 20 +- 21 files changed, 445 insertions(+), 603 deletions(-) rename tests/pyunit/stdlib/resources/{pyunit_downloader_checks.py => pyunit_json_client_checks.py} (87%) delete mode 100644 tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py delete mode 100644 tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py index bd473eb038..ab8262bf92 100644 --- a/src/python/gem5/resources/client.py +++ b/src/python/gem5/resources/client.py @@ -31,6 +31,7 @@ from typing import Optional, Dict, List from .client_api.client_wrapper import ClientWrapper from gem5.gem5_default_config import config from m5.util import inform +from _m5 import core def getFileContent(file_path: Path) -> Dict: @@ -49,17 +50,7 @@ def getFileContent(file_path: Path) -> Dict: clientwrapper = None -def get_resource_json_obj( - resource_id, - resource_version: Optional[str] = None, - clients: Optional[List[str]] = None, -) -> Dict: - """ - Get the resource json object from the clients wrapper - :param resource_id: The resource id - :param resource_version: The resource version - :param clients: The list of clients to query - """ +def _get_clientwrapper(): global clientwrapper if clientwrapper is None: # First check if the config file path is provided in the environment variable @@ -78,7 +69,42 @@ def get_resource_json_obj( gem5_config = config inform("Using default config") clientwrapper = ClientWrapper(gem5_config) + return clientwrapper - return clientwrapper.get_resource_json_obj_from_client( - resource_id, resource_version, clients + +def list_resources( + clients: Optional[List[str]] = None, + gem5_version: Optional[str] = core.gem5Version, +) -> Dict[str, List[str]]: + """ + List all the resources available + + :param clients: The list of clients to query + :param gem5_version: The gem5 version of the resource to get. By default, + it is the gem5 version of the current build. If set to none, it will return + all gem5 versions of the resource. + :return: A Python Dict where the key is the resource id and the value is + a list of all the supported resource versions. + """ + return _get_clientwrapper().list_resources(clients, gem5_version) + + +def get_resource_json_obj( + resource_id, + resource_version: Optional[str] = None, + clients: Optional[List[str]] = None, + gem5_version: Optional[str] = core.gem5Version, +) -> Dict: + """ + Get the resource json object from the clients wrapper + :param resource_id: The resource id + :param resource_version: The resource version + :param clients: The list of clients to query + :param gem5_version: The gem5 versions to filter the resources based on + compatibility. By default, it is the gem5 version of the current build. + If None, filtering based on compatibility is not performed. + """ + + return _get_clientwrapper().get_resource_json_obj_from_client( + resource_id, resource_version, clients, gem5_version ) diff --git a/src/python/gem5/resources/client_api/abstract_client.py b/src/python/gem5/resources/client_api/abstract_client.py index 74a513fc56..7f8ad6166e 100644 --- a/src/python/gem5/resources/client_api/abstract_client.py +++ b/src/python/gem5/resources/client_api/abstract_client.py @@ -25,7 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import ABC, abstractmethod -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional import urllib.parse @@ -63,9 +63,61 @@ class AbstractClient(ABC): return False @abstractmethod + def get_resources( + self, + resource_id: Optional[str] = None, + resource_version: Optional[str] = None, + gem5_version: Optional[str] = None, + ) -> List[Dict[str, Any]]: + """ + :param resource_id: The ID of the Resource. Optional, if not set, all + resources will be returned. + :param resource_version: The version of the Resource. Optional, if + not set, all resource versions will be returned. Note: If `resource_id` + is not set, this parameter will be ignored. + :param gem5_version: The version of gem5. Optional, if not set, all + versions will be returned. + :return: A list of all the Resources with the given ID. + """ + raise NotImplementedError + + def filter_incompatible_resources( + self, + resources_to_filter: List[Dict[str, Any]], + gem5_version: Optional[str] = None, + ) -> List[Dict[str, Any]]: + """Returns a filtered list resources based on gem5 version + compatibility. + + Note: This function assumes if the minor component of + a resource's gem5_version is not specified, the resource is compatible + with all minor versions of the same major version. + Likewise, if no hot-fix component is specified, it is assumed that + the resource is compatible with all hot-fix versions of the same + minor version. + + * '20.1' would be compatible with gem5 '20.1.1.0' and '20.1.2.0'. + * '21.5.2' would be compatible with gem5 '21.5.2.0' and '21.5.2.0'. + * '22.3.2.4' would only be compatible with gem5 '22.3.2.4'. + + :param resources_to_filter: The list of resources to filter. + :param gem5_version: The gem5 version in which the filtered resources + should be compatible. If None, no filtering will be done. + : + """ + if not gem5_version: + return resources_to_filter + + filtered_resources = [] + for resource in resources_to_filter: + for version in resource["gem5_versions"]: + if gem5_version.startswith(version): + filtered_resources.append(resource) + return filtered_resources + def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: """ :param resource_id: The ID of the Resource. :return: A list of all the Resources with the given ID. """ - raise NotImplementedError + return self.get_resources(resource_id=resource_id) diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py index 4a6e5cf691..7d2a27c3f7 100644 --- a/src/python/gem5/resources/client_api/atlasclient.py +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -64,14 +64,26 @@ class AtlasClient(AbstractClient): token = result["access_token"] return token - def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: + def get_resources( + self, + resource_id: Optional[str] = None, + resource_version: Optional[str] = None, + gem5_version: Optional[str] = None, + ) -> List[Dict[str, Any]]: url = f"{self.url}/action/find" data = { "dataSource": self.dataSource, "collection": self.collection, "database": self.database, - "filter": {"id": resource_id}, } + filter = {} + if resource_id: + filter["id"] = resource_id + if resource_version is not None: + filter["resource_version"] = resource_version + + if filter: + data["filter"] = filter data = json.dumps(data).encode("utf-8") headers = { @@ -88,4 +100,8 @@ class AtlasClient(AbstractClient): result = json.loads(response.read().decode("utf-8")) resources = result["documents"] - return resources + # I do this as a lazy post-processing step because I can't figure out + # how to do this via an Atlas query, which may be more efficient. + return self.filter_incompatible_resources( + resources_to_filter=resources, gem5_version=gem5_version + ) diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index 69787a0441..d2baabc52d 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -58,6 +58,38 @@ class ClientWrapper: warn(f"Error creating client {client}: {str(e)}") return clients + def list_resources( + self, + clients: Optional[List[str]] = None, + gem5_version: Optional[str] = core.gem5Version, + ) -> Dict[str, List[str]]: + + clients_to_search = ( + list(self.clients.keys()) if clients is None else clients + ) + # There's some duplications of functionality here (similar code in + # `get_all_resources_by_id`. This code could be refactored to avoid + # this). + resources = [] + for client in clients_to_search: + if client not in self.clients: + raise Exception(f"Client: {client} does not exist") + try: + resources.extend( + self.clients[client].get_resources( + gem5_version=gem5_version + ) + ) + except Exception as e: + warn(f"Error getting resources from client {client}: {str(e)}") + + to_return = {} + for resource in resources: + if resource["id"] not in to_return: + to_return[resource["id"]] = [] + to_return[resource["id"]].append(resource["resource_version"]) + return to_return + def get_all_resources_by_id( self, resource_id: str, @@ -97,6 +129,7 @@ class ClientWrapper: resource_id: str, resource_version: Optional[str] = None, clients: Optional[List[str]] = None, + gem5_version: Optional[str] = core.gem5Version, ) -> Dict: """ This function returns the resource object from the client with the @@ -105,6 +138,9 @@ class ClientWrapper: :param resource_version: The version of the resource to search for. :param clients: A list of clients to search through. If None, all clients are searched. + :param gem5_version: The gem5 version to check compatibility with. If + None, no compatibility check is performed. By default, is the current + version of gem5. :return: The resource object as a Python dictionary if found. If not found, exception is thrown. """ @@ -123,7 +159,9 @@ class ClientWrapper: else: compatible_resources = ( - self._get_resources_compatible_with_gem5_version(resources) + self._get_resources_compatible_with_gem5_version( + resources, gem5_version=gem5_version + ) ) if len(compatible_resources) == 0: resource_to_return = self._sort_resources(resources)[0] @@ -132,7 +170,10 @@ class ClientWrapper: compatible_resources )[0] - self._check_resource_version_compatibility(resource_to_return) + if gem5_version: + self._check_resource_version_compatibility( + resource_to_return, gem5_version=gem5_version + ) return resource_to_return @@ -171,16 +212,31 @@ class ClientWrapper: ) -> List: """ Returns a list of compatible resources with the current gem5 version. + + Note: This function assumes if the minor component of + a resource's gem5_version is not specified, it that the + resource is compatible all minor versions of the same major version. + Likewise, if no hot-fix component is specified, it is assumed that + the resource is compatible with all hot-fix versions of the same + minor version. + + * '20.1' would be compatible with gem5 '20.1.1.0' and '20.1.2.0'. + * '21.5.2' would be compatible with gem5 '21.5.2.0' and '21.5.2.0'. + * '22.3.2.4' would only be compatible with gem5 '22.3.2.4'. + :param resources: A list of resources to filter. :return: A list of compatible resources as Python dictionaries. - If no compatible resources are found, the original list of resources - is returned. + + **Note**: This is a big duplication of code. This functionality already + exists in the `AbstractClient` class. This code should be refactored + to avoid this duplication. """ - compatible_resources = [ - resource - for resource in resources - if gem5_version in resource["gem5_versions"] - ] + + compatible_resources = [] + for resource in resources: + for version in resource["gem5_versions"]: + if gem5_version.startswith(version): + compatible_resources.append(resource) return compatible_resources def _sort_resources(self, resources: List) -> List: @@ -227,7 +283,12 @@ class ClientWrapper: """ if not resource: return False - if gem5_version not in resource["gem5_versions"]: + if ( + gem5_version + and not self._get_resources_compatible_with_gem5_version( + [resource], gem5_version=gem5_version + ) + ): warn( f"Resource {resource['id']} with version " f"{resource['resource_version']} is not known to be compatible" diff --git a/src/python/gem5/resources/client_api/jsonclient.py b/src/python/gem5/resources/client_api/jsonclient.py index 225126e2a8..9e837131b0 100644 --- a/src/python/gem5/resources/client_api/jsonclient.py +++ b/src/python/gem5/resources/client_api/jsonclient.py @@ -58,13 +58,31 @@ class JSONClient(AbstractClient): ) self.resources = json.loads(response.read().decode("utf-8")) - def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: - """ - :param resource_id: The ID of the Resource. - :return: A list of all the Resources with the given ID. - """ - return [ - resource - for resource in self.resources - if resource["id"] == resource_id - ] + def get_resources_json(self) -> List[Dict[str, Any]]: + """Returns a JSON representation of the resources.""" + return self.resources + + def get_resources( + self, + resource_id: Optional[str] = None, + resource_version: Optional[str] = None, + gem5_version: Optional[str] = None, + ) -> List[Dict[str, Any]]: + filter = self.resources # Unfiltered. + if resource_id: + filter = [ # Filter by resource_id. + resource + for resource in filter + if resource["id"] == resource_id + ] + if resource_version: + filter = [ # Filter by resource_version. + resource + for resource in filter + if resource["resource_version"] == resource_version + ] + + # Filter by gem5_version. + return self.filter_incompatible_resources( + resources_to_filter=filter, gem5_version=gem5_version + ) diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index 0781d9b15a..bb5ca84cc0 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -24,24 +24,24 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import json import urllib.request import urllib.parse -import hashlib import os import shutil import gzip -import hashlib -import base64 import time import random from pathlib import Path import tarfile -from tempfile import gettempdir from urllib.error import HTTPError -from typing import List, Dict, Set, Optional +from typing import List, Optional, Dict -from .client import get_resource_json_obj +from _m5 import core + +from .client import ( + get_resource_json_obj, + list_resources as client_list_resources, +) from .md5_utils import md5_file, md5_dir from ..utils.progress_bar import tqdm, progress_hook @@ -53,188 +53,6 @@ information about resources from resources.gem5.org. """ -def _resources_json_version_required() -> str: - """ - Specifies the version of resources.json to obtain. - """ - return "develop" - - -def _get_resources_json_uri() -> str: - return "https://resources.gem5.org/resources.json" - - -def _url_validator(url): - try: - result = urllib.parse.urlparse(url) - return all([result.scheme, result.netloc, result.path]) - except: - return False - - -def _get_resources_json_at_path(path: str, use_caching: bool = True) -> Dict: - """ - Returns a resource JSON, in the form of a Python Dict. The location - of the JSON must be specified. - - If `use_caching` is True, and a URL is passed, a copy of the JSON will be - cached locally, and used for up to an hour after retrieval. - - :param path: The URL or local path of the JSON file. - :param use_caching: True if a cached file is to be used (up to an hour), - otherwise the file will be retrieved from the URL regardless. True by - default. Only valid in cases where a URL is passed. - """ - - # If a local valid path is passed, just load it. - if Path(path).is_file(): - return json.load(open(path)) - - # If it's not a local path, it should be a URL. We check this here and - # raise an Exception if it's not. - if not _url_validator(path): - raise Exception( - f"Resources location '{path}' is not a valid path or URL." - ) - - download_path = os.path.join( - gettempdir(), - f"gem5-resources-{hashlib.md5(path.encode()).hexdigest()}" - f"-{str(os.getuid())}.json", - ) - - # We apply a lock on the resources file for when it's downloaded, or - # re-downloaded, and read. This stops a corner-case from occuring where - # the file is re-downloaded while being read by another gem5 thread. - # Note the timeout is 120 so the `_download` function is given time to run - # its Truncated Exponential Backoff algorithm - # (maximum of roughly 1 minute). Typically this code will run quickly. - with FileLock(f"{download_path}.lock", timeout=120): - - # The resources.json file can change at any time, but to avoid - # excessive retrieval we cache a version locally and use it for up to - # an hour before obtaining a fresh copy. - # - # `time.time()` and `os.path.getmtime(..)` both return an unix epoch - # time in seconds. Therefore, the value of "3600" here represents an - # hour difference between the two values. `time.time()` gets the - # current time, and `os.path.getmtime()` gets the modification - # time of the file. This is the most portable solution as other ideas, - # like "file creation time", are not always the same concept between - # operating systems. - if ( - not use_caching - or not os.path.exists(download_path) - or (time.time() - os.path.getmtime(download_path)) > 3600 - ): - _download(path, download_path) - - with open(download_path) as f: - file_contents = f.read() - - try: - to_return = json.loads(file_contents) - except json.JSONDecodeError: - # This is a bit of a hack. If the URL specified exists in a Google - # Source repo (which is the case when on the gem5 develop branch) we - # retrieve the JSON in base64 format. This cannot be loaded directly as - # text. Conversion is therefore needed. - to_return = json.loads(base64.b64decode(file_contents).decode("utf-8")) - - return to_return - - -def _get_resources_json() -> Dict: - """ - Gets the Resources JSON. - - :returns: The Resources JSON (as a Python Dictionary). - """ - - path = os.getenv("GEM5_RESOURCE_JSON", _get_resources_json_uri()) - to_return = _get_resources_json_at_path(path=path) - - # If the current version pulled is not correct, look up the - # "previous-versions" field to find the correct one. - # If the resource JSON file does not have a "version" field or it's - # null/None, then we will use this resource JSON file (this is usefull for - # testing purposes). - version = _resources_json_version_required() - json_version = None if "version" not in to_return else to_return["version"] - - if json_version and json_version != version: - if version in to_return["previous-versions"].keys(): - to_return = _get_resources_json_at_path( - path=to_return["previous-versions"][version] - ) - else: - # This should never happen, but we thrown an exception to explain - # that we can't find the version. - raise Exception( - f"Version '{version}' of resources.json cannot be found." - ) - - return to_return - - -def _get_url_base() -> str: - """ - Obtains the "url_base" string from the resources.json file. - - :returns: The "url_base" string value from the resources.json file. - """ - json = _get_resources_json() - if "url_base" in json.keys(): - return json["url_base"] - return "" - - -def _get_resources( - valid_types: Set[str], resources_group: Optional[Dict] = None -) -> Dict[str, Dict]: - """ - A recursive function to get all the workload/resource of the specified type - in the resources.json file. - - :param valid_types: The type to return (i.e., "resource" or "workload). - :param resource_group: Used for recursion: The current resource group being - iterated through. - - :returns: A dictionary of artifact names to the resource JSON objects. - """ - - if resources_group is None: - resources_group = _get_resources_json()["resources"] - - to_return = {} - for resource in resources_group: - if resource["type"] in valid_types: - # If the type is valid then we add it directly to the map - # after a check that the name is unique. - if resource["name"] in to_return.keys(): - raise Exception( - f"Error: Duplicate resource with name '{resource['name']}'." - ) - to_return[resource["name"]] = resource - elif resource["type"] == "group": - # If it's a group we get recursive. We then check to see if there - # are any duplication of keys. - new_map = _get_resources( - valid_types=valid_types, resources_group=resource["contents"] - ) - intersection = set(new_map.keys()).intersection(to_return.keys()) - if len(intersection) > 0: - # Note: if this error is received it's likely an error with - # the resources.json file. The resources names need to be - # unique keyes. - raise Exception( - f"Error: Duplicate resources with names: {str(intersection)}." - ) - to_return.update(new_map) - - return to_return - - def _download(url: str, download_to: str, max_attempts: int = 6) -> None: """ Downloads a file. @@ -336,61 +154,26 @@ def _download(url: str, download_to: str, max_attempts: int = 6) -> None: ) -def list_resources() -> List[str]: +def list_resources( + clients: Optional[List] = None, gem5_version: Optional[str] = None +) -> Dict[str, List[str]]: """ - Lists all available resources by name. + Lists all available resources. Returns a dictionary where the key is the + id of the resources and the value is a list of that resource's versions. + + :param clients: A list of clients to use when listing resources. If None, + all clients will be used. None by default. + + :param gem5_version: The gem5 version to which all resources should be + compatible with. If None, compatibility of resources is not considered and + all resources will be returned. + + **Note**: This function is here for legacy reasons. The `list_resources` + function was originally stored here. In order to remain backwards + compatible, this function will call the `client_list_resources` function - :returns: A list of resources by name. """ - from .resource import _get_resource_json_type_map - - return _get_resources( - valid_types=_get_resource_json_type_map.keys() - ).keys() - - -def get_workload_json_obj(workload_name: str) -> Dict: - """ - Get a JSON object of a specified workload. - - :param workload_name: The name of the workload. - - :raises Exception: An exception is raised if the specified workload does - not exit. - """ - workload_map = _get_resources(valid_types={"workload"}) - - if workload_name not in workload_map: - raise Exception( - f"Error: Workload with name {workload_name} does not exist" - ) - - return workload_map[workload_name] - - -def get_resources_json_obj(resource_name: str) -> Dict: - """ - Get a JSON object of a specified resource. - - :param resource_name: The name of the resource. - - :returns: The JSON object (in the form of a dictionary). - - :raises Exception: An exception is raised if the specified resources does - not exist. - """ - from .resource import _get_resource_json_type_map - - resource_map = _get_resources( - valid_types=_get_resource_json_type_map.keys() - ) - - if resource_name not in resource_map: - raise Exception( - f"Error: Resource with name '{resource_name}' does not exist" - ) - - return resource_map[resource_name] + return client_list_resources(clients=clients, gem5_version=gem5_version) def get_resource( @@ -401,6 +184,7 @@ def get_resource( download_md5_mismatch: bool = True, resource_version: Optional[str] = None, clients: Optional[List] = None, + gem5_version: Optional[str] = core.gem5Version, ) -> None: """ Obtains a gem5 resource and stored it to a specified location. If the @@ -429,6 +213,10 @@ def get_resource( :param clients: A list of clients to use when obtaining the resource. If None, all clients will be used. None by default. + :param gem5_version: The gem5 version to use when obtaining the resource. + By default, the version of gem5 being used is used. This is used primarily + for testing purposes. + :raises Exception: An exception is thrown if a file is already present at `to_path` but it does not have the correct md5 sum. An exception will also be thrown is a directory is present at `to_path` @@ -444,6 +232,7 @@ def get_resource( resource_name, resource_version=resource_version, clients=clients, + gem5_version=gem5_version, ) if os.path.exists(to_path): diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 22adf15670..bc9f4480ba 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -28,6 +28,7 @@ from abc import ABCMeta import os from pathlib import Path from m5.util import warn, fatal +from _m5 import core from .downloader import get_resource @@ -559,17 +560,15 @@ def obtain_resource( download_md5_mismatch: bool = True, resource_version: Optional[str] = None, clients: Optional[List] = None, + gem5_version=core.gem5Version, ) -> AbstractResource: """ This function primarily serves as a factory for resources. It will return the correct `AbstractResource` implementation based on the resource - requested, by referencing the "resource.json" file (by default, that hosted - at https://resources.gem5.org/resources.json). In addition to this, this - function will download the resource if not detected in the - `resource_directory`. + requested. :param resource_name: The name of the gem5 resource as it appears under the - "name" field in the `resource.json` file. + "id" field in the `resource.json` file. :param resource_directory: The location of the directory in which the resource is to be stored. If this parameter is not set, it will set to the environment variable `GEM5_RESOURCE_DIR`. If the environment is not @@ -582,11 +581,17 @@ def obtain_resource( Not a required parameter. None by default. :param clients: A list of clients to search for the resource. If this parameter is not set, it will default search all clients. + :param gem5_version: The gem5 version to use to filter incompatible + resource versions. By default set to the current gem5 version. If None, + this filtering is not performed. """ # Obtain the resource object entry for this resource resource_json = get_resource_json_obj( - resource_id, resource_version=resource_version, clients=clients + resource_id, + resource_version=resource_version, + clients=clients, + gem5_version=gem5_version, ) to_path = None @@ -629,6 +634,7 @@ def obtain_resource( download_md5_mismatch=download_md5_mismatch, resource_version=resource_version, clients=clients, + gem5_version=gem5_version, ) # Obtain the type from the JSON. From this we will determine what subclass diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index 148ab3f35a..0798b891ab 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -27,6 +27,8 @@ from .resource import obtain_resource from .client import get_resource_json_obj +from _m5 import core + from typing import Dict, Any, List, Optional @@ -160,6 +162,7 @@ class Workload(AbstractWorkload): resource_directory: Optional[str] = None, resource_version: Optional[str] = None, clients: Optional[List] = None, + gem5_version: Optional[str] = core.gem5Version, ) -> None: """ This constructor will load the workload details from the workload with @@ -201,12 +204,17 @@ class Workload(AbstractWorkload): :param resource_directory: An optional parameter that specifies where any resources should be download and accessed from. If None, a default location will be used. None by default. + :param gem5_version: The gem5 version for the Workload to be loaded. + By default, the current gem5 version is used. This will filter + resources which are incompatible with the current gem5 version. If + None, no filtering will be done. """ workload_json = get_resource_json_obj( workload_name, resource_version=resource_version, clients=clients, + gem5_version=gem5_version, ) func = workload_json["function"] @@ -219,7 +227,9 @@ class Workload(AbstractWorkload): value = workload_json["resources"][key] assert isinstance(value, str) params[key] = obtain_resource( - value, resource_directory=resource_directory + value, + resource_directory=resource_directory, + gem5_version=gem5_version, ) if "additional_params" in workload_json: diff --git a/tests/gem5/configs/download_check.py b/tests/gem5/configs/download_check.py index decc62c2d7..2180f4f26a 100644 --- a/tests/gem5/configs/download_check.py +++ b/tests/gem5/configs/download_check.py @@ -26,10 +26,11 @@ from gem5.resources.downloader import ( list_resources, - get_resources_json_obj, get_resource, ) +from gem5.resources.client import get_resource_json_obj + from gem5.resources.md5_utils import md5 import os @@ -51,6 +52,15 @@ parser.add_argument( "checked", ) +parser.add_argument( + "--gem5-version", + type=str, + required=False, + help="The gem5 version to check the resources against. Resources not " + "compatible with this version will be ignored. If not set, no " + "compatibility tests are performed.", +) + parser.add_argument( "--download-directory", type=str, @@ -67,39 +77,59 @@ if not Path(args.download_directory).exists(): ids = args.ids +resource_list = list_resources(gem5_version=args.gem5_version) if len(ids) == 0: - ids = list_resources() + ids = resource_list # We log all the errors as they occur then dump them at the end. This means we # can be aware of all download errors in a single failure. errors = str() for id in ids: - if id not in list_resources(): + if id not in resource_list: errors += ( f"Resource with ID '{id}' not found in " + f"`list_resources()`.{os.linesep}" ) continue - resource_json = get_resources_json_obj(id) - download_path = os.path.join(args.download_directory, id) - try: - get_resource(resource_name=id, to_path=download_path) - except Exception as e: - errors += f"Failure to download resource '{id}'.{os.linesep}" - errors += f"Exception message:{os.linesep}{str(e)}" - errors += f"{os.linesep}{os.linesep}" - continue + for resource_version in ids[id]: - if md5(Path(download_path)) != resource_json["md5sum"]: - errors += ( - f"Downloaded resource '{id}' md5 " - + f"({md5(Path(download_path))}) differs to that in the " - + f"JSON ({resource_json['md5sum']}).{os.linesep}" + resource_json = get_resource_json_obj( + resource_id=id, + resource_version=resource_version, + gem5_version=args.gem5_version, ) + if resource_json["category"] == "workload": + # Workloads are not downloaded as part of this test. + continue + download_path = os.path.join( + args.download_directory, f"{id}-v{resource_version}" + ) + try: + get_resource( + resource_name=id, + resource_version=resource_version, + gem5_version=args.gem5_version, + to_path=download_path, + ) + except Exception as e: + errors += ( + f"Failure to download resource '{id}', " + + f"v{resource_version}.{os.linesep}" + ) + errors += f"Exception message:{os.linesep}{str(e)}" + errors += f"{os.linesep}{os.linesep}" + continue - # Remove the downloaded resource. + if md5(Path(download_path)) != resource_json["md5sum"]: + errors += ( + f"Downloaded resource '{id}' md5 " + + f"({md5(Path(download_path))}) differs to that recorded in " + + f" gem5-resources ({resource_json['md5sum']}).{os.linesep}" + ) + + # Remove the downloaded resource. shutil.rmtree(download_path, ignore_errors=True) # If errors exist, raise an exception highlighting them. diff --git a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py index 344f67b8b0..f190b1ed5f 100644 --- a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py @@ -25,13 +25,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import unittest -from gem5.isas import ISA from gem5.resources.client import get_resource_json_obj -import gem5.resources.client from gem5.resources.client_api.client_wrapper import ClientWrapper -from typing import Dict from unittest.mock import patch -from unittest import mock import json from urllib.error import HTTPError import io @@ -62,23 +58,8 @@ mock_config_mongo = { }, } -mock_config_combined = { - "sources": { - "gem5-resources": { - "dataSource": "gem5-vision", - "database": "gem5-vision", - "collection": "versions_test", - "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", - "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", - "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", - "isMongo": True, - }, - "baba": { - "url": mock_json_path, - "isMongo": False, - }, - }, -} +mock_config_combined = mock_config_mongo +mock_config_combined["sources"]["baba"] = mock_config_json["sources"]["baba"] mock_json = {} @@ -145,12 +126,12 @@ class ClientWrapperTestSuite(unittest.TestCase): def test_get_resource_json_obj(self): # Test that the resource object is correctly returned resource = "this-is-a-test-resource" - resource = get_resource_json_obj(resource) + resource = get_resource_json_obj(resource, gem5_version="develop") self.assertEqual(resource["id"], "this-is-a-test-resource") - self.assertEqual(resource["resource_version"], "2.0.0") + self.assertEqual(resource["resource_version"], "1.1.0") self.assertEqual(resource["category"], "binary") self.assertEqual( - resource["description"], "This is a test resource but double newer" + resource["description"], "This is a test resource but newer" ) self.assertEqual( resource["source_url"], @@ -167,7 +148,9 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id = "test-id" client = "invalid" with self.assertRaises(Exception) as context: - get_resource_json_obj(resource_id, clients=[client]) + get_resource_json_obj( + resource_id, clients=[client], gem5_version="develop" + ) self.assertTrue( f"Client: {client} does not exist" in str(context.exception) ) @@ -181,7 +164,9 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id = "this-is-a-test-resource" resource_version = "1.0.0" resource = get_resource_json_obj( - resource_id, resource_version=resource_version + resource_id, + resource_version=resource_version, + gem5_version="develop", ) self.assertEqual(resource["id"], "this-is-a-test-resource") self.assertEqual(resource["resource_version"], "1.0.0") @@ -200,17 +185,18 @@ class ClientWrapperTestSuite(unittest.TestCase): @patch("urllib.request.urlopen", side_effect=mocked_requests_post) def test_get_resource_json_obj_1(self, mock_get): resource = "x86-ubuntu-18.04-img" - resource = get_resource_json_obj(resource) + resource = get_resource_json_obj(resource, gem5_version="develop") self.assertEqual(resource["id"], "x86-ubuntu-18.04-img") - self.assertEqual(resource["resource_version"], "1.1.0") + self.assertEqual(resource["resource_version"], "2.0.0") self.assertEqual(resource["category"], "disk-image") self.assertEqual( resource["description"], - "A disk image containing Ubuntu 18.04 for x86. This image will run an `m5 readfile` instruction after booting. If no script file is specified an `m5 exit` instruction will be executed.", + "This is a test resource", ) self.assertEqual( resource["source_url"], - "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + "https://github.com/gem5/gem5-resources/tree/develop/" + "src/x86-ubuntu", ) self.assertEqual(resource["architecture"], "X86") @@ -227,6 +213,7 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id, resource_version=resource_version, clients=["gem5-resources"], + gem5_version="develop", ) self.assertEqual(resource["id"], "x86-ubuntu-18.04-img") self.assertEqual(resource["resource_version"], "1.0.0") @@ -246,7 +233,9 @@ class ClientWrapperTestSuite(unittest.TestCase): def test_get_resource_json_obj_with_id_invalid_mongodb(self, mock_get): resource_id = "invalid-id" with self.assertRaises(Exception) as context: - get_resource_json_obj(resource_id, clients=["gem5-resources"]) + get_resource_json_obj( + resource_id, clients=["gem5-resources"], gem5_version="develop" + ) self.assertTrue( "Resource with ID 'invalid-id' not found." in str(context.exception) @@ -267,12 +256,13 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id, resource_version=resource_version, clients=["gem5-resources"], + gem5_version="develop", ) self.assertTrue( f"Resource x86-ubuntu-18.04-img with version '2.5.0'" " not found.\nResource versions can be found at: " - f"https://resources.gem5.org/resources/x86-ubuntu-18.04-img/versions" - in str(context.exception) + "https://resources.gem5.org/resources/x86-ubuntu-18.04-img/" + "versions" in str(context.exception) ) @patch( @@ -286,12 +276,13 @@ class ClientWrapperTestSuite(unittest.TestCase): get_resource_json_obj( resource_id, resource_version=resource_version, + gem5_version="develop", ) self.assertTrue( - f"Resource this-is-a-test-resource with version '2.5.0'" + "Resource this-is-a-test-resource with version '2.5.0'" " not found.\nResource versions can be found at: " - f"https://resources.gem5.org/resources/this-is-a-test-resource/versions" - in str(context.exception) + "https://resources.gem5.org/resources/this-is-a-test-resource/" + "versions" in str(context.exception) ) @patch( @@ -308,11 +299,13 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id_mongo, resource_version=resource_version_mongo, clients=["gem5-resources"], + gem5_version="develop", ) resource_json = get_resource_json_obj( resource_id_json, resource_version=resource_version_json, clients=["baba"], + gem5_version="develop", ) self.assertEqual(resource_mongo["id"], "x86-ubuntu-18.04-img") self.assertEqual(resource_mongo["resource_version"], "1.0.0") @@ -322,7 +315,8 @@ class ClientWrapperTestSuite(unittest.TestCase): ) self.assertEqual( resource_mongo["source_url"], - "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", + "https://github.com/gem5/gem5-resources/tree/develop/src/" + "x86-ubuntu", ) self.assertEqual(resource_mongo["architecture"], "X86") @@ -347,6 +341,7 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id = "simpoint-resource" resource = get_resource_json_obj( resource_id, + gem5_version="develop", ) self.assertEqual(resource["id"], resource_id) self.assertEqual(resource["resource_version"], "0.2.0") @@ -371,6 +366,7 @@ class ClientWrapperTestSuite(unittest.TestCase): resource_id = "x86-ubuntu-18.04-img" resource_json = get_resource_json_obj( resource_id, + gem5_version="develop", ) self.assertEqual(resource_json["id"], "x86-ubuntu-18.04-img") @@ -378,8 +374,7 @@ class ClientWrapperTestSuite(unittest.TestCase): self.assertEqual(resource_json["category"], "disk-image") resource_json = get_resource_json_obj( - resource_id, - resource_version="1.0.0", + resource_id, resource_version="1.0.0", gem5_version="develop" ) self.assertEqual(resource_json["id"], "x86-ubuntu-18.04-img") @@ -396,6 +391,7 @@ class ClientWrapperTestSuite(unittest.TestCase): with self.assertRaises(Exception) as context: get_resource_json_obj( resource_id, + gem5_version="develop", ) self.assertTrue( f"Resource {resource_id} has multiple resources with" @@ -428,6 +424,7 @@ class ClientWrapperTestSuite(unittest.TestCase): with contextlib.redirect_stderr(f): get_resource_json_obj( resource_id, + gem5_version="develop", ) self.assertTrue( "Error getting resources from client gem5-resources:" @@ -440,21 +437,7 @@ class ClientWrapperTestSuite(unittest.TestCase): @patch( "gem5.resources.client.clientwrapper", - ClientWrapper( - { - "sources": { - "gem5-resources": { - "dataSource": "gem5-vision", - "database": "gem5-vision", - "collection": "versions_test", - "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v", - "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", - "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", - "isMongo": True, - } - }, - } - ), + ClientWrapper(mock_config_mongo), ) @patch("urllib.request.urlopen", side_effect=mocked_requests_post) def test_invalid_url(self, mock_get): @@ -464,6 +447,7 @@ class ClientWrapperTestSuite(unittest.TestCase): with contextlib.redirect_stderr(f): get_resource_json_obj( resource_id, + gem5_version="develop", ) self.assertTrue( "Error getting resources from client gem5-resources:" @@ -476,21 +460,7 @@ class ClientWrapperTestSuite(unittest.TestCase): @patch( "gem5.resources.client.clientwrapper", - ClientWrapper( - { - "sources": { - "gem5-resources": { - "dataSource": "gem5-vision", - "database": "gem5-vision", - "collection": "versions_test", - "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", - "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", - "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", - "isMongo": True, - } - }, - } - ), + ClientWrapper(mock_config_mongo), ) @patch("urllib.request.urlopen", side_effect=mocked_requests_post) def test_invalid_url(self, mock_get): @@ -500,6 +470,7 @@ class ClientWrapperTestSuite(unittest.TestCase): with contextlib.redirect_stderr(f): get_resource_json_obj( resource_id, + gem5_version="develop", ) self.assertTrue( "Error getting resources from client gem5-resources:" diff --git a/tests/pyunit/stdlib/resources/pyunit_downloader_checks.py b/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py similarity index 87% rename from tests/pyunit/stdlib/resources/pyunit_downloader_checks.py rename to tests/pyunit/stdlib/resources/pyunit_json_client_checks.py index 19169e480e..88db3d4967 100644 --- a/tests/pyunit/stdlib/resources/pyunit_downloader_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py @@ -30,15 +30,11 @@ import os from typing import Dict import json -from gem5.resources.downloader import ( - _get_resources_json_at_path, - _get_resources_json, - _resources_json_version_required, -) +from gem5.resources.client_api.jsonclient import JSONClient -class ResourceDownloaderTestSuite(unittest.TestCase): - """Test cases for gem5.resources.downloader""" +class JSONClientTestSuite(unittest.TestCase): + """Test cases for gem5.resources.client_api.jsonclient""" @classmethod def setUpClass(cls) -> str: @@ -142,12 +138,9 @@ class ResourceDownloaderTestSuite(unittest.TestCase): file.close() cls.file_path = file.name - os.environ["GEM5_RESOURCE_JSON"] = cls.file_path - @classmethod def tearDownClass(cls) -> None: os.remove(cls.file_path) - del os.environ["GEM5_RESOURCE_JSON"] def verify_json(self, json: Dict) -> None: """ @@ -167,32 +160,22 @@ class ResourceDownloaderTestSuite(unittest.TestCase): self.assertEquals("test-version", json[3]["id"]) def test_get_resources_json_at_path(self) -> None: - # Tests the gem5.resources.downloader._get_resources_json_at_path() - # function. + # Tests JSONClient.get_resources_json() - json = _get_resources_json_at_path(path=self.file_path) - self.verify_json(json=json) - - def test_get_resources_json(self) -> None: - # Tests the gem5.resources.downloader._get_resources_json() function. - - json = _get_resources_json() + client = JSONClient(path=self.file_path) + json = client.get_resources_json() self.verify_json(json=json) def test_get_resources_json_invalid_url(self) -> None: - # Tests the gem5.resources.downloader._get_resources_json() function in - # case where an invalid url is passed as the URL/PATH of the - # resources.json file. + # Tests the JSONClient.get_resources_json() function in case where an + # invalid url is passed as the URL/PATH of the resources JSON file. path = "NotAURLorFilePath" - os.environ["GEM5_RESOURCE_JSON"] = path with self.assertRaises(Exception) as context: - _get_resources_json() + client = JSONClient(path=path) + json = client.get_resources_json() self.assertTrue( f"Resources location '{path}' is not a valid path or URL." in str(context.exception) ) - - # Set back to the old path - os.environ["GEM5_RESOURCE_JSON"] = self.file_path diff --git a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py index 791d96c1f1..b1eda4e6ed 100644 --- a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py @@ -30,12 +30,7 @@ import io import contextlib from pathlib import Path -from gem5.resources.resource import * - -from gem5.resources.looppoint import ( - LooppointCsvLoader, - LooppointJsonLoader, -) +from gem5.resources.resource import obtain_resource, BinaryResource from gem5.isas import ISA @@ -61,24 +56,6 @@ mock_config_json = { new=ClientWrapper(mock_config_json), ) class TestObtainResourcesCheck(unittest.TestCase): - @classmethod - def setUpClass(cls): - """Prior to running the suite we set the resource directory to - "ref/resource-specialization.json" - """ - os.environ["GEM5_RESOURCE_JSON"] = os.path.join( - os.path.realpath(os.path.dirname(__file__)), - "refs", - "obtain-resource.json", - ) - - @classmethod - def tearDownClass(cls) -> None: - """After running the suite we unset the gem5-resource JSON file, as to - not interfere with others tests. - """ - del os.environ["GEM5_RESOURCE_JSON"] - def get_resource_dir(cls) -> str: """To ensure the resources are cached to the same directory as all other tests, this function returns the location of the testing @@ -99,26 +76,27 @@ class TestObtainResourcesCheck(unittest.TestCase): resource = obtain_resource( resource_id="test-binary-resource", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) - self.assertEquals("2.5.0", resource.get_resource_version()) + self.assertEquals("1.7.0", resource.get_resource_version()) self.assertIsInstance(resource, BinaryResource) - # self.assertIn(gem5Version, resource.get_gem5_versions()) - self.assertEquals("test description", resource.get_description()) + self.assertEquals( + "test description v1.7.0", resource.get_description() + ) self.assertEquals("src/test-source", resource.get_source()) self.assertEquals(ISA.ARM, resource.get_architecture()) def test_obtain_resources_with_version_compatible(self): - gem5Version = core.gem5Version resource = obtain_resource( resource_id="test-binary-resource", resource_directory=self.get_resource_dir(), - resource_version="1.7.0", + resource_version="1.5.0", + gem5_version="develop", ) - self.assertEquals("1.7.0", resource.get_resource_version()) + self.assertEquals("1.5.0", resource.get_resource_version()) self.assertIsInstance(resource, BinaryResource) - # self.assertIn(gem5Version, resource.get_gem5_versions()) self.assertEquals( - "test description v1.7.0", resource.get_description() + "test description for 1.5.0", resource.get_description() ) self.assertEquals("src/test-source", resource.get_source()) self.assertEquals(ISA.ARM, resource.get_architecture()) @@ -143,6 +121,7 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_id="test-binary-resource", resource_directory=self.get_resource_dir(), resource_version="1.5.0", + gem5_version="develop", ) self.assertEquals("1.5.0", resource.get_resource_version()) self.assertIsInstance(resource, BinaryResource) @@ -157,6 +136,7 @@ class TestObtainResourcesCheck(unittest.TestCase): obtain_resource( resource_id="invalid-id", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertTrue( "Resource with ID 'invalid-id' not found." @@ -169,6 +149,7 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_id="invalid-id", resource_directory=self.get_resource_dir(), resource_version="1.7.0", + gem5_version="develop", ) self.assertTrue( "Resource with ID 'invalid-id' not found." @@ -182,8 +163,6 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_directory=self.get_resource_dir(), resource_version="3.0.0", ) - print("context.exception: ", context.exception) - print(str(context.exception)) self.assertTrue( f"Resource test-binary-resource with version '3.0.0'" " not found.\nResource versions can be found at: " diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py b/tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py deleted file mode 100644 index 8f6674ff0d..0000000000 --- a/tests/pyunit/stdlib/resources/pyunit_resource_download_checks.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (c) 2023 The Regents of the University of California -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import unittest -import tempfile -import os -from typing import Dict - -from gem5.resources.downloader import ( - get_resources_json_obj, -) - - -class ResourceDownloadTestSuite(unittest.TestCase): - """Test cases for gem5.resources.downloader""" - - @classmethod - def setUpClass(cls) -> str: - pass - - def get_resource_json_by_id(self) -> None: - """Get a resource by its id""" - resources = get_resources_json_obj("test-version") - self.assertEqual(resources["id"], "test-version") - self.assertEqual(resources["resource_version"], "2.0.0") - - def get_resource_json_invalid_id(self) -> None: - """Should throw an exception when trying to get a resource that doesn't exist""" - with self.assertRaises(Exception) as context: - get_resources_json_obj("this-resource-doesnt-exist") - self.assertTrue( - f"Error: Resource with name 'this-resource-doesnt-exist' does not exist" - in str(context.exception) - ) - - def get_resource_json_by_id_and_version(self) -> None: - """Get a resource by its id and version""" - resources = get_resources_json_obj("test-version", "1.0.0") - self.assertEqual(resources["id"], "test-version") - self.assertEqual(resources["resource_version"], "1.0.0") - - def get_resource_json_by_id_and_invalid_version(self) -> None: - """Get a resource by its id and an invalid version (does not exist)""" - with self.assertRaises(Exception) as context: - get_resources_json_obj("test-version", "3.0.0") - self.assertTrue( - f"Specified Version 3.0.0 does not exist for the resource 'test-version'." - in str(context.exception) - ) diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py index 5c22a7341e..f2088db8ef 100644 --- a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py +++ b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py @@ -62,24 +62,6 @@ class ResourceSpecializationSuite(unittest.TestCase): function. """ - @classmethod - def setUpClass(cls): - """Prior to running the suite we set the resource directory to - "ref/resource-specialization.json" - """ - os.environ["GEM5_RESOURCE_JSON"] = os.path.join( - os.path.realpath(os.path.dirname(__file__)), - "refs", - "resource-specialization.json", - ) - - @classmethod - def tearDownClass(cls) -> None: - """After running the suite we unset the gem5-resource JSON file, as to - not interfere with others tests. - """ - del os.environ["GEM5_RESOURCE_JSON"] - def get_resource_dir(cls) -> str: """To ensure the resources are cached to the same directory as all other tests, this function returns the location of the testing @@ -99,6 +81,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="binary-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, BinaryResource) @@ -114,6 +97,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="kernel-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, KernelResource) @@ -129,6 +113,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="bootloader-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, BootloaderResource) @@ -144,6 +129,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="disk-image-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, DiskImageResource) @@ -159,6 +145,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="checkpoint-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, CheckpointResource) @@ -173,6 +160,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="git-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, GitResource) @@ -185,6 +173,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="simpoint-directory-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, SimpointDirectoryResource) @@ -219,6 +208,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="simpoint-example", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, SimpointResource) @@ -240,6 +230,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource_id="file-example", resource_directory=self.get_resource_dir(), resource_version="1.0.0", + gem5_version="develop", ) self.assertIsInstance(resource, FileResource) @@ -268,6 +259,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource = obtain_resource( resource_id="looppoint-pinpoint-csv-resource", resource_directory=self.get_resource_dir(), + gem5_version="develop", ) self.assertIsInstance(resource, LooppointCsvResource) @@ -289,6 +281,7 @@ class ResourceSpecializationSuite(unittest.TestCase): resource_id="looppoint-json-restore-resource-region-1", resource_directory=self.get_resource_dir(), resource_version="1.0.0", + gem5_version="develop", ) self.assertIsInstance(resource, LooppointJsonResource) diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index b898faeb79..b59e09d4fe 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -40,17 +40,7 @@ from gem5.resources.client_api.client_wrapper import ClientWrapper from unittest.mock import patch from pathlib import Path -mock_config_json1 = { - "sources": { - "baba": { - "url": Path(__file__).parent - / "refs/workload-checks-custom-workload.json", - "isMongo": False, - } - }, -} - -mock_config_json2 = { +mock_config_json = { "sources": { "baba": { "url": Path(__file__).parent / "refs/workload-checks.json", @@ -68,29 +58,19 @@ class CustomWorkloadTestSuite(unittest.TestCase): @classmethod @patch( "gem5.resources.client.clientwrapper", - new=ClientWrapper(mock_config_json1), + new=ClientWrapper(mock_config_json), ) def setUpClass(cls) -> None: - os.environ["GEM5_RESOURCE_JSON"] = os.path.join( - os.path.realpath(os.path.dirname(__file__)), - "refs", - "workload-checks-custom-workload.json", - ) - cls.custom_workload = CustomWorkload( function="set_se_binary_workload", parameters={ - "binary": obtain_resource("x86-hello64-static"), + "binary": obtain_resource( + "x86-hello64-static", gem5_version="develop" + ), "arguments": ["hello", 6], }, ) - @classmethod - def tearDownClass(cls): - # Unset the environment variable so this test does not interfere with - # others. - os.environ["GEM5_RESOURCE_JSON"] - def test_get_function_str(self) -> None: # Tests `CustomResource.get_function_str` @@ -140,7 +120,8 @@ class CustomWorkloadTestSuite(unittest.TestCase): "test", self.custom_workload.get_parameters()["binary"] ) - # We set the overridden parameter back to it's old valu self.custom_workload.set_parameter("binary", old_value) + # We set the overridden parameter back to it's old value + self.custom_workload.set_parameter("binary", old_value) class WorkloadTestSuite(unittest.TestCase): @@ -151,21 +132,10 @@ class WorkloadTestSuite(unittest.TestCase): @classmethod @patch( "gem5.resources.client.clientwrapper", - ClientWrapper(mock_config_json2), + ClientWrapper(mock_config_json), ) def setUpClass(cls): - os.environ["GEM5_RESOURCE_JSON"] = os.path.join( - os.path.realpath(os.path.dirname(__file__)), - "refs", - "workload-checks.json", - ) - cls.workload = Workload("simple-boot") - - @classmethod - def tearDownClass(cls): - # Unset the environment variable so this test does not interfere with - # others. - os.environ["GEM5_RESOURCE_JSON"] + cls.workload = Workload("simple-boot", gem5_version="develop") def test_get_function_str(self) -> None: # Tests `Resource.get_function_str` diff --git a/tests/pyunit/stdlib/resources/refs/mongo-mock.json b/tests/pyunit/stdlib/resources/refs/mongo-mock.json index b6376cc5e4..e2fb058ff7 100644 --- a/tests/pyunit/stdlib/resources/refs/mongo-mock.json +++ b/tests/pyunit/stdlib/resources/refs/mongo-mock.json @@ -22,7 +22,7 @@ "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", "resource_version": "1.0.0", "gem5_versions": [ - "23.0" + "develop" ], "example_usage": "get_resource(resource_name=\"x86-ubuntu-18.04-img\")" }, @@ -49,7 +49,7 @@ "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", "resource_version": "1.1.0", "gem5_versions": [ - "23.0" + "develop" ], "example_usage": "get_resource(resource_name=\"x86-ubuntu-18.04-img\")" } diff --git a/tests/pyunit/stdlib/resources/refs/obtain-resource.json b/tests/pyunit/stdlib/resources/refs/obtain-resource.json index fac95e106a..9125bf4ae6 100644 --- a/tests/pyunit/stdlib/resources/refs/obtain-resource.json +++ b/tests/pyunit/stdlib/resources/refs/obtain-resource.json @@ -24,7 +24,7 @@ "source": "src/test-source", "resource_version": "2.0.0", "gem5_versions": [ - "develop" + "23.0" ] }, { @@ -38,7 +38,8 @@ "source": "src/test-source", "resource_version": "1.7.0", "gem5_versions": [ - "develop" + "develop", + "develop-2" ] }, { @@ -52,8 +53,7 @@ "source": "src/test-source", "resource_version": "1.5.0", "gem5_versions": [ - "21.1", - "22.1" + "develop" ] } ] diff --git a/tests/pyunit/stdlib/resources/refs/resource-specialization.json b/tests/pyunit/stdlib/resources/refs/resource-specialization.json index 1129f1bd05..414bf73b11 100644 --- a/tests/pyunit/stdlib/resources/refs/resource-specialization.json +++ b/tests/pyunit/stdlib/resources/refs/resource-specialization.json @@ -10,6 +10,7 @@ "source": "src/linux-kernel", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -25,6 +26,7 @@ "root_partition": "1", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -39,6 +41,7 @@ "source": "src/simple", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -51,6 +54,7 @@ "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -66,6 +70,7 @@ "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -75,10 +80,11 @@ "description": null, "is_zipped": false, "is_tar_archive": true, - "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -87,11 +93,12 @@ "id": "file-example", "description": null, "is_zipped": false, - "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "md5sum": "2efd144c11829ab18d54eae6371e120a", "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", "source": null, "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -106,6 +113,7 @@ "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -125,6 +133,7 @@ "workload_name": "Example Workload", "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -148,6 +157,7 @@ ], "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -161,6 +171,7 @@ "source": null, "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] }, @@ -170,11 +181,12 @@ "description": "A looppoint json file resource.", "is_zipped": false, "region_id": "1", - "md5sum": "a71ed64908b082ea619b26b940a643c1", + "md5sum": "efb85ebdf90c5cee655bf2e05ae7692a", "url": "http://dist.gem5.org/dist/develop/looppoints/x86-matrix-multiply-omp-100-8-looppoint-json-20230128", "source": null, "resource_version": "1.0.0", "gem5_versions": [ + "develop", "23.0" ] } diff --git a/tests/pyunit/stdlib/resources/refs/resources.json b/tests/pyunit/stdlib/resources/refs/resources.json index 812caeff43..56930f37d5 100644 --- a/tests/pyunit/stdlib/resources/refs/resources.json +++ b/tests/pyunit/stdlib/resources/refs/resources.json @@ -21,7 +21,7 @@ "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", "resource_version": "1.0.0", "gem5_versions": [ - "23.0" + "develop" ], "example_usage": "get_resource(resource_name=\"rv64mi-p-sbreak\")" }, @@ -48,7 +48,7 @@ "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", "resource_version": "1.1.0", "gem5_versions": [ - "23.0" + "develop" ], "example_usage": "get_resource(resource_name=\"rv64mi-p-sbreak\")" }, @@ -71,7 +71,7 @@ "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/asmtest", "resource_version": "2.0.0", "gem5_versions": [ - "23.1" + "999.1" ], "example_usage": "get_resource(resource_name=\"rv64mi-p-sbreak\")" }, @@ -94,7 +94,7 @@ "source_url": "", "resource_version": "1.0.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -122,7 +122,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -150,7 +150,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -178,7 +178,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -206,7 +206,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -234,7 +234,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -262,7 +262,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -290,7 +290,7 @@ "source_url": "", "resource_version": "0.2.0", "gem5_versions": [ - "23.0" + "develop" ], "workload_name": "x86-print-this-15000-with-simpoints", "example_usage": "get_resource(resource_name=\"x86-print-this-1500-simpoints\")", @@ -322,7 +322,7 @@ "source_url": "https://github.com/gem5/gem5-resources/tree/develop/src/x86-ubuntu", "resource_version": "2.0.0", "gem5_versions": [ - "23.0" + "develop" ], "example_usage": "get_resource(resource_name=\"x86-ubuntu-18.04-img\")" } diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json b/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json deleted file mode 100644 index a7e9c9d84f..0000000000 --- a/tests/pyunit/stdlib/resources/refs/workload-checks-custom-workload.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "category": "binary", - "id": "x86-hello64-static", - "description": "A 'Hello World!' binary.", - "architecture": "X86", - "is_zipped": false, - "md5sum": "dbf120338b37153e3334603970cebd8c", - "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/x86/linux/hello64-static", - "source": "src/simple", - "resource_version": "1.0.0", - "gem5_versions": [ - "23.0" - ] - } -] diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks.json b/tests/pyunit/stdlib/resources/refs/workload-checks.json index d41001d26c..dcb8577619 100644 --- a/tests/pyunit/stdlib/resources/refs/workload-checks.json +++ b/tests/pyunit/stdlib/resources/refs/workload-checks.json @@ -10,7 +10,7 @@ "source": "src/linux-kernel", "resource_version": "1.0.0", "gem5_versions": [ - "23.0" + "develop" ] }, { @@ -25,7 +25,7 @@ "root_partition": "1", "resource_version": "1.0.0", "gem5_versions": [ - "23.0" + "develop" ] }, { @@ -42,7 +42,21 @@ }, "resource_version": "1.0.0", "gem5_versions": [ - "23.0" + "develop" + ] + }, + { + "category": "binary", + "id": "x86-hello64-static", + "description": "A 'Hello World!' binary.", + "architecture": "X86", + "is_zipped": false, + "md5sum": "dbf120338b37153e3334603970cebd8c", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/x86/linux/hello64-static", + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": [ + "develop" ] } ] From d5bdf6cf79a7710331ba340cfd26cb63b2ee37d8 Mon Sep 17 00:00:00 2001 From: Yan Lee Date: Tue, 23 May 2023 01:07:45 -0700 Subject: [PATCH 028/693] mem: port: add TracingExtension for debug purpose TracingExtension contains a stack recording the port names passed through of the Packet. The target receiving the Packet can dump out the whole path of this Packet for the debug purpose. This mechanism can be enabled with the debug flag PortTrace. Change-Id: Ic11e708b35fdddc4f4b786d91b35fd4def08948c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71538 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro Reviewed-by: Yu-hsin Wang --- src/mem/SConscript | 1 + src/mem/port.cc | 24 +++++++++++++++ src/mem/port.hh | 73 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/mem/SConscript b/src/mem/SConscript index 351f24e907..6e017e0397 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -151,6 +151,7 @@ DebugFlag('MemCtrl') DebugFlag('MMU') DebugFlag('MemoryAccess') DebugFlag('PacketQueue') +DebugFlag("PortTrace") DebugFlag('ResponsePort') DebugFlag('StackDist') DebugFlag("DRAMSim2") diff --git a/src/mem/port.cc b/src/mem/port.cc index 2a253b91a3..2f754c89df 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -45,6 +45,7 @@ #include "mem/port.hh" #include "base/trace.hh" +#include "debug/PortTrace.hh" #include "debug/ResponsePort.hh" #include "sim/sim_object.hh" @@ -186,6 +187,29 @@ RequestPort::printAddr(Addr a) sendFunctional(&pkt); } +void +RequestPort::addTrace(PacketPtr pkt) const +{ + if (!gem5::debug::PortTrace || !pkt) + return; + auto ext = pkt->getExtension(); + if (!ext) { + ext = std::make_shared(); + pkt->setExtension(ext); + } + ext->add(name(), _responsePort->name()); +} + +void +RequestPort::removeTrace(PacketPtr pkt) const +{ + if (!gem5::debug::PortTrace || !pkt) + return; + auto ext = pkt->getExtension(); + panic_if(!ext, "There is no TracingExtension in the packet."); + ext->remove(); +} + /** * Response port */ diff --git a/src/mem/port.hh b/src/mem/port.hh index a3acffc427..2555706444 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -46,6 +46,10 @@ #ifndef __MEM_PORT_HH__ #define __MEM_PORT_HH__ +#include +#include +#include + #include "base/addr_range.hh" #include "mem/packet.hh" #include "mem/protocol/atomic.hh" @@ -64,6 +68,43 @@ class SlavePort; class ResponsePort; +/** + * TracingExtension is an Extension of the Packet for recording the trace + * of the Packet. The stack in the TracingExtension holds the name of the + * ports that the Packet has passed through. + */ +class TracingExtension : public gem5::Extension +{ + public: + TracingExtension() = default; + TracingExtension(const std::stack& q) { trace_ = q; } + + std::unique_ptr clone() const override + { + return std::make_unique(trace_); + } + + void + add(std::string request_port, std::string response_port) + { + trace_.push(request_port); + trace_.push(response_port); + } + + void + remove() + { + trace_.pop(); // Remove the response port name. + trace_.pop(); // Remove the request port name. + } + + bool empty() { return trace_.empty(); } + std::stack& getTrace() { return trace_; } + + private: + std::stack trace_; +}; + /** * A RequestPort is a specialisation of a Port, which * implements the default protocol for the three different level of @@ -266,6 +307,10 @@ class RequestPort: public Port, public AtomicRequestProtocol, { panic("%s was not expecting a snoop retry.\n", name()); } + + private: + void addTrace(PacketPtr pkt) const; + void removeTrace(PacketPtr pkt) const; }; class [[deprecated]] MasterPort : public RequestPort @@ -393,7 +438,11 @@ class ResponsePort : public Port, public AtomicResponseProtocol, sendTimingResp(PacketPtr pkt) { try { - return TimingResponseProtocol::sendResp(_requestPort, pkt); + _requestPort->removeTrace(pkt); + bool succ = TimingResponseProtocol::sendResp(_requestPort, pkt); + if (!succ) + _requestPort->addTrace(pkt); + return succ; } catch (UnboundPortException) { reportUnbound(); } @@ -487,7 +536,10 @@ inline Tick RequestPort::sendAtomic(PacketPtr pkt) { try { - return AtomicRequestProtocol::send(_responsePort, pkt); + addTrace(pkt); + Tick tick = AtomicRequestProtocol::send(_responsePort, pkt); + removeTrace(pkt); + return tick; } catch (UnboundPortException) { reportUnbound(); } @@ -497,8 +549,11 @@ inline Tick RequestPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) { try { - return AtomicRequestProtocol::sendBackdoor(_responsePort, - pkt, backdoor); + addTrace(pkt); + Tick tick = AtomicRequestProtocol::sendBackdoor(_responsePort, + pkt, backdoor); + removeTrace(pkt); + return tick; } catch (UnboundPortException) { reportUnbound(); } @@ -508,7 +563,9 @@ inline void RequestPort::sendFunctional(PacketPtr pkt) const { try { - return FunctionalRequestProtocol::send(_responsePort, pkt); + addTrace(pkt); + FunctionalRequestProtocol::send(_responsePort, pkt); + removeTrace(pkt); } catch (UnboundPortException) { reportUnbound(); } @@ -530,7 +587,11 @@ inline bool RequestPort::sendTimingReq(PacketPtr pkt) { try { - return TimingRequestProtocol::sendReq(_responsePort, pkt); + addTrace(pkt); + bool succ = TimingRequestProtocol::sendReq(_responsePort, pkt); + if (!succ) + removeTrace(pkt); + return succ; } catch (UnboundPortException) { reportUnbound(); } From 3c0c3fb623c9b590829715aa45367564cb797599 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Mon, 26 Jun 2023 17:17:18 -0700 Subject: [PATCH 029/693] resources: Catch ConnectionResourceError in downloading resources This handles an error we see within GitHub Actions that occassionally occurs when downloading resources. We retry in the same way we do when handling HTTPErrors. Change-Id: I4dce5d607ccc41ad53b51e39082c486e644d815c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71858 Tested-by: kokoro Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power --- src/python/gem5/resources/downloader.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index bb5ca84cc0..d606f34717 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -139,6 +139,22 @@ def _download(url: str, download_to: str, max_attempts: int = 6) -> None: time.sleep((2**attempt) + random.uniform(0, 1)) else: raise e + except ConnectionResetError as e: + # This catches the ConnectionResetError we see occassionally see + # when accessing resources on GitHub Actions. It retries using a + # Truncated Exponential backoff algorithm, truncating after + # "max_attempts". If any other is retrieved we raise the error. + if e.errno == 104: + attempt += 1 + if attempt >= max_attempts: + raise Exception( + f"After {attempt} attempts, the resource json could " + "not be retrieved. OS Error Code retrieved: " + f"{e.errno}" + ) + time.sleep((2**attempt) + random.uniform(0, 1)) + else: + raise e except ValueError as e: raise Exception( "Environment variable GEM5_USE_PROXY is set to " From 6d776eb46848d2e91cbedf7af18c7fdd9f785393 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Tue, 27 Jun 2023 10:24:25 -0700 Subject: [PATCH 030/693] resources: Output error message in downloader.py This allows for the actual error message to be output in addition to the output gem5 has on ValueErrors and ImportErrors. Change-Id: Ic52f5646aa41dbf7c217ab27d142c0a18fa24c55 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71859 Tested-by: kokoro Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power --- src/python/gem5/resources/downloader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index d606f34717..1aeb487e61 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -157,12 +157,14 @@ def _download(url: str, download_to: str, max_attempts: int = 6) -> None: raise e except ValueError as e: raise Exception( + f"ValueError: {e}\n" "Environment variable GEM5_USE_PROXY is set to " f"'{use_proxy}'. The expected form is " ":'." ) except ImportError as e: raise Exception( + f"ImportError: {e}\n" "An import error has occurred. This is likely due " "the Python SOCKS client module not being " "installed. It can be installed with " From 051801a7bfa772698d2e1587ebff78de93ff4b7d Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Tue, 27 Jun 2023 10:27:35 -0700 Subject: [PATCH 031/693] misc: Add workflow files to develop This copies our .github folder from stable into the develop branch, which allows the GitHub Actions workflows to run on both branches Change-Id: I864939f86f0fbd6d73676f137df2670d3eac1d1a Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71860 Reviewed-by: Bobby Bruce Tested-by: kokoro Maintainer: Bobby Bruce --- .github/workflows/ci-tests.yaml | 80 +++ .github/workflows/compiler-tests.yaml | 52 ++ .github/workflows/daily-tests.yaml | 878 ++++++++++++++++++++++++++ .github/workflows/weekly-tests.yaml | 176 ++++++ 4 files changed, 1186 insertions(+) create mode 100644 .github/workflows/ci-tests.yaml create mode 100644 .github/workflows/compiler-tests.yaml create mode 100644 .github/workflows/daily-tests.yaml create mode 100644 .github/workflows/weekly-tests.yaml diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml new file mode 100644 index 0000000000..61ba4b5b53 --- /dev/null +++ b/.github/workflows/ci-tests.yaml @@ -0,0 +1,80 @@ +# This workflow runs after a pull-request has been approved by a reviewer. + +name: CI Tests + +on: + pull_request: + types: [opened, edited, synchronize, ready_for_review] + + +jobs: + pre-commit: + # runs on github hosted runner + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.0 + + build-gem5: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: pre-commit # only runs if pre-commit passes + outputs: + artifactname: ${{ steps.name.outputs.test }} + steps: + - uses: actions/checkout@v3 + - id: name + run: echo "test=$(date +"%Y-%m-%d_%H.%M.%S")-artifact" >> $GITHUB_OUTPUT + + - name: Build gem5 + run: | + scons build/ALL/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.name.outputs.test }} + path: build/ALL/gem5.opt + - run: echo "This job's status is ${{ job.status }}." + + unittests-all-opt: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: pre-commit # only runs if pre-commit passes + timeout-minutes: 60 + steps: + - uses: actions/checkout@v3 + - name: CI Unittests + working-directory: ${{ github.workspace }} + run: scons build/ALL/unittests.opt -j $(nproc) + - run: echo "This job's status is ${{ job.status }}." + + testlib-quick: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, build-gem5] + timeout-minutes: 360 # 6 hours + steps: + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.artifactname}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: The TestLib CI Tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml new file mode 100644 index 0000000000..52569e2e01 --- /dev/null +++ b/.github/workflows/compiler-tests.yaml @@ -0,0 +1,52 @@ +# This workflow runs all of the compiler tests + +name: Compiler Tests +run-name: ${{ github.actor }} is running compiler tests + + +on: + # Runs every Friday from 7AM UTC + schedule: + - cron: '00 7 * * 5' + # Allows us to manually start workflow for testing + workflow_dispatch: + +jobs: + # replication of compiler-tests.sh + all-compilers: + strategy: + matrix: + image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, gcc-version-7, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, clang-version-6.0, ubuntu-18.04_all-dependencies, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] + opts: [.opt, .fast] + runs-on: [self-hosted, linux, x64, run] + timeout-minutes: 2880 # 48 hours + container: gcr.io/gem5-test/${{ matrix.image }}:latest + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Compile build/ALL/gem5${{ matrix.opts }} with ${{ matrix.image }} + run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/ALL/gem5${{ matrix.opts }} + timeout-minutes: 600 # 10 hours + + # Tests the two latest gcc and clang supported compilers against all gem5 compilations. + latest-compilers-all-gem5-builds: + strategy: + matrix: + gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base] + image: [gcc-version-12, clang-version-14] + opts: [.opt] + runs-on: [self-hosted, linux, x64, run] + timeout-minutes: 2880 # 48 hours + container: gcr.io/gem5-test/${{ matrix.image }}:latest + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Compile build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} with ${{ matrix.image }} + run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} + timeout-minutes: 600 # 10 hours diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml new file mode 100644 index 0000000000..5fab058b79 --- /dev/null +++ b/.github/workflows/daily-tests.yaml @@ -0,0 +1,878 @@ +# This workflow runs all of the long tests within main.py, extra tests in nightly.sh, and unittests + +name: Daily Tests + +on: + # Runs every day from 7AM UTC + schedule: + - cron: '0 7 * * *' + +jobs: +# building all necessary versions of gem5 + build-gem5: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ALL/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ALL/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-ALL_CHI: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL_CHI" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ALL_CHI/gem5.opt --default=ALL PROTOCOL=CHI -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ALL_CHI/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-ARM: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ARM" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ARM/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ARM/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-ALL_MSI: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL_MSI" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ALL_MSI/gem5.opt --default=ALL PROTOCOL=MSI -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ALL_MSI/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-ALL_MESI_Two_Level: + runs-on: [self-hosted, linux, x64, build,] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL_MESI_Two_Level" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ALL_MESI_Two_Level/gem5.opt --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ALL_MESI_Two_Level/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-NULL: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-NULL" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/NULL/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/NULL/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-NULL_MI_example: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-NULL_MI_example" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/NULL_MI_example/gem5.opt --default=NULL PROTOCOL=MI_example -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/NULL_MI_example/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-RISCV: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-RISCV" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/RISCV/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/RISCV/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + build-gem5-VEGA_X86: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-VEGA_X86" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/VEGA_X86/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/VEGA_X86/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + + # This runs the unit tests for the build/ALL/unittests.debug build. + unittests-all-debug: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: ALL/unittests.debug UnitTests + run: | + ls + scons build/ALL/unittests.debug -j $(nproc) + + # This runs the unit tests for the build/ALL/unittests.fast build. + unittests-all-fast: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: ALL/unittests.fast UnitTests + run: | + ls + scons build/ALL/unittests.fast -j $(nproc) + +# start running all of the long tests + testlib-long-arm-boot-tests: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ALL_CHI] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_CHI.outputs.build-name}} + path: build/ALL_CHI + - run: chmod u+x build/ALL_CHI/gem5.opt + - name: long arm-boot-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/arm-boot-tests --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-fs: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ARM] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ARM.outputs.build-name}} + path: build/ARM + - run: chmod u+x build/ARM/gem5.opt + - name: long fs + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/fs --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-gem5_library_example_tests: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt + - name: long gem5_library_example_tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/gem5_library_example_tests --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-gpu: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-VEGA_X86] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-VEGA_X86.outputs.build-name}} + path: build/VEGA_X86 + - run: chmod u+x build/VEGA_X86/gem5.opt + - name: long gpu + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/gpu --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-insttest_se: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: long insttest_se + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/insttest_se --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + +# kvm tests don't work on github actions + # testlib-long-kvm-fork-tests: + # runs-on: [self-hosted, linux, x64, run] + # container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + # needs: build-gem5 + # timeout-minutes: 1440 # 24 hours + # steps: + # - uses: actions/checkout@v3 + # with: + # # Scheduled workflows run on the default branch by default. We + # # therefore need to explicitly checkout the develop branch. + # ref: develop + # - uses: actions/download-artifact@v3 + # with: + # name: ${{ env.artifact-name }} + # path: build/ALL/gem5.opt + # - run: chmod u+x build/ALL/gem5.opt + # - name: long kvm-fork-tests + # working-directory: ${{ github.workspace }}/tests + # run: ./main.py run gem5/kvm-fork-tests --length=long --skip-build -vv -t $(nproc) + # - uses: actions/upload-artifact@v3 + # env: + # MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + # with: + # name: ${{ env.MY_STEP_VAR }} + # path: tests/testing-results + # retention-days: 7 + # - run: echo "This job's status is ${{ job.status }}." + + # testlib-long-kvm-switch-tests: + # runs-on: [self-hosted, linux, x64, run] + # container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + # needs: build-gem5 + # timeout-minutes: 1440 # 24 hours + # steps: + # - uses: actions/checkout@v3 + # with: + # # Scheduled workflows run on the default branch by default. We + # # therefore need to explicitly checkout the develop branch. + # ref: develop + # - uses: actions/download-artifact@v3 + # with: + # name: ${{ env.artifact-name }} + # path: build/ALL/gem5.opt + # - run: chmod u+x build/ALL/gem5.opt + # - name: long kvm-switch-tests + # working-directory: ${{ github.workspace }}/tests + # run: ./main.py run gem5/kvm-switch-tests --length=long --skip-build -vv -t $(nproc) + # - uses: actions/upload-artifact@v3 + # env: + # MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + # with: + # name: ${{ env.MY_STEP_VAR }} + # path: tests/testing-results + # retention-days: 7 + # - run: echo "This job's status is ${{ job.status }}." + + testlib-long-learning_gem5: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5-ALL_MSI + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_MSI.outputs.build-name}} + path: build/ALL_MSI + - run: chmod u+x build/ALL_MSI/gem5.opt + - name: long learning_gem5 + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/learning_gem5 --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-m5_threads: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: long m5_threads + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/m5threads_test_atomic --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-memory: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5-NULL + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-NULL.outputs.build-name}} + path: build/NULL + - run: chmod u+x build/NULL/gem5.opt + - name: long memory + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/memory --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-multi_isa: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5-ARM, build-gem5-VEGA_X86, build-gem5-RISCV] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ARM.outputs.build-name}} + path: build/ARM + - run: chmod u+x build/ARM/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-VEGA_X86.outputs.build-name}} + path: build/VEGA_X86 + - run: chmod u+x build/VEGA_X86/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-RISCV.outputs.build-name}} + path: build/RISCV + - run: chmod u+x build/RISCV/gem5.opt + - name: long multi_isa + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/multi_isa --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-replacement-policies: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5-NULL_MI_example + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-NULL_MI_example.outputs.build-name}} + path: build/NULL_MI_example + - run: chmod u+x build/NULL_MI_example/gem5.opt + - name: long replacement-policies + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/replacement-policies --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-riscv-boot-tests: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: long riscv-boot-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/riscv-boot-tests --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-stdlib: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5-ARM, build-gem5-VEGA_X86, build-gem5-RISCV] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ARM.outputs.build-name}} + path: build/ARM + - run: chmod u+x build/ARM/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-VEGA_X86.outputs.build-name}} + path: build/VEGA_X86 + - run: chmod u+x build/VEGA_X86/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-RISCV.outputs.build-name}} + path: build/RISCV + - run: chmod u+x build/RISCV/gem5.opt + - name: long stdlib + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/stdlib --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-x86-boot-tests: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: long x86-boot-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/x86-boot-tests --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + # This runs the SST-gem5 integration compilation and tests it with + # ext/sst/sst/example.py. + sst-test: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/sst-env:latest + timeout-minutes: 180 + + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Build RISCV/libgem5_opt.so with SST + run: scons build/RISCV/libgem5_opt.so --without-tcmalloc --duplicate-sources --ignore-style -j $(nproc) + - name: Compile ext/sst + working-directory: ${{ github.workspace }}/ext/sst + run: make -j $(nproc) + - name: Run SST test + working-directory: ${{ github.workspace }}/ext/sst + run: sst --add-lib-path=./ sst/example.py + + # This runs the gem5 within SystemC ingration and runs a simple hello-world + # simulation with it. + systemc-test: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/systemc-env:latest + timeout-minutes: 180 + + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Build ARM/gem5.opt + run: scons build/ARM/gem5.opt --ignore-style --duplicate-sources -j$(nproc) + - name: Build ARM/libgem5_opt.so + run: scons build/ARM/libgem5_opt.so --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 -j$(nproc) --duplicate-sources + - name: Compile gem5 withing SystemC + working-directory: ${{ github.workspace }}/util/systemc/gem5_within_systemc + run: make + - name: Run gem5 within SystemC test + run: ./build/ARM/gem5.opt configs/deprecated/example/se.py -c tests/test-progs/hello/bin/arm/linux/hello + - name: Continue gem5 within SystemC test + run: LD_LIBRARY_PATH=build/ARM/:/opt/systemc/lib-linux64/ ./util/systemc/gem5_within_systemc/gem5.opt.sc m5out/config.ini + + # Runs the gem5 Nighyly GPU tests. + gpu-tests: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/gcn-gpu:latest + timeout-minutes: 720 # 12 hours + + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Compile build/GCN3_X86/gem5.opt + run: scons build/GCN3_X86/gem5.opt -j $(nproc) + - name: Get Square test-prog from gem5-resources + uses: wei/wget@v1 + with: + args: -q http://dist.gem5.org/dist/develop/test-progs/square/square # Removed -N bc it wasn't available within actions, should be okay bc workspace is clean every time: https://github.com/coder/sshcode/issues/102 + - name: Run Square test with GCN3_X86/gem5.opt (SE mode) + run: | + mkdir -p tests/testing-results + ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c square + - name: Get allSyncPrims-1kernel from gem5-resources + uses: wei/wget@v1 + with: + args: -q http://dist.gem5.org/dist/develop/test-progs/heterosync/gcn3/allSyncPrims-1kernel # Removed -N bc it wasn't available within actions, should be okay bc workspace is clean every time + - name: Run allSyncPrims-1kernel sleepMutex test with GCN3_X86/gem5.opt (SE mode) + run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="sleepMutex 10 16 4" + - name: Run allSyncPrims-1kernel lfTreeBarrUsing test with GCN3_X86/gem5.opt (SE mode) + run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="lfTreeBarrUniq 10 16 4" diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml new file mode 100644 index 0000000000..4c3f6b55bc --- /dev/null +++ b/.github/workflows/weekly-tests.yaml @@ -0,0 +1,176 @@ +# This workflow runs all of the very-long tests within main.py + +name: Weekly Tests + +on: + # Runs every Sunday from 7AM UTC + schedule: + - cron: '00 7 * * 6' + # Allows us to manually start workflow for testing + workflow_dispatch: + +jobs: + build-gem5: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ALL/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ALL/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + +# start running the very-long tests + testlib-very-long-gem5_library_example_tests: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5] + timeout-minutes: 4320 # 3 days + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: very-long gem5_library_example_tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/gem5_library_example_tests --length very-long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + + testlib-long-gem5-resources: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5] + timeout-minutes: 4320 # 3 days + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: very-long gem5-resources tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/gem5-resources --length very-long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-very-long-parsec-benchmarks: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 4320 # 3 days + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: very-long x86-boot-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/x86-boot-tests --length very-long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." + + testlib-very-long-x86-boot-tests: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 4320 # 3 days + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: very-long x86-boot-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/x86-boot-tests --length very-long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." From f54b3e6e75a4d8d84de20265171ae0cf420ce505 Mon Sep 17 00:00:00 2001 From: handsomeliu Date: Sun, 19 Mar 2023 13:54:21 +0800 Subject: [PATCH 032/693] mem: Support backdoor request in AddrMapper Change-Id: Iedbe8eb75006ce1b81e85910af848fb8c4cba646 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/69057 Tested-by: kokoro Reviewed-by: Yu-hsin Wang Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini --- src/mem/SConscript | 3 + src/mem/addr_mapper.cc | 36 +++++++- src/mem/addr_mapper.hh | 42 +++++++++ src/mem/backdoor_manager.cc | 148 +++++++++++++++++++++++++++++++ src/mem/backdoor_manager.hh | 89 +++++++++++++++++++ src/mem/backdoor_manager.test.cc | 140 +++++++++++++++++++++++++++++ 6 files changed, 457 insertions(+), 1 deletion(-) create mode 100644 src/mem/backdoor_manager.cc create mode 100644 src/mem/backdoor_manager.hh create mode 100644 src/mem/backdoor_manager.test.cc diff --git a/src/mem/SConscript b/src/mem/SConscript index 6e017e0397..e2a91146d0 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -71,6 +71,7 @@ SimObject('ThreadBridge.py', sim_objects=['ThreadBridge']) Source('abstract_mem.cc') Source('addr_mapper.cc') +Source('backdoor_manager.cc') Source('bridge.cc') Source('coherent_xbar.cc') Source('cfi_mem.cc') @@ -105,6 +106,8 @@ Source('serial_link.cc') Source('mem_delay.cc') Source('port_terminator.cc') +GTest('backdoor_manager.test', 'backdoor_manager.test.cc', + 'backdoor_manager.cc', with_tag('gem5_trace')) GTest('translation_gen.test', 'translation_gen.test.cc') Source('translating_port_proxy.cc') diff --git a/src/mem/addr_mapper.cc b/src/mem/addr_mapper.cc index 091b9d56aa..3c4054b6ef 100644 --- a/src/mem/addr_mapper.cc +++ b/src/mem/addr_mapper.cc @@ -84,6 +84,19 @@ AddrMapper::recvFunctionalSnoop(PacketPtr pkt) pkt->setAddr(orig_addr); } +void +AddrMapper::recvMemBackdoorReq(const MemBackdoorReq &req, + MemBackdoorPtr &backdoor) +{ + AddrRange remapped_req_range = AddrRange(remapAddr(req.range().start()), + remapAddr(req.range().end())); + MemBackdoorReq remapped_req(remapped_req_range, req.flags()); + memSidePort.sendMemBackdoorReq(remapped_req, backdoor); + if (backdoor != nullptr) { + backdoor = getRevertedBackdoor(backdoor, req.range()); + } +} + Tick AddrMapper::recvAtomic(PacketPtr pkt) { @@ -104,6 +117,19 @@ AddrMapper::recvAtomicSnoop(PacketPtr pkt) return ret_tick; } +Tick +AddrMapper::recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr& backdoor) +{ + Addr orig_addr = pkt->getAddr(); + pkt->setAddr(remapAddr(orig_addr)); + Tick ret_tick = memSidePort.sendAtomicBackdoor(pkt, backdoor); + pkt->setAddr(orig_addr); + if (backdoor != nullptr) { + backdoor = getRevertedBackdoor(backdoor, pkt->getAddrRange()); + } + return ret_tick; +} + bool AddrMapper::recvTimingReq(PacketPtr pkt) { @@ -206,7 +232,8 @@ AddrMapper::recvRangeChange() RangeAddrMapper::RangeAddrMapper(const RangeAddrMapperParams &p) : AddrMapper(p), originalRanges(p.original_ranges), - remappedRanges(p.remapped_ranges) + remappedRanges(p.remapped_ranges), + backdoorManager(originalRanges, remappedRanges) { if (originalRanges.size() != remappedRanges.size()) fatal("AddrMapper: original and shadowed range list must " @@ -232,6 +259,13 @@ RangeAddrMapper::remapAddr(Addr addr) const return addr; } +MemBackdoorPtr +RangeAddrMapper::getRevertedBackdoor(MemBackdoorPtr &backdoor, + const AddrRange &range) +{ + return backdoorManager.getRevertedBackdoor(backdoor, range); +} + AddrRangeList RangeAddrMapper::getAddrRanges() const { diff --git a/src/mem/addr_mapper.hh b/src/mem/addr_mapper.hh index 40a0bb033b..41709f38ab 100644 --- a/src/mem/addr_mapper.hh +++ b/src/mem/addr_mapper.hh @@ -38,6 +38,10 @@ #ifndef __MEM_ADDR_MAPPER_HH__ #define __MEM_ADDR_MAPPER_HH__ +#include + +#include "mem/backdoor_manager.hh" +#include "mem/packet.hh" #include "mem/port.hh" #include "params/AddrMapper.hh" #include "params/RangeAddrMapper.hh" @@ -77,6 +81,20 @@ class AddrMapper : public SimObject */ virtual Addr remapAddr(Addr addr) const = 0; + /** + * This function returns a backdoor that fulfills the initiator request, + * based on the target backdoor at the first parameter. + * Note that this function should return a backdoor in original address + * space, while the target backdoor is in remapped address space. Address + * reverting logic is probably required in this function. + * + * @param backdoor the backdoor obtained from target + * @param range the initiator request to be fulfilled + * @return a backdoor that fulfill the initiator request + */ + virtual MemBackdoorPtr getRevertedBackdoor(MemBackdoorPtr &backdoor, + const AddrRange &range) = 0; + class AddrMapperSenderState : public Packet::SenderState { @@ -168,12 +186,24 @@ class AddrMapper : public SimObject mapper.recvFunctional(pkt); } + void recvMemBackdoorReq(const MemBackdoorReq &req, + MemBackdoorPtr &backdoor) override + { + mapper.recvMemBackdoorReq(req, backdoor); + } + Tick recvAtomic(PacketPtr pkt) override { return mapper.recvAtomic(pkt); } + Tick + recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr& backdoor) override + { + return mapper.recvAtomicBackdoor(pkt, backdoor); + } + bool recvTimingReq(PacketPtr pkt) override { @@ -209,10 +239,15 @@ class AddrMapper : public SimObject void recvFunctionalSnoop(PacketPtr pkt); + void recvMemBackdoorReq(const MemBackdoorReq &req, + MemBackdoorPtr &backdoor); + Tick recvAtomic(PacketPtr pkt); Tick recvAtomicSnoop(PacketPtr pkt); + Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr& backdoor); + bool recvTimingReq(PacketPtr pkt); bool recvTimingResp(PacketPtr pkt); @@ -269,12 +304,19 @@ class RangeAddrMapper : public AddrMapper std::vector remappedRanges; Addr remapAddr(Addr addr) const override; + + MemBackdoorPtr getRevertedBackdoor(MemBackdoorPtr &backdoor, + const AddrRange &range) override; + void recvRangeChange() override { // TODO Check that our peer is actually expecting to receive accesses // in our output range(s). } + + private: + BackdoorManager backdoorManager; }; } // namespace gem5 diff --git a/src/mem/backdoor_manager.cc b/src/mem/backdoor_manager.cc new file mode 100644 index 0000000000..32d267c7a3 --- /dev/null +++ b/src/mem/backdoor_manager.cc @@ -0,0 +1,148 @@ +/* + * Copyright 2023 Google, Inc + * 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. + * + * 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. + */ + +#include + +#include "base/logging.hh" +#include "mem/backdoor_manager.hh" + +namespace gem5 +{ + +BackdoorManager::BackdoorManager(const std::vector &original_ranges, + const std::vector &remapped_ranges) + : originalRanges(original_ranges), + remappedRanges(remapped_ranges), + backdoorLists(original_ranges.size()) +{ +} + +MemBackdoorPtr +BackdoorManager::getRevertedBackdoor(MemBackdoorPtr backdoor, + const AddrRange &pkt_range) +{ + MemBackdoorPtr reverted_backdoor = findBackdoor(pkt_range); + if (reverted_backdoor == nullptr) { + reverted_backdoor = createRevertedBackdoor(backdoor, pkt_range); + } + return reverted_backdoor; +} + +MemBackdoorPtr +BackdoorManager::createRevertedBackdoor(MemBackdoorPtr backdoor, + const AddrRange &pkt_range) +{ + std::unique_ptr reverted_backdoor = std::make_unique(); + reverted_backdoor->flags(backdoor->flags()); + reverted_backdoor->ptr(backdoor->ptr()); + + Addr addr = pkt_range.start(); + for (int i = 0; i < originalRanges.size(); ++i) { + if (originalRanges[i].contains(addr)) { + /** Does not support interleaved range backdoors. */ + if (originalRanges[i].interleaved() || + remappedRanges[i].interleaved()) { + return nullptr; + } + + /** Shrink the backdoor to fit inside address range. */ + AddrRange shrinked_backdoor_range = + backdoor->range() & remappedRanges[i]; + + Addr backdoor_offset = + shrinked_backdoor_range.start() - remappedRanges[i].start(); + Addr backdoor_size = shrinked_backdoor_range.size(); + + /** Create the backdoor in original address view. */ + reverted_backdoor->range(AddrRange( + originalRanges[i].start() + backdoor_offset, + originalRanges[i].start() + backdoor_offset + backdoor_size)); + + /** + * The backdoor pointer also needs to be shrinked to point to the + * beginning of the range. + */ + Addr shrinked_offset = + shrinked_backdoor_range.start() - backdoor->range().start(); + reverted_backdoor->ptr(backdoor->ptr() + shrinked_offset); + + /** + * Bind the life cycle of the created backdoor with the target + * backdoor. Invalid and delete the created backdoor when the + * target backdoor is invalidated. + */ + MemBackdoorPtr reverted_backdoor_raw_ptr = reverted_backdoor.get(); + auto it = backdoorLists[i].insert(backdoorLists[i].end(), + std::move(reverted_backdoor)); + backdoor->addInvalidationCallback( + [this, i, it](const MemBackdoor &backdoor) { + (*it)->invalidate(); // *it is unique_ptr reverted_backdoor + this->backdoorLists[i].erase(it); + }); + return reverted_backdoor_raw_ptr; + } + } + // Backdoor is not valid. Return an empty one. + panic("Target does not provide valid backdoor."); +} + +MemBackdoorPtr +BackdoorManager::findBackdoor(const AddrRange &pkt_range) const +{ + Addr addr = pkt_range.start(); + Addr size = pkt_range.size(); + for (int i = 0; i < originalRanges.size(); ++i) { + /** The original ranges should be disjoint, so at most one range + * contains the begin address. + */ + if (originalRanges[i].contains(addr)) { + if (!originalRanges[i].contains(addr + size - 1)) { + /** The request range doesn't fit in any address range. */ + return nullptr; + } + for (const auto &backdoor : backdoorLists[i]) { + if (backdoor->range().contains(addr) && + backdoor->range().contains(addr + size - 1)) { + return backdoor.get(); + } + } + } + } + return nullptr; +} + +} // namespace gem5 diff --git a/src/mem/backdoor_manager.hh b/src/mem/backdoor_manager.hh new file mode 100644 index 0000000000..676987c370 --- /dev/null +++ b/src/mem/backdoor_manager.hh @@ -0,0 +1,89 @@ +/* + * Copyright 2023 Google, Inc + * 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. + * + * 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. + */ + +#ifndef __MEM_BACKDOOR_MANAGER_HH__ +#define __MEM_BACKDOOR_MANAGER_HH__ + +#include +#include +#include + +#include "mem/backdoor.hh" +#include "mem/packet.hh" + +namespace gem5 +{ + +/** + * This class manages the backdoors for RangeAddrMapper. It provides + * functionalities such as backdoor remapping, resource managing. + */ +class BackdoorManager +{ + public: + explicit BackdoorManager(const std::vector &original_ranges, + const std::vector &remapped_ranges); + + MemBackdoorPtr getRevertedBackdoor(MemBackdoorPtr backdoor, + const AddrRange &pkt_range); + + protected: + /** + * This function creates a new backdoor, whose address range contains the + * original request address. The address range is in initiator address + * view, and shouldn't exceed the original address range. + */ + MemBackdoorPtr createRevertedBackdoor(MemBackdoorPtr backdoor, + const AddrRange &pkt_range); + /** + * This function returns a created backdoor that fulfills the request, or + * returns nullptr if there's no. + */ + MemBackdoorPtr findBackdoor(const AddrRange &pkt_range) const; + + const std::vector &originalRanges; + const std::vector &remappedRanges; + + /** + * In this vector, each entry contains a list of backdoors that in the + * range in original address view. + */ + std::vector>> backdoorLists; +}; +} // namespace gem5 + +#endif //__MEM_BACKDOOR_MANAGER_HH__ diff --git a/src/mem/backdoor_manager.test.cc b/src/mem/backdoor_manager.test.cc new file mode 100644 index 0000000000..05abc50f2f --- /dev/null +++ b/src/mem/backdoor_manager.test.cc @@ -0,0 +1,140 @@ +/* + * Copyright 2023 Google, Inc. + * + * 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. + */ + +#include +#include + +#include "base/addr_range.hh" +#include "base/gtest/logging.hh" +#include "mem/backdoor.hh" +#include "mem/backdoor_manager.hh" + +namespace gem5 +{ +namespace backdoor_manager_test +{ +const std::vector kOriginalRange({AddrRange(0x0, 0x1000)}); +const std::vector kRemappedRange({AddrRange(0x1000, 0x2000)}); + +class BackdoorManagerTest : public BackdoorManager, public ::testing::Test +{ + public: + BackdoorManagerTest() : BackdoorManager(kOriginalRange, kRemappedRange) + { + } +}; + +TEST_F(BackdoorManagerTest, BasicRemapTest) +{ + /** + * The backdoor range is remappedRanges[0], and should be reverted into + * originalRanges[0]. + */ + AddrRange pkt_range = originalRanges[0]; + + uint8_t *ptr = nullptr; + MemBackdoor remapped_backdoor(remappedRanges[0], ptr, + MemBackdoor::Flags::Readable); + MemBackdoorPtr reverted_backdoor = + getRevertedBackdoor(&remapped_backdoor, pkt_range); + + EXPECT_EQ(reverted_backdoor->range(), originalRanges[0]); + EXPECT_EQ(reverted_backdoor->ptr(), ptr); + ASSERT_EQ(backdoorLists[0].size(), 1); + EXPECT_EQ(backdoorLists[0].begin()->get(), reverted_backdoor); + + /** + * After the target backdoor is invalidated, the new created backdoor should + * be freed and removed from the backdoor list. + */ + remapped_backdoor.invalidate(); + EXPECT_EQ(backdoorLists[0].size(), 0); +} + +TEST_F(BackdoorManagerTest, ShrinkTest) +{ + AddrRange pkt_range = originalRanges[0]; + + /** + * The backdoor range is larger than the address remapper's address range. + * Backdoor is expected to be shrinked. + */ + Addr diff = 0x1000; + AddrRange remapped_backdoor_range( + remappedRanges[0].start() - diff, // 0x0 + remappedRanges[0].end() + diff); // 0x3000 + + uint8_t *ptr = nullptr; + MemBackdoor remapped_backdoor(remapped_backdoor_range, ptr, + MemBackdoor::Flags::Readable); + MemBackdoorPtr reverted_backdoor = + getRevertedBackdoor(&remapped_backdoor, pkt_range); + + EXPECT_EQ(reverted_backdoor->range(), originalRanges[0]); + EXPECT_EQ(reverted_backdoor->ptr(), ptr + diff); + + remapped_backdoor.invalidate(); +} + +TEST_F(BackdoorManagerTest, ReuseTest) +{ + /** + * The two packets have different address range, but both contained in the + * original address range. + */ + Addr mid = originalRanges[0].start() + originalRanges[0].size() / 2; + AddrRange pkt_range_0 = AddrRange(originalRanges[0].start(), mid); + AddrRange pkt_range_1 = AddrRange(mid, originalRanges[0].end()); + + /** + * The address range of the backdoor covers the whole address range, so + * both packets can be fulfilled by this backdoor. + */ + uint8_t *ptr = nullptr; + MemBackdoor remapped_backdoor(remappedRanges[0], ptr, + MemBackdoor::Flags::Readable); + /** + * For the first packet, a new backdoor should be constructed. + */ + MemBackdoorPtr reverted_backdoor_0 = + getRevertedBackdoor(&remapped_backdoor, pkt_range_0); + EXPECT_EQ(backdoorLists[0].size(), 1); + + /** + * For the second packet, it should return the same backdoor as previous + * one, and no new backdoor should be constructed. + */ + MemBackdoorPtr reverted_backdoor_1 = + getRevertedBackdoor(&remapped_backdoor, pkt_range_1); + EXPECT_EQ(reverted_backdoor_0, reverted_backdoor_1); + EXPECT_EQ(backdoorLists[0].size(), 1); + + remapped_backdoor.invalidate(); +} + +} // namespace backdoor_manager_test +} // namespace gem5 From 079fc47dc202ffe7c77e1e94bb1d5e0ee38d1816 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 28 Jun 2023 14:49:48 -0500 Subject: [PATCH 033/693] dev-amdgpu: Perform frame writes atomically The PCI read/write functions are atomic functions in gem5, meaning they expect a response with a latency value on the same simulation Tick. For reads to a PCI device, the response must also include a data value read from the device. The AMDGPU device has a PCI BAR which mirrors the frame buffer memory. Currently reads are done atomically, but writes are sent to a DMA device without waiting for a write completion ACK. As a result, it is possible that writes can be queued in the DMA device long enough that another read for a queued address arrives. This happens very deterministically with the AtomicSimpleCPU and causes GPUFS to break with that CPU. This change makes writes to the frame BAR atomic the same as reads. This avoids that problem and as a result the AtomicSimpleCPU can now load the driver for GPUFS simulations. Change-Id: I9a8e8b172712c78b667ebcec81a0c5d0060234db Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71898 Maintainer: Matt Sinclair Tested-by: kokoro Reviewed-by: Matt Sinclair Maintainer: Matthew Poremba Reviewed-by: Matthew Poremba --- src/dev/amdgpu/amdgpu_device.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc index 3260d058b0..d1058f1606 100644 --- a/src/dev/amdgpu/amdgpu_device.cc +++ b/src/dev/amdgpu/amdgpu_device.cc @@ -349,6 +349,22 @@ AMDGPUDevice::writeFrame(PacketPtr pkt, Addr offset) } nbio.writeFrame(pkt, offset); + + /* + * Write the value to device memory. This must be done functionally + * because this method is called by the PCIDevice::write method which + * is a non-timing write. + */ + RequestPtr req = std::make_shared(offset, pkt->getSize(), 0, + vramRequestorId()); + PacketPtr writePkt = Packet::createWrite(req); + uint8_t *dataPtr = new uint8_t[pkt->getSize()]; + std::memcpy(dataPtr, pkt->getPtr(), + pkt->getSize() * sizeof(uint8_t)); + writePkt->dataDynamic(dataPtr); + + auto system = cp->shader()->gpuCmdProc.system(); + system->getDeviceMemory(writePkt)->access(writePkt); } void @@ -489,8 +505,6 @@ AMDGPUDevice::write(PacketPtr pkt) switch (barnum) { case FRAMEBUFFER_BAR: - gpuMemMgr->writeRequest(offset, pkt->getPtr(), - pkt->getSize(), 0, nullptr); writeFrame(pkt, offset); break; case DOORBELL_BAR: From 841e6fe978da1ca028ffb93d2401435ef86c8b64 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 28 Jun 2023 16:35:54 -0500 Subject: [PATCH 034/693] arch-vega: Add Vega D16 decodings and fix V_SWAP_B32 Vega adds multiple new D16 instructions which load a byte or short into the lower or upper 16 bits of a register for packed math. The decoder table has subDecode tables for FLAT instructions which represents 32 opcodes in each subDecode table. The subDecode table for opcodes 32-63 is missing so it is added here. The opcode for V_SWAP_B32 is also off by one- In the ISA manual this instruction is opcode 81, the instruction before is 79, and there is no opcode 80, so the decoder entry is swapped with the invalid decoding below it. Change-Id: I278fea574ea684ccc6302d5b4d0f5dd8813a88ad Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71899 Reviewed-by: Matt Sinclair Maintainer: Matt Sinclair Tested-by: kokoro --- src/arch/amdgpu/vega/decoder.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/amdgpu/vega/decoder.cc b/src/arch/amdgpu/vega/decoder.cc index fd3a803bb8..a86dd668ec 100644 --- a/src/arch/amdgpu/vega/decoder.cc +++ b/src/arch/amdgpu/vega/decoder.cc @@ -495,7 +495,7 @@ namespace VegaISA &Decoder::decode_invalid, &Decoder::decode_invalid, &Decoder::subDecode_OP_FLAT, - &Decoder::decode_invalid, + &Decoder::subDecode_OP_FLAT, &Decoder::subDecode_OP_FLAT, &Decoder::subDecode_OP_FLAT, &Decoder::decode_invalid, @@ -3140,8 +3140,8 @@ namespace VegaISA &Decoder::decode_OP_VOP1__V_CVT_NORM_I16_F16, &Decoder::decode_OP_VOP1__V_CVT_NORM_U16_F16, &Decoder::decode_OP_VOP1__V_SAT_PK_U8_I16, - &Decoder::decode_OP_VOP1__V_SWAP_B32, &Decoder::decode_invalid, + &Decoder::decode_OP_VOP1__V_SWAP_B32, &Decoder::decode_invalid, &Decoder::decode_invalid, &Decoder::decode_invalid, From ce715601ad3eb00eb26c4b1930f849fe7b52b7ee Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 29 Jun 2023 11:44:09 -0500 Subject: [PATCH 035/693] configs: Add GPUFS --root-partition option Different GPUFS disk images have different root partitions that Linux needs to boot from. In particular, Ubuntu's new installer has a GRUB partition that cannot seem to be removed. Adding this as an option prevents needing to edit a config script to change one character each time a different disk image is used. Change-Id: Iac2996ea096047281891a70aa2901401ac9746fc Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71918 Tested-by: kokoro Reviewed-by: Matt Sinclair Maintainer: Matt Sinclair --- configs/example/gpufs/runfs.py | 7 +++++++ configs/example/gpufs/system/system.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index b045b801c6..5346622155 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -151,6 +151,13 @@ def addRunFSOptions(parser): help="Exit simulation after running this many kernels", ) + parser.add_argument( + "--root-partition", + type=str, + default="/dev/sda1", + help="Root partition of disk image", + ) + def runGpuFSSystem(args): """ diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index 263ffc0a43..40e0016014 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -50,7 +50,7 @@ def makeGpuFSSystem(args): "earlyprintk=ttyS0", "console=ttyS0,9600", "lpj=7999923", - "root=/dev/sda1", + f"root={args.root_partition}", "drm_kms_helper.fbdev_emulation=0", "modprobe.blacklist=amdgpu", "modprobe.blacklist=psmouse", From 1aa8d6c004f41fa5386f2baf26d037358e2781c1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:51:57 -0800 Subject: [PATCH 036/693] scons: Pass the DISPLAY environment variable through to SCons. This lets gui programs run correctly within SCons, specifically the kconfig "guiconfig" helper utility. Change-Id: Iec51df3db89ac7e7411e6c08fe8201afb69dc63e Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/56952 Reviewed-by: Matthew Poremba Maintainer: Matthew Poremba Tested-by: kokoro --- site_scons/gem5_scons/defaults.py | 1 + 1 file changed, 1 insertion(+) diff --git a/site_scons/gem5_scons/defaults.py b/site_scons/gem5_scons/defaults.py index 996cfd495f..f800b6755c 100644 --- a/site_scons/gem5_scons/defaults.py +++ b/site_scons/gem5_scons/defaults.py @@ -67,6 +67,7 @@ def EnvDefaults(env): "LINKFLAGS_EXTRA", "LANG", "LC_CTYPE", + "DISPLAY", ] ) From fe7b18c2d75276857edf24861a6d160796110bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= Date: Fri, 23 Jun 2023 14:15:41 +0200 Subject: [PATCH 037/693] arch-riscv: Make virtual method RISC-V private * Prior commit defined a shared virtual method that is only used in RISC-V. This patch makes the method only visible to the RISC-V ISA. Change-Id: Ie31e1e1e5933d7c3b9f5af0c20822d3a6a382eee Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71818 Reviewed-by: Roger Chang Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power Tested-by: kokoro --- src/arch/generic/isa.hh | 1 - src/arch/riscv/faults.cc | 3 ++- src/arch/riscv/isa.hh | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/arch/generic/isa.hh b/src/arch/generic/isa.hh index 58f66fc99b..e9e4d95d7b 100644 --- a/src/arch/generic/isa.hh +++ b/src/arch/generic/isa.hh @@ -70,7 +70,6 @@ class BaseISA : public SimObject public: virtual PCStateBase *newPCState(Addr new_inst_addr=0) const = 0; virtual void clear() {} - virtual void clearLoadReservation(ContextID cid) {} virtual RegVal readMiscRegNoEffect(RegIndex idx) const = 0; virtual RegVal readMiscReg(RegIndex idx) = 0; diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 8fb8f81261..a929902e8b 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -154,7 +154,8 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) } // Clear load reservation address - tc->getIsaPtr()->clearLoadReservation(tc->contextId()); + auto isa = static_cast(tc->getIsaPtr()); + isa->clearLoadReservation(tc->contextId()); // Set PC to fault handler address Addr addr = mbits(tc->readMiscReg(tvec), 63, 2); diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 7ef5c526f5..31001c04b4 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -92,13 +92,6 @@ class ISA : public BaseISA return new PCState(new_inst_addr, rv_type); } - void - clearLoadReservation(ContextID cid) override - { - Addr& load_reservation_addr = load_reservation_addrs[cid]; - load_reservation_addr = INVALID_RESERVATION_ADDR; - } - public: RegVal readMiscRegNoEffect(RegIndex idx) const override; RegVal readMiscReg(RegIndex idx) override; @@ -142,6 +135,13 @@ class ISA : public BaseISA void resetThread() override; RiscvType rvType() const { return rv_type; } + + void + clearLoadReservation(ContextID cid) + { + Addr& load_reservation_addr = load_reservation_addrs[cid]; + load_reservation_addr = INVALID_RESERVATION_ADDR; + } }; } // namespace RiscvISA From 05ffa354268301821518fd430d069cd23049527d Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 29 Jun 2023 16:48:48 -0700 Subject: [PATCH 038/693] configs: Create base GPUFS vega config and atomic config Move the Vega KVM script code to a common base file and add scripts for KVM and atomic. Since atomic is now possible in GPUFS this gives a way to run it without editing the current scripts. Change-Id: I094bc4d4df856563535c28c1f6d6cc045d6734cd Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71939 Tested-by: kokoro Reviewed-by: Matt Sinclair Maintainer: Matt Sinclair --- configs/example/gpufs/vega10.py | 153 +++++++++++++++++++++++++ configs/example/gpufs/vega10_atomic.py | 32 ++++++ configs/example/gpufs/vega10_kvm.py | 127 +------------------- 3 files changed, 188 insertions(+), 124 deletions(-) create mode 100644 configs/example/gpufs/vega10.py create mode 100644 configs/example/gpufs/vega10_atomic.py diff --git a/configs/example/gpufs/vega10.py b/configs/example/gpufs/vega10.py new file mode 100644 index 0000000000..9eff5a2974 --- /dev/null +++ b/configs/example/gpufs/vega10.py @@ -0,0 +1,153 @@ +# Copyright (c) 2022-2023 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder 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 HOLDER 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. + +import m5 +import runfs +import base64 +import tempfile +import argparse +import sys +import os + +from amd import AmdGPUOptions +from common import Options +from common import GPUTLBOptions +from ruby import Ruby + + +demo_runscript_without_checkpoint = """\ +export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH +export HSA_ENABLE_INTERRUPT=0 +dmesg -n8 +dd if=/root/roms/vega10.rom of=/dev/mem bs=1k seek=768 count=128 +if [ ! -f /lib/modules/`uname -r`/updates/dkms/amdgpu.ko ]; then + echo "ERROR: Missing DKMS package for kernel `uname -r`. Exiting gem5." + /sbin/m5 exit +fi +modprobe -v amdgpu ip_block_mask=0xff ppfeaturemask=0 dpm=0 audio=0 +echo "Running {} {}" +echo "{}" | base64 -d > myapp +chmod +x myapp +./myapp {} +/sbin/m5 exit +""" + +demo_runscript_with_checkpoint = """\ +export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH +export HSA_ENABLE_INTERRUPT=0 +dmesg -n8 +dd if=/root/roms/vega10.rom of=/dev/mem bs=1k seek=768 count=128 +if [ ! -f /lib/modules/`uname -r`/updates/dkms/amdgpu.ko ]; then + echo "ERROR: Missing DKMS package for kernel `uname -r`. Exiting gem5." + /sbin/m5 exit +fi +modprobe -v amdgpu ip_block_mask=0xff ppfeaturemask=0 dpm=0 audio=0 +echo "Running {} {}" +echo "{}" | base64 -d > myapp +chmod +x myapp +/sbin/m5 checkpoint +./myapp {} +/sbin/m5 exit +""" + + +def addDemoOptions(parser): + parser.add_argument( + "-a", "--app", default=None, help="GPU application to run" + ) + parser.add_argument( + "-o", "--opts", default="", help="GPU application arguments" + ) + + +def runVegaGPUFS(cpu_type): + parser = argparse.ArgumentParser() + runfs.addRunFSOptions(parser) + Options.addCommonOptions(parser) + AmdGPUOptions.addAmdGPUOptions(parser) + Ruby.define_options(parser) + GPUTLBOptions.tlb_options(parser) + addDemoOptions(parser) + + # Parse now so we can override options + args = parser.parse_args() + demo_runscript = "" + + # Create temp script to run application + if args.app is None: + print(f"No application given. Use {sys.argv[0]} -a ") + sys.exit(1) + elif args.kernel is None: + print(f"No kernel path given. Use {sys.argv[0]} --kernel ") + sys.exit(1) + elif args.disk_image is None: + print(f"No disk path given. Use {sys.argv[0]} --disk-image ") + sys.exit(1) + elif args.gpu_mmio_trace is None: + print(f"No MMIO trace path. Use {sys.argv[0]} --gpu-mmio-trace ") + sys.exit(1) + elif not os.path.isfile(args.app): + print("Could not find applcation", args.app) + sys.exit(1) + + # Choose runscript Based on whether any checkpointing args are set + if args.checkpoint_dir is not None: + demo_runscript = demo_runscript_with_checkpoint + else: + demo_runscript = demo_runscript_without_checkpoint + + with open(os.path.abspath(args.app), "rb") as binfile: + encodedBin = base64.b64encode(binfile.read()).decode() + + _, tempRunscript = tempfile.mkstemp() + with open(tempRunscript, "w") as b64file: + runscriptStr = demo_runscript.format( + args.app, args.opts, encodedBin, args.opts + ) + b64file.write(runscriptStr) + + if args.second_disk == None: + args.second_disk = args.disk_image + + # Defaults for Vega10 + args.ruby = True + args.cpu_type = cpu_type + args.num_cpus = 1 + args.mem_size = "3GB" + args.dgpu = True + args.dgpu_mem_size = "16GB" + args.dgpu_start = "0GB" + args.checkpoint_restore = 0 + args.disjoint = True + args.timing_gpu = True + args.script = tempRunscript + args.dgpu_xor_low_bit = 0 + + # Run gem5 + runfs.runGpuFSSystem(args) diff --git a/configs/example/gpufs/vega10_atomic.py b/configs/example/gpufs/vega10_atomic.py new file mode 100644 index 0000000000..4ff2cc2e72 --- /dev/null +++ b/configs/example/gpufs/vega10_atomic.py @@ -0,0 +1,32 @@ +# Copyright (c) 2023 Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder 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 HOLDER 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. + +import vega10 + +vega10.runVegaGPUFS("AtomicSimpleCPU") diff --git a/configs/example/gpufs/vega10_kvm.py b/configs/example/gpufs/vega10_kvm.py index 11f9fe2f80..39dc5e0110 100644 --- a/configs/example/gpufs/vega10_kvm.py +++ b/configs/example/gpufs/vega10_kvm.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Advanced Micro Devices, Inc. +# Copyright (c) 2022-2023 Advanced Micro Devices, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,127 +27,6 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import m5 -import runfs -import base64 -import tempfile -import argparse -import sys -import os +import vega10 -from amd import AmdGPUOptions -from common import Options -from common import GPUTLBOptions -from ruby import Ruby - - -demo_runscript_without_checkpoint = """\ -export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH -export HSA_ENABLE_INTERRUPT=0 -dmesg -n8 -dd if=/root/roms/vega10.rom of=/dev/mem bs=1k seek=768 count=128 -if [ ! -f /lib/modules/`uname -r`/updates/dkms/amdgpu.ko ]; then - echo "ERROR: Missing DKMS package for kernel `uname -r`. Exiting gem5." - /sbin/m5 exit -fi -modprobe -v amdgpu ip_block_mask=0xff ppfeaturemask=0 dpm=0 audio=0 -echo "Running {} {}" -echo "{}" | base64 -d > myapp -chmod +x myapp -./myapp {} -/sbin/m5 exit -""" - -demo_runscript_with_checkpoint = """\ -export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH -export HSA_ENABLE_INTERRUPT=0 -dmesg -n8 -dd if=/root/roms/vega10.rom of=/dev/mem bs=1k seek=768 count=128 -if [ ! -f /lib/modules/`uname -r`/updates/dkms/amdgpu.ko ]; then - echo "ERROR: Missing DKMS package for kernel `uname -r`. Exiting gem5." - /sbin/m5 exit -fi -modprobe -v amdgpu ip_block_mask=0xff ppfeaturemask=0 dpm=0 audio=0 -echo "Running {} {}" -echo "{}" | base64 -d > myapp -chmod +x myapp -/sbin/m5 checkpoint -./myapp {} -/sbin/m5 exit -""" - - -def addDemoOptions(parser): - parser.add_argument( - "-a", "--app", default=None, help="GPU application to run" - ) - parser.add_argument( - "-o", "--opts", default="", help="GPU application arguments" - ) - - -if __name__ == "__m5_main__": - parser = argparse.ArgumentParser() - runfs.addRunFSOptions(parser) - Options.addCommonOptions(parser) - AmdGPUOptions.addAmdGPUOptions(parser) - Ruby.define_options(parser) - GPUTLBOptions.tlb_options(parser) - addDemoOptions(parser) - - # Parse now so we can override options - args = parser.parse_args() - demo_runscript = "" - - # Create temp script to run application - if args.app is None: - print(f"No application given. Use {sys.argv[0]} -a ") - sys.exit(1) - elif args.kernel is None: - print(f"No kernel path given. Use {sys.argv[0]} --kernel ") - sys.exit(1) - elif args.disk_image is None: - print(f"No disk path given. Use {sys.argv[0]} --disk-image ") - sys.exit(1) - elif args.gpu_mmio_trace is None: - print(f"No MMIO trace path. Use {sys.argv[0]} --gpu-mmio-trace ") - sys.exit(1) - elif not os.path.isfile(args.app): - print("Could not find applcation", args.app) - sys.exit(1) - - # Choose runscript Based on whether any checkpointing args are set - if args.checkpoint_dir is not None: - demo_runscript = demo_runscript_with_checkpoint - else: - demo_runscript = demo_runscript_without_checkpoint - - with open(os.path.abspath(args.app), "rb") as binfile: - encodedBin = base64.b64encode(binfile.read()).decode() - - _, tempRunscript = tempfile.mkstemp() - with open(tempRunscript, "w") as b64file: - runscriptStr = demo_runscript.format( - args.app, args.opts, encodedBin, args.opts - ) - b64file.write(runscriptStr) - - if args.second_disk == None: - args.second_disk = args.disk_image - - # Defaults for Vega10 - args.ruby = True - args.cpu_type = "X86KvmCPU" - args.num_cpus = 1 - args.mem_size = "3GB" - args.dgpu = True - args.dgpu_mem_size = "16GB" - args.dgpu_start = "0GB" - args.checkpoint_restore = 0 - args.disjoint = True - args.timing_gpu = True - args.script = tempRunscript - args.dgpu_xor_low_bit = 0 - - # Run gem5 - runfs.runGpuFSSystem(args) +vega10.runVegaGPUFS("X86KvmCPU") From 7cc4f820d7b06b17f834cafc406957ae2dee3e8e Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Tue, 4 Jul 2023 17:33:05 +0800 Subject: [PATCH 039/693] scons: Pass the CPATH environment variable through to SCons. For sandbox environment, the default include may be override by CPATH. To make the SCons can work in this environment, we need to pass CPATH into SCons. Change-Id: I1015f20a553a2e18595c8d2a89b209ca665879fd Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/72038 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- site_scons/gem5_scons/defaults.py | 1 + 1 file changed, 1 insertion(+) diff --git a/site_scons/gem5_scons/defaults.py b/site_scons/gem5_scons/defaults.py index f800b6755c..944f7e5da6 100644 --- a/site_scons/gem5_scons/defaults.py +++ b/site_scons/gem5_scons/defaults.py @@ -52,6 +52,7 @@ def EnvDefaults(env): "CC", "CXX", "HOME", + "CPATH", "LD_LIBRARY_PATH", "LIBRARY_PATH", "PATH", From fa905fd512b7c29ba01b011b37461362cf991593 Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Wed, 5 Jul 2023 17:01:22 +0800 Subject: [PATCH 040/693] scons: Add -rdynamic when building python embed binary When you build Python from scratch, the modules would be separated shared libraries. They would be dlopen when doing module import. To make the separated shared libraries can share the symbol in the binary, we should add -rdynamic when compliing. Change-Id: I26bf9fd7ea5068fd2d08c8f059b37ff34073e8c2 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/72040 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- src/SConscript | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SConscript b/src/SConscript index 1b4430327c..f54a881f72 100644 --- a/src/SConscript +++ b/src/SConscript @@ -626,6 +626,7 @@ PySource('m5', 'python/m5/info.py') gem5py_m5_env = gem5py_env.Clone() gem5py_env.Append(CPPPATH=env['CPPPATH']) gem5py_env.Append(LIBS='z') +gem5py_env.Append(LINKFLAGS='-rdynamic') gem5py_env.Program(gem5py, 'python/gem5py.cc')[0] m5_module_source = \ Source.all.with_all_tags(env, 'm5_module', 'gem5 lib') @@ -647,6 +648,7 @@ env.AlwaysBuild(tags) # env['SHOBJSUFFIX'] = '${OBJSUFFIX}s' +env.Append(LINKFLAGS='-rdynamic') envs = { 'debug': env.Clone(ENV_LABEL='debug', OBJSUFFIX='.do'), From 34d984d147340008e2d4e43da055de8b00287e07 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 12 Jun 2023 12:15:31 -0700 Subject: [PATCH 041/693] util: Update GitHub Runners Vagrant to overcommit memory SE mode tests were failing in some cases where the VM did not have enough memory to satisfy the constraints of the simulated system. This change ensures the VM allows overcommitting of memory. Change-Id: I1800288e16146bdae612a401c2ff282d8664892d Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71498 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- util/github-runners-vagrant/Vagrantfile-builder | 5 +++++ util/github-runners-vagrant/Vagrantfile-runner | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/util/github-runners-vagrant/Vagrantfile-builder b/util/github-runners-vagrant/Vagrantfile-builder index 242e094d19..cd36e7894c 100644 --- a/util/github-runners-vagrant/Vagrantfile-builder +++ b/util/github-runners-vagrant/Vagrantfile-builder @@ -22,6 +22,11 @@ Vagrant.configure("2") do |config| config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. config.vm.provision :reload + config.vm.provision :shell, run: 'always', inline: <<-SHELL + # When running gem5 in SE mode we must overcommit memory. + # This is run on every startup of the VM. + /sbin/sysctl vm.overcommit_memory=1 + SHELL config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL if [ -d ~/actions-runner ]; then # This will be run everytime the VM is run (once created). diff --git a/util/github-runners-vagrant/Vagrantfile-runner b/util/github-runners-vagrant/Vagrantfile-runner index ab601cd9c8..854e5f58b1 100644 --- a/util/github-runners-vagrant/Vagrantfile-runner +++ b/util/github-runners-vagrant/Vagrantfile-runner @@ -22,6 +22,11 @@ Vagrant.configure("2") do |config| config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. config.vm.provision :reload + config.vm.provision :shell, run: 'always', inline: <<-SHELL + # When running gem5 in SE mode we must overcommit memory. + # This is run on every startup of the VM. + /sbin/sysctl vm.overcommit_memory=1 + SHELL config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL if [ -d ~/actions-runner ]; then # This will be run everytime the VM is run (once created). From 1fd392e7bfb9c5657247da51b5687a3dc67444cb Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 12 Jun 2023 12:17:47 -0700 Subject: [PATCH 042/693] util: '-eq' -> '-ge' for if in vm_manager.sh A small nit-pick change that ensures that cases where the number of arguments being >1 does not result in the argument checking being skipped (NOTE: arguments after the first are never processed and are ignored). Change-Id: If7e9c16c2c3581ea95ed888586736618d1ae5f5f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71499 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Reviewed-by: Daniel Carvalho Tested-by: kokoro --- util/github-runners-vagrant/vm_manager.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh index 1cae8d2686..0e2f4b747f 100755 --- a/util/github-runners-vagrant/vm_manager.sh +++ b/util/github-runners-vagrant/vm_manager.sh @@ -9,7 +9,7 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) export VAGRANT_HOME=${SCRIPT_DIR} param="up" -if [[ $# -eq 1 ]]; then +if [[ $# -ge 1 ]]; then param=$1 if [[ "${param}" != "destroy" ]]; then echo "Only valid parameter is 'destroy', to destroy all VMs" From c391fdfbb46f278b0848fec45ca79a75814100cb Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 12 Jun 2023 12:19:25 -0700 Subject: [PATCH 043/693] util: Add 'shutdown' argument option to vm_manager.sh This allows for the VMs to be shutdown rather than destroyed. The can be rebooted with `./vm_manager.sh` after shutdown. Change-Id: I58329ec835af664bfb970b029e09ad16c5472015 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71500 Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce Tested-by: kokoro --- util/github-runners-vagrant/vm_manager.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh index 0e2f4b747f..ce46eb3fe7 100755 --- a/util/github-runners-vagrant/vm_manager.sh +++ b/util/github-runners-vagrant/vm_manager.sh @@ -11,8 +11,8 @@ export VAGRANT_HOME=${SCRIPT_DIR} param="up" if [[ $# -ge 1 ]]; then param=$1 - if [[ "${param}" != "destroy" ]]; then - echo "Only valid parameter is 'destroy', to destroy all VMs" + if [[ "${param}" != "destroy" ]] && [[ "${param}" != "shutdown" ]]; then + echo "Only valid parameters are 'destroy' and 'shutdown' to destroy all VMs or shutdown all VMs" exit 1 fi fi @@ -23,6 +23,8 @@ for (( i=1; i<=NUM_RUNNERS; i++ )); do sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${RUNNER_PREFIX}${i}\"/g" Vagrantfile-runner if [[ "${param}" == "destroy" ]]; then VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant destroy -f + elif [[ "${param}" == "shutdown" ]]; then + VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant halt -f else VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant up --provider=libvirt fi @@ -33,6 +35,8 @@ for (( i=1; i<=NUM_BUILDERS; i++ )); do sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${BUILDER_PREFIX}${i}\"/g" Vagrantfile-builder if [[ "${param}" == "destroy" ]]; then VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant destroy -f + elif [[ "${param}" == "shutdown" ]]; then + VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant halt -f else VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant up --provider=libvirt fi From 84b457c6aa64f0abaa9e1fd524ed6ee9f13cc16d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 13 Jun 2023 20:19:55 -0700 Subject: [PATCH 044/693] util: Add 'swapspace' daemon to runner VM. As these VMs, particularly the runners, don't have much memory, the 'swapspace' daemon allows for dynamic swap spaces to be created for when more memory is required. Change-Id: Ie8e734a8fde54e122df33dda187c6c4aafdcd006 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71680 Maintainer: Bobby Bruce Tested-by: kokoro Reviewed-by: Bobby Bruce --- util/github-runners-vagrant/Vagrantfile-builder | 3 +++ util/github-runners-vagrant/Vagrantfile-runner | 3 +++ 2 files changed, 6 insertions(+) diff --git a/util/github-runners-vagrant/Vagrantfile-builder b/util/github-runners-vagrant/Vagrantfile-builder index cd36e7894c..c0c2380b95 100644 --- a/util/github-runners-vagrant/Vagrantfile-builder +++ b/util/github-runners-vagrant/Vagrantfile-builder @@ -20,6 +20,9 @@ Vagrant.configure("2") do |config| # sets up vm config.vm.provision :shell, path: "provision_root.sh" config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" + # To ensure we don't run out of memory, we enable dynamic Swap Space. This is + # done via the "swapspace" daemon: https://pqxx.org/development/swapspace/ + config.vm.provision :shell, inline: "sudo apt install swapspace -y" # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. config.vm.provision :reload config.vm.provision :shell, run: 'always', inline: <<-SHELL diff --git a/util/github-runners-vagrant/Vagrantfile-runner b/util/github-runners-vagrant/Vagrantfile-runner index 854e5f58b1..eb4054ed16 100644 --- a/util/github-runners-vagrant/Vagrantfile-runner +++ b/util/github-runners-vagrant/Vagrantfile-runner @@ -20,6 +20,9 @@ Vagrant.configure("2") do |config| # sets up vm config.vm.provision :shell, path: "provision_root.sh" config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" + # To ensure we don't run out of memory, we enable dynamic Swap Space. This is + # done via the "swapspace" daemon: https://pqxx.org/development/swapspace/ + config.vm.provision :shell, inline: "sudo apt install swapspace -y" # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. config.vm.provision :reload config.vm.provision :shell, run: 'always', inline: <<-SHELL From 42c52b1add087bee3f68e7d6d3f817ca8983db81 Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Thu, 6 Jul 2023 10:26:24 +0800 Subject: [PATCH 045/693] scons: Update default environment comments Change-Id: Ib6dcf1a6390010682365f393241c1e022aeeb813 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/72058 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- site_scons/gem5_scons/defaults.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/site_scons/gem5_scons/defaults.py b/site_scons/gem5_scons/defaults.py index 944f7e5da6..aeca94fe59 100644 --- a/site_scons/gem5_scons/defaults.py +++ b/site_scons/gem5_scons/defaults.py @@ -44,7 +44,7 @@ from gem5_python_paths import extra_python_paths def EnvDefaults(env): - # export TERM so that clang reports errors in color + # initialize the toolchain related env with host environment use_vars = set( [ "AS", @@ -60,15 +60,15 @@ def EnvDefaults(env): "PROTOC", "PYTHONPATH", "RANLIB", - "TERM", - "PYTHON_CONFIG", - "CCFLAGS_EXTRA", - "GEM5PY_CCFLAGS_EXTRA", - "GEM5PY_LINKFLAGS_EXTRA", - "LINKFLAGS_EXTRA", - "LANG", - "LC_CTYPE", - "DISPLAY", + "TERM", # for clang reports errors in color + "PYTHON_CONFIG", # gem5 specific build env + "CCFLAGS_EXTRA", # gem5 specific build env + "GEM5PY_CCFLAGS_EXTRA", # gem5 specific build env + "GEM5PY_LINKFLAGS_EXTRA", # gem5 specific build env + "LINKFLAGS_EXTRA", # gem5 specific build env + "LANG", # for work with non-ascii directory path + "LC_CTYPE", # for work with non-ascii directory path + "DISPLAY", # for gui program, ex kconfig guiconfig ] ) From b4687aa7d97073e3ed59eb47b878f8466e772e13 Mon Sep 17 00:00:00 2001 From: Wei-Han Chen Date: Wed, 21 Jun 2023 08:20:16 +0000 Subject: [PATCH 046/693] dev: Warn when resp packet is error in dma port This CL adds a warning when the response packet is error. Change-Id: I8e94dc2b85cd1753a4d6265cfda3cd5d6325f425 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71778 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Reviewed-by: Yu-hsin Wang Tested-by: kokoro --- src/dev/dma_device.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dev/dma_device.cc b/src/dev/dma_device.cc index 24e931ef8d..70a74eeb2f 100644 --- a/src/dev/dma_device.cc +++ b/src/dev/dma_device.cc @@ -68,6 +68,7 @@ DmaPort::handleRespPacket(PacketPtr pkt, Tick delay) { // Should always see a response with a sender state. assert(pkt->isResponse()); + warn_if(pkt->isError(), "Response pkt error."); // Get the DMA sender state. auto *state = dynamic_cast(pkt->senderState); From 833afc3451d5e3cd7a4b3e908d26f14ce0705754 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Mon, 5 Dec 2022 10:03:13 +0000 Subject: [PATCH 047/693] mem-ruby: AbstractController can send retry req to mem controller Prior to this patch, when a memory controller was failing at sending a response to AbstractController, it would not wakeup until the next request. This patch gives the opportunity to Ruby models to notify memory response buffer dequeue so that AbstractController can send a retry request if necessary. A dequeueMemRspQueue function has been added AbstractController to automate the dequeue+notify operation. Note that models that don't notify AbstractController will continue working as before. Change-Id: I261bb4593c126208c98825e54f538638d818d16b Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67658 Tested-by: kokoro Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce --- .../slicc_interface/AbstractController.cc | 43 ++++++++++++++++--- .../slicc_interface/AbstractController.hh | 15 ++++++- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc index 2d10422487..f7b01cf939 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.cc +++ b/src/mem/ruby/slicc_interface/AbstractController.cc @@ -62,8 +62,10 @@ AbstractController::AbstractController(const Params &p) m_buffer_size(p.buffer_size), m_recycle_latency(p.recycle_latency), m_mandatory_queue_latency(p.mandatory_queue_latency), m_waiting_mem_retry(false), + m_mem_ctrl_waiting_retry(false), memoryPort(csprintf("%s.memory", name()), this), addrRanges(p.addr_ranges.begin(), p.addr_ranges.end()), + mRetryRespEvent{*this, false}, stats(this) { if (m_version == 0) { @@ -367,11 +369,17 @@ AbstractController::functionalMemoryWrite(PacketPtr pkt) return num_functional_writes + 1; } -void +bool AbstractController::recvTimingResp(PacketPtr pkt) { - assert(getMemRespQueue()); - assert(pkt->isResponse()); + auto* memRspQueue = getMemRespQueue(); + gem5_assert(memRspQueue); + gem5_assert(pkt->isResponse()); + + if (!memRspQueue->areNSlotsAvailable(1, curTick())) { + m_mem_ctrl_waiting_retry = true; + return false; + } std::shared_ptr msg = std::make_shared(clockEdge()); (*msg).m_addr = pkt->getAddr(); @@ -395,8 +403,9 @@ AbstractController::recvTimingResp(PacketPtr pkt) panic("Incorrect packet type received from memory controller!"); } - getMemRespQueue()->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1))); + memRspQueue->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1))); delete pkt; + return true; } Tick @@ -438,11 +447,33 @@ const } +void +AbstractController::memRespQueueDequeued() { + if (m_mem_ctrl_waiting_retry && !mRetryRespEvent.scheduled()) { + schedule(mRetryRespEvent, clockEdge(Cycles{1})); + } +} + +void +AbstractController::dequeueMemRespQueue() { + auto* q = getMemRespQueue(); + gem5_assert(q); + q->dequeue(clockEdge()); + memRespQueueDequeued(); +} + +void +AbstractController::sendRetryRespToMem() { + if (m_mem_ctrl_waiting_retry) { + m_mem_ctrl_waiting_retry = false; + memoryPort.sendRetryResp(); + } +} + bool AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt) { - controller->recvTimingResp(pkt); - return true; + return controller->recvTimingResp(pkt); } void diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index a5ab5c2c44..7fdb88b07d 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -61,6 +61,7 @@ #include "mem/ruby/system/CacheRecorder.hh" #include "params/RubyController.hh" #include "sim/clocked_object.hh" +#include "sim/eventq.hh" namespace gem5 { @@ -100,6 +101,14 @@ class AbstractController : public ClockedObject, public Consumer virtual MessageBuffer* getMandatoryQueue() const = 0; virtual MessageBuffer* getMemReqQueue() const = 0; virtual MessageBuffer* getMemRespQueue() const = 0; + + // That function must be called by controller when dequeuing mem resp queue + // for memory controller to receive the retry request in time + void memRespQueueDequeued(); + // Or that function can be called to perform both dequeue and notification + // at once. + void dequeueMemRespQueue(); + virtual AccessPermission getAccessPermission(const Addr &addr) = 0; virtual void print(std::ostream & out) const = 0; @@ -165,7 +174,7 @@ class AbstractController : public ClockedObject, public Consumer Port &getPort(const std::string &if_name, PortID idx=InvalidPortID); - void recvTimingResp(PacketPtr pkt); + bool recvTimingResp(PacketPtr pkt); Tick recvAtomic(PacketPtr pkt); const AddrRangeList &getAddrRanges() const { return addrRanges; } @@ -364,6 +373,7 @@ class AbstractController : public ClockedObject, public Consumer Cycles m_recycle_latency; const Cycles m_mandatory_queue_latency; bool m_waiting_mem_retry; + bool m_mem_ctrl_waiting_retry; /** * Port that forwards requests and receives responses from the @@ -411,6 +421,9 @@ class AbstractController : public ClockedObject, public Consumer NetDest downstreamDestinations; NetDest upstreamDestinations; + void sendRetryRespToMem(); + MemberEventWrapper<&AbstractController::sendRetryRespToMem> mRetryRespEvent; + public: struct ControllerStats : public statistics::Group { From 20dd44427324469210461dfb3b9573210da07d2f Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Thu, 2 Feb 2023 16:31:54 +0000 Subject: [PATCH 048/693] mem-ruby: Switch to dequeueMemRspQueue() in all Ruby protocols Change-Id: I33bca345d985618e3fca62e9ddd5bcc3ad8226a3 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67659 Tested-by: kokoro Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce --- src/learning_gem5/part3/MSI-dir.sm | 2 +- src/mem/ruby/protocol/MESI_Two_Level-dir.sm | 2 +- src/mem/ruby/protocol/MI_example-dir.sm | 2 +- src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm | 2 +- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 2 +- src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm | 2 +- src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm | 2 +- src/mem/ruby/protocol/MOESI_CMP_token-dir.sm | 2 +- src/mem/ruby/protocol/MOESI_hammer-dir.sm | 2 +- src/mem/ruby/protocol/RubySlicc_Defines.sm | 2 ++ src/mem/ruby/protocol/chi/CHI-mem.sm | 2 +- 11 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/learning_gem5/part3/MSI-dir.sm b/src/learning_gem5/part3/MSI-dir.sm index ca5ea3e534..70d960114a 100644 --- a/src/learning_gem5/part3/MSI-dir.sm +++ b/src/learning_gem5/part3/MSI-dir.sm @@ -448,7 +448,7 @@ machine(MachineType:Directory, "Directory protocol") } action(popMemQueue, "pM", desc="Pop the memory queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } // Stalling actions diff --git a/src/mem/ruby/protocol/MESI_Two_Level-dir.sm b/src/mem/ruby/protocol/MESI_Two_Level-dir.sm index 9d6975570c..aa614248b1 100644 --- a/src/mem/ruby/protocol/MESI_Two_Level-dir.sm +++ b/src/mem/ruby/protocol/MESI_Two_Level-dir.sm @@ -299,7 +299,7 @@ machine(MachineType:Directory, "MESI Two Level directory protocol") } action(l_popMemQueue, "q", desc="Pop off-chip request queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(kd_wakeUpDependents, "kd", desc="wake-up dependents") { diff --git a/src/mem/ruby/protocol/MI_example-dir.sm b/src/mem/ruby/protocol/MI_example-dir.sm index 11d2862b91..bbaa7d0789 100644 --- a/src/mem/ruby/protocol/MI_example-dir.sm +++ b/src/mem/ruby/protocol/MI_example-dir.sm @@ -523,7 +523,7 @@ machine(MachineType:Directory, "Directory protocol") } action(l_popMemQueue, "q", desc="Pop off-chip request queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } // TRANSITIONS diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm index f16c2576a2..ec8ffe6325 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm @@ -1397,7 +1397,7 @@ machine(MachineType:Directory, "AMD_Base-like protocol") } action(pm_popMemQueue, "pm", desc="pop mem queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(pt_popTriggerQueue, "pt", desc="pop trigger queue") { diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index 3b38e3b1ff..4dd03a19c0 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -1169,7 +1169,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") } action(pm_popMemQueue, "pm", desc="pop mem queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(pt_popTriggerQueue, "pt", desc="pop trigger queue") { diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm index 8608608590..5e815a7165 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm @@ -1103,7 +1103,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") } action(pm_popMemQueue, "pm", desc="pop mem queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(pt_popTriggerQueue, "pt", desc="pop trigger queue") { diff --git a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm index 3b4a8012c5..f21400c945 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm @@ -598,7 +598,7 @@ machine(MachineType:Directory, "Directory protocol") } action(q_popMemQueue, "q", desc="Pop off-chip request queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") { diff --git a/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm b/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm index 97ea292eb7..7f2bdf94e0 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm @@ -821,7 +821,7 @@ machine(MachineType:Directory, "Token protocol") } action(l_popMemQueue, "q", desc="Pop off-chip request queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(r_bounceResponse, "r", desc="Bounce response to starving processor") { diff --git a/src/mem/ruby/protocol/MOESI_hammer-dir.sm b/src/mem/ruby/protocol/MOESI_hammer-dir.sm index 8fd447fdf4..833ccd3b18 100644 --- a/src/mem/ruby/protocol/MOESI_hammer-dir.sm +++ b/src/mem/ruby/protocol/MOESI_hammer-dir.sm @@ -1141,7 +1141,7 @@ machine(MachineType:Directory, "AMD Hammer-like protocol") } action(l_popMemQueue, "q", desc="Pop off-chip request queue") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } action(g_popTriggerQueue, "g", desc="Pop trigger queue") { diff --git a/src/mem/ruby/protocol/RubySlicc_Defines.sm b/src/mem/ruby/protocol/RubySlicc_Defines.sm index 6ae3a6cb12..590a134ef9 100644 --- a/src/mem/ruby/protocol/RubySlicc_Defines.sm +++ b/src/mem/ruby/protocol/RubySlicc_Defines.sm @@ -37,3 +37,5 @@ Cycles recycle_latency; // memory controllers. void functionalMemoryRead(Packet *pkt); bool functionalMemoryWrite(Packet *pkt); + +void dequeueMemRespQueue(); diff --git a/src/mem/ruby/protocol/chi/CHI-mem.sm b/src/mem/ruby/protocol/chi/CHI-mem.sm index 820f2dfcf4..1e34d234c2 100644 --- a/src/mem/ruby/protocol/chi/CHI-mem.sm +++ b/src/mem/ruby/protocol/chi/CHI-mem.sm @@ -663,7 +663,7 @@ machine(MachineType:Memory, "Memory controller interface") : } action(popMemoryQueue, "pmem", desc="Pop memory queue.") { - memQueue_in.dequeue(clockEdge()); + dequeueMemRespQueue(); } // Stall/wake-up only used for requests that arrive when we are on the From d79941df7a6f48b6f3f89d919e8285c814e092e0 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Mon, 10 Oct 2022 15:51:01 +0200 Subject: [PATCH 049/693] configs: Fix default CustomMesh for use with Garnet Garnet routers do not support 0 latency switches. Use 1 instead if the network is garnet. Change-Id: I09841a01eaf413bee0a1629307ecff0ae2bda948 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67660 Reviewed-by: Jason Lowe-Power Tested-by: kokoro Maintainer: Jason Lowe-Power --- configs/topologies/CustomMesh.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configs/topologies/CustomMesh.py b/configs/topologies/CustomMesh.py index c62b39a9c2..21fa2dcc13 100644 --- a/configs/topologies/CustomMesh.py +++ b/configs/topologies/CustomMesh.py @@ -171,7 +171,9 @@ class CustomMesh(SimpleTopology): def _createRNFRouter(self, mesh_router): # Create a zero-latency router bridging node controllers # and the mesh router - node_router = self._Router(router_id=len(self._routers), latency=0) + node_router = self._Router( + router_id=len(self._routers), latency=self.node_router_latency + ) self._routers.append(node_router) # connect node_router <-> mesh router @@ -270,6 +272,7 @@ class CustomMesh(SimpleTopology): self._ExtLink = ExtLink self._Router = Router + self.node_router_latency = 1 if options.network == "garnet" else 0 if hasattr(options, "router_link_latency"): self._router_link_latency = options.router_link_latency self._node_link_latency = options.node_link_latency From 159953080a747275dba79359f57e6b28c2c06e32 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Wed, 5 Oct 2022 10:49:48 +0200 Subject: [PATCH 050/693] mem-ruby: Fix of an address bug in MESI_Two_Level-dir.sm Physical access address and line address were mixed up in qw_queueMemoryWBRequest_partial Change-Id: I0b238ffc59d2bb3de221d96905c75b7616eac964 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67661 Tested-by: kokoro Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power --- src/mem/ruby/protocol/MESI_Two_Level-dir.sm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/ruby/protocol/MESI_Two_Level-dir.sm b/src/mem/ruby/protocol/MESI_Two_Level-dir.sm index aa614248b1..84ec578788 100644 --- a/src/mem/ruby/protocol/MESI_Two_Level-dir.sm +++ b/src/mem/ruby/protocol/MESI_Two_Level-dir.sm @@ -365,7 +365,7 @@ machine(MachineType:Directory, "MESI Two Level directory protocol") desc="Queue off-chip writeback request") { peek(requestNetwork_in, RequestMsg) { enqueue(memQueue_out, MemoryMsg, to_mem_ctrl_latency) { - out_msg.addr := address; + out_msg.addr := in_msg.addr; out_msg.Type := MemoryRequestType:MEMORY_WB; out_msg.Sender := machineID; out_msg.MessageSize := MessageSizeType:Writeback_Data; From 91b4540477f51d924d46489af9c2bed0f5fda8e5 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Tue, 2 Aug 2022 07:07:33 +0000 Subject: [PATCH 051/693] python: Fix namespaced enums params code generation The wrapper_name parameter was not properly handled. Enums were always generated in the enums namespace even if required differently by wrapper_name. Change-Id: I366846ce39dfe10effc2cc145e7772a3fd171b92 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67662 Tested-by: kokoro Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce --- build_tools/enum_cc.py | 4 ++-- src/python/m5/params.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build_tools/enum_cc.py b/build_tools/enum_cc.py index 5d82b401b2..173143fc38 100644 --- a/build_tools/enum_cc.py +++ b/build_tools/enum_cc.py @@ -97,7 +97,7 @@ const char *${name}Strings[static_cast(${name}::Num_${name})] = ) else: code( - """namespace enums + """namespace ${wrapper_name} {""" ) code.indent(1) @@ -112,7 +112,7 @@ code("};") if not enum.wrapper_is_struct and not enum.is_class: code.dedent(1) - code("} // namespace enums") + code("} // namespace ${wrapper_name}") code("} // namespace gem5") diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 2ca6dfcc14..2559b553d2 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -1560,8 +1560,8 @@ class MetaEnum(MetaParamValue): if cls.is_class: cls.cxx_type = f"{name}" else: - cls.cxx_type = f"enums::{name}" - + scope = init_dict.get("wrapper_name", "enums") + cls.cxx_type = f"{scope}::{name}" super().__init__(name, bases, init_dict) From 2f327fa2b8da751e8859a6d781d8458ef704bad6 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Tue, 20 Jun 2023 19:09:53 +0000 Subject: [PATCH 052/693] base: define is_iterable type trait Change-Id: I38bb0ddcbb95645797f1d20724b78aff3bef4580 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71838 Maintainer: Daniel Carvalho Tested-by: kokoro Reviewed-by: Daniel Carvalho --- src/base/type_traits.hh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/base/type_traits.hh b/src/base/type_traits.hh index 1fec93d9d1..a42f786443 100644 --- a/src/base/type_traits.hh +++ b/src/base/type_traits.hh @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BASE_TYPETRAITS_HH__ -#define __BASE_TYPETRAITS_HH__ +#ifndef BASE_TYPETRAITS_HH +#define BASE_TYPETRAITS_HH #include #include @@ -92,6 +92,19 @@ template using MemberFunctionArgsTuple_t = typename MemberFunctionSignature::argsTuple_t; + +// iterable type trait +template +struct is_iterable: std::false_type {}; + +template +struct is_iterable())), + decltype(end(std::declval()))>>: std::true_type {}; + +template +constexpr bool is_iterable_v = is_iterable::value; + } // namespace gem5 -#endif // __BASE_TYPETRAITS_HH__ +#endif // BASE_TYPETRAITS_HH From 5282fac31796e26a279c58388fb1def47558f281 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Tue, 20 Jun 2023 19:10:49 +0000 Subject: [PATCH 053/693] base: define is_std_hash_enabled type trait Change-Id: I7ffb7f80a90006d6b8cd42bdf3d63e34c6dbda01 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71839 Reviewed-by: Bobby Bruce Tested-by: kokoro Maintainer: Bobby Bruce --- src/base/type_traits.hh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/base/type_traits.hh b/src/base/type_traits.hh index a42f786443..fd13044765 100644 --- a/src/base/type_traits.hh +++ b/src/base/type_traits.hh @@ -105,6 +105,17 @@ struct is_iterable constexpr bool is_iterable_v = is_iterable::value; +// std::hash-enabled type trait +template +struct is_std_hash_enabled: std::false_type {}; + +template +struct is_std_hash_enabled())>>: std::true_type {}; + +template +constexpr bool is_std_hash_enabled_v = is_std_hash_enabled::value; + } // namespace gem5 #endif // BASE_TYPETRAITS_HH From eb241e8a991c3c86551cbbd8cbb2d7548c773454 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Tue, 20 Jun 2023 19:14:18 +0000 Subject: [PATCH 054/693] base: Provide several hash implementations for common types These types include std::pair, std::tuple, all iterable types and any composition of these. Convenience hash factory and computation functions are also provided. These functions are in the stl_helpers namespace and must not move to ::std which could cause undefined behaviour. This is because specialization of std templates for std or native types (or composition of these) is undefined behaviour. This inconvenience can't be circumvented for generic code. Users are free to bring these hash implementations to namespace std after specialization for their own non-std and non-native types. Change-Id: Ifd0f0b64e5421d5d44890eb25428cc9c53484eb3 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67663 Reviewed-by: Daniel Carvalho Maintainer: Daniel Carvalho Tested-by: kokoro --- src/base/stl_helpers.hh | 2 + src/base/stl_helpers/SConscript | 28 ++++ src/base/stl_helpers/hash_helpers.hh | 170 ++++++++++++++++++++++ src/base/stl_helpers/hash_helpers.test.cc | 85 +++++++++++ 4 files changed, 285 insertions(+) create mode 100644 src/base/stl_helpers/SConscript create mode 100644 src/base/stl_helpers/hash_helpers.hh create mode 100644 src/base/stl_helpers/hash_helpers.test.cc diff --git a/src/base/stl_helpers.hh b/src/base/stl_helpers.hh index d12f266350..1d19f56676 100644 --- a/src/base/stl_helpers.hh +++ b/src/base/stl_helpers.hh @@ -31,10 +31,12 @@ #include #include +#include #include #include #include "base/compiler.hh" +#include "base/stl_helpers/hash_helpers.hh" namespace gem5 { diff --git a/src/base/stl_helpers/SConscript b/src/base/stl_helpers/SConscript new file mode 100644 index 0000000000..1143dc2d42 --- /dev/null +++ b/src/base/stl_helpers/SConscript @@ -0,0 +1,28 @@ +# Copyright (c) 2023 Arteris, Inc. and its applicable licensors and affiliates. +# 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. + +Import('*') + +GTest('hash_helpers.test', 'hash_helpers.test.cc') diff --git a/src/base/stl_helpers/hash_helpers.hh b/src/base/stl_helpers/hash_helpers.hh new file mode 100644 index 0000000000..f638ea92f2 --- /dev/null +++ b/src/base/stl_helpers/hash_helpers.hh @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023 Arteris, Inc. and its applicable licensors and + * affiliates. + * 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. + */ + +#ifndef BASE_STL_HELPERS_HASH_HELPERS_HH +#define BASE_STL_HELPERS_HASH_HELPERS_HH + +#include +#include +#include +#include +#include +#include +#include + +#include "base/type_traits.hh" + +namespace gem5::stl_helpers +{ + +namespace hash_impl +{ +// The math in hash_combine and hash_refine functions are inspired from Jon +// Maiga's work hosted at https://github.com/jonmaiga/mx3 under the CC0 +// license. It makes use of two components: a stream mixer for combination and +// a scalar mixer for refinement. +// The stream mixer is a lighter weight function with lower entropy used to +// combine hash values while the scalar mixer is a high entropy function that +// increases the overall hashing quality. +// The tradeoff of not using hash_refine has not been thoroughtly tested and is +// only done based on Maiga's return on exprerience. +static constexpr uint64_t C = 0xbea225f9eb34556d; +template +constexpr size_t hash_combine(T... hashes) { + // gcc reports unused variable if T is the empty pack + [[maybe_unused]] auto combine = [](uint64_t a, uint64_t b) { + b *= C; + b ^= b >> 39; + a += b * C; + a *= C; + return a; + }; + // The following couple of expressions is equivalent to a hypothetical + // functional "acc = hashes.fold_left(0, combine)". The comma operator + // effectively repeats the expression in the second level parenthesis for + // each argument in the parameter pack hashes, in order. Thus, final value + // of acc is the recursive combination of all hashes. + uint64_t acc{0}; + ((acc = combine(acc, static_cast(hashes))), ...); + return static_cast(acc); +} + +constexpr size_t hash_refine(size_t x) { + x ^= x >> 32; + x *= C; + x ^= x >> 29; + x *= C; + x ^= x >> 32; + x *= C; + x ^= x >> 29; + return static_cast(x); +} + +// SFINAE-enabled hash functor +template +struct hash; + +// Reuse std::hash whenever possible +template +struct hash>>: std::hash +{}; + +// Enable type deduction for hash object construction +template +constexpr auto make_hash_for(const T&) { + return hash(); +} + +// Compute a hash without the hassle of constructing a hash functor +template +constexpr auto hash_value(const T& v) { + return make_hash_for(v)(v); +} + +// Hash for tuple +template +struct hash> +{ + constexpr size_t operator()(const std::tuple& t) const { + if constexpr (sizeof...(T) == 0) { + return 0; + } else { + return std::apply([](const auto&... e){ + return hash_refine(hash_combine(hash_value(e)...)); + }, t); + } + } +}; + +// Hash for pairs (based on hash for 2-uple) +template +struct hash> +{ + constexpr size_t operator()(const std::pair& p) const { + return hash_value(std::tie(p.first, p.second)); + } +}; + +// Hash for any iterable of stl_helpers::hash-enabled types. +template +struct hash && is_iterable_v>> +{ + constexpr size_t operator()(const T& t) const { + auto b = begin(t); + auto e = end(t); + if (b == e) return 0; + // Equivalent to hypothetical functional style + // return t.map(hash_value).reduce(hash_combine) + auto h = std::accumulate(next(b), e, hash_value(*b), + [](const auto& acc, const auto& val) { + return hash_combine(acc, hash_value(val)); + }); + return hash_refine(h); + } +}; + +template +constexpr bool is_hash_enabled = false; + +template +constexpr bool is_hash_enabled()(std::declval()))>> = true; + +} // namespace hash_impl + +// Export useful hash_impl functions +using hash_impl::hash; +using hash_impl::make_hash_for; +using hash_impl::hash_value; +using hash_impl::is_hash_enabled; + +} // namespace gem5::stl_helpers + +#endif // BASE_STL_HELPERS_HASH_HELPERS_HH diff --git a/src/base/stl_helpers/hash_helpers.test.cc b/src/base/stl_helpers/hash_helpers.test.cc new file mode 100644 index 0000000000..f6f07c5808 --- /dev/null +++ b/src/base/stl_helpers/hash_helpers.test.cc @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 Arteris, Inc. and its applicable licensors and + * affiliates. + * 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. + */ + +#include + +#include +#include +#include +#include +#include + +#include "base/stl_helpers/hash_helpers.hh" + +using namespace gem5; + +TEST(HashHelpers, isHashEnabled) +{ + EXPECT_TRUE(stl_helpers::is_hash_enabled); + EXPECT_TRUE(stl_helpers::is_hash_enabled); + EXPECT_TRUE(stl_helpers::is_hash_enabled); + EXPECT_TRUE(stl_helpers::is_hash_enabled); + EXPECT_TRUE(stl_helpers::is_hash_enabled); + using vector_t = std::vector; + EXPECT_TRUE(stl_helpers::is_hash_enabled); + using tuple_t = std::tuple; + EXPECT_TRUE(stl_helpers::is_hash_enabled); + EXPECT_TRUE((stl_helpers::is_hash_enabled>)); + EXPECT_TRUE((stl_helpers::is_hash_enabled< + std::unordered_map>)); +} + +// The following tests do not test the hash value as it is considered an +// implementation detail and there is no contract on the way that value is +// computed. Testing for hash quality is extremelly computationnaly intensive +// and is not suitable for unit tests. Consider these tests to be more of a +// "does it compile?" check as well as a small set of examples for the user. +TEST(HashHelpers, hashPair) +{ + auto p = std::make_pair(1, std::string("hello")); + auto hashVal = stl_helpers::hash_value(p); + auto hashFunc = stl_helpers::hash>{}; + EXPECT_EQ(hashVal, hashFunc(p)); +} + +TEST(HashHelpers, hashTuple) +{ + auto t = std::make_tuple(1, "hello", 4.2, std::make_pair(true, 0.f)); + auto hashVal = stl_helpers::hash_value(t); + auto hashFunc = stl_helpers::hash{}; + EXPECT_EQ(hashVal, hashFunc(t)); +} + +TEST(HashHelpers, hashVector) +{ + auto v = std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9}; + auto hashVal = stl_helpers::hash_value(v); + auto hashFunc = stl_helpers::hash{}; + EXPECT_EQ(hashVal, hashFunc(v)); +} From b8af5f6a6cf494c17e40654807b3870872002c90 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Mon, 27 Feb 2023 14:02:41 +0000 Subject: [PATCH 055/693] base: stl_hlp::unordered_{map,set} with stl_hlp::hash by default Change-Id: Iad01d7fa6ff6293a2d931ba796666ad3550c6e44 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67664 Reviewed-by: Daniel Carvalho Tested-by: kokoro Maintainer: Daniel Carvalho --- src/base/stl_helpers/hash_helpers.hh | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/base/stl_helpers/hash_helpers.hh b/src/base/stl_helpers/hash_helpers.hh index f638ea92f2..1432d522bd 100644 --- a/src/base/stl_helpers/hash_helpers.hh +++ b/src/base/stl_helpers/hash_helpers.hh @@ -40,6 +40,11 @@ #include "base/type_traits.hh" +#include +#include +#include +#include + namespace gem5::stl_helpers { @@ -165,6 +170,32 @@ using hash_impl::make_hash_for; using hash_impl::hash_value; using hash_impl::is_hash_enabled; +/* + * Provide unordered_map and unordered_set with stl_helpers::hash functions. + * These aliases enable clean use of stl_helpers::hash as default Hash template + * parameter. The reason for not using an alias is that template type aliases + * with default template arguments do not behave well with template parameter + * deductions in certain situations. One must remember that std::unordered_X + * is not a polymorphic type and as such, gem5::stl_helpers::unordered_X shall + * never be owned as a std::unordered_X. + */ +template< + typename Key, + typename T, + typename Hash = hash, + typename KeyEqual = std::equal_to, + typename Allocator = std::allocator< std::pair >> +struct unordered_map: std::unordered_map +{}; + +template< + typename Key, + typename Hash = hash, + typename KeyEqual = std::equal_to, + typename Allocator = std::allocator> +struct unordered_set: std::unordered_set +{}; + } // namespace gem5::stl_helpers #endif // BASE_STL_HELPERS_HASH_HELPERS_HH From 223a2ce234b4df5199ab2dae109d1db6993894c5 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Thu, 2 Feb 2023 18:11:39 +0000 Subject: [PATCH 056/693] misc: Add the magic_enum.hh external header (v0.9.2) Also increase maximum enum supported value to 0x100 This library is courtesy of Daniil Goncharov and hosted at https://github.com/Neargye/magic_enum/tree/master. It enables compile-time and runtime string to/from enum value conversion as well as other fancy enum introspection-like things. The MIT lincence should not conflict with gem5 in any way. Copying the file for now but a submodule might be more suitable if gem5 uses them in the future. Change-Id: Ib0c8f943b79c703f1247c11c7291fb4fb1548b0f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67665 Tested-by: kokoro Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce --- ext/magic_enum/SConscript | 37 + ext/magic_enum/magic_enum.hh | 1462 ++++++++++++++++++++++++++++++++++ 2 files changed, 1499 insertions(+) create mode 100644 ext/magic_enum/SConscript create mode 100644 ext/magic_enum/magic_enum.hh diff --git a/ext/magic_enum/SConscript b/ext/magic_enum/SConscript new file mode 100644 index 0000000000..9ba39bcaa9 --- /dev/null +++ b/ext/magic_enum/SConscript @@ -0,0 +1,37 @@ +# Copyright (c) 2022 Arteris, Inc. and its applicable licensors and affiliates. +# All rights reserved. This license is licensed under the Gem5 license. +# +# 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. +# +# 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. + +Import('env') + +env.Append(CPPDEFINES=['MAGIC_ENUM_RANGE_MAX=0x100']) \ No newline at end of file diff --git a/ext/magic_enum/magic_enum.hh b/ext/magic_enum/magic_enum.hh new file mode 100644 index 0000000000..1763cc314e --- /dev/null +++ b/ext/magic_enum/magic_enum.hh @@ -0,0 +1,1462 @@ +// __ __ _ ______ _____ +// | \/ | (_) | ____| / ____|_ _ +// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_ +// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _| +// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| +// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| +// __/ | https://github.com/Neargye/magic_enum +// |___/ version 0.9.2 +// +// Licensed under the MIT License . +// SPDX-License-Identifier: MIT +// Copyright (c) 2019 - 2023 Daniil Goncharov . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef NEARGYE_MAGIC_ENUM_HPP +#define NEARGYE_MAGIC_ENUM_HPP + +#define MAGIC_ENUM_VERSION_MAJOR 0 +#define MAGIC_ENUM_VERSION_MINOR 9 +#define MAGIC_ENUM_VERSION_PATCH 2 + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(MAGIC_ENUM_CONFIG_FILE) +#include MAGIC_ENUM_CONFIG_FILE +#endif + +#if !defined(MAGIC_ENUM_USING_ALIAS_OPTIONAL) +#include +#endif +#if !defined(MAGIC_ENUM_USING_ALIAS_STRING) +#include +#endif +#if !defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW) +#include +#endif + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-warning-option" +# pragma clang diagnostic ignored "-Wenum-constexpr-conversion" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'. +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 26495) // Variable 'static_str::chars_' is uninitialized. +# pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. +# pragma warning(disable : 26451) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call. +# pragma warning(disable : 4514) // Unreferenced inline function has been removed. +#endif + +// Checks magic_enum compiler compatibility. +#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910 || defined(__RESHARPER__) +# undef MAGIC_ENUM_SUPPORTED +# define MAGIC_ENUM_SUPPORTED 1 +#endif + +// Checks magic_enum compiler aliases compatibility. +#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920 +# undef MAGIC_ENUM_SUPPORTED_ALIASES +# define MAGIC_ENUM_SUPPORTED_ALIASES 1 +#endif + +// Enum value must be greater or equals than MAGIC_ENUM_RANGE_MIN. By default MAGIC_ENUM_RANGE_MIN = -128. +// If need another min range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN. +#if !defined(MAGIC_ENUM_RANGE_MIN) +# define MAGIC_ENUM_RANGE_MIN -128 +#endif + +// Enum value must be less or equals than MAGIC_ENUM_RANGE_MAX. By default MAGIC_ENUM_RANGE_MAX = 128. +// If need another max range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MAX. +#if !defined(MAGIC_ENUM_RANGE_MAX) +# define MAGIC_ENUM_RANGE_MAX 0x100 +#endif + +// Improve ReSharper C++ intellisense performance with builtins, avoiding unnecessary template instantiations. +#if defined(__RESHARPER__) +# undef MAGIC_ENUM_GET_ENUM_NAME_BUILTIN +# undef MAGIC_ENUM_GET_TYPE_NAME_BUILTIN +# if __RESHARPER__ >= 20230100 +# define MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V) __rscpp_enumerator_name(V) +# define MAGIC_ENUM_GET_TYPE_NAME_BUILTIN(T) __rscpp_type_name() +# else +# define MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V) nullptr +# define MAGIC_ENUM_GET_TYPE_NAME_BUILTIN(T) nullptr +# endif +#endif + +namespace magic_enum { + +// If need another optional type, define the macro MAGIC_ENUM_USING_ALIAS_OPTIONAL. +#if defined(MAGIC_ENUM_USING_ALIAS_OPTIONAL) +MAGIC_ENUM_USING_ALIAS_OPTIONAL +#else +using std::optional; +#endif + +// If need another string_view type, define the macro MAGIC_ENUM_USING_ALIAS_STRING_VIEW. +#if defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW) +MAGIC_ENUM_USING_ALIAS_STRING_VIEW +#else +using std::string_view; +#endif + +// If need another string type, define the macro MAGIC_ENUM_USING_ALIAS_STRING. +#if defined(MAGIC_ENUM_USING_ALIAS_STRING) +MAGIC_ENUM_USING_ALIAS_STRING +#else +using std::string; +#endif + +using char_type = string_view::value_type; +static_assert(std::is_same_v, "magic_enum::customize requires same string_view::value_type and string::value_type"); +static_assert([] { + if constexpr (std::is_same_v) { + constexpr const char c[] = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|"; + constexpr const wchar_t wc[] = L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|"; + static_assert(std::size(c) == std::size(wc), "magic_enum::customize identifier characters are multichars in wchar_t."); + + for (std::size_t i = 0; i < std::size(c); ++i) { + if (c[i] != wc[i]) { + return false; + } + } + } + return true; +} (), "magic_enum::customize wchar_t is not compatible with ASCII."); + +namespace customize { + +// Enum value must be in range [MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]. By default MAGIC_ENUM_RANGE_MIN = -128, MAGIC_ENUM_RANGE_MAX = 128. +// If need another range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN and MAGIC_ENUM_RANGE_MAX. +// If need another range for specific enum type, add specialization enum_range for necessary enum type. +template +struct enum_range { + static_assert(std::is_enum_v, "magic_enum::customize::enum_range requires enum type."); + static constexpr int min = MAGIC_ENUM_RANGE_MIN; + static constexpr int max = MAGIC_ENUM_RANGE_MAX; + static_assert(max > min, "magic_enum::customize::enum_range requires max > min."); +}; + +static_assert(MAGIC_ENUM_RANGE_MAX > MAGIC_ENUM_RANGE_MIN, "MAGIC_ENUM_RANGE_MAX must be greater than MAGIC_ENUM_RANGE_MIN."); +static_assert((MAGIC_ENUM_RANGE_MAX - MAGIC_ENUM_RANGE_MIN) < (std::numeric_limits::max)(), "MAGIC_ENUM_RANGE must be less than UINT16_MAX."); + +namespace detail { + +enum class customize_tag { + default_tag, + invalid_tag, + custom_tag +}; + +} // namespace magic_enum::customize::detail + +class customize_t : public std::pair { + public: + constexpr customize_t(string_view srt) : std::pair{detail::customize_tag::custom_tag, srt} {} + constexpr customize_t(const char_type* srt) : customize_t{string_view{srt}} {} + constexpr customize_t(detail::customize_tag tag) : std::pair{tag, string_view{}} { + assert(tag != detail::customize_tag::custom_tag); + } +}; + +// Default customize. +inline constexpr auto default_tag = customize_t{detail::customize_tag::default_tag}; +// Invalid customize. +inline constexpr auto invalid_tag = customize_t{detail::customize_tag::invalid_tag}; + +// If need custom names for enum, add specialization enum_name for necessary enum type. +template +constexpr customize_t enum_name(E) noexcept { + return default_tag; +} + +// If need custom type name for enum, add specialization enum_type_name for necessary enum type. +template +constexpr customize_t enum_type_name() noexcept { + return default_tag; +} + +} // namespace magic_enum::customize + +namespace detail { + +template +struct supported +#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED || defined(MAGIC_ENUM_NO_CHECK_SUPPORT) + : std::true_type {}; +#else + : std::false_type {}; +#endif + +template , std::enable_if_t, int> = 0> +using enum_constant = std::integral_constant; + +template +inline constexpr bool always_false_v = false; + +template +struct has_is_flags : std::false_type {}; + +template +struct has_is_flags::is_flags)>> : std::bool_constant::is_flags)>>> {}; + +template +struct range_min : std::integral_constant {}; + +template +struct range_min::min)>> : std::integral_constant::min), customize::enum_range::min> {}; + +template +struct range_max : std::integral_constant {}; + +template +struct range_max::max)>> : std::integral_constant::max), customize::enum_range::max> {}; + +struct str_view { + const char* str_ = nullptr; + std::size_t size_ = 0; +}; + +template +class static_str { + public: + constexpr explicit static_str(str_view str) noexcept : static_str{str.str_, std::make_integer_sequence{}} { + assert(str.size_ == N); + } + + constexpr explicit static_str(string_view str) noexcept : static_str{str.data(), std::make_integer_sequence{}} { + assert(str.size() == N); + } + + constexpr const char_type* data() const noexcept { return chars_; } + + constexpr std::uint16_t size() const noexcept { return N; } + + constexpr operator string_view() const noexcept { return {data(), size()}; } + + private: + template + constexpr static_str(const char* str, std::integer_sequence) noexcept : chars_{static_cast(str[I])..., static_cast('\0')} {} + + template + constexpr static_str(string_view str, std::integer_sequence) noexcept : chars_{str[I]..., static_cast('\0')} {} + + char_type chars_[static_cast(N) + 1]; +}; + +template <> +class static_str<0> { + public: + constexpr explicit static_str() = default; + + constexpr explicit static_str(str_view) noexcept {} + + constexpr explicit static_str(string_view) noexcept {} + + constexpr const char_type* data() const noexcept { return nullptr; } + + constexpr std::uint16_t size() const noexcept { return 0; } + + constexpr operator string_view() const noexcept { return {}; } +}; + +template > +class case_insensitive { + static constexpr char_type to_lower(char_type c) noexcept { + return (c >= static_cast('A') && c <= static_cast('Z')) ? static_cast(c + (static_cast('a') - static_cast('A'))) : c; + } + + public: + template + constexpr auto operator()(L lhs,R rhs) const noexcept -> std::enable_if_t, char_type> && std::is_same_v, char_type>, bool> { + return Op{}(to_lower(lhs), to_lower(rhs)); + } +}; + +constexpr std::size_t find(string_view str, char_type c) noexcept { +#if defined(__clang__) && __clang_major__ < 9 && defined(__GLIBCXX__) || defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__) +// https://stackoverflow.com/questions/56484834/constexpr-stdstring-viewfind-last-of-doesnt-work-on-clang-8-with-libstdc +// https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html + constexpr bool workaround = true; +#else + constexpr bool workaround = false; +#endif + + if constexpr (workaround) { + for (std::size_t i = 0; i < str.size(); ++i) { + if (str[i] == c) { + return i; + } + } + + return string_view::npos; + } else { + return str.find(c); + } +} + +template +constexpr bool is_default_predicate() noexcept { + return std::is_same_v, std::equal_to> || + std::is_same_v, std::equal_to<>>; +} + +template +constexpr bool is_nothrow_invocable() { + return is_default_predicate() || + std::is_nothrow_invocable_r_v; +} + +template +constexpr bool cmp_equal(string_view lhs, string_view rhs, [[maybe_unused]] BinaryPredicate&& p) noexcept(is_nothrow_invocable()) { +#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__) + // https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html + // https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html + constexpr bool workaround = true; +#else + constexpr bool workaround = false; +#endif + + if constexpr (!is_default_predicate() || workaround) { + if (lhs.size() != rhs.size()) { + return false; + } + + const auto size = lhs.size(); + for (std::size_t i = 0; i < size; ++i) { + if (!p(lhs[i], rhs[i])) { + return false; + } + } + + return true; + } else { + return lhs == rhs; + } +} + +template +constexpr bool cmp_less(L lhs, R rhs) noexcept { + static_assert(std::is_integral_v && std::is_integral_v, "magic_enum::detail::cmp_less requires integral type."); + + if constexpr (std::is_signed_v == std::is_signed_v) { + // If same signedness (both signed or both unsigned). + return lhs < rhs; + } else if constexpr (std::is_same_v) { // bool special case + return static_cast(lhs) < rhs; + } else if constexpr (std::is_same_v) { // bool special case + return lhs < static_cast(rhs); + } else if constexpr (std::is_signed_v) { + // If 'right' is negative, then result is 'false', otherwise cast & compare. + return rhs > 0 && lhs < static_cast>(rhs); + } else { + // If 'left' is negative, then result is 'true', otherwise cast & compare. + return lhs < 0 || static_cast>(lhs) < rhs; + } +} + +template +constexpr I log2(I value) noexcept { + static_assert(std::is_integral_v, "magic_enum::detail::log2 requires integral type."); + + if constexpr (std::is_same_v) { // bool special case + return assert(false), value; + } else { + auto ret = I{0}; + for (; value > I{1}; value >>= I{1}, ++ret) {} + + return ret; + } +} + +#if defined(__cpp_lib_array_constexpr) && __cpp_lib_array_constexpr >= 201603L +# define MAGIC_ENUM_ARRAY_CONSTEXPR 1 +#else +template +constexpr std::array, N> to_array(T (&a)[N], std::index_sequence) noexcept { + return {{a[I]...}}; +} +#endif + +template +inline constexpr bool is_enum_v = std::is_enum_v && std::is_same_v>; + +template +constexpr auto n() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + if constexpr (supported::value) { +#if defined(MAGIC_ENUM_GET_TYPE_NAME_BUILTIN) + constexpr auto name_ptr = MAGIC_ENUM_GET_TYPE_NAME_BUILTIN(E); + constexpr auto name = name_ptr ? str_view{name_ptr, std::char_traits::length(name_ptr)} : str_view{}; +#elif defined(__clang__) + auto name = str_view{__PRETTY_FUNCTION__ + 34, sizeof(__PRETTY_FUNCTION__) - 36}; +#elif defined(__GNUC__) + auto name = str_view{__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1}; + if (name.str_[name.size_ - 1] == ']') { + name.size_ -= 50; + name.str_ += 49; + } else { + name.size_ -= 40; + name.str_ += 37; + } +#elif defined(_MSC_VER) + auto name = str_view{__FUNCSIG__ + 40, sizeof(__FUNCSIG__) - 57}; +#else + auto name = str_view{}; +#endif + return name; + } else { + return str_view{}; // Unsupported compiler or Invalid customize. + } +} + +template +constexpr auto type_name() noexcept { + [[maybe_unused]] constexpr auto custom = customize::enum_type_name(); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return static_str{name}; + } else if constexpr (custom.first == customize::detail::customize_tag::invalid_tag) { + return static_str<0>{}; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { + constexpr auto name = n(); + return static_str{name}; + } else { + static_assert(always_false_v, "magic_enum::customize invalid."); + } +} + +template +inline constexpr auto type_name_v = type_name(); + +template +constexpr auto n() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + if constexpr (supported::value) { +#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN) + constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V); + auto name = name_ptr ? str_view{name_ptr, std::char_traits::length(name_ptr)} : str_view{}; +#elif defined(__clang__) + auto name = str_view{__PRETTY_FUNCTION__ + 34, sizeof(__PRETTY_FUNCTION__) - 36}; + if (name.size_ > 22 && name.str_[0] == '(' && name.str_[1] == 'a' && name.str_[10] == ' ' && name.str_[22] == ':') { + name.size_ -= 23; + name.str_ += 23; + } + if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) { + name = str_view{}; + } +#elif defined(__GNUC__) + auto name = str_view{__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1}; + if (name.str_[name.size_ - 1] == ']') { + name.size_ -= 55; + name.str_ += 54; + } else { + name.size_ -= 40; + name.str_ += 37; + } + if (name.str_[0] == '(') { + name = str_view{}; + } +#elif defined(_MSC_VER) + str_view name; + if ((__FUNCSIG__[5] == '_' && __FUNCSIG__[35] != '(') || (__FUNCSIG__[5] == 'c' && __FUNCSIG__[41] != '(')) { + name = str_view{__FUNCSIG__ + 35, sizeof(__FUNCSIG__) - 52}; + } +#else + auto name = str_view{}; +#endif + std::size_t p = 0; + for (std::size_t i = name.size_; i > 0; --i) { + if (name.str_[i] == ':') { + p = i + 1; + break; + } + } + if (p > 0) { + name.size_ -= p; + name.str_ += p; + } + return name; + } else { + return str_view{}; // Unsupported compiler or Invalid customize. + } +} + +#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER < 1920 +# define MAGIC_ENUM_VS_2017_WORKAROUND 1 +#endif + +#if defined(MAGIC_ENUM_VS_2017_WORKAROUND) +template +constexpr auto n() noexcept { + static_assert(is_enum_v, "magic_enum::detail::n requires enum type."); + + str_view name = str_view{__FUNCSIG__, sizeof(__FUNCSIG__) - 17}; + std::size_t p = 0; + for (std::size_t i = name.size_; i > 0; --i) { + if (name.str_[i] == ',' || name.str_[i] == ':') { + p = i + 1; + break; + } + } + if (p > 0) { + name.size_ -= p; + name.str_ += p; + } + if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) { + name = str_view{}; + } + return name; +} +#endif + +template +constexpr auto enum_name() noexcept { + [[maybe_unused]] constexpr auto custom = customize::enum_name(V); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return static_str{name}; + } else if constexpr (custom.first == customize::detail::customize_tag::invalid_tag) { + return static_str<0>{}; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { +#if defined(MAGIC_ENUM_VS_2017_WORKAROUND) + constexpr auto name = n(); +#else + constexpr auto name = n(); +#endif + return static_str{name}; + } else { + static_assert(always_false_v, "magic_enum::customize invalid."); + } +} + +template +inline constexpr auto enum_name_v = enum_name(); + +template +constexpr bool is_valid() noexcept { +#if defined(__clang__) && __clang_major__ >= 16 + // https://reviews.llvm.org/D130058, https://reviews.llvm.org/D131307 + constexpr E v = __builtin_bit_cast(E, V); +#else + constexpr E v = static_cast(V); +#endif + [[maybe_unused]] constexpr auto custom = customize::enum_name(v); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return name.size() != 0; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { +#if defined(MAGIC_ENUM_VS_2017_WORKAROUND) + return n().size_ != 0; +#else + return n().size_ != 0; +#endif + } else { + return false; + } +} + +enum class enum_subtype { + common, + flags +}; + +template > +constexpr U ualue(std::size_t i) noexcept { + if constexpr (std::is_same_v) { // bool special case + static_assert(O == 0, "magic_enum::detail::ualue requires valid offset."); + + return static_cast(i); + } else if constexpr (S == enum_subtype::flags) { + return static_cast(U{1} << static_cast(static_cast(i) + O)); + } else { + return static_cast(static_cast(i) + O); + } +} + +template > +constexpr E value(std::size_t i) noexcept { + return static_cast(ualue(i)); +} + +template > +constexpr int reflected_min() noexcept { + if constexpr (S == enum_subtype::flags) { + return 0; + } else { + constexpr auto lhs = range_min::value; + constexpr auto rhs = (std::numeric_limits::min)(); + + if constexpr (cmp_less(rhs, lhs)) { + return lhs; + } else { + return rhs; + } + } +} + +template > +constexpr int reflected_max() noexcept { + if constexpr (S == enum_subtype::flags) { + return std::numeric_limits::digits - 1; + } else { + constexpr auto lhs = range_max::value; + constexpr auto rhs = (std::numeric_limits::max)(); + + if constexpr (cmp_less(lhs, rhs)) { + return lhs; + } else { + return rhs; + } + } +} + +#define MAGIC_ENUM_FOR_EACH_256(T) \ + T( 0)T( 1)T( 2)T( 3)T( 4)T( 5)T( 6)T( 7)T( 8)T( 9)T( 10)T( 11)T( 12)T( 13)T( 14)T( 15)T( 16)T( 17)T( 18)T( 19)T( 20)T( 21)T( 22)T( 23)T( 24)T( 25)T( 26)T( 27)T( 28)T( 29)T( 30)T( 31) \ + T( 32)T( 33)T( 34)T( 35)T( 36)T( 37)T( 38)T( 39)T( 40)T( 41)T( 42)T( 43)T( 44)T( 45)T( 46)T( 47)T( 48)T( 49)T( 50)T( 51)T( 52)T( 53)T( 54)T( 55)T( 56)T( 57)T( 58)T( 59)T( 60)T( 61)T( 62)T( 63) \ + T( 64)T( 65)T( 66)T( 67)T( 68)T( 69)T( 70)T( 71)T( 72)T( 73)T( 74)T( 75)T( 76)T( 77)T( 78)T( 79)T( 80)T( 81)T( 82)T( 83)T( 84)T( 85)T( 86)T( 87)T( 88)T( 89)T( 90)T( 91)T( 92)T( 93)T( 94)T( 95) \ + T( 96)T( 97)T( 98)T( 99)T(100)T(101)T(102)T(103)T(104)T(105)T(106)T(107)T(108)T(109)T(110)T(111)T(112)T(113)T(114)T(115)T(116)T(117)T(118)T(119)T(120)T(121)T(122)T(123)T(124)T(125)T(126)T(127) \ + T(128)T(129)T(130)T(131)T(132)T(133)T(134)T(135)T(136)T(137)T(138)T(139)T(140)T(141)T(142)T(143)T(144)T(145)T(146)T(147)T(148)T(149)T(150)T(151)T(152)T(153)T(154)T(155)T(156)T(157)T(158)T(159) \ + T(160)T(161)T(162)T(163)T(164)T(165)T(166)T(167)T(168)T(169)T(170)T(171)T(172)T(173)T(174)T(175)T(176)T(177)T(178)T(179)T(180)T(181)T(182)T(183)T(184)T(185)T(186)T(187)T(188)T(189)T(190)T(191) \ + T(192)T(193)T(194)T(195)T(196)T(197)T(198)T(199)T(200)T(201)T(202)T(203)T(204)T(205)T(206)T(207)T(208)T(209)T(210)T(211)T(212)T(213)T(214)T(215)T(216)T(217)T(218)T(219)T(220)T(221)T(222)T(223) \ + T(224)T(225)T(226)T(227)T(228)T(229)T(230)T(231)T(232)T(233)T(234)T(235)T(236)T(237)T(238)T(239)T(240)T(241)T(242)T(243)T(244)T(245)T(246)T(247)T(248)T(249)T(250)T(251)T(252)T(253)T(254)T(255) + +template +constexpr void valid_count(bool* valid, std::size_t& count) noexcept { +#define MAGIC_ENUM_V(O) \ + if constexpr ((I + O) < Size) { \ + if constexpr (is_valid(I + O)>()) { \ + valid[I + O] = true; \ + ++count; \ + } \ + } + + MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_V); + + if constexpr ((I + 256) < Size) { + valid_count(valid, count); + } +#undef MAGIC_ENUM_V +} + +template +struct valid_count_t { + std::size_t count = 0; + bool valid[N] = {}; +}; + +template +constexpr auto valid_count() noexcept { + valid_count_t vc; + valid_count(vc.valid, vc.count); + return vc; +} + +template +constexpr auto values() noexcept { + constexpr auto vc = valid_count(); + + if constexpr (vc.count > 0) { +#if defined(MAGIC_ENUM_ARRAY_CONSTEXPR) + std::array values = {}; +#else + E values[vc.count] = {}; +#endif + for (std::size_t i = 0, v = 0; v < vc.count; ++i) { + if (vc.valid[i]) { + values[v++] = value(i); + } + } +#if defined(MAGIC_ENUM_ARRAY_CONSTEXPR) + return values; +#else + return to_array(values, std::make_index_sequence{}); +#endif + } else { + return std::array{}; + } +} + +template > +constexpr auto values() noexcept { + constexpr auto min = reflected_min(); + constexpr auto max = reflected_max(); + constexpr auto range_size = max - min + 1; + static_assert(range_size > 0, "magic_enum::enum_range requires valid size."); + static_assert(range_size < (std::numeric_limits::max)(), "magic_enum::enum_range requires valid size."); + + return values(); +} + +template > +constexpr enum_subtype subtype(std::true_type) noexcept { + if constexpr (std::is_same_v) { // bool special case + return enum_subtype::common; + } else if constexpr (has_is_flags::value) { + return customize::enum_range::is_flags ? enum_subtype::flags : enum_subtype::common; + } else { +#if defined(MAGIC_ENUM_AUTO_IS_FLAGS) + constexpr auto flags_values = values(); + constexpr auto default_values = values(); + if (flags_values.size() == 0 || default_values.size() > flags_values.size()) { + return enum_subtype::common; + } + for (std::size_t i = 0; i < default_values.size(); ++i) { + const auto v = static_cast(default_values[i]); + if (v != 0 && (v & (v - 1)) != 0) { + return enum_subtype::common; + } + } + return enum_subtype::flags; +#else + return enum_subtype::common; +#endif + } +} + +template +constexpr enum_subtype subtype(std::false_type) noexcept { + // For non-enum type return default common subtype. + return enum_subtype::common; +} + +template > +inline constexpr auto subtype_v = subtype(std::is_enum{}); + +template +inline constexpr auto values_v = values(); + +template > +using values_t = decltype((values_v)); + +template +inline constexpr auto count_v = values_v.size(); + +template > +inline constexpr auto min_v = (count_v > 0) ? static_cast(values_v.front()) : U{0}; + +template > +inline constexpr auto max_v = (count_v > 0) ? static_cast(values_v.back()) : U{0}; + +template +constexpr auto names(std::index_sequence) noexcept { + return std::array{{enum_name_v[I]>...}}; +} + +template +inline constexpr auto names_v = names(std::make_index_sequence>{}); + +template > +using names_t = decltype((names_v)); + +template +constexpr auto entries(std::index_sequence) noexcept { + return std::array, sizeof...(I)>{{{values_v[I], enum_name_v[I]>}...}}; +} + +template +inline constexpr auto entries_v = entries(std::make_index_sequence>{}); + +template > +using entries_t = decltype((entries_v)); + +template > +constexpr bool is_sparse() noexcept { + if constexpr (count_v == 0) { + return false; + } else if constexpr (std::is_same_v) { // bool special case + return false; + } else { + constexpr auto max = (S == enum_subtype::flags) ? log2(max_v) : max_v; + constexpr auto min = (S == enum_subtype::flags) ? log2(min_v) : min_v; + constexpr auto range_size = max - min + 1; + + return range_size != count_v; + } +} + +template > +inline constexpr bool is_sparse_v = is_sparse(); + +template > +constexpr U values_ors() noexcept { + static_assert(S == enum_subtype::flags, "magic_enum::detail::values_ors requires valid subtype."); + + auto ors = U{0}; + for (std::size_t i = 0; i < count_v; ++i) { + ors |= static_cast(values_v[i]); + } + + return ors; +} + +template +struct enable_if_enum {}; + +template +struct enable_if_enum { + using type = R; + static_assert(supported::value, "magic_enum unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); +}; + +template , typename D = std::decay_t> +using enable_if_t = typename enable_if_enum && std::is_invocable_r_v, R>::type; + +template >, int> = 0> +using enum_concept = T; + +template > +struct is_scoped_enum : std::false_type {}; + +template +struct is_scoped_enum : std::bool_constant>> {}; + +template > +struct is_unscoped_enum : std::false_type {}; + +template +struct is_unscoped_enum : std::bool_constant>> {}; + +template >> +struct underlying_type {}; + +template +struct underlying_type : std::underlying_type> {}; + +#if defined(MAGIC_ENUM_ENABLE_HASH) + +template +inline constexpr bool has_hash = true; + +template +struct constexpr_hash_t; + +template +struct constexpr_hash_t>> { + constexpr auto operator()(Value value) const noexcept { + using U = typename underlying_type::type; + if constexpr (std::is_same_v) { // bool special case + return static_cast(value); + } else { + return static_cast(value); + } + } + using secondary_hash = constexpr_hash_t; +}; + +template +struct constexpr_hash_t>> { + static constexpr std::uint32_t crc_table[256] { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL + }; + constexpr std::uint32_t operator()(string_view value) const noexcept { + auto crc = static_cast(0xffffffffL); + for (const auto c : value) { + crc = (crc >> 8) ^ crc_table[(crc ^ static_cast(c)) & 0xff]; + } + return crc ^ 0xffffffffL; + } + + struct secondary_hash { + constexpr std::uint32_t operator()(string_view value) const noexcept { + auto acc = static_cast(2166136261ULL); + for (const auto c : value) { + acc = ((acc ^ static_cast(c)) * static_cast(16777619ULL)) & (std::numeric_limits::max)(); + } + return static_cast(acc); + } + }; +}; + +template +inline constexpr Hash hash_v{}; + +template +constexpr auto calculate_cases(std::size_t Page) noexcept { + constexpr std::array values = *GlobValues; + constexpr std::size_t size = values.size(); + + using switch_t = std::invoke_result_t; + static_assert(std::is_integral_v && !std::is_same_v); + const std::size_t values_to = (std::min)(static_cast(256), size - Page); + + std::array result{}; + auto fill = result.begin(); + { + auto first = values.begin() + static_cast(Page); + auto last = values.begin() + static_cast(Page + values_to); + while (first != last) { + *fill++ = hash_v(*first++); + } + } + + // dead cases, try to avoid case collisions + for (switch_t last_value = result[values_to - 1]; fill != result.end() && last_value != (std::numeric_limits::max)(); *fill++ = ++last_value) { + } + + { + auto it = result.begin(); + auto last_value = (std::numeric_limits::min)(); + for (; fill != result.end(); *fill++ = last_value++) { + while (last_value == *it) { + ++last_value, ++it; + } + } + } + + return result; +} + +template +constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v) { + if constexpr (std::is_void_v) { + std::forward(f)(std::forward(args)...); + } else { + return static_cast(std::forward(f)(std::forward(args)...)); + } +} + +enum class case_call_t { + index, + value +}; + +template +inline constexpr auto default_result_type_lambda = []() noexcept(std::is_nothrow_default_constructible_v) { return T{}; }; + +template <> +inline constexpr auto default_result_type_lambda = []() noexcept {}; + +template +constexpr bool has_duplicate() noexcept { + using value_t = std::decay_t; + using hash_value_t = std::invoke_result_t; + std::arraysize()> hashes{}; + std::size_t size = 0; + for (auto elem : *Arr) { + hashes[size] = hash_v(elem); + for (auto i = size++; i > 0; --i) { + if (hashes[i] < hashes[i - 1]) { + auto tmp = hashes[i]; + hashes[i] = hashes[i - 1]; + hashes[i - 1] = tmp; + } else if (hashes[i] == hashes[i - 1]) { + return false; + } else { + break; + } + } + } + return true; +} + +#define MAGIC_ENUM_CASE(val) \ + case cases[val]: \ + if constexpr ((val) + Page < size) { \ + if (!pred(values[val + Page], searched)) { \ + break; \ + } \ + if constexpr (CallValue == case_call_t::index) { \ + if constexpr (std::is_invocable_r_v>) { \ + return detail::invoke_r(std::forward(lambda), std::integral_constant{}); \ + } else if constexpr (std::is_invocable_v>) { \ + assert(false && "magic_enum::detail::constexpr_switch wrong result type."); \ + } \ + } else if constexpr (CallValue == case_call_t::value) { \ + if constexpr (std::is_invocable_r_v>) { \ + return detail::invoke_r(std::forward(lambda), enum_constant{}); \ + } else if constexpr (std::is_invocable_r_v>) { \ + assert(false && "magic_enum::detail::constexpr_switch wrong result type."); \ + } \ + } \ + break; \ + } else [[fallthrough]]; + +template ::value_type>, + typename BinaryPredicate = std::equal_to<>, + typename Lambda, + typename ResultGetterType> +constexpr decltype(auto) constexpr_switch( + Lambda&& lambda, + typename std::decay_t::value_type searched, + ResultGetterType&& def, + BinaryPredicate&& pred = {}) { + using result_t = std::invoke_result_t; + using hash_t = std::conditional_t(), Hash, typename Hash::secondary_hash>; + static_assert(has_duplicate(), "magic_enum::detail::constexpr_switch duplicated hash found, please report it: https://github.com/Neargye/magic_enum/issues."); + constexpr std::array values = *GlobValues; + constexpr std::size_t size = values.size(); + constexpr std::array cases = calculate_cases(Page); + + switch (hash_v(searched)) { + MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_CASE) + default: + if constexpr (size > 256 + Page) { + return constexpr_switch(std::forward(lambda), searched, std::forward(def)); + } + break; + } + return def(); +} + +#undef MAGIC_ENUM_CASE + +#else +template +inline constexpr bool has_hash = false; +#endif + +template +constexpr auto for_each(F&& f, std::index_sequence) { + constexpr bool has_void_return = (std::is_void_v[I]>>> || ...); + constexpr bool all_same_return = (std::is_same_v[0]>>, std::invoke_result_t[I]>>> && ...); + + if constexpr (has_void_return) { + (f(enum_constant[I]>{}), ...); + } else if constexpr (all_same_return) { + return std::array{f(enum_constant[I]>{})...}; + } else { + return std::tuple{f(enum_constant[I]>{})...}; + } +} + +template +constexpr bool all_invocable(std::index_sequence) { + if constexpr (count_v == 0) { + return false; + } else { + return (std::is_invocable_v[I]>> && ...); + } +} + +} // namespace magic_enum::detail + +// Checks is magic_enum supported compiler. +inline constexpr bool is_magic_enum_supported = detail::supported::value; + +template +using Enum = detail::enum_concept; + +// Checks whether T is an Unscoped enumeration type. +// Provides the member constant value which is equal to true, if T is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration) type. Otherwise, value is equal to false. +template +struct is_unscoped_enum : detail::is_unscoped_enum {}; + +template +inline constexpr bool is_unscoped_enum_v = is_unscoped_enum::value; + +// Checks whether T is an Scoped enumeration type. +// Provides the member constant value which is equal to true, if T is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) type. Otherwise, value is equal to false. +template +struct is_scoped_enum : detail::is_scoped_enum {}; + +template +inline constexpr bool is_scoped_enum_v = is_scoped_enum::value; + +// If T is a complete enumeration type, provides a member typedef type that names the underlying type of T. +// Otherwise, if T is not an enumeration type, there is no member type. Otherwise (T is an incomplete enumeration type), the program is ill-formed. +template +struct underlying_type : detail::underlying_type {}; + +template +using underlying_type_t = typename underlying_type::type; + +template +using enum_constant = detail::enum_constant; + +// Returns type name of enum. +template +[[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_t { + constexpr string_view name = detail::type_name_v>; + static_assert(!name.empty(), "magic_enum::enum_type_name enum type does not have a name."); + + return name; +} + +// Returns number of enum values. +template > +[[nodiscard]] constexpr auto enum_count() noexcept -> detail::enable_if_t { + return detail::count_v, S>; +} + +// Returns enum value at specified index. +// No bounds checking is performed: the behavior is undefined if index >= number of enum values. +template > +[[nodiscard]] constexpr auto enum_value(std::size_t index) noexcept -> detail::enable_if_t> { + using D = std::decay_t; + + if constexpr (detail::is_sparse_v) { + return assert((index < detail::count_v)), detail::values_v[index]; + } else { + constexpr auto min = (S == detail::enum_subtype::flags) ? detail::log2(detail::min_v) : detail::min_v; + + return assert((index < detail::count_v)), detail::value(index); + } +} + +// Returns enum value at specified index. +template > +[[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_t> { + using D = std::decay_t; + static_assert(I < detail::count_v, "magic_enum::enum_value out of range."); + + return enum_value(I); +} + +// Returns std::array with enum values, sorted by enum value. +template > +[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_t> { + return detail::values_v, S>; +} + +// Returns integer value from enum value. +template +[[nodiscard]] constexpr auto enum_integer(E value) noexcept -> detail::enable_if_t> { + return static_cast>(value); +} + +// Returns underlying value from enum value. +template +[[nodiscard]] constexpr auto enum_underlying(E value) noexcept -> detail::enable_if_t> { + return static_cast>(value); +} + +// Obtains index in enum values from enum value. +// Returns optional with index. +template > +[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t> { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::count_v == 0) { + static_cast(value); + return {}; // Empty enum. + } else if constexpr (detail::is_sparse_v || (S == detail::enum_subtype::flags)) { +#if defined(MAGIC_ENUM_ENABLE_HASH) + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::index>( + [](std::size_t i) { return optional{i}; }, + value, + detail::default_result_type_lambda>); +#else + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (enum_value(i) == value) { + return i; + } + } + return {}; // Invalid value or out of range. +#endif + } else { + const auto v = static_cast(value); + if (v >= detail::min_v && v <= detail::max_v) { + return static_cast(v - detail::min_v); + } + return {}; // Invalid value or out of range. + } +} + +// Obtains index in enum values from enum value. +// Returns optional with index. +template +[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t> { + using D = std::decay_t; + + return enum_index(value); +} + +// Obtains index in enum values from static storage enum variable. +template >> +[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_t { + constexpr auto index = enum_index, S>(V); + static_assert(index, "magic_enum::enum_index enum value does not have a index."); + + return *index; +} + +// Returns name from static storage enum variable. +// This version is much lighter on the compile times and is not restricted to the enum_range limitation. +template +[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_t { + constexpr string_view name = detail::enum_name_v, V>; + static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name."); + + return name; +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template > +[[nodiscard]] constexpr auto enum_name(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + + if (const auto i = enum_index(value)) { + return detail::names_v[*i]; + } + return {}; +} + +// Returns name from enum value. +// If enum value does not have name or value out of range, returns empty string. +template +[[nodiscard]] constexpr auto enum_name(E value) -> detail::enable_if_t { + using D = std::decay_t; + + return enum_name(value); +} + +// Returns std::array with names, sorted by enum value. +template > +[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_t> { + return detail::names_v, S>; +} + +// Returns std::array with pairs (value, name), sorted by enum value. +template > +[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_t> { + return detail::entries_v, S>; +} + +// Allows you to write magic_enum::enum_cast("bar", magic_enum::case_insensitive); +inline constexpr auto case_insensitive = detail::case_insensitive<>{}; + +// Obtains enum value from integer value. +// Returns optional with enum value. +template > +[[nodiscard]] constexpr auto enum_cast(underlying_type_t value) noexcept -> detail::enable_if_t>> { + using D = std::decay_t; + + if constexpr (detail::count_v == 0) { + static_cast(value); + return {}; // Empty enum. + } else { + if constexpr (detail::is_sparse_v || (S == detail::enum_subtype::flags)) { +#if defined(MAGIC_ENUM_ENABLE_HASH) + return detail::constexpr_switch<&detail::values_v, detail::case_call_t::value>( + [](D v) { return optional{v}; }, + static_cast(value), + detail::default_result_type_lambda>); +#else + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (value == static_cast>(enum_value(i))) { + return static_cast(value); + } + } + return {}; // Invalid value or out of range. +#endif + } else { + if (value >= detail::min_v && value <= detail::max_v) { + return static_cast(value); + } + return {}; // Invalid value or out of range. + } + } +} + +// Obtains enum value from name. +// Returns optional with enum value. +template , typename BinaryPredicate = std::equal_to<>> +[[nodiscard]] constexpr auto enum_cast(string_view value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t>, BinaryPredicate> { + using D = std::decay_t; + + if constexpr (detail::count_v == 0) { + static_cast(value); + return {}; // Empty enum. + } else { + if constexpr (detail::is_default_predicate() && detail::has_hash) { +#if defined(MAGIC_ENUM_ENABLE_HASH) + return detail::constexpr_switch<&detail::names_v, detail::case_call_t::index>( + [](std::size_t i) { return optional{detail::values_v[i]}; }, + value, + detail::default_result_type_lambda>, + [&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); }); +#else + static_assert(detail::always_false_v, "magic_enum::enum_cast invalid."); +#endif + } else { + for (std::size_t i = 0; i < detail::count_v; ++i) { + if (detail::cmp_equal(value, detail::names_v[i], p)) { + return enum_value(i); + } + } + return {}; // Invalid value or out of range. + } + } +} + +// Checks whether enum contains value with such value. +template > +[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + using U = underlying_type_t; + + return static_cast(enum_cast(static_cast(value))); +} + +// Checks whether enum contains value with such value. +template +[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + using U = underlying_type_t; + + return static_cast(enum_cast(static_cast(value))); +} + +// Checks whether enum contains value with such integer value. +template > +[[nodiscard]] constexpr auto enum_contains(underlying_type_t value) noexcept -> detail::enable_if_t { + using D = std::decay_t; + + return static_cast(enum_cast(value)); +} + +// Checks whether enum contains enumerator with such name. +template , typename BinaryPredicate = std::equal_to<>> +[[nodiscard]] constexpr auto enum_contains(string_view value, BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable()) -> detail::enable_if_t { + using D = std::decay_t; + + return static_cast(enum_cast(value, std::move(p))); +} + +template , typename F, detail::enable_if_t = 0> +constexpr auto enum_for_each(F&& f) { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_for_each requires enum type."); + constexpr auto sep = std::make_index_sequence>{}; + + if constexpr (detail::all_invocable(sep)) { + return detail::for_each(std::forward(f), sep); + } else { + static_assert(detail::always_false_v, "magic_enum::enum_for_each requires invocable of all enum value."); + } +} + +template +inline constexpr auto as_flags = AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common; + +template +inline constexpr auto as_common = AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags; + +namespace bitwise_operators { + +template = 0> +constexpr E operator~(E rhs) noexcept { + return static_cast(~static_cast>(rhs)); +} + +template = 0> +constexpr E operator|(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) | static_cast>(rhs)); +} + +template = 0> +constexpr E operator&(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) & static_cast>(rhs)); +} + +template = 0> +constexpr E operator^(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) ^ static_cast>(rhs)); +} + +template = 0> +constexpr E& operator|=(E& lhs, E rhs) noexcept { + return lhs = (lhs | rhs); +} + +template = 0> +constexpr E& operator&=(E& lhs, E rhs) noexcept { + return lhs = (lhs & rhs); +} + +template = 0> +constexpr E& operator^=(E& lhs, E rhs) noexcept { + return lhs = (lhs ^ rhs); +} + +} // namespace magic_enum::bitwise_operators + +} // namespace magic_enum + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + +#undef MAGIC_ENUM_GET_ENUM_NAME_BUILTIN +#undef MAGIC_ENUM_GET_TYPE_NAME_BUILTIN +#undef MAGIC_ENUM_VS_2017_WORKAROUND +#undef MAGIC_ENUM_ARRAY_CONSTEXPR +#undef MAGIC_ENUM_FOR_EACH_256 + +#endif // NEARGYE_MAGIC_ENUM_HPP From 3756af8ed91f0860dcfb0a7111478212980e37ae Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 6 Jul 2023 08:13:01 -0700 Subject: [PATCH 057/693] gpu-compute,configs: Make sim exits conditional The unconditional exit event when a kernel completes that was added in c644eae2ddd34cf449a9c4476730bd29703c4dd7 is causing scripts that do not ignore unknown exit events to end simulation prematurely. One such script is the apu_se.py script used in SE mode GPU simulation. Make this exit conditional to the parameter being set to a valid value to avoid this problem. Change-Id: I1d2c082291fdbcf27390913ffdffb963ec8080dd Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/72098 Reviewed-by: Jason Lowe-Power Maintainer: Matt Sinclair Maintainer: Jason Lowe-Power Reviewed-by: Matt Sinclair Tested-by: kokoro --- configs/example/gpufs/system/system.py | 3 ++- src/gpu-compute/GPU.py | 4 ++++ src/gpu-compute/dispatcher.cc | 7 +++++-- src/gpu-compute/dispatcher.hh | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index 40e0016014..19df310295 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -115,7 +115,8 @@ def makeGpuFSSystem(args): numHWQueues=args.num_hw_queues, walker=hsapp_pt_walker, ) - dispatcher = GPUDispatcher() + dispatcher_exit_events = True if args.exit_at_gpu_kernel > -1 else False + dispatcher = GPUDispatcher(kernel_exit_events=dispatcher_exit_events) cp_pt_walker = VegaPagetableWalker() gpu_cmd_proc = GPUCommandProcessor( hsapp=gpu_hsapp, dispatcher=dispatcher, walker=cp_pt_walker diff --git a/src/gpu-compute/GPU.py b/src/gpu-compute/GPU.py index c5449cc398..c64a6b791d 100644 --- a/src/gpu-compute/GPU.py +++ b/src/gpu-compute/GPU.py @@ -328,6 +328,10 @@ class GPUDispatcher(SimObject): cxx_class = "gem5::GPUDispatcher" cxx_header = "gpu-compute/dispatcher.hh" + kernel_exit_events = Param.Bool( + False, "Enable exiting sim loop after a kernel" + ) + class GPUCommandProcessor(DmaVirtDevice): type = "GPUCommandProcessor" diff --git a/src/gpu-compute/dispatcher.cc b/src/gpu-compute/dispatcher.cc index b19bccca50..7b36bce591 100644 --- a/src/gpu-compute/dispatcher.cc +++ b/src/gpu-compute/dispatcher.cc @@ -51,7 +51,8 @@ GPUDispatcher::GPUDispatcher(const Params &p) : SimObject(p), shader(nullptr), gpuCmdProc(nullptr), tickEvent([this]{ exec(); }, "GPU Dispatcher tick", false, Event::CPU_Tick_Pri), - dispatchActive(false), stats(this) + dispatchActive(false), kernelExitEvents(p.kernel_exit_events), + stats(this) { schedule(&tickEvent, 0); } @@ -332,7 +333,9 @@ GPUDispatcher::notifyWgCompl(Wavefront *wf) curTick(), kern_id); DPRINTF(GPUKernelInfo, "Completed kernel %d\n", kern_id); - exitSimLoop("GPU Kernel Completed"); + if (kernelExitEvents) { + exitSimLoop("GPU Kernel Completed"); + } } if (!tickEvent.scheduled()) { diff --git a/src/gpu-compute/dispatcher.hh b/src/gpu-compute/dispatcher.hh index 7699ceff7c..eafa0804b1 100644 --- a/src/gpu-compute/dispatcher.hh +++ b/src/gpu-compute/dispatcher.hh @@ -92,6 +92,8 @@ class GPUDispatcher : public SimObject std::queue doneIds; // is there a kernel in execution? bool dispatchActive; + // Enable exiting sim loop after each kernel completion + bool kernelExitEvents; protected: struct GPUDispatcherStats : public statistics::Group From 4912e909788ec74d5afd2d6e5a6e45d283a6e00d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 3 Jul 2023 10:03:57 -0700 Subject: [PATCH 058/693] stdlib: Change default gem5-resources DB collection This was set to "test_collection", which was used during development. Changing to "resources". Change-Id: I52c83c6b73f3a227fbb05dc321a4bc38210ad71c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/72018 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/python/gem5_default_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gem5_default_config.py b/src/python/gem5_default_config.py index 980c883109..6b689f58d5 100644 --- a/src/python/gem5_default_config.py +++ b/src/python/gem5_default_config.py @@ -29,7 +29,7 @@ config = { "gem5-resources": { "dataSource": "gem5-vision", "database": "gem5-vision", - "collection": "versions_test", + "collection": "resources", "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", From c5f9daa86c89aa05bcb3611eb466f630ec8b75ed Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 3 Jul 2023 13:03:05 -0700 Subject: [PATCH 059/693] stdlib,tests: Fix download_check.py This was causing the Weekly tests to fail. The removing of the download directory should only happen at the end. Prior to this patch it was deleted and then referenced, which caused problems. Change-Id: I134782e89a13f5c3cd5c1912ad53a701d0413d16 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/72019 Maintainer: Jason Lowe-Power Tested-by: kokoro Reviewed-by: Jason Lowe-Power --- tests/gem5/configs/download_check.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/gem5/configs/download_check.py b/tests/gem5/configs/download_check.py index 2180f4f26a..e3b06a578d 100644 --- a/tests/gem5/configs/download_check.py +++ b/tests/gem5/configs/download_check.py @@ -94,7 +94,6 @@ for id in ids: continue for resource_version in ids[id]: - resource_json = get_resource_json_obj( resource_id=id, resource_version=resource_version, @@ -129,8 +128,8 @@ for id in ids: + f" gem5-resources ({resource_json['md5sum']}).{os.linesep}" ) - # Remove the downloaded resource. - shutil.rmtree(download_path, ignore_errors=True) +# Remove the downloaded resource. +shutil.rmtree(args.download_directory, ignore_errors=True) # If errors exist, raise an exception highlighting them. if errors: From 9b9dc09f6eb2c60b17d34531f41450c0ba096bd4 Mon Sep 17 00:00:00 2001 From: KUNAL PAI Date: Fri, 2 Jun 2023 18:14:09 -0700 Subject: [PATCH 060/693] resources: Add the gem5 Resources Manager A GUI web-based tool to manage gem5 Resources. Can manage in two data sources, a MongoDB database or a JSON file. The JSON file can be both local or remote. JSON files are written to a temporary file before writing to the local file. The Manager supports the following functions on a high-level: - searching for a resource by ID - navigating to a resource version - adding a new resource - adding a new version to a resource - editing any information within a searched resource (while enforcing the gem5 Resources schema found at: https://resources.gem5.org/gem5-resources-schema.json) - deleting a resource version - undo and redo up to the last 10 operations The Manager also allows a user to save a session through localStorage and re-access it through a password securely. This patch also provides a Command Line Interface tool mainly for MongoDB-related functions. This CLI tool can currently: - backup a MongoDB collection to a JSON file - restore a JSON file to a MongoDB collection - search for a resource through its ID and view its JSON object - make a JSON file that is compliant with the gem5 Resources Schema Co-authored-by: Parth Shah Co-authored-by: Harshil2107 Co-authored-by: aarsli Change-Id: I8107f609c869300b5323d4942971a7ce7c28d6b5 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71218 Reviewed-by: Bobby Bruce Tested-by: kokoro Maintainer: Bobby Bruce --- util/gem5-resources-manager/.gitignore | 12 + util/gem5-resources-manager/README.md | 216 +++++ util/gem5-resources-manager/api/client.py | 134 +++ .../api/create_resources_json.py | 333 +++++++ .../gem5-resources-manager/api/json_client.py | 217 +++++ .../api/mongo_client.py | 237 +++++ .../gem5_resource_cli.py | 285 ++++++ util/gem5-resources-manager/requirements.txt | 29 + util/gem5-resources-manager/server.py | 884 ++++++++++++++++++ util/gem5-resources-manager/static/help.md | 65 ++ .../static/images/favicon.png | Bin 0 -> 2051 bytes .../static/images/gem5ColorLong.gif | Bin 0 -> 9192 bytes .../static/images/gem5ResourcesManager.png | Bin 0 -> 45905 bytes util/gem5-resources-manager/static/js/app.js | 135 +++ .../static/js/editor.js | 589 ++++++++++++ .../gem5-resources-manager/static/js/index.js | 75 ++ .../gem5-resources-manager/static/js/login.js | 330 +++++++ .../static/styles/global.css | 231 +++++ .../gem5-resources-manager/templates/404.html | 20 + .../templates/base.html | 96 ++ .../templates/editor.html | 355 +++++++ .../templates/help.html | 20 + .../templates/index.html | 116 +++ .../templates/login/login_json.html | 242 +++++ .../templates/login/login_mongodb.html | 189 ++++ util/gem5-resources-manager/test/__init__.py | 0 util/gem5-resources-manager/test/api_test.py | 722 ++++++++++++++ .../test/comprehensive_test.py | 407 ++++++++ .../test/json_client_test.py | 262 ++++++ .../test/mongo_client_test.py | 281 ++++++ .../test/refs/resources.json | 196 ++++ 31 files changed, 6678 insertions(+) create mode 100644 util/gem5-resources-manager/.gitignore create mode 100644 util/gem5-resources-manager/README.md create mode 100644 util/gem5-resources-manager/api/client.py create mode 100644 util/gem5-resources-manager/api/create_resources_json.py create mode 100644 util/gem5-resources-manager/api/json_client.py create mode 100644 util/gem5-resources-manager/api/mongo_client.py create mode 100644 util/gem5-resources-manager/gem5_resource_cli.py create mode 100644 util/gem5-resources-manager/requirements.txt create mode 100644 util/gem5-resources-manager/server.py create mode 100644 util/gem5-resources-manager/static/help.md create mode 100644 util/gem5-resources-manager/static/images/favicon.png create mode 100644 util/gem5-resources-manager/static/images/gem5ColorLong.gif create mode 100644 util/gem5-resources-manager/static/images/gem5ResourcesManager.png create mode 100644 util/gem5-resources-manager/static/js/app.js create mode 100644 util/gem5-resources-manager/static/js/editor.js create mode 100644 util/gem5-resources-manager/static/js/index.js create mode 100644 util/gem5-resources-manager/static/js/login.js create mode 100644 util/gem5-resources-manager/static/styles/global.css create mode 100644 util/gem5-resources-manager/templates/404.html create mode 100644 util/gem5-resources-manager/templates/base.html create mode 100644 util/gem5-resources-manager/templates/editor.html create mode 100644 util/gem5-resources-manager/templates/help.html create mode 100644 util/gem5-resources-manager/templates/index.html create mode 100644 util/gem5-resources-manager/templates/login/login_json.html create mode 100644 util/gem5-resources-manager/templates/login/login_mongodb.html create mode 100644 util/gem5-resources-manager/test/__init__.py create mode 100644 util/gem5-resources-manager/test/api_test.py create mode 100644 util/gem5-resources-manager/test/comprehensive_test.py create mode 100644 util/gem5-resources-manager/test/json_client_test.py create mode 100644 util/gem5-resources-manager/test/mongo_client_test.py create mode 100644 util/gem5-resources-manager/test/refs/resources.json diff --git a/util/gem5-resources-manager/.gitignore b/util/gem5-resources-manager/.gitignore new file mode 100644 index 0000000000..ce625cd446 --- /dev/null +++ b/util/gem5-resources-manager/.gitignore @@ -0,0 +1,12 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ + +# Unit test / coverage reports +.coverage +database/* +instance +instance/* + +# Environments +.env +.venv diff --git a/util/gem5-resources-manager/README.md b/util/gem5-resources-manager/README.md new file mode 100644 index 0000000000..efbbf97b16 --- /dev/null +++ b/util/gem5-resources-manager/README.md @@ -0,0 +1,216 @@ +# gem5 Resources Manager + +This directory contains the code to convert the JSON file to a MongoDB database. This also contains tools to manage the database as well as the JSON file. + +# Table of Contents +- [gem5 Resources Manager](#gem5-resources-manager) +- [Table of Contents](#table-of-contents) +- [Resources Manager](#resources-manager) + - [Setup](#setup) + - [Selecting a Database](#selecting-a-database) + - [MongoDB](#mongodb) + - [JSON File](#json-file) + - [Adding a Resource](#adding-a-resource) + - [Updating a Resource](#updating-a-resource) + - [Deleting a Resource](#deleting-a-resource) + - [Adding a New Version](#adding-a-new-version) + - [Validation](#validation) +- [CLI tool](#cli-tool) + - [create\_resources\_json](#create_resources_json) + - [restore\_backup](#restore_backup) + - [backup\_mongodb](#backup_mongodb) + - [get\_resource](#get_resource) +- [Changes to Structure of JSON](#changes-to-structure-of-json) +- [Testing](#testing) + +# Resources Manager + +This is a tool to manage the resources JSON file and the MongoDB database. This tool is used to add, delete, update, view, and search for resources. + +## Setup + +First, install the requirements: + +```bash +pip3 install -r requirements.txt +``` + +Then run the flask server: + +```bash +python3 server.py +``` + +Then, you can access the server at `http://localhost:5000`. + +## Selecting a Database + +The Resource Manager currently supports 2 database options: MongoDB and JSON file. + +Select the database you want to use by clicking on the button on home page. + +### MongoDB + +The MongoDB database is hosted on MongoDB Atlas. To use this database, you need to have the MongoDB URI, collection name, and database name. Once you have the information, enter it into the form and click "login" or "save and login" to login to the database. + +Another way to use the MongoDB database is to switch to the Generate URI tab and enter the information there. This would generate a URI that you can use to login to the database. + +### JSON File + +There are currently 3 ways to use the JSON file: + +1. Adding a URL to the JSON file +2. Uploading a JSON file +3. Using an existing JSON file + +## Adding a Resource + +Once you are logged in, you can use the search bar to search for resources. If the ID doesn't exist, it would be prefilled with the required fields. You can then edit the fields and click "add" to add the resource to the database. + +## Updating a Resource + +If the ID exists, the form would be prefilled with the existing data. You can then edit the fields and click "update" to update the resource in the database. + +## Deleting a Resource + +If the ID exists, the form would be prefilled with the existing data. You can then click "delete" to delete the resource from the database. + +## Adding a New Version + +If the ID exists, the form would be prefilled with the existing data. Change the `resource_version` field to the new version and click "add" to add the new version to the database. You will only be able to add a new version if the `resource_version` field is different from any of the existing versions. + +## Validation + +The Resource Manager validates the data before adding it to the database. If the data is invalid, it would show an error message and not add the data to the database. The validation is done using the [schema](schema/schema.json) file. The Monaco editor automatically validates the data as you type and displays the errors in the editor. + +To view the schema, click on the "Show Schema" button on the left side of the page. + +# CLI tool + +```bash +usage: gem5_resource_cli.py [-h] [-u URI] [-d DATABASE] [-c COLLECTION] {get_resource,backup_mongodb,restore_backup,create_resources_json} ... + +CLI for gem5-resources. + +positional arguments: + {get_resource,backup_mongodb,restore_backup,create_resources_json} + The command to run. + get_resource Retrieves a resource from the collection based on the given ID. if a resource version is provided, it will retrieve the resource + with the given ID and version. + backup_mongodb Backs up the MongoDB collection to a JSON file. + restore_backup Restores a backup of the MongoDB collection from a JSON file. + create_resources_json + Creates a JSON file of all the resources in the collection. + +optional arguments: + -h, --help show this help message and exit + -u URI, --uri URI The URI of the MongoDB database. (default: None) + -d DATABASE, --database DATABASE + The MongoDB database to use. (default: gem5-vision) + -c COLLECTION, --collection COLLECTION + The MongoDB collection to use. (default: versions_test) +``` + +By default, the cli uses environment variables to get the URI. You can create a .env file with the `MONGO_URI` variable set to your URI. If you want to use a different URI, you can use the `-u` flag to specify the URI. + +## create_resources_json + +This command is used to create a new JSON file from the old JSON file. This is used to make the JSON file "parseable" by removing the nested JSON and adding the new fields. + +```bash +usage: gem5_resource_cli.py create_resources_json [-h] [-v VERSION] [-o OUTPUT] [-s SOURCE] + +optional arguments: + -h, --help show this help message and exit + -v VERSION, --version VERSION + The version of the resources to create the JSON file for. (default: dev) + -o OUTPUT, --output OUTPUT + The JSON file to create. (default: resources.json) + -s SOURCE, --source SOURCE + The path to the gem5 source code. (default: ) +``` + +A sample command to run this is: + +```bash +python3 gem5_resource_cli.py create_resources_json -o resources_new.json -s ./gem5 +``` + +## restore_backup + +This command is used to update the MongoDB database with the new JSON file. This is used to update the database with the new JSON file. + +```bash +usage: gem5_resource_cli.py restore_backup [-h] [-f FILE] + +optional arguments: + -h, --help show this help message and exit + +required arguments: + -f FILE, --file FILE The JSON file to restore the MongoDB collection from. +``` + +A sample command to run this is: + +```bash +python3 gem5_resource_cli.py restore_backup -f resources.json +``` + +## backup_mongodb + +This command is used to backup the MongoDB database to a JSON file. This is used to create a backup of the database. + +```bash +usage: gem5_resource_cli.py backup_mongodb [-h] -f FILE + +optional arguments: + -h, --help show this help message and exit + +required arguments: + -f FILE, --file FILE The JSON file to back up the MongoDB collection to. +``` + +A sample command to run this is: + +```bash +python3 gem5_resource_cli.py backup_mongodb -f resources.json +``` + +## get_resource + +This command is used to get a resource from the MongoDB database. This is used to get a resource from the database. + +```bash +usage: gem5_resource_cli.py get_resource [-h] -i ID [-v VERSION] + +optional arguments: + -h, --help show this help message and exit + -v VERSION, --version VERSION + The version of the resource to retrieve. + +required arguments: + -i ID, --id ID The ID of the resource to retrieve. +``` + +A sample command to run this is: + +```bash +python3 gem5_resource_cli.py get_resource -i x86-ubuntu-18.04-img -v 1.0.0 +``` +# Changes to Structure of JSON + +To view the new schema, see [schema.json](https://resources.gem5.org/gem5-resources-schema.json). + +# Testing + +To run the tests, run the following command: + +```bash +coverage run -m unittest discover -s test -p '*_test.py' +``` + +To view the coverage report, run the following command: + +```bash +coverage report +``` diff --git a/util/gem5-resources-manager/api/client.py b/util/gem5-resources-manager/api/client.py new file mode 100644 index 0000000000..20a91b50d2 --- /dev/null +++ b/util/gem5-resources-manager/api/client.py @@ -0,0 +1,134 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from abc import ABC, abstractmethod +from typing import Dict, List + + +class Client(ABC): + def __init__(self): + self.__undo_stack = [] + self.__redo_stack = [] + self.__undo_limit = 10 + + @abstractmethod + def find_resource(self, query: Dict) -> Dict: + raise NotImplementedError + + @abstractmethod + def get_versions(self, query: Dict) -> List[Dict]: + raise NotImplementedError + + @abstractmethod + def update_resource(self, query: Dict) -> Dict: + raise NotImplementedError + + @abstractmethod + def check_resource_exists(self, query: Dict) -> Dict: + raise NotImplementedError + + @abstractmethod + def insert_resource(self, query: Dict) -> Dict: + raise NotImplementedError + + @abstractmethod + def delete_resource(self, query: Dict) -> Dict: + raise NotImplementedError + + @abstractmethod + def save_session(self) -> Dict: + raise NotImplementedError + + def undo_operation(self) -> Dict: + """ + This function undoes the last operation performed on the database. + """ + if len(self.__undo_stack) == 0: + return {"status": "Nothing to undo"} + operation = self.__undo_stack.pop() + print(operation) + if operation["operation"] == "insert": + self.delete_resource(operation["resource"]) + elif operation["operation"] == "delete": + self.insert_resource(operation["resource"]) + elif operation["operation"] == "update": + self.update_resource(operation["resource"]) + temp = operation["resource"]["resource"] + operation["resource"]["resource"] = operation["resource"][ + "original_resource" + ] + operation["resource"]["original_resource"] = temp + else: + raise Exception("Invalid Operation") + self.__redo_stack.append(operation) + return {"status": "Undone"} + + def redo_operation(self) -> Dict: + """ + This function redoes the last operation performed on the database. + """ + if len(self.__redo_stack) == 0: + return {"status": "No operations to redo"} + operation = self.__redo_stack.pop() + print(operation) + if operation["operation"] == "insert": + self.insert_resource(operation["resource"]) + elif operation["operation"] == "delete": + self.delete_resource(operation["resource"]) + elif operation["operation"] == "update": + self.update_resource(operation["resource"]) + temp = operation["resource"]["resource"] + operation["resource"]["resource"] = operation["resource"][ + "original_resource" + ] + operation["resource"]["original_resource"] = temp + else: + raise Exception("Invalid Operation") + self.__undo_stack.append(operation) + return {"status": "Redone"} + + def _add_to_stack(self, operation: Dict) -> Dict: + if len(self.__undo_stack) == self.__undo_limit: + self.__undo_stack.pop(0) + self.__undo_stack.append(operation) + self.__redo_stack.clear() + return {"status": "Added to stack"} + + def get_revision_status(self) -> Dict: + """ + This function saves the status of revision operations to a dictionary. + + The revision operations whose statuses are saved are undo and redo. + + If the stack of a given revision operation is empty, the status of + that operation is set to 1 else the status is set to 0. + + :return: A dictionary containing the status of revision operations. + """ + return { + "undo": 1 if len(self.__undo_stack) == 0 else 0, + "redo": 1 if len(self.__redo_stack) == 0 else 0, + } diff --git a/util/gem5-resources-manager/api/create_resources_json.py b/util/gem5-resources-manager/api/create_resources_json.py new file mode 100644 index 0000000000..8d406a9ad5 --- /dev/null +++ b/util/gem5-resources-manager/api/create_resources_json.py @@ -0,0 +1,333 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import json +import requests +import base64 +import os +from jsonschema import validate + + +class ResourceJsonCreator: + """ + This class generates the JSON which is pushed onto MongoDB. + On a high-level, it does the following: + - Adds certain fields to the JSON. + - Populates those fields. + - Makes sure the JSON follows the schema. + """ + + # Global Variables + base_url = "https://github.com/gem5/gem5/tree/develop" # gem5 GitHub URL + resource_url_map = { + "dev": ( + "https://gem5.googlesource.com/public/gem5-resources/+/refs/heads/" + "develop/resources.json?format=TEXT" + ), + "22.1": ( + "https://gem5.googlesource.com/public/gem5-resources/+/refs/heads/" + "stable/resources.json?format=TEXT" + ), + "22.0": ( + "http://resources.gem5.org/prev-resources-json/" + "resources-21-2.json" + ), + "21.2": ( + "http://resources.gem5.org/prev-resources-json/" + "resources-22-0.json" + ), + } + + def __init__(self): + self.schema = {} + with open("schema/schema.json", "r") as f: + self.schema = json.load(f) + + def _get_file_data(self, url): + json_data = None + try: + json_data = requests.get(url).text + json_data = base64.b64decode(json_data).decode("utf-8") + return json.loads(json_data) + except: + json_data = requests.get(url).json() + return json_data + + def _get_size(self, url): + """ + Helper function to return the size of a download through its URL. + Returns 0 if URL has an error. + + :param url: Download URL + """ + try: + response = requests.head(url) + size = int(response.headers.get("content-length", 0)) + return size + except Exception as e: + return 0 + + def _search_folder(self, folder_path, id): + """ + Helper function to find the instance of a string in a folder. + This is recursive, i.e., subfolders will also be searched. + + :param folder_path: Path to the folder to begin searching + :param id: Phrase to search in the folder + + :returns matching_files: List of file paths to the files containing id + """ + matching_files = [] + for filename in os.listdir(folder_path): + file_path = os.path.join(folder_path, filename) + if os.path.isfile(file_path): + with open( + file_path, "r", encoding="utf-8", errors="ignore" + ) as f: + contents = f.read() + if id in contents: + file_path = file_path.replace("\\", "/") + matching_files.append(file_path) + elif os.path.isdir(file_path): + matching_files.extend(self._search_folder(file_path, id)) + return matching_files + + def _change_type(self, resource): + if resource["type"] == "workload": + # get the architecture from the name and remove 64 from it + resource["architecture"] = ( + resource["name"].split("-")[0].replace("64", "").upper() + ) + return resource + if "kernel" in resource["name"]: + resource["type"] = "kernel" + elif "bootloader" in resource["name"]: + resource["type"] = "bootloader" + elif "benchmark" in resource["documentation"]: + resource["type"] = "disk-image" + # if tags not in resource: + if "tags" not in resource: + resource["tags"] = [] + resource["tags"].append("benchmark") + if ( + "additional_metadata" in resource + and "root_partition" in resource["additional_metadata"] + and resource["additional_metadata"]["root_partition"] + is not None + ): + resource["root_partition"] = resource["additional_metadata"][ + "root_partition" + ] + else: + resource["root_partition"] = "" + elif resource["url"] is not None and ".img.gz" in resource["url"]: + resource["type"] = "disk-image" + if ( + "additional_metadata" in resource + and "root_partition" in resource["additional_metadata"] + and resource["additional_metadata"]["root_partition"] + is not None + ): + resource["root_partition"] = resource["additional_metadata"][ + "root_partition" + ] + else: + resource["root_partition"] = "" + elif "binary" in resource["documentation"]: + resource["type"] = "binary" + elif "checkpoint" in resource["documentation"]: + resource["type"] = "checkpoint" + elif "simpoint" in resource["documentation"]: + resource["type"] = "simpoint" + return resource + + def _extract_code_examples(self, resource, source): + """ + This function goes by IDs present in the resources DataFrame. + It finds which files use those IDs in gem5/configs. + It adds the GitHub URL of those files under "example". + It finds whether those files are used in gem5/tests/gem5. + If yes, it marks "tested" as True. If not, it marks "tested" as False. + "example" and "tested" are made into a JSON for every code example. + This list of JSONs is assigned to the 'code_examples' field of the + DataFrame. + + :param resources: A DataFrame containing the current state of + resources. + :param source: Path to gem5 + + :returns resources: DataFrame with ['code-examples'] populated. + """ + id = resource["id"] + # search for files in the folder tree that contain the 'id' value + matching_files = self._search_folder( + source + "/configs", '"' + id + '"' + ) + filenames = [os.path.basename(path) for path in matching_files] + tested_files = [] + for file in filenames: + tested_files.append( + True + if len(self._search_folder(source + "/tests/gem5", file)) > 0 + else False + ) + + matching_files = [ + file.replace(source, self.base_url) for file in matching_files + ] + + code_examples = [] + + for i in range(len(matching_files)): + json_obj = { + "example": matching_files[i], + "tested": tested_files[i], + } + code_examples.append(json_obj) + return code_examples + + def unwrap_resources(self, ver): + data = self._get_file_data(self.resource_url_map[ver]) + resources = data["resources"] + new_resources = [] + for resource in resources: + if resource["type"] == "group": + for group in resource["contents"]: + new_resources.append(group) + else: + new_resources.append(resource) + return new_resources + + def _get_example_usage(self, resource): + if resource["category"] == "workload": + return f"Workload(\"{resource['id']}\")" + else: + return f"obtain_resource(resource_id=\"{resource['id']}\")" + + def _parse_readme(self, url): + metadata = { + "tags": [], + "author": [], + "license": "", + } + try: + request = requests.get(url) + content = request.text + content = content.split("---")[1] + content = content.split("---")[0] + if "tags:" in content: + tags = content.split("tags:\n")[1] + tags = tags.split(":")[0] + tags = tags.split("\n")[:-1] + tags = [tag.strip().replace("- ", "") for tag in tags] + if tags == [""] or tags == None: + tags = [] + metadata["tags"] = tags + if "author:" in content: + author = content.split("author:")[1] + author = author.split("\n")[0] + author = ( + author.replace("[", "").replace("]", "").replace('"', "") + ) + author = author.split(",") + author = [a.strip() for a in author] + metadata["author"] = author + if "license:" in content: + license = content.split("license:")[1].split("\n")[0] + metadata["license"] = license + except: + pass + return metadata + + def _add_fields(self, resources, source): + new_resources = [] + for resource in resources: + res = self._change_type(resource) + res["gem5_versions"] = ["23.0"] + res["resource_version"] = "1.0.0" + res["category"] = res["type"] + del res["type"] + res["id"] = res["name"] + del res["name"] + res["description"] = res["documentation"] + del res["documentation"] + if "additional_metadata" in res: + for k, v in res["additional_metadata"].items(): + res[k] = v + del res["additional_metadata"] + res["example_usage"] = self._get_example_usage(res) + if "source" in res: + url = ( + "https://raw.githubusercontent.com/gem5/" + "gem5-resources/develop/" + + str(res["source"]) + + "/README.md" + ) + res["source_url"] = ( + "https://github.com/gem5/gem5-resources/tree/develop/" + + str(res["source"]) + ) + else: + url = "" + res["source_url"] = "" + metadata = self._parse_readme(url) + if "tags" in res: + res["tags"].extend(metadata["tags"]) + else: + res["tags"] = metadata["tags"] + res["author"] = metadata["author"] + res["license"] = metadata["license"] + + res["code_examples"] = self._extract_code_examples(res, source) + + if "url" in resource: + download_url = res["url"].replace( + "{url_base}", "http://dist.gem5.org/dist/develop" + ) + res["url"] = download_url + res["size"] = self._get_size(download_url) + else: + res["size"] = 0 + + res = {k: v for k, v in res.items() if v is not None} + + new_resources.append(res) + return new_resources + + def _validate_schema(self, resources): + for resource in resources: + try: + validate(resource, schema=self.schema) + except Exception as e: + print(resource) + raise e + + def create_json(self, version, source, output): + resources = self.unwrap_resources(version) + resources = self._add_fields(resources, source) + self._validate_schema(resources) + with open(output, "w") as f: + json.dump(resources, f, indent=4) diff --git a/util/gem5-resources-manager/api/json_client.py b/util/gem5-resources-manager/api/json_client.py new file mode 100644 index 0000000000..24cfaee88c --- /dev/null +++ b/util/gem5-resources-manager/api/json_client.py @@ -0,0 +1,217 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from pathlib import Path +import json +from api.client import Client +from typing import Dict, List + + +class JSONClient(Client): + def __init__(self, file_path): + super().__init__() + self.file_path = Path("database/") / file_path + self.resources = self._get_resources(self.file_path) + + def _get_resources(self, path: Path) -> List[Dict]: + """ + Retrieves the resources from the JSON file. + :param path: The path to the JSON file. + :return: The resources as a JSON string. + """ + with open(path) as f: + return json.load(f) + + def find_resource(self, query: Dict) -> Dict: + """ + Finds a resource within a list of resources based on the + provided query. + :param query: The query object containing the search criteria. + :return: The resource that matches the query. + """ + found_resources = [] + for resource in self.resources: + if ( + "resource_version" not in query + or query["resource_version"] == "" + or query["resource_version"] == "Latest" + ): + if resource["id"] == query["id"]: + found_resources.append(resource) + else: + if ( + resource["id"] == query["id"] + and resource["resource_version"] + == query["resource_version"] + ): + return resource + if not found_resources: + return {"exists": False} + return max( + found_resources, + key=lambda resource: tuple( + map(int, resource["resource_version"].split(".")) + ), + ) + + def get_versions(self, query: Dict) -> List[Dict]: + """ + Retrieves all versions of a resource with the given ID from the + list of resources. + :param query: The query object containing the search criteria. + :return: A list of all versions of the resource. + """ + versions = [] + for resource in self.resources: + if resource["id"] == query["id"]: + versions.append( + {"resource_version": resource["resource_version"]} + ) + versions.sort( + key=lambda resource: tuple( + map(int, resource["resource_version"].split(".")) + ), + reverse=True, + ) + return versions + + def update_resource(self, query: Dict) -> Dict: + """ + Updates a resource within a list of resources based on the + provided query. + + The function iterates over the resources and checks if the "id" and + "resource_version" of a resource match the values in the query. + If there is a match, it removes the existing resource from the list + and appends the updated resource. + + After updating the resources, the function saves the updated list to + the specified file path. + + :param query: The query object containing the resource + identification criteria. + :return: A dictionary indicating that the resource was updated. + """ + original_resource = query["original_resource"] + modified_resource = query["resource"] + if ( + original_resource["id"] != modified_resource["id"] + and original_resource["resource_version"] + != modified_resource["resource_version"] + ): + return {"status": "Cannot change resource id"} + for resource in self.resources: + if ( + resource["id"] == original_resource["id"] + and resource["resource_version"] + == original_resource["resource_version"] + ): + self.resources.remove(resource) + self.resources.append(modified_resource) + + self.write_to_file() + return {"status": "Updated"} + + def check_resource_exists(self, query: Dict) -> Dict: + """ + Checks if a resource exists within a list of resources based on the + provided query. + + The function iterates over the resources and checks if the "id" and + "resource_version" of a resource match the values in the query. + If a matching resource is found, it returns a dictionary indicating + that the resource exists. + If no matching resource is found, it returns a dictionary indicating + that the resource does not exist. + + :param query: The query object containing the resource identification + criteria. + :return: A dictionary indicating whether the resource exists. + """ + for resource in self.resources: + if ( + resource["id"] == query["id"] + and resource["resource_version"] == query["resource_version"] + ): + return {"exists": True} + return {"exists": False} + + def insert_resource(self, query: Dict) -> Dict: + """ + Inserts a new resource into a list of resources. + + The function appends the query (new resource) to the resources list, + indicating the insertion. + It then writes the updated resources to the specified file path. + + :param query: The query object containing the resource identification + criteria. + :return: A dictionary indicating that the resource was inserted. + """ + if self.check_resource_exists(query)["exists"]: + return {"status": "Resource already exists"} + self.resources.append(query) + self.write_to_file() + return {"status": "Inserted"} + + def delete_resource(self, query: Dict) -> Dict: + """ + This function deletes a resource from the list of resources based on + the provided query. + + :param query: The query object containing the resource identification + criteria. + :return: A dictionary indicating that the resource was deleted. + """ + for resource in self.resources: + if ( + resource["id"] == query["id"] + and resource["resource_version"] == query["resource_version"] + ): + self.resources.remove(resource) + self.write_to_file() + return {"status": "Deleted"} + + def write_to_file(self) -> None: + """ + This function writes the list of resources to a file at the specified + file path. + + :return: None + """ + with Path(self.file_path).open("w") as outfile: + json.dump(self.resources, outfile, indent=4) + + def save_session(self) -> Dict: + """ + This function saves the client session to a dictionary. + :return: A dictionary containing the client session. + """ + session = { + "client": "json", + "filename": self.file_path.name, + } + return session diff --git a/util/gem5-resources-manager/api/mongo_client.py b/util/gem5-resources-manager/api/mongo_client.py new file mode 100644 index 0000000000..845524b886 --- /dev/null +++ b/util/gem5-resources-manager/api/mongo_client.py @@ -0,0 +1,237 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import json +from bson import json_util +from api.client import Client +from pymongo.errors import ConnectionFailure, ConfigurationError +from pymongo import MongoClient +from typing import Dict, List +import pymongo + + +class DatabaseConnectionError(Exception): + "Raised for failure to connect to MongoDB client" + pass + + +class MongoDBClient(Client): + def __init__(self, mongo_uri, database_name, collection_name): + super().__init__() + self.mongo_uri = mongo_uri + self.collection_name = collection_name + self.database_name = database_name + self.collection = self._get_database( + mongo_uri, database_name, collection_name + ) + + def _get_database( + self, + mongo_uri: str, + database_name: str, + collection_name: str, + ) -> pymongo.collection.Collection: + """ + This function returns a MongoDB database object for the specified + collection. + It takes three arguments: 'mongo_uri', 'database_name', and + 'collection_name'. + + :param: mongo_uri: URI of the MongoDB instance + :param: database_name: Name of the database + :param: collection_name: Name of the collection + :return: database: MongoDB database object + """ + + try: + client = MongoClient(mongo_uri) + client.admin.command("ping") + except ConnectionFailure: + client.close() + raise DatabaseConnectionError( + "Could not connect to MongoClient with given URI!" + ) + except ConfigurationError as e: + raise DatabaseConnectionError(e) + + database = client[database_name] + if database.name not in client.list_database_names(): + raise DatabaseConnectionError("Database Does not Exist!") + + collection = database[collection_name] + if collection.name not in database.list_collection_names(): + raise DatabaseConnectionError("Collection Does not Exist!") + + return collection + + def find_resource(self, query: Dict) -> Dict: + """ + Find a resource in the database + + :param query: JSON object with id and resource_version + :return: json_resource: JSON object with request resource or + error message + """ + if "resource_version" not in query or query["resource_version"] == "": + resource = ( + self.collection.find({"id": query["id"]}, {"_id": 0}) + .sort("resource_version", -1) + .limit(1) + ) + else: + resource = ( + self.collection.find( + { + "id": query["id"], + "resource_version": query["resource_version"], + }, + {"_id": 0}, + ) + .sort("resource_version", -1) + .limit(1) + ) + json_resource = json_util.dumps(resource) + res = json.loads(json_resource) + if res == []: + return {"exists": False} + return res[0] + + def update_resource(self, query: Dict) -> Dict[str, str]: + """ + This function updates a resource in the database by first checking if + the resource version in the request matches the resource version + stored in the database. + If they match, the resource is updated in the database. If they do not + match, the update is rejected. + + :param: query: JSON object with original_resource and the + updated resource + :return: json_response: JSON object with status message + """ + original_resource = query["original_resource"] + modified_resource = query["resource"] + try: + self.collection.replace_one( + { + "id": original_resource["id"], + "resource_version": original_resource["resource_version"], + }, + modified_resource, + ) + except Exception as e: + print(e) + return {"status": "Resource does not exist"} + return {"status": "Updated"} + + def get_versions(self, query: Dict) -> List[Dict]: + """ + This function retrieves all versions of a resource with the given ID + from the database. + It takes two arguments, the database object and a JSON object + containing the 'id' key of the resource to be retrieved. + + :param: query: JSON object with id + :return: json_resource: JSON object with all resource versions + """ + versions = self.collection.find( + {"id": query["id"]}, {"resource_version": 1, "_id": 0} + ).sort("resource_version", -1) + # convert to json + res = json_util.dumps(versions) + return json_util.loads(res) + + def delete_resource(self, query: Dict) -> Dict[str, str]: + """ + This function deletes a resource from the database by first checking + if the resource version in the request matches the resource version + stored in the database. + If they match, the resource is deleted from the database. If they do + not match, the delete operation is rejected + + :param: query: JSON object with id and resource_version + :return: json_response: JSON object with status message + """ + self.collection.delete_one( + {"id": query["id"], "resource_version": query["resource_version"]} + ) + return {"status": "Deleted"} + + def insert_resource(self, query: Dict) -> Dict[str, str]: + """ + This function inserts a new resource into the database using the + 'insert_one' method of the MongoDB client. + The function takes two arguments, the database object and the JSON + object representing the new resource to be inserted. + + :param: json: JSON object representing the new resource to be inserted + :return: json_response: JSON object with status message + """ + try: + self.collection.insert_one(query) + except Exception as e: + return {"status": "Resource already exists"} + return {"status": "Inserted"} + + def check_resource_exists(self, query: Dict) -> Dict: + """ + This function checks if a resource exists in the database by searching + for a resource with a matching 'id' and 'resource_version' in + the database. + The function takes two arguments, the database object and a JSON object + containing the 'id' and 'resource_version' keys. + + :param: json: JSON object with id and resource_version + :return: json_response: JSON object with boolean 'exists' key + """ + resource = ( + self.collection.find( + { + "id": query["id"], + "resource_version": query["resource_version"], + }, + {"_id": 0}, + ) + .sort("resource_version", -1) + .limit(1) + ) + json_resource = json_util.dumps(resource) + res = json.loads(json_resource) + if res == []: + return {"exists": False} + return {"exists": True} + + def save_session(self) -> Dict: + """ + This function saves the client session to a dictionary. + :return: A dictionary containing the client session. + """ + session = { + "client": "mongodb", + "uri": self.mongo_uri, + "database": self.database_name, + "collection": self.collection_name, + } + return session diff --git a/util/gem5-resources-manager/gem5_resource_cli.py b/util/gem5-resources-manager/gem5_resource_cli.py new file mode 100644 index 0000000000..28528bec92 --- /dev/null +++ b/util/gem5-resources-manager/gem5_resource_cli.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import json +from pymongo import MongoClient +from api.create_resources_json import ResourceJsonCreator +import os +from dotenv import load_dotenv +import argparse +from itertools import cycle +from shutil import get_terminal_size +from threading import Thread +from time import sleep + +load_dotenv() + +# read MONGO_URI from environment variable +MONGO_URI = os.getenv("MONGO_URI") + + +class Loader: + def __init__(self, desc="Loading...", end="Done!", timeout=0.1): + """ + A loader-like context manager + + Args: + desc (str, optional): The loader's description. + Defaults to "Loading...". + end (str, optional): Final print. Defaults to "Done!". + timeout (float, optional): Sleep time between prints. + Defaults to 0.1. + """ + self.desc = desc + self.end = end + self.timeout = timeout + + self._thread = Thread(target=self._animate, daemon=True) + self.steps = ["⢿", "⣻", "⣽", "⣾", "⣷", "⣯", "⣟", "⡿"] + self.done = False + + def start(self): + self._thread.start() + return self + + def _animate(self): + for c in cycle(self.steps): + if self.done: + break + print(f"\r{self.desc} {c}", flush=True, end="") + sleep(self.timeout) + + def __enter__(self): + self.start() + + def stop(self): + self.done = True + cols = get_terminal_size((80, 20)).columns + print("\r" + " " * cols, end="", flush=True) + print(f"\r{self.end}", flush=True) + + def __exit__(self, exc_type, exc_value, tb): + # handle exceptions with those variables ^ + self.stop() + + +def get_database(collection="versions_test", uri=MONGO_URI, db="gem5-vision"): + """ + Retrieves the MongoDB database for gem5-vision. + """ + CONNECTION_STRING = uri + try: + client = MongoClient(CONNECTION_STRING) + client.server_info() + except: + print("\nCould not connect to MongoDB") + exit(1) + return client[db][collection] + + +collection = None + + +def cli(): + parser = argparse.ArgumentParser( + description="CLI for gem5-resources.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "-u", + "--uri", + help="The URI of the MongoDB database.", + type=str, + default=MONGO_URI, + ) + parser.add_argument( + "-d", + "--database", + help="The MongoDB database to use.", + type=str, + default="gem5-vision", + ) + parser.add_argument( + "-c", + "--collection", + help="The MongoDB collection to use.", + type=str, + default="versions_test", + ) + + subparsers = parser.add_subparsers( + help="The command to run.", dest="command", required=True + ) + + parser_get_resource = subparsers.add_parser( + "get_resource", + help=( + "Retrieves a resource from the collection based on the given ID." + "\n if a resource version is provided, it will retrieve the " + "resource with the given ID and version." + ), + ) + req_group = parser_get_resource.add_argument_group( + title="required arguments" + ) + req_group.add_argument( + "-i", + "--id", + help="The ID of the resource to retrieve.", + type=str, + required=True, + ) + parser_get_resource.add_argument( + "-v", + "--version", + help="The version of the resource to retrieve.", + type=str, + required=False, + ) + parser_get_resource.set_defaults(func=get_resource) + + parser_backup_mongodb = subparsers.add_parser( + "backup_mongodb", + help="Backs up the MongoDB collection to a JSON file.", + ) + req_group = parser_backup_mongodb.add_argument_group( + title="required arguments" + ) + req_group.add_argument( + "-f", + "--file", + help="The JSON file to back up the MongoDB collection to.", + type=str, + required=True, + ) + parser_backup_mongodb.set_defaults(func=backup_mongodb) + + parser_update_mongodb = subparsers.add_parser( + "restore_backup", + help="Restores a backup of the MongoDB collection from a JSON file.", + ) + req_group = parser_update_mongodb.add_argument_group( + title="required arguments" + ) + req_group.add_argument( + "-f", + "--file", + help="The JSON file to restore the MongoDB collection from.", + type=str, + ) + parser_update_mongodb.set_defaults(func=restore_backup) + + parser_create_resources_json = subparsers.add_parser( + "create_resources_json", + help="Creates a JSON file of all the resources in the collection.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser_create_resources_json.add_argument( + "-v", + "--version", + help="The version of the resources to create the JSON file for.", + type=str, + default="dev", + ) + parser_create_resources_json.add_argument( + "-o", + "--output", + help="The JSON file to create.", + type=str, + default="resources.json", + ) + parser_create_resources_json.add_argument( + "-s", + "--source", + help="The path to the gem5 source code.", + type=str, + default="", + ) + parser_create_resources_json.set_defaults(func=create_resources_json) + + args = parser.parse_args() + if args.collection: + global collection + with Loader("Connecting to MongoDB...", end="Connected to MongoDB"): + collection = get_database(args.collection, args.uri, args.database) + args.func(args) + + +def get_resource(args): + # set the end after the loader is created + loader = Loader("Retrieving resource...").start() + resource = None + if args.version: + resource = collection.find_one( + {"id": args.id, "resource_version": args.version}, {"_id": 0} + ) + else: + resource = collection.find({"id": args.id}, {"_id": 0}) + resource = list(resource) + if resource: + loader.end = json.dumps(resource, indent=4) + else: + loader.end = "Resource not found" + + loader.stop() + + +def backup_mongodb(args): + """ + Backs up the MongoDB collection to a JSON file. + + :param file: The JSON file to back up the MongoDB collection to. + """ + with Loader( + "Backing up the database...", + end="Backed up the database to " + args.file, + ): + # get all the data from the collection + resources = collection.find({}, {"_id": 0}) + # write to resources.json + with open(args.file, "w") as f: + json.dump(list(resources), f, indent=4) + + +def restore_backup(args): + with Loader("Restoring backup...", end="Updated the database\n"): + with open(args.file) as f: + resources = json.load(f) + # clear the collection + collection.delete_many({}) + # push the new data + collection.insert_many(resources) + + +def create_resources_json(args): + with Loader("Creating resources JSON...", end="Created " + args.output): + creator = ResourceJsonCreator() + creator.create_json(args.version, args.source, args.output) + + +if __name__ == "__main__": + cli() diff --git a/util/gem5-resources-manager/requirements.txt b/util/gem5-resources-manager/requirements.txt new file mode 100644 index 0000000000..72771183ed --- /dev/null +++ b/util/gem5-resources-manager/requirements.txt @@ -0,0 +1,29 @@ +attrs==23.1.0 +blinker==1.6.2 +certifi==2023.5.7 +cffi==1.15.1 +charset-normalizer==3.1.0 +click==8.1.3 +colorama==0.4.6 +coverage==7.2.7 +cryptography==39.0.2 +dnspython==2.3.0 +Flask==2.3.2 +idna==3.4 +importlib-metadata==6.6.0 +itsdangerous==2.1.2 +Jinja2==3.1.2 +jsonschema==4.17.3 +Markdown==3.4.3 +MarkupSafe==2.1.3 +mongomock==4.1.2 +packaging==23.1 +pycparser==2.21 +pymongo==4.3.3 +pyrsistent==0.19.3 +requests==2.31.0 +sentinels==1.0.0 +urllib3==2.0.2 +Werkzeug==2.3.4 +zipp==3.15.0 +python-dotenv==1.0.0 diff --git a/util/gem5-resources-manager/server.py b/util/gem5-resources-manager/server.py new file mode 100644 index 0000000000..ec298d6c70 --- /dev/null +++ b/util/gem5-resources-manager/server.py @@ -0,0 +1,884 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from flask import ( + render_template, + Flask, + request, + redirect, + url_for, + make_response, +) +from bson import json_util +import json +import jsonschema +import requests +import markdown +import base64 +import secrets +from pathlib import Path +from werkzeug.utils import secure_filename +from cryptography.fernet import Fernet, InvalidToken +from cryptography.hazmat.primitives.kdf.scrypt import Scrypt +from cryptography.exceptions import InvalidSignature +from api.json_client import JSONClient +from api.mongo_client import MongoDBClient + +databases = {} + +response = requests.get( + "https://resources.gem5.org/gem5-resources-schema.json" +) +schema = json.loads(response.content) + + +UPLOAD_FOLDER = Path("database/") +TEMP_UPLOAD_FOLDER = Path("database/.tmp/") +CONFIG_FILE = Path("instance/config.py") +SESSIONS_COOKIE_KEY = "sessions" +ALLOWED_EXTENSIONS = {"json"} +CLIENT_TYPES = ["mongodb", "json"] + + +app = Flask(__name__, instance_relative_config=True) + + +if not CONFIG_FILE.exists(): + CONFIG_FILE.parent.mkdir() + with CONFIG_FILE.open("w+") as f: + f.write(f"SECRET_KEY = {secrets.token_bytes(32)}") + + +app.config.from_pyfile(CONFIG_FILE.name) + + +# Sorts keys in any serialized dict +# Default = True +# Set False to persevere JSON key order +app.json.sort_keys = False + + +def startup_config_validation(): + """ + Validates the startup configuration. + + Raises: + ValueError: If the 'SECRET_KEY' is not set or is not of type 'bytes'. + """ + if not app.secret_key: + raise ValueError("SECRET_KEY not set") + if not isinstance(app.secret_key, bytes): + raise ValueError("SECRET_KEY must be of type 'bytes'") + + +def startup_dir_file_validation(): + """ + Validates the startup directory and file configuration. + + Creates the required directories if they do not exist. + """ + for dir in [UPLOAD_FOLDER, TEMP_UPLOAD_FOLDER]: + if not dir.is_dir(): + dir.mkdir() + + +with app.app_context(): + startup_config_validation() + startup_dir_file_validation() + + +@app.route("/") +def index(): + """ + Renders the index HTML template. + + :return: The rendered index HTML template. + """ + return render_template("index.html") + + +@app.route("/login/mongodb") +def login_mongodb(): + """ + Renders the MongoDB login HTML template. + + :return: The rendered MongoDB login HTML template. + """ + return render_template("login/login_mongodb.html") + + +@app.route("/login/json") +def login_json(): + """ + Renders the JSON login HTML template. + + :return: The rendered JSON login HTML template. + """ + return render_template("login/login_json.html") + + +@app.route("/validateMongoDB", methods=["POST"]) +def validate_mongodb(): + """ + Validates the MongoDB connection parameters and redirects to the editor route if successful. + + This route expects a POST request with a JSON payload containing an alias for the session and the listed parameters in order to validate the MongoDB instance. + + This route expects the following JSON payload parameters: + - uri: The MongoDB connection URI. + - collection: The name of the collection in the MongoDB database. + - database: The name of the MongoDB database. + - alias: The value by which the session will be keyed in `databases`. + + If the 'uri' parameter is empty, a JSON response with an error message and status code 400 (Bad Request) is returned. + If the connection parameters are valid, the route redirects to the 'editor' route with the appropriate query parameters. + + :return: A redirect response to the 'editor' route or a JSON response with an error message and status code 400. + """ + global databases + try: + databases[request.json["alias"]] = MongoDBClient( + mongo_uri=request.json["uri"], + database_name=request.json["database"], + collection_name=request.json["collection"], + ) + except Exception as e: + return {"error": str(e)}, 400 + return redirect( + url_for("editor", alias=request.json["alias"]), + 302, + ) + + +@app.route("/validateJSON", methods=["GET"]) +def validate_json_get(): + """ + Validates the provided JSON URL and redirects to the editor route if successful. + + This route expects the following query parameters: + - q: The URL of the JSON file. + - filename: An optional filename for the uploaded JSON file. + + If the 'q' parameter is empty, a JSON response with an error message and status code 400 (Bad Request) is returned. + If the JSON URL is valid, the function retrieves the JSON content, saves it to a file, and redirects to the 'editor' + route with the appropriate query parameters. + + :return: A redirect response to the 'editor' route or a JSON response with an error message and status code 400. + """ + filename = request.args.get("filename") + url = request.args.get("q") + if not url: + return {"error": "empty"}, 400 + response = requests.get(url) + if response.status_code != 200: + return {"error": "invalid status"}, response.status_code + filename = secure_filename(request.args.get("filename")) + path = UPLOAD_FOLDER / filename + if (UPLOAD_FOLDER / filename).is_file(): + temp_path = TEMP_UPLOAD_FOLDER / filename + with temp_path.open("wb") as f: + f.write(response.content) + return {"conflict": "existing file in server"}, 409 + with path.open("wb") as f: + f.write(response.content) + global databases + if filename in databases: + return {"error": "alias already exists"}, 409 + try: + databases[filename] = JSONClient(filename) + except Exception as e: + return {"error": str(e)}, 400 + return redirect( + url_for("editor", alias=filename), + 302, + ) + + +@app.route("/validateJSON", methods=["POST"]) +def validate_json_post(): + """ + Validates and processes the uploaded JSON file. + + This route expects a file with the key 'file' in the request files. + If the file is not present, a JSON response with an error message + and status code 400 (Bad Request) is returned. + If the file already exists in the server, a JSON response with a + conflict error message and status code 409 (Conflict) is returned. + If the file's filename conflicts with an existing alias, a JSON + response with an error message and status code 409 (Conflict) is returned. + If there is an error while processing the JSON file, a JSON response + with the error message and status code 400 (Bad Request) is returned. + If the file is successfully processed, a redirect response to the + 'editor' route with the appropriate query parameters is returned. + + :return: A JSON response with an error message and + status code 400 or 409, or a redirect response to the 'editor' route. + """ + temp_path = None + if "file" not in request.files: + return {"error": "empty"}, 400 + file = request.files["file"] + filename = secure_filename(file.filename) + path = UPLOAD_FOLDER / filename + if path.is_file(): + temp_path = TEMP_UPLOAD_FOLDER / filename + file.save(temp_path) + return {"conflict": "existing file in server"}, 409 + file.save(path) + global databases + if filename in databases: + return {"error": "alias already exists"}, 409 + try: + databases[filename] = JSONClient(filename) + except Exception as e: + return {"error": str(e)}, 400 + return redirect( + url_for("editor", alias=filename), + 302, + ) + + +@app.route("/existingJSON", methods=["GET"]) +def existing_json(): + """ + Handles the request for an existing JSON file. + + This route expects a query parameter 'filename' + specifying the name of the JSON file. + If the file is not present in the 'databases', + it tries to create a 'JSONClient' instance for the file. + If there is an error while creating the 'JSONClient' + instance, a JSON response with the error message + and status code 400 (Bad Request) is returned. + If the file is present in the 'databases', a redirect + response to the 'editor' route with the appropriate + query parameters is returned. + + :return: A JSON response with an error message + and status code 400, or a redirect response to the 'editor' route. + """ + filename = request.args.get("filename") + global databases + if filename not in databases: + try: + databases[filename] = JSONClient(filename) + except Exception as e: + return {"error": str(e)}, 400 + return redirect( + url_for("editor", alias=filename), + 302, + ) + + +@app.route("/existingFiles", methods=["GET"]) +def get_existing_files(): + """ + Retrieves the list of existing files in the upload folder. + + This route returns a JSON response containing the names of the existing files in the upload folder configured in the + Flask application. + + :return: A JSON response with the list of existing files. + """ + files = [f.name for f in UPLOAD_FOLDER.iterdir() if f.is_file()] + return json.dumps(files) + + +@app.route("/resolveConflict", methods=["GET"]) +def resolve_conflict(): + """ + Resolves file conflict with JSON files. + + This route expects the following query parameters: + - filename: The name of the file that is conflicting or an updated name for it to resolve the name conflict + - resolution: A resolution option, defined as follows: + - clearInput: Deletes the conflicting file and does not proceed with login + - openExisting: Opens the existing file in `UPLOAD_FOLDER` + - overwrite: Overwrites the existing file with the conflicting file + - newFilename: Renames conflicting file, moving it to `UPLOAD_FOLDER` + + If the resolution parameter is not from the list given, an error is returned. + + The conflicting file in `TEMP_UPLOAD_FOLDER` is deleted. + + :return: A JSON response containing an error, or a success response, or a redirect to the editor. + """ + filename = secure_filename(request.args.get("filename")) + resolution = request.args.get("resolution") + resolution_options = [ + "clearInput", + "openExisting", + "overwrite", + "newFilename", + ] + temp_path = TEMP_UPLOAD_FOLDER / filename + if not resolution: + return {"error": "empty"}, 400 + if resolution not in resolution_options: + return {"error": "invalid resolution"}, 400 + if resolution == resolution_options[0]: + temp_path.unlink() + return {"success": "input cleared"}, 204 + if resolution in resolution_options[-2:]: + next(TEMP_UPLOAD_FOLDER.glob("*")).replace(UPLOAD_FOLDER / filename) + if temp_path.is_file(): + temp_path.unlink() + global databases + if filename in databases: + return {"error": "alias already exists"}, 409 + try: + databases[filename] = JSONClient(filename) + except Exception as e: + return {"error": str(e)}, 400 + return redirect( + url_for("editor", alias=filename), + 302, + ) + + +@app.route("/editor") +def editor(): + """ + Renders the editor page based on the specified database type. + + This route expects a GET request with specific query parameters: + - "alias": An optional alias for the MongoDB database. + + The function checks if the query parameters are present. If not, it returns a 404 error. + + The function determines the database type based on the instance of the client object stored in the databases['alias']. If the type is not in the + "CLIENT_TYPES" configuration, it returns a 404 error. + + :return: The rendered editor template based on the specified database type. + """ + global databases + if not request.args: + return render_template("404.html"), 404 + alias = request.args.get("alias") + if alias not in databases: + return render_template("404.html"), 404 + + client_type = "" + if isinstance(databases[alias], JSONClient): + client_type = CLIENT_TYPES[1] + elif isinstance(databases[alias], MongoDBClient): + client_type = CLIENT_TYPES[0] + else: + return render_template("404.html"), 404 + + response = make_response( + render_template("editor.html", client_type=client_type, alias=alias) + ) + + response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" + response.headers["Pragma"] = "no-cache" + response.headers["Expires"] = "0" + + return response + + +@app.route("/help") +def help(): + """ + Renders the help page. + + This route reads the contents of the "help.md" file located in the "static" folder and renders it as HTML using the + Markdown syntax. The rendered HTML is then passed to the "help.html" template for displaying the help page. + + :return: The rendered help page HTML. + """ + with Path("static/help.md").open("r") as f: + return render_template( + "help.html", rendered_html=markdown.markdown(f.read()) + ) + + +@app.route("/find", methods=["POST"]) +def find(): + """ + Finds a resource based on the provided search criteria. + + This route expects a POST request with a JSON payload containing the alias of the session which is to be searched for the + resource and the search criteria. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to find the resource by calling `find_resource()` on the session where the operation is + accomplished by the concrete client class. + + The result of the `find_resource` operation is returned as a JSON response. + + :return: A JSON response containing the result of the `find_resource` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + return database.find_resource(request.json) + + +@app.route("/update", methods=["POST"]) +def update(): + """ + Updates a resource with provided changes. + + This route expects a POST request with a JSON payload containing the alias of the session which contains the resource + that is to be updated and the data for updating the resource. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to update the resource by calling `update_resource()` on the session where the operation is + accomplished by the concrete client class. + + The `_add_to_stack` function of the session is called to insert the operation, update, and necessary data onto the revision + operations stack. + + The result of the `update_resource` operation is returned as a JSON response. It contains the original and the modified resources. + + :return: A JSON response containing the result of the `update_resource` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + original_resource = request.json["original_resource"] + modified_resource = request.json["resource"] + status = database.update_resource( + { + "original_resource": original_resource, + "resource": modified_resource, + } + ) + database._add_to_stack( + { + "operation": "update", + "resource": { + "original_resource": modified_resource, + "resource": original_resource, + }, + } + ) + return status + + +@app.route("/versions", methods=["POST"]) +def getVersions(): + """ + Retrieves the versions of a resource based on the provided search criteria. + + This route expects a POST request with a JSON payload containing the alias of the session which contains the resource + whose versions are to be retrieved and the search criteria. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to get the versions of a resource by calling `get_versions()` on the session where the operation is + accomplished by the concrete client class. + + The result of the `get_versions` operation is returned as a JSON response. + + :return: A JSON response containing the result of the `get_versions` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + return database.get_versions(request.json) + + +@app.route("/categories", methods=["GET"]) +def getCategories(): + """ + Retrieves the categories of the resources. + + This route returns a JSON response containing the categories of the resources. The categories are obtained from the + "enum" property of the "category" field in the schema. + + :return: A JSON response with the categories of the resources. + """ + return json.dumps(schema["properties"]["category"]["enum"]) + + +@app.route("/schema", methods=["GET"]) +def getSchema(): + """ + Retrieves the schema definition of the resources. + + This route returns a JSON response containing the schema definition of the resources. The schema is obtained from the + `schema` variable. + + :return: A JSON response with the schema definition of the resources. + """ + return json_util.dumps(schema) + + +@app.route("/keys", methods=["POST"]) +def getFields(): + """ + Retrieves the required fields for a specific category based on the provided data. + + This route expects a POST request with a JSON payload containing the data for retrieving the required fields. + The function constructs an empty object `empty_object` with the "category" and "id" values from the request payload. + + The function then uses the JSONSchema validator to validate the `empty_object` against the `schema`. It iterates + through the validation errors and handles two types of errors: + + 1. "is a required property" error: If a required property is missing in the `empty_object`, the function retrieves + the default value for that property from the schema and sets it in the `empty_object`. + + 2. "is not valid under any of the given schemas" error: If a property is not valid under the current schema, the + function evolves the validator to use the schema corresponding to the requested category. It then iterates + through the validation errors again and handles any missing required properties as described in the previous + step. + + Finally, the `empty_object` with the required fields populated (including default values if applicable) is returned + as a JSON response. + + :return: A JSON response containing the `empty_object` with the required fields for the specified category. + """ + empty_object = { + "category": request.json["category"], + "id": request.json["id"], + } + validator = jsonschema.Draft7Validator(schema) + errors = list(validator.iter_errors(empty_object)) + for error in errors: + if "is a required property" in error.message: + required = error.message.split("'")[1] + empty_object[required] = error.schema["properties"][required][ + "default" + ] + if "is not valid under any of the given schemas" in error.message: + validator = validator.evolve( + schema=error.schema["definitions"][request.json["category"]] + ) + for e in validator.iter_errors(empty_object): + if "is a required property" in e.message: + required = e.message.split("'")[1] + if "default" in e.schema["properties"][required]: + empty_object[required] = e.schema["properties"][ + required + ]["default"] + else: + empty_object[required] = "" + return json.dumps(empty_object) + + +@app.route("/delete", methods=["POST"]) +def delete(): + """ + Deletes a resource. + + This route expects a POST request with a JSON payload containing the alias of the session from which a resource is to be + deleted and the data for deleting the resource. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to delete the resource by calling `delete_resource()` on the session where the operation is + accomplished by the concrete client class. + + The `_add_to_stack` function of the session is called to insert the operation, delete, and necessary data onto the revision + operations stack. + + The result of the `delete` operation is returned as a JSON response. + + :return: A JSON response containing the result of the `delete` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + resource = request.json["resource"] + status = database.delete_resource(resource) + database._add_to_stack({"operation": "delete", "resource": resource}) + return status + + +@app.route("/insert", methods=["POST"]) +def insert(): + """ + Inserts a new resource. + + This route expects a POST request with a JSON payload containing the alias of the session to which the data + is to be inserted and the data for inserting the resource. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to insert the new resource by calling `insert_resource()` on the session where the operation is + accomplished by the concrete client class. + + The `_add_to_stack` function of the session is called to insert the operation, insert, and necessary data onto the revision + operations stack. + + The result of the `insert` operation is returned as a JSON response. + + :return: A JSON response containing the result of the `insert` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + resource = request.json["resource"] + status = database.insert_resource(resource) + database._add_to_stack({"operation": "insert", "resource": resource}) + return status + + +@app.route("/undo", methods=["POST"]) +def undo(): + """ + Undoes last operation performed on the session. + + This route expects a POST request with a JSON payload containing the alias of the session whose last operation + is to be undone. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to undo the last operation performed on the session by calling `undo_operation()` on the + session where the operation is accomplished by the concrete client class. + + The result of the `undo_operation` operation is returned as a JSON response. + + :return: A JSON response containing the result of the `undo_operation` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + return database.undo_operation() + + +@app.route("/redo", methods=["POST"]) +def redo(): + """ + Redoes last operation performed on the session. + + This route expects a POST request with a JSON payload containing the alias of the session whose last operation + is to be redone. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is returned. + + The Client API is used to redo the last operation performed on the session by calling `redo_operation()` on the + session where the operation is accomplished by the concrete client class. + + The result of the `redo_operation` operation is returned as a JSON response. + + :return: A JSON response containing the result of the `redo_operation` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + return database.redo_operation() + + +@app.route("/getRevisionStatus", methods=["POST"]) +def get_revision_status(): + """ + Gets the status of revision operations. + + This route expects a POST request with a JSON payload containing the alias of the session whose revision operations + statuses is being requested. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is + returned. + + The Client API is used to get the status of the revision operations by calling `get_revision_status()` on the + session where the operation is accomplished by the concrete client class. + + The result of the `get_revision_status` is returned as a JSON response. + + :return: A JSON response contain the result of the `get_revision_status` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + return database.get_revision_status() + + +def fernet_instance_generation(password): + """ + Generates Fernet instance for use in Saving and Loading Session. + + Utilizes Scrypt Key Derivation Function with `SECRET_KEY` as salt value and recommended + values for `length`, `n`, `r`, and `p` parameters. Derives key using `password`. Derived + key is then used to initialize Fernet instance. + + :param password: User provided password + :return: Fernet instance + """ + return Fernet( + base64.urlsafe_b64encode( + Scrypt(salt=app.secret_key, length=32, n=2**16, r=8, p=1).derive( + password.encode() + ) + ) + ) + + +@app.route("/saveSession", methods=["POST"]) +def save_session(): + """ + Generates ciphertext of session that is to be saved. + + This route expects a POST request with a JSON payload containing the alias of the session that is to be + saved and a password to be used in encrypting the session data. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is + returned. + + The `save_session()` method is called to get the necessary session data from the corresponding `Client` + as a dictionary. + + A Fernet instance, using the user provided password, is instantiated. The session data is encrypted using this + instance. If an Exception is raised, an error response is returned. + + The result of the save_session operation is returned as a JSON response. The ciphertext is returned or an error + message if an error occurred. + + :return: A JSON response containing the result of the save_session operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + session = databases[alias].save_session() + try: + fernet_instance = fernet_instance_generation(request.json["password"]) + ciphertext = fernet_instance.encrypt(json.dumps(session).encode()) + except (TypeError, ValueError): + return {"error": "Failed to Encrypt Session!"}, 400 + return {"ciphertext": ciphertext.decode()}, 200 + + +@app.route("/loadSession", methods=["POST"]) +def load_session(): + """ + Loads session from data specified in user request. + + This route expects a POST request with a JSON payload containing the encrypted ciphertext containing the session + data, the alias of the session that is to be restored, and the password associated with it. + + A Fernet instance, using the user provided password, is instantiated. The session data is decrypted using this + instance. If an Exception is raised, an error response is returned. + + The `Client` type is retrieved from the session data and a redirect to the appropriate login with the stored + parameters from the session data is applied. + + The result of the load_session operation is returned either as a JSON response containing the error message + or a redirect. + + :return: A JSON response containing the error of the load_session operation or a redirect. + """ + alias = request.json["alias"] + session = request.json["session"] + try: + fernet_instance = fernet_instance_generation(request.json["password"]) + session_data = json.loads(fernet_instance.decrypt(session)) + except (InvalidSignature, InvalidToken): + return {"error": "Incorrect Password! Please Try Again!"}, 400 + client_type = session_data["client"] + if client_type == CLIENT_TYPES[0]: + try: + databases[alias] = MongoDBClient( + mongo_uri=session_data["uri"], + database_name=session_data["database"], + collection_name=session_data["collection"], + ) + except Exception as e: + return {"error": str(e)}, 400 + + return redirect( + url_for("editor", type=CLIENT_TYPES[0], alias=alias), + 302, + ) + elif client_type == CLIENT_TYPES[1]: + return redirect( + url_for("existing_json", filename=session_data["filename"]), + 302, + ) + else: + return {"error": "Invalid Client Type!"}, 409 + + +@app.errorhandler(404) +def handle404(error): + """ + Error handler for 404 (Not Found) errors. + + This function is called when a 404 error occurs. It renders the "404.html" template and returns it as a response with + a status code of 404. + + :param error: The error object representing the 404 error. + :return: A response containing the rendered "404.html" template with a status code of 404. + """ + return render_template("404.html"), 404 + + +@app.route("/checkExists", methods=["POST"]) +def checkExists(): + """ + Checks if a resource exists based on the provided data. + + This route expects a POST request with a JSON payload containing the alias of the session in which it is to be + determined whether a given resource exists and the necessary data for checking the existence of the resource. + + The alias is used in retrieving the session from `databases`. If the session is not found, an error is + returned. + + The Client API is used to check the existence of the resource by calling `check_resource_exists()` on the + session where the operation is accomplished by the concrete client class. + + The result of the `check_resource_exists` is returned as a JSON response. + + :return: A JSON response contain the result of the `check_resource_exists` operation. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + database = databases[alias] + return database.check_resource_exists(request.json) + + +@app.route("/logout", methods=["POST"]) +def logout(): + """ + Logs the user out of the application. + + Deletes the alias from the `databases` dictionary. + + :param alias: The alias of the database to logout from. + + :return: A redirect to the index page. + """ + alias = request.json["alias"] + if alias not in databases: + return {"error": "database not found"}, 400 + databases.pop(alias) + return (redirect(url_for("index")), 302) + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/util/gem5-resources-manager/static/help.md b/util/gem5-resources-manager/static/help.md new file mode 100644 index 0000000000..c79d26dea4 --- /dev/null +++ b/util/gem5-resources-manager/static/help.md @@ -0,0 +1,65 @@ +# Help + +## Load Previous Session +Retrieves list of saved sessions from browser localStorage. +If found, displays list, can select a session to restore, and if entered password is correct session is restored and redirects to editor. + +## MongoDB +Set up editor view for MongoDB Instance. + +### Login: Enter URI +Utilize if the MongoDB connection string is known. + +#### Fields: + - URI: [MongoDB](https://www.mongodb.com/docs/manual/reference/connection-string/) + +#### Additional Fields: + - Collection: Specify collection in MongoDB instance to retrieve + - Database: Specify database in MongoDB instance to retrieve + - Alias: Optional. Provide a display alias to show on editor view instead of URI + +### Login: Generate URI +Provides method to generate MongoDB URI connection string if it is not known or to supply with additional parameters. + +#### Fields: + + - Connection: Specify connection mode, Standard or DNS Seed List, as defined by [MongoDB](https://www.mongodb.com/docs/manual/reference/connection-string/) + - Username: Optional. + - Password: Optional. + - Host: Specify host/list of hosts for instance + - Retry Writes: Allow MongoDB to retry a write to database once if they fail the first time + - Write Concern: Determines level of acknowledgement required from database for write operations, specifies how many nodes must acknowledge the operation before it is considered successful. (Currently set to majority) + - Options: Optional. Additional parameters that can be set when connecting to the instance + +#### Additional Fields: + - Collection: Specify collection in MongoDB instance to retrieve + - Database: Specify database in MongoDB instance to retrieve + - Alias: Optional field to provide a display alias to show on editor view instead of URI + +## JSON +Set up editor view for JSON file. Can Specify a URL to a remote JSON file to be imported +or select a local JSON file. + + +## Editor +Page containing Monaco VSCode Diff Editor to allow editing of database entries. + +### Database Actions: +Actions that can be performed on database currently in use. + +- Search: Search for resource in database with exact Resource ID +- Version: Dropdown that allows for selection of a particular resource version of resource currently in view +- Category: Specify category of resource to viewed as defined by schema +- Undo: Undoes last edit to database +- Redo: Redoes last undone change to database +- Show Schema: Sets view for schema of current database (read only) +- Save Session: Save session in encrypted format to browser localStorage +- Logout: Removes sessions from list of active sessions + +### Editing Actions: +Actions that can be performed on resource currently in view. + +- Add New Resource: Add a new resource to database +- Add New Version: Insert a new version of current resource +- Delete: Permanently delete resource +- Update: Update resource with edits made diff --git a/util/gem5-resources-manager/static/images/favicon.png b/util/gem5-resources-manager/static/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..d0103efa4ddf94367c8e7d73ab9db8442aab0c9d GIT binary patch literal 2051 zcmZ`)dpy&N8~$!18Y`pD+&UHsxwOnBB9Y5RhJ`p&tTDI7uq<<%Zb#xAmxv#gTq?P& zV&xL%P|4=LBN|cEnM>oC+%LcN=kJf-=l#6z^M0P^eLl~h?=5$n6AY>f1poks#n|H| zi2T{IyCgG)!B~=jRIsh9EdV_KQ*M(e{Zk}i@U8&BI1B*H>j1DWp_oDdxQqgTnE(K= z%m)AjwW!g5w({hImtI%PTf%e;_{nEX zR0oHDnL6hEiS@bPjy-&&Z-`%J66(sA#S9MHRU4XAc$6Aa4B^T|b*QX#&7F6nBeUW^ zW9GjOD6+Mpv~@N{r$k$cvxM1%aJA-)9|Vvi=qPydAepo=c))S^^~W)2uCtbbn;~~chxH*=~`i8Cr=gD6EJuB z<4CL9_~YK1q}Sr72eq#JQ$sMiKS%(tT@!#D8%Az7Y}AjUzl!o2atcV~{1hoW_&{Oy z(2Xy_H!o|n#)M^^Vg=FlU(j`8bm*_FxFHMaHw{XUaYH&6FaF@gtY9OSQww_cR`g~% z#cppX^8BAEr>U<48K=NKkoUZ}PW3ZvMNf1uT1TADlSiMv>OMgPT+@7XYn8PAQ)vFC z{e+RWI}_X|e`c4f^hvP1RAb6%4i|3~A2EPfUP+$(P+!nALPQJZ$lB(ws!GyHok;0y z@tVBro(g}?>z4JkAWBvU*Gp+?2>p60*&x3@G z-Re6--E5nr%?g{vnXGGm=9i}GqMg;a{pc4(ieq|NnqxLqJIpm-m|qvF2{If){!r*E zxOKyHPG=pzpxpjJdshJpPn%9;y zq9;7L9D3au|6Ctcfj4wcAdG7Pw=wAg4#?ZhOU5 z9-0YvJBD$Wex3Mcfa06i-*Pb&mM~n}`cNDoV_53=YT5py!lOLKBG%ST${LDK&Fr~O zJ7iuPMK)`jk>%$+foC>?3!l^8|3#@Bs%n->n0Om(5gVd$&FPPDL#Io!6>kims8VuI z;rVwkX^?}Lr^vAx4dx9h^I9Hy*UF5rXoTTr&r5@tJVRd}NMwRA)cN=2fygO#wRM&m zChS%k!#fM98>Zpmr3rr+JUV9|L5^^s?!INvE(boJP5v}!7C*Z+z5^1A3gY|WLy_eh zA&8{z{M!>3>Pv~9Y8WptBL4Hy?E6rahJpj=bY7LN_Vc_Srdn?G9e}7Ga(1au?ougF?>Y=0u|F! zr9v1>AE_ntId@;N$X}+%1rHKAt~Nb~ar$xXDC`m@zv6hQNbYGKXu3XN_dxFrTLJCG zQP-yLW6|^#DRk5G8qkTcxtg;&Zd)_#590y21FKzLE5^hn`{ldaaq*DQ_r?5XVfWj% zjg;_|Hm28!*5&R}IgU{=Y*m_UD_HvL{JA>TuGRd8$llR+p6c_`^yHq=N{U}-2@;QY z4s}mkWt7ou2OfL>n%FXUa?}j8s!r8HH5%Kxa0nb+nn0|_JaXLg?Z3s}zFC(KKK_7Z zAT`&CX40W)4t^#jvim&d12Hq19RtJ%Ad<~Rr3KwSMCTEuC2%pLZym*4&J9^*RbEd>jbHB3!{J=q1GofE?!pIvkwt*l{1Dhj-@NWGU*| zd03g+!Ta^8M~p!W0>u5`t~-T;g7d#$P(xAsVzC=iW7%D4$4gU5*%xw`0?YVH1FM-h zy)RM4b@3}M&6?B^m+3F%-#QDyt_Li7mG0yU_lA?no z02rf;QHCgU!(*nNC}T_0W0uBfeaV7C6}kI8`yT@(GBA`J_x}ywVN>!FgUZi@vyo&P zofsVi(CKue(1`FD5|J8Y6d4^{D6&$O9Gzo$`q1!1I+7Y4Ne;afgrvn$gOH(A8VLZd z6iqJ5%SL(Y>UOztdDyRb0HP&lM3Pg|QgX@J2T?-WGfmn9AzHPbNbWGdvxC>6-XX(f cVv3!OfEfgwwrFRXD~SNG4mkT7yMU|z1M+o}Z!6(b8(h-(bAbmYADRw9Jl>lboHO zpxEZTyuJ;h%HZ<$V8hyh&*ISR@(iNMXT{w>vCP21!hp=*;NamvuE@yA%CNGu;o;(j z(d2^Afnd4LiHeQ)_xAvoyL)_p0Gz@AlC_D8 zju4f#0GYo4oWTH=y3EbaFr&W!lC=hfBLjgOL|qNKC4wF#lf0Fko= zpvFL~#Q>PTP_fAXleL?ho(G`Ej*pT6ox%vA$m8SWK&!>T7z~%1H>++kNp6crB=;-O|>+2AkyyD~I`1tt1z$sU zuduR;i;n5(>gnq0zP`Wc>FLMF$&!?p5T3vA@bHn7mgnc_52MTH=jVXU;Ogq?z~$`& zpT@nuznPky1)#@Z!Pt9zex|6Zl$Doo#Mj5i$A%3ix7_7~g@|Cf&x?$XpSr=<*Vvz+qL-PR z>FMck!PJA$b%6A^8LW00930EC2ui0CxiX000R80RIUbNU)&6g9sBUT*$DY!-o(fN}Ncs zqQ#3CGiuz(v7^V2AVZ2ANwTELlPFWFT*({Vj%brcUw(Z-vbL-yCySMM(z=I1PPQ1ABpQY2=YX4#^{uOg1T` zk{A}*86}; zVxi}rc)n?)nsrXtW{gA>YA7g(CThu|j5g{hqlqGFXrYJ%YG;j>W{T0EFly>4MV!9) z>8KEeY6PjMGBhZhskVwxn|Zqbnv@`u)@tjmxaO+su7wKm+L>?a35cvng^K2uc%1R8 zjKN|72qnZGW$dw2CJS4Z%>q(I710_sEwxBmdo7IFZktC!AF#r~1njm;11qd_3)8pY z0x9me{*+rq9&r$)ia61fkj21-*kK132qWyq!VD0=!3XlHL~p%4-aD?o{ATixD%kL| z2pR+%obbX)lx(ueZZJ>}#1WS?F~v4o3|lQ2#{mWy7s%2C8X#vOG8ZJ5+{e&F6Mb?C z9JD;r%P`L<^UOvFYp%^;G||MzAuDWhA4_!Y^(B{h-SyBVGmx~>A2HoDj88-D?9?|~ zjkV8OC&6{smt3Lu-hAu-?R6g|%MdTx9I3r_+pv}5EG7HKkxA88gIuuIcQ3Iw9hh68 z`R16@vG>>|6QBy=8W|2V;)%aqMI1IW5_uMryCHPfdS|{l6S(KTxfP!Ky#(OE3{JX5 z#-?ce@gpjWTPfN$4u|~hty&J{rGR+J@3AUPClsS6Hh6‰K%zbuSLf+(;J^R7ofpF-A1Umsi z`{|Dfn(JQ@WH7q_l`4SY8KC;02Qmb5ZGrQ{ode+@h8DW;g<_x}9O|Gy?_Hs5NpJ%P zJ@^n~oo{uIvzp}p5H>v&Ht>Ni^n()lutX*Lp@lN6!~Q(?yBzM2hpGZ0cuFxs_R&pt zw6oq3lgNiMl7bY3AOtDO$iyd#;ek@bpcVWUJ_2Adi#Ix79)id|6IxD;OsE4A#oz}s z5+V_Zlz;>fnFvCZQHe2};r22ZwvusSe0NNU55*IT)_L(@)6<*gm~eAkN_$w zQ3+Dt~ViTJX zg(x=ROjs^*jc&9h2B`=*E&!l|y(Gvlg%f}-nDd-nXhTIp5jU)Xl9<&?p&(m$%0x6X znx2@1KK1GU2~SY760)Qv1t&R29J+xE{NRZmx-f(xM4|`~g=j8Y95RL#5CMLB85CvgHF$qFQg)mY>l~f2pFhokm>B~TXXbmm}kt2eTnl@at2ukRO zP=`v?ekdRkitwmI*y*||X+2RT{5_xS&7lvzG%sRjT$(4yC)-VSuApjAG z1&Jdtp{46)w_S#uLFkAS(Dr$r~x*v5(w;)GYG-4Xu?AvKH^{qi%G&DG1eN6HHS6G^fCudaDa=T z)Pj6=i1ZZ+5Wrf?Nm6mYz;#K8MJ!+jlSC23rEz<0j1mV|w_XUCutt1Lu^@ZIbZPpq zWV(Q09kaIx0We4?nhLuVhvWy1kbonfXv^LvfeUuXLVr`jWG5%s0g4dGBbsbx<2vB~ z4k!u4kDG=Eo?avYb3UD&OSiTg2?4!~3BY>WoZumtn92aCZ%9bsiAGc+5%}%i4Sk!1 z7^9>O1|YPE74Y7Uv|-SiesYvYVhAGiIYx*8^h0QMY8a)O&#k5r0`|O^N8~uv?B(=8 zLLtONi-ZIbn8YR?O^7FUf`;3yeT#+FJ zJi!J4$%exnBOy2B3=3!YiyU5&az|Lng=qtTF{_1+d;H@cZ*#(t(F9q<8zdJ0AjSbk zFo{NMInw%Fb`}6&l5`(DzzQIEL@<5x1m~P1XCSY{$MkTa4;@fF9Qusr;O)QYVdHH5 z_!y>6^{Q7r1IZQ4RAKXCY5g0|IQGxF+zqqVfK*PyHV)LG}R|%b#h{oOSbDdKp z=t`Fn(gk7&qbq&yc+5MDm`)fy+nm^hy2oWNP;CCPqJ}`zSYT~Ev_%vAm`q;O==d5N)6c z`KNyt5rQ=mWU8hRA7WuYa&7}Lfj%N(S(p$XB78UEg&*`I2p|L)*ARw)2xeF#Bghv} z*KyRhc-O~*U$BRK*oS-Ag4(xuQx|z{HG?7%ewRmnD<^h4ND5s4mS0zJ3BFYbXs`%P zz%m_i2Siw65)lAQNK{Jb5C#`uN??Q&(FOfyTnRT35$7XBV1W=32wd1B6xWJ9@`@HA zi$+3m4)HBURuM$@Bd9|ck|0!eI0krVeJkjPX3&hz_>6wIg4ZXAFsKDZWr!i+0}YUf zDmMc4wt0_;JKXeTVOEJvfD9g?2iF!|7oi811&VgZ5M6L>hL#a`aCpUKiVhJ7&c}-t zAq38cQV9Sg2;c}A;a~w75!3Q#2Wg8pf(d-_2*!AadH4o>_>5+t1{%4M8i|p8sDjg2 z27@?M*obmBaD&9qjbYbl#Ks4^<%3lOW@%?NG~j8ecv+GE5RVlBaPZiAQ`lAt@Prug zX#ysc3(J4mTHNX&d7%#nFiF@aV7Z?DVLHemxEkIP3iYW$QE-li3V2l0v%C|%{6W5 zm}8;n5TDpqtLPD`_>*;XE!iOr=1AvzG>(sUfbk6SW_AmO4oLIk0y zcO{{oGJ>9OVG0ykmin2I{5b{x8K3|P1x5-5L<*p_*_LXMn_r-UN6-x-@dN#&Pouz9 zEoX0y@KyLmLA*6b$`+Vb0|xJ>5!{)NJMo=pS`uoCS@rmVv}h9LNhK`W5jYwnI_gU~ zViI6TBQ#nUJV1TQ*qT7vpIZ>1N1CWk-~@^PdZYnLpiFw8Uw{O~pkntFP0}xW%IKPfDx`<%1&X?;%DSw}ny5;;1(8|~l^PNtfJm#Le*quQ)QVuu3Q@Aqclf7kVJ9_(`n% zIh#dlq{=D<3cIij%dpDor~(SDQ$Pj7U|(f~N)nI^ij)k9ltz!_t#U+1^glsVBTj6>$ zCz}y%U|jHu69Hgcr-~9hiCLUz5XO?T9DxW(!nbzXBSTvxFp3hrs;hC~1WHS&O)I1a z8?_2cwMa0zlv}xzOSM?bs7NXR;2;vs5JB|hL~PVXZuCZybW1k`t^*^OB^w8M5Dpn} zw{~T-JYkrw+7hWMRI7Rrd#e&>;FU7+rz`QhI5M8%G;uEB2sknaa-k24>zYk#u*jOQ zl1sTyaJ|@@y_Ji(%Blpg;JL^D1iCK-NiPIP`88I#^kwZQnBr=(c~A-&F``6OqBW7b z{SXQ0l)w7Bzx><3`)j)^3#anB5=Gl1fa?(jJR`!}o*Ot4PHB*E;SKm{k%elo2TlYL40#{ ztEWY*60`~<5bP4PddLX>AqWQ?5>tr)a1j6l%e1n2#aXPuNWj5S0LEm{$)4QFVH^e5 ziv)Xc#vefdmJ?4YL_gZ2J>0`NaV(Q_%(ggOt``BoZDo`ihP?i~4$q1XlnfwGD{KcLu0M>lX*6hh&+`;kC3nD=P#H2vAvpd|QJKobf zptE1AYc)5#EwGCbFDq2++7tHM%bHev`Pve|+rT6-l}W5uIHJgFp$rrpy+xYETP)39 zoC=+M&0+A+5dF~C+{vjx1qsI)#aN8Nm@LhkOa%=s01>SOO1;z(oz2_8 z4&Qt*Kr=hkb2**EH(`^`2UXJSY_hIf1(d)I83DwXHN-Y?t}h*M>?p`K(#RVzkT{ae zDgoCvBG)z%pENR`Z2=9G?6}XY#Y9a73~kL2z0_=Q*oe*456ua>AQBfaFd`E)LnAhM zqc>n9Hh@FJ2xAA#HpeAf$2d$0fY1)+T3js)6MCH12iMX9(Yq{REX*qtuH6%UYa{=h z7C(KgSS$sAJOY}GwowAQk^hh2H{A~GfG~v?pxta zjs=kajNzDta6|?#~>0jFf~*IIeD(<1XBpOj_XLCTW&=3-ImWz5x613L;?+s?#{Lj_0+`GrP{~ zJhKRv*wxyd2f%*lMgR&N;pmZW6Z)PMv%TzoMibEfBF>HzoqiV8zS~1R>iDhgsNU`0 z4ha%J@en}nA+ZKgvpD8r=Qr~_>V7rwF6fmQ@9IwIb-dl&jRkO03;B*&^UM>D?g0M( zuIwr?@cvNnlpgS5KJ99emY~ktqR#N8zTc_-<_j?KoRIXKQ1K$MVa;;x^j<(6&j<(p z@gGm(w(BVTN3MEdYSaIM(j141NUN00@jP1)iFiW4bEkUWV(g$fw~VU)0u z^JmYX1&|zA8uE~he$Wbgwu>b-@smfERQKdemM2V@=qemSg5-PDsKd@oN zD(PC*q5`pL`;j%<7G#j34}-Y<$S|(IjdX?Djhk2RUq^Qv&iz~1aL0TkO`=rE@?}h! zG;QMC*>e@p!~cj1c9_+O(xptRI+a?LDIm~TJU?8MS(4hc0W!Na09&m8p4qwK3MQNz zA>X2YeML7|>0DZ0j}i)kh~YQnBE z47f8)2MPlDuBh;kGVi<)i&8JMHtOrg0R{ycq6mcoP|<-lS`@-Fd`;jl!gh<86)ZtJ)Qd?LLL{$~8+8p^!HISky~Ut2gxGRkE-`T!J~UNS06t5>@;9L_qQ&&#f(mvBTi+CB zP-i3q zAe#p}Sk-OO7S)ica~vB4L-|73O6TVFkO)CZ7#fE{*V z;r81lIYRG_rfg2txn?$e<#MCm`VnyW86o)Brq+ z2qFQP=$v2>Km;L-4?Y249O9Z+!NygjYg)_9rxbAiy&LiAYisz}I@R^b78dJzQi?lOlpzEDUwIA4=eQ8A1C z!6x;aUmtnc!wRuM3Hs|_D*i{rBD%|f2$Um8q*osW$i^*g_#$kewJ;lTrwff%cLZ_=#e)6XfZ9I42dYacfy^46CtfiPaKn2Cyam# znKlXr8&XoP^pVa`6|$io?de1O`Eq~#`yT)Wm`J`E(3tBC341cR7Uq4V3y-voH0N{B z6%FB<6lud9plKU!e#D#o5$7n&I3&T;%bXmETBH<2&?BLMNll8UJm*PIm>No-`}E%- zCsxE_4iu#y`4mKzFa$|fq@tdTmP6wM(G?j$UmBDI1|d1oQHju_!7<}U6++H8B0>-y z5gxJNxYHwLW0oy>387pnQ?$-Bh&2V^Fr839fqvnbV5LYU52}D6bOEYeP=xX_Y1D++ zHIqs(z#W!a5Ix*M5*N*6Mme(49d-2oo2DEmu@Ha=M~rkJh6seziZzF=(p5;=kb? zu2Yp;MT74DeY z^kz7{z%=A+Z;Df2EsDPNb;W}@(o+DZ*lQtqjfztY-N#CGvQ|x)WXaY_1{Vttp*69M zU?GeNmv@FPDJw8jYh>BFWQYO(jPF}JCSu*zHw`83aYY{CTo)e~uoJlhma_~wMTAnu z98EA8sX7ry<(O(j&}@|hM2mY!r@W^nE0L2-13h@yU7sp#>~d4>X|2U2IZ(3QY9?3b5tNWR(y z)cO8!s;M1Nf$mn&*&f6Hw&y*Og@QYpdg%h9zpR9W@>3y=npAA|3zeL6ifX?J|r(3$~_t8x-Mih$=u4 zvYGYH{}O<+16T=?2>f3ZhKKPM2*QhN zf4vN0*8*|{e{02}9X1LmY~9-~7P5yV0CzBeaoeMWNUR-vP-H#pJMJ4nw7&I)Yf#6T8v{Wc#K|i}5gbJ7yFsMl zK+(D)g*zxljPKtHq%K)ggm6vRse!~ml?M|{M;nnY17!b;4fP2|KZi$s+AL{O}? zQGCT5EX7uI#d%}JSyT~KghgEpK3Tj)T&zW3T*O@*Mi1=8U~G?EY$RJeMjRwYXM{jw zWX5odwPln>5`0E%^uK7dMi=a{YUIW@%tmqKMK1%#Ypk+wG{*oOM|SkMZB)l~L`Qfm zs&=eLZo32Y%SV0OM}F)_e?&i^3$JYYM}jO!gVe`>v`2+pNQP`khkQtgj7W)`NQ$gT zi@Zq1jLb-l+(?e>NRRwTkPJzY97&QaNs~NDluSvLTuGK}Ntb*{n2br8oJpFjNt?V$ zoXkm`+)1A7NuT^lpbSc(97>`rN~1hVq)bYsTuP>FN~e5EsEkUfoJy*!N~^p|tjtQS z+)A$OO0WD%unbGF980n+OS3#nv`kC2TuZiWOSgPWxQt7=oJ+c_OS`;Fyv$3z+)KXf yOTYX}zzj^m98AJ2Ov5}(#7s=ZTujDnOvijo$c#+MoJ`8BOv}7X%xsH*0029sic<3c literal 0 HcmV?d00001 diff --git a/util/gem5-resources-manager/static/images/gem5ResourcesManager.png b/util/gem5-resources-manager/static/images/gem5ResourcesManager.png new file mode 100644 index 0000000000000000000000000000000000000000..dac4cb595e608feeaa617056d9da1c116b0c06e2 GIT binary patch literal 45905 zcmY&M zCoL*2eODBAS5#X30pag#KceSEMAZpsB?Wztr(5aZfIG^E*CpQWuU`a$upBu7%ZH>Q zwAv35y6gc!s;_jw&v7v}uUo4T!Y~*X#LExJ$qFbeypvPN`wqbBapMZ2s{m||b&8wY zzCJc++AiAu?fuMs%_DPFbJF{;xUt^utf^e?Jq(2X|G$xJi@W*|oVcN%b>obEqmuwq zOog<2TvXXI$Jw_0$_)S5!Mm!;grUFlRBZEI447M5dL*s0gzJnsD&GXj0=Ti0BXE7XAy|INuNjd>7|IW@ZZehyqE~8KX5Rd z+p}LTKg2NIXz%_Hyk9=a>$7QcE zd`q)!XTW9y?`{)_$YY9A0%osO0Y1@7Fa$F_C^po?x(9*N7CB??Zj~&SxH)Fkg{R7| zm^)Fc{UgK+DgasQUc$ix+}(6dEQGlfzErX?I*Ua~*-QGw(Eb%6=88%E5-;t(;9sd+ z`0s_+Z$FrFw0s1Jwa{uy_gVQ)X|<116HU1{Ier4`+YyewhkWwa!oeF4%qEXJw=Y{ z-7U&kepL9_u_uM=t~jLGPtJer8LJZ=8he;O;Sw|8@g#&mOKt6T*KtMTQe!$y@^t&ZVlKtIs4yGXI-`M!931(?c!+_D19%kGDqFIa39{bwG4u?r^-3 z`Ztsgztj9ZH#$`FZrDiEKPkD#J~)d3avaeAyUPNH$8`I&-IS^jek1m8V0@JuqBlif zMUFgXC#-F9lPlQX5G8xvMq?%dGK(O*pFKFT4+#w&q53yjzJmt+=)ha!Dkpb9>?01O z$W}N%iBpY-~&&Ak@7d76wmi+AhH3)k*TG{ zk(TLynV)OD;@y~$y3;UJvQ=KR(B8)>u6#$a7@o5C;#nII{L}L1Spk&>%h&Z5wz+-z zeB`={$)x}_Zhj@ABt~gtO(_SAE8P4@1B!IHBcG}i?E7}5tmT@2_^r0$)@Hk$hZRZ< z<`%-y$GI_PwBYxk$m43Ehh+`;cB}C@tJJg1o=DwwdZ=nC76u>N16oz}^|LuuwXONR z_@VOTY7xBf)*oXMkLVS8^KrEe41dOBA2`A6X2kH4Y}3rSJLGAwmoJm$7o88ZMdzy> z`|firj#00x?m71t4-S3Vem5x6@K-ti>H5t*e_8Cv4vv!=xYJ8d9CY{$8oE(bEU{Ej zbX#H<7+|&7U=f-r80ErbRdDDLZ8;{gKcJ;A_%%_-`T}2H=V7zoQ}^JyF>qDuY)G*g zqR^Y|-hKa=quuzion_6E5RXtRgBHwGJWFml&gX>xR^1Hi);$eDF&WF5ws|AEjt5F> zW5Bl4*O$hNy|kuZ#pV4kQp?$iP$!J4!W$e&--IjbZZu4307h{Vk4BhFgukmA^&J&P!n~6oLYEMc zXQB?Gjm}CD6)*b}TPIPqnUIEHbP%nOSnch@8J^(H=9$;|KblV0D&$ou%;kd0+TkO+ zb0BOCko2?Y#I%?FEh_7e+>kF?fnEb#d>GsfquGt287)UA)^5rt9bdsTwJTwq$sw^> z?erx^`r^8|=|)H$I!#_Me4_1FW9Gb1n$T5K*XPNm)W~)q&8aYnLT`Yzk#&|Nts0D) zhE`o$9meEbBJ=#qc8d$=n=I#K5lifgSIeLXL9zP@)pPS|%vjH?KGCht#~WomYN)MN->5lKvk1q!JB_`DW9+ z8bnKPxk1RAkzxWTqAzsRS%bu55#srf8LJ!mq%*jz)DI5<#GU*%r`qICl0e^nLG;bO zo8?|}0JmzVX}`U?EBgB?QW4jwiyoYN)hOwAp1)@9pJPh-P^?#t9(Tvl&QH~RnVI6~ zP?P6al>Xq%6M{D$|44&sLXI`4YQ5OA(8&69tBRWflU{XhPw(sLI%DwV?>n9QBkFCz|#(4tfFvLk2_&}o=L|lACIwHA}Z_>DNo>3@WRDwT*E^#n8 zo-}PRc<|R2IAH@;g? z>EGbK#*Jle<}LpXjC_lA?F~bJ_vhta%*?=Gs-JIx|NZMF?lQSf5iTJLtF~ zWUs7!%_EfVepAT~QktxXfu!((h6keb+Qb~vwCd43F}y01%=uC6ZW;i~pepBQ*3Y{3 zY64#|Rw_6y2Ta3n)N)w1G_L9%k6&Z`tOf&5gZprA211^YlFe$e8$G=|2Fl$?)?MAn z_PXftl7CqE;n;&pIKv;a6qTp8V6YJ?GO!C7l*L>bz=j zxaBXum#XYzkS5e@7zB5#$@&}J)+WFs`SVt;*;gm!peBGj$IsUzY|Zp5^~+@V23{rRl66Iw|XCbU^m_Kf0m5i~?$SRw}2P)+NUUhbRptnF-G3rOpdZKnu(hxS!jlsm99W zJV9A14#lsc?-qj3>Eb#-+#$)5e`N5;gXUvUZ(?!@XbQA_e>50S`LeGr@je)2LiCz z^ki{($R?Tx+I~<-uF-VYuewRBYPa*{)28W(l?C07j>Bp4pxF1^pfVVJ=Ef8qpVo|N zML6jf7-MSW`^|Q=85I=OpsOfpc003CwiLuZ*pMnMTeU?8J`be>+y@LNB-XGd=Y-+j zTuPcmu7q`7oijtxO7+mPlKJModr!}~41=Kf76Ao_UiPTcsV-<%=y6kw6M)N}Tst$ftLUTazct3lV@d=AH&&DRe zZ)U-MX~FUSt+hO!(L;y?T&MJye8e?t^3HL`6Q8Ry<5Dt`uu^Tpf|biU#C&dtoyZrJ z)mRfVNyfSDTegNB6z|<+?DfoE0jg$WV`qu@9oQ&`R4NqR+T_n%$w^#=bU3X}@mK^Qbcvtb$!i)%;#zx1M z)=K+()g7xgAyCXS&Y<>2mWU1uNByX#e7PSD)|X70G8?aSp7;M^6A0^TZ>6MmI2gZ5 zRG*Tk(ND3heGan!`lpc%BFqd+OGho2^+9XN^KUqWd@B4Sa2)a^-TU(OG;9@OUXO)! zhEek6bgs}pa-!99{XoAOA?wLa`)~ye|1NJi7^ub#T8ZcGzEf3`Gdr0S7Dr8V~02KEZX!XssKprz*z_&DZK?PQnxO(&j5%CyiSQUZ8M_OJx<(!6K z*w*8oy3CTjf`(;Ov(`n7Gp9!?`J_K-DF1TkPfA)oO4@+aXg?GHA*GE2V;=;mup5rN zV>Q7HIf|c*;%0g9A#P_hoiv~~cS#KQCY^UP&&X$E6~YaiboQ@a#(NP7-lQLChqpKBpl^=rG5H|r?mt9+P3=!7Zv<-0d z-qgMlrRUB-HN+kC_LkmoUzJlVb$hQg_;P6O&j;puI|CHVH=P^{;ex)f`l%B+6G(J> zYVhXcZ$V|o>!{g(y@m; zAf$p7h8MxsuU0hHxhW`n>(vV4c3MwH7U6NNIdLXaBJMC$^uJY2R*|o`}nc>IaN$bJUQ}_FkZkj=`htqco=` zKkySAw1svT81q7%q{c(~oTS$_D~^kvtBP1&x+ z>4h(E5mGW!ZTa-zhrG|nn?H}>(^`jZ&BSey(MaT{W>S`$9ut8G)Zr4Z(&L)+!z_he z2a%kku4~j{q{hZjBW>OvnyC^?S5mn}W)uGz7U(qcL6hA+QG$vc_mu3xSnAC3@-yfc4O`DHu zzISA0{`rekb4%b#L)z_O=*fIX#?A#x_L^k>;dN-)PKL=~i|gUW`1RR0JGq+vmv^2I zY*D^}zWl*rM1rC>j45+f9)&}xwpFOoV`)q8o-Ve4_wt?8@*!wgt9aR_Ld#OY>2Rtp zav_WRpi1uZJ2K1B_F}EzmbpBU>8TA$H#W-s>^9mrI+K1XR6eERfUX2h07BEK%YDL) zS=c*PS^`^|hrE^@Zm}CzlwUB8jKG)R@R`^V>yc2ag7j^V?z6*fm-5XPWvMHfzlS@W z<1`@^erqxt=OBB@2T{l8e2?-k-sW{k_6NhU0cI@#@-&F6@>yBX68-xar9aie!9$iv zF$}A1c{L5|lTjLr6KXoo<+haC!&>1)Q=hR1!Aj7Hm&~$Y7UUOh4gSjC()?Z-CST4RN}g?9 zCznIju7z=wH^Z!FHrzJd-*%5Lg%XjnPvKWolNQgfq=8cv<&Rg)eU@WY{k+>q7)sZQ z(bl_nq-L~>k}&K3nNQZPyAS=#SEQSc7auHK|7zIu|7GxH>u4b5o}E^I z*!k}@Q*RN8_ut@p7dnaXm|wf;Yo<8ha*4K143(lBsXxuZW-c|$=?$*9PB=h~?fZAz zHP4bL4`x3G%nc`Ykbf~m*{MIIz(K6i$v z_HHsM@r^otPj1$h9l|QzF#YUF^Z3h);iBGg((Rgas>}-9>^+_HD((?`A^e0LAjz0$qct)cjck49400CJ?52|q-Wcz+1 z@NP7=&uhVRdV_P`U55FL{&_e=`u)< z3)ge;s(&u8YiD|JX_yhu^;NOPZKDWjl__}M(s@Btq_f}m{`aplt<(p4)j3ku6yX?g z)nvpvgr4*b%Yf#{WG3i9h1hTz6i4!YfaUu;Zc6V1%NhK@P;&jIwQ9?ymh;A=_RQuH zDVV2|xU_T~aA9cF2}*_~dbylhQ1{gDXu7A=_R*NWI)~`V#;Pin|0Z}wFo6_oQxNX| zSJ_;OEjOSnS3)$bGY?>07YBO3D-SyO@Cfk=I_mDD5(h%DrnClMTN-O$ER;%H?L21u zC=d2OYhQhR`ZH?^!E@$xBY_WF@i>`c$gy&2iMI zd+XG_WegVY(_X_YHP!;kHM{MXo8F_^v$VTf9rF_e;|S}Lr!#;D+}SoW>Ni5)E=hjR zL}hJ2ehHa296PssUZKv5+9xoEG+i?1u)%Ba%zrSgzH;#K$P4bO-HVrmXm2aHQyIYi ze*d*J$;SG#!GLb>Jq1HHiEQ(xwgyR$yA0=XIVD>5G>VFfY2F#e$Q3gH&6nzDjUv$;Xw2H_pgt9n>`Y~tI58slfUE?k34w7mX<8v zUSXA0Pm6;`L*Oy)$j!GuUbCjk)UFffF+G>r)lLL{2clpy=4T}$R=~ZgMfG<+#(WDO z#GbsjtRBY9Z77JozM0}dJf!-0>MgD5EK(pv*83>&6W>_*>-ROxX}GZVW0%`3W|u=X zL((O?HPPQton0s#MeX#9&wg^9@dOC~!AeEZB*a*YS_`~Ir={Eh3NcCY>44h4l}UDL zO?i3iTjvxf&!kvUCZ~e04m_>AB*_5|h~~+Z_Sw;lX+;kEDX4JJgx~YO!YbapSs=>` zwuyW3LpEP)c2_}~v@4Mw2F~M)K|BorVsRH@{k@julr-YH^-u#q(j{a7&fyk2ZClS- ziDz~`Io*8P>1a-U`3zU5Fx+6$>=Gyl9_=_I?~iKBb@dPWkb-*w7sjvqJ|o z?7afObLnHfFEuAI9MWW6A-^?>^0BcJ%?+_g$d=bFf4pC)$PoGdVDT$z-GPb8JYm0L z1gm-eGKFVlX5H*yHFoDDRP2b#0NSV%_xbgj%a><^jbCK$Vn+V1eGgb)L1)#$$oH5Snnhjvp|a)L>7 z0LBf;09zpE7b;B=MW<}`rTAfMpsWr}iR7jHgSQH9`ojCL?u&Dk_NZ@C)WY&oyZ(>x zmLZyF19)z-+hMiI1pVnS>^ZO1;v$U^uL)s$KC9M7I-JKiSet&!wC8$teWr?S(c8(x zWUoQ500nRWz+;k3-OqzQ;i*ySL)RbkYNn^$zr3gtiGhDdLOdjlnx0*zzZY5f1aQfY z>^-UvDw(};m@cmE!x(aF*;yvJJ~ArmGSwYq)Dyfc^km;bid645Jm&iNaKUF(*DpJ5 zuT%^%DOT*bvub4yBLw4Ni%!+g2B*x;CZ|(0gTTZBn?*)98e*=2-(z5?S0G;*YSpdA zXKyZDpADwoXCe1Yj6kFY(0~jbZGd_$mGM;p4cO2$K=b=Rb)Am0~E_J0`vb`x@1%9N{ArI2u z7;vEh8B~df&pq~$I}wcwoRb)kKln}L^HW6D?ezO=Bf9<^RapI)?bkDiA!M0GQ8u%4 zNbTlKs_8fr*`b-!jR~p-kzZE-767m7^sLXgy=|DaMU2u`CvgE5xbyYe;N;Fb{&g>)ia;4hZ!^R;j+>2 z*moAdyS5fD&RC3shOHlQq_o9s-VOZtGdE~3D7#rG?BG57NvImQ_e*vK?VeBjSy<;| z&NxIWEDmu?p_elMaKMSCw|Hz-T8VGtG0A}@l|{s(*Cua0{R;^60^}s(Mn73E3`&P( z&|P2~@gt0QyVI#wk(f#|n7%VwcX^BHENHOCk(#OH!mEL_m3IR$iJ%7&KAvm zKA9Pk*{5O1DNX|lJo}-8_60WoVe3_b4kaZ8CZg4EQeV?nZ|u)V5OYBy5UY3Ri(!}% z^cx@9Lq#K4gPllarz(3}HrM$*tsgUsB#PD1r+IKhOR9zOa*UJ-o$Ml=YvNNoai;WJ z<+H2UDmK%ZeUak0SQPpfh0sHK`JN7=vPbuKUz$C$$dew3et7RI^U~4#kFeDu66b@3 z_%XTVB!p2W!qANC8@nJHW>CZv6Fp=3DFdO`Uhd3|yk6I*Ikt_MF4h>JeK}Po*Wdd= zK~7BGA7RV7u}udLO9+^sj2v;}E@79>dO6K~Z{($!BV(R>qIPj6MLl?y1ZgmcDwX%a za}m!acDf`X7UNCWYPDg5Pj5=$#^IKLY-X?~{G&F_0G}^D_xUbwY%3H`lIf5cnr5f zLY|!^-@<8S`h$bi@#|X&55Ivr$re5!kXe&LyyGmMYT}83!(N)zEtiX3@M;xSx4Y6P zBKaQ4S5*bEaJ_)h(W-mYr|utLnY>W1852QIRxz=cL}gtGX6nl`yU;i=gA9_WON8W@ zxQL6#<5t-IqG4siP7Hxg=%bsfcTlg_fv;wRKrM`zsq38V380HLc+0RIFbmT49tp@G092yzf4mDDJBqjFXBZ*KQPjF4C zbbGP(A^Rdt=u!O)@H_wVrDN5v3NDf@^|+-ZgG}QjTkRX{>O&ZD#bm^X&JaGmkx!~@ zN|40g5JRJ1!>DiE&kJYis0*a)WN2<)CU7&E*~#QRusa+@ApNzk|K7|W`GSJ>Ef(eu zrJC%gv*}3j@x}`A>3^K&o3b6ZouK(+eNLjsR8kR|fHT4AWmU9_97Iy%?IyZVpLnKt zF}stByu}=CT zl3x|!THg|+_lP3hEPL3G)@^2{Xr8>NvWtbswcTWXcyhm|%-K*Jp}ROx&4X9k_`b0s z7v?ANqnmzip8l13Tr%5#yr!ANdjx7vO85F6X~D(pA1>oca-q&MXL zzH)?OpA4Ns1{-!ivcKe^xG>&h~p2@b!)tSR+ zB4u4K>u2H+f#wk?--t?KmEsoX{c*m5q)ZOZ7=l9ky7=APEVNy9skbvx@%XlRol7#r=>7vM&+;2}1Xa=lPoQ7^5aTNv6i0Ua+zrIE;mQlMWDAet zJ_kD=XCC3rFuopD9^$BaItFigG>6!);mm8N9)o?O@w}Ub4=TBgYPL+14B2Wm580|$9^ZPdsKK%VAxVvr*^7_zPCbuaR9((gVdKD-C^?Xy9D2^-d~pn76u&ldMEGon$+8|%NgDX^CCQ(ZguHOycMh&^^w#;nD1vL`{IaDz+G0n`qJk=!uDN$IK6jA`uFn|-rzepOp>70qstD31*x|=nF zsGbo&=|q)q3JEw&J$M6p{u@m&Imw{CS|}LrI?zh7QH#={T}~nasKFshiODqUxM@M= z0EQP%>Zrm%SEUm0uq-M?H7Wbjut?(NDWx$u?5^(h4&H~%X&G+$8 zgf26QILn{qO4m4lM;7W5?F06yVfsDikMKcGaP`f&Ur7dRMd7hFlUGjrvi=@L@R$uC zxbs+^3D~>d;?v9Xy`AyRhx{CcNk*$655VZURc8*E1~eHnzpabn2fN)@J-k3E&GWRE zvM|q*TORl30d?>yZDnn0b+q1#nI=hw+LhYt>iNmFshyskiJX+iwRtDN!y-51BSuE$ zjIVF{(64yB3}O%&Z~uxkzq@~KS(CVlGg)!e4kmWAHXYPrZNyQ@m?bM91u?t5>=&zQ zsUsZukw}1$m8y9i1N8>467&{ICV_6N!#-ormF@a!vN`uXtFj75fC~G3^8WkIR@!<6 z?V9_wTGiA}+I!k%oDK6wU^orI+dyL+o%$Td7Oi6+CrxE;Z5GBSeR%i^tBda?kP;D?PDhG`G=)3a2|u8e?vXe|CQ|mJ;t&uh^KO-3f?@4V2j+M2kD) ze;YOtg5VG|biK5EHVSMjEA}&3(HIlH^UzkUDI88+Y4LZt9`86LQ5p>ACKnFQn^v1~ zW1)-WQY)1k4Y6oxSghe2g&(8=jfv6w1I5vJV|(v+@^S>noS0)S%KY=sf%}s^Alw_y zXI581D&(`N`j4)A4yjdhby_DB(pVxSCxa!zQ2?+(84qhW*%BdjbAhFNM>L72*#OVk zn@<`OcteOeAY&xA{lW&=HMtDh$fCsqm0_*th52+4!JRZBk~#N z%9gE$zaOJJ4TgT3;%U(^ijX{%_O804dfh{BMV7Y1Mtd|d#@v*VpN>vb&m1n+3k~J& z5h-epnEN~4$1?!RlSaX2t$|nr6M0gk0^KzqBWc^b#lxI9m18`~c} z9v+NMI%yTzZdp>1(e*h(DFnJ+1NBD#TdZs{S$TgGS7VYi|@&ukwlsndWM6bsErz6e(sCr+CXY+4aWHm0bUDk8)RoO2!Hu&d>a2HCDJbF|? z@>NG+0e57@Q{6>_nrg}DqzT=!e;*d=C_vaHRe$QpY2bIHzZvZJu-bmI`#lSPHKLF- z=`)_?2Iio52a2gStN#!wEU(6^M#(D+ zAU$Icb?4u;McQUoqg*L4ej%;!Gx9T9D8(SOWmJw|isU^&g{ zW@885;5ft)T(4|B0WP?$AJ72N1cE;hxK}E2c`#7E^3|MFMqrUT z?>FL`n-_GZgyslCC9A$4`$J?n0o%Yb|xHfprd$vr&Exh3*s1WDPTRRoCs2oJtwdPRy5@t4<{)O3+MjmoI^!3 z@v%01%2ykTx(CBJ1p=`Pdm({{QZT1C%lC*EEb2xPCpI8CR4L#(S1)3u$E2<`Grdo% zk5dF=6lByM!1{(BqMNY6l+8A@DtndkW^bquIrOnODUYeZ8aFf)xp61#t4Sw zOy$dZ>gn)rr-KQn%E~Qs@I_0h@pw{QZC0fi#G8~YOTxi#maL>AtZ1Zx-680$9nzO4Z&qnVU{K06d;!c%ZLwK-fcDoiUaJ-A)99RRgTLdx? zPMIF<_W0i|RWD^UI6|swr}6jibXx)ZW!fxy4pdG5IGhQGeKYy|%1d*6zPFgt=uq_L z-kY2pZHwoXV@m!eMn|2}F9O*<-%LJR9VNZA4myvz68Z(9KZlHL?sMwc z8IXF34qL>zF%AejmIg(CAXm8EvN3D)`yWkCyS*zSYdPHX&9B_ZJgA>wGwgH2u51Kb zknY&cH=}VeS@U}}?CQp0G2i9i14eC5?Bo7mS}L^U{&se$_rmo9puG(Cz~%LG#Gh7X z;A*f9vQ_D?Xoe1G@43pxE_C!^sWJX?gEQa47+mvE!zh9aG8@u*Yk6P7@5W0OoY@O@ zJjJsF%iD)+u@A}E?>xSY442hh;G$kQe)fu5tc3MjXx=^tb(X3ixRC(o{0N~wtxm%B zR$!T=!DyQn$4qN?e^rET+()|)OL=;D#6}>BvB2s>20tJ0M2R20AyJ5nS>5sWmJO6D zpO!5UXEk$E57*dorFv;^d5`8>QX*&E!>RwP_%VH2ILH&@b^fx%Nz`k`vNYg?7k3pM zb$rFC9eSnC(H3cFNHhjtr&hmVrhUNksBOYRL`M~PNX^Ev``l0vMGlAmN-`Q&+L+qj z1Xd#mrvL%bdDNk~^RC!pu#HKwC@c_`q64GAKJbiT1-EvW(gaYe-SpHup4>{wavf_) zDbQlwMQgGu{i|^@_8W+9)d=(=-uPr5FuGZZMT_Q)*w_4IbRa%pvzyTYgheBLhQDaD z)C`*#dZ#w4addQaJh7~;0>59mQO=i+-s7|S5A1{0YvWuKPyAl?rgDYl9jJdqh>K-* zN^|piMwti_yu3Gn&r2Mo!@F7sFrAS2N~7zZU_1_qtV8r$)ZcU7L@V-8R`2@|a||d0 z!`n#4r~+nQTm|yRBCxh(+=N=8ewJ=5_B!Lymt+cAZF8>J!%bOVxxA(S)nNIocoBo; zD4g#)QMjj8;woE&t8qX#Q#Qy+7guzi1e_ZBYkJXcTy?|gORkER=~ta0j6RnJ>=TvV z!S}ZJfvJ>u6U#sYcpTO}S!c?L^va7=MdMm!+09*MOk$#5%poo@w|rtvas8-HMA854 zqIE#@5k+Brkw`^~ICqS6Y$K3~(poH3O!7t5+V2whvdq;}gN-&*{9Dv;WPEChrbY7Od_hHA=!(ovIBC7%Cbg0F9=ayTy_#zpToQ#UtN(ag z?<_|TmYS?>#j?Ur$XqqUV~R&Wt3FJalbtaz2YU>mTun?Ny2Kf=I2oaY zN`4$@Zo)F{`{_k2!9gLA_LW(9k45qhX1!HiK^Qs(A}dDs;b5GPfyx8XmBjwz{uJWh z26zvD0z}8-RoCrD{G964$qzv%za=Ex(yCsY zKjeFlu(Dz4&hh)p+%jW-sjvW#eQCFNYKq4zG9$7E@HC;5Ylj5{h8TJMP*HM1yK`g< zLo{_<)s6MevW5}JQZEiYHaz?Pg>ochu7lO9gbzVVq^e|3tMammd8WU|fzdHK$*`%^ zta6!8o&1S(nsXLB6i|xdH_Ibnj@`)YB*{USL%Lem$`o)UT#W~k;kxGu;mvj-vmR>Q zd6TWZo(9+3A1`TO1iLFKDVmkI$&O~i%4rgXwpGQa_BTq;0$M9d#UW{`i*|(17K1q8 z_gg4fniUY+^y4_i!WLl27~z&ho|~dF87s?o;;3OEal^EPU7mc+fH+0W)0-?Dipz-FbJgIti674Hq1%UAv=!~&dp`0spom;H-c zz*FMF@bh24sg0=0UZ(d}5zt(f-doIxJwqS?3lIP8FC1_IQbPIHbt#ABH5W!-nI~pb z82LL;`hni!_qGz&wq6&gg3)cO4U3h4sZfVpVmXp$g@5y)S?ByP>V}G}g^SKMxfu~k z{yk4A(siX-07nB2(*Gn~lW!E+9Ypzl|C!c^ig^ zPhsmX*}lL22dS!|;(D;pK0MZFfui}Zv}&Yast9LHKfz*rvrQ#}gvm^;pV1^EWi6G+ z4lRl`-M&N~jVj!BizP}?9(ioWM1vC|bP?6u;`W5!;4vHae*_v1)5?ts6(*QAa^tj{B|{nx|c)m`*Yobt%;ECQGS7EA;|KHGrRxK1dR7-T*V zpZ=#N=M!UE<%Ms(Uxv2rxfV{kIoe2kzA{h$6o)%OJ(fnRGohQ|`nG74UQ;gp z|59qd*Zi(IO8clLi0Li4;*4PAfklR#luTw7gC`@HyC!UqgIwaTl*=mZ?k0;6kmaVy zZkyF{Y`Qq;OS*BCwCK9mJ#gYZaiFpVlt=(4JaPF33wEX#chwQZ;4j6STU`F6Y@RJ& zvcEjz2s^o&8Vf`)Kt`?HsC5`BG{?&KzD)V6aGNCFlhso?_P6ykhkJgT%Qy*8?&T=_8>cV@ymr)MC`?hY zC$f_JA7#_x09{hmTxwELfzXuJF5FS$BSt61M@4dMg8*#=JMmQSLarhWsZQ+hQQ2wL07pVgmVpFx0=HZWu(EnfHw4=uWUij`qri3 z2UXbW?hO$u0Sg|2#Z;;t7mz1S?=x{;4fX-0Bc2gj0o7s$b#-eiJq(3{6p$E^01<3e2>hg__tpgLiVy})w3u&^|jYg8) zj3+5Z9G+&G0K`r*8lMvEB!A;AnKO7;VOfI_l^6O&s|Gw<82@>=fi+Gqvw+4yqAYf> znufxy>P*eZSJxE-Y;7bMaWsS!#FnyAEH?(196%rSK>QBA6qbKkyPjjfz&pX7-w1~4 z!gSjuFs&ae;kB;7C=473UVWo!=-@13 zX3I_Ea&(>3v*|T8p}ofDn>W5{=PFnCES{i=R+{C_7$6r=Vou#^VZ2nB`0?*PL63Wa5pdNy+$a? zH;XZl<*Ngbx@aQKUXTZ``i(Y41isN)$yA#5XH~cU`NE6O&RP476lWR_eLh}BsN``& zM9Y6fTUmJ?vk~^Y>Ca@iRmY9H|HqMKFOI*`>e2ND+Gg)Qft|reD6`ULT0=Ix`bd1i z1x-j)JW%hp77QdGq5~Q8?g#*+sgTZlINhzYAK~mpxS8Gp$ANhgvg8h`D7qP`woR5@ zxZsx~hTp_m@1`JJZv&9`9Vf45^y`Dx4;|jMNo#4r4#BZ02p_kW)Wh=3s+sx&W$0g) zdr&mR$2%|@bRoGLS-IGyQf}AE<`fZ<-30XQP@Z(Bl(v8QX?l+IBTo9;8TpF)f_39T1d zFAo%AGE*48d5zkq8H9zo?0EV!%O9D^i*;Y+%d2qoN6QTd6WcHaZSYQYhfdla(m;25 zzPs_2(@6af(lFbq8NKHkS|23Ojc#M~NjPI>=tWvkQdbHpc3=Rlq5{9KKJ@Uuj)ev| z3S-p8+s&xW@73&{Mjtx&R@@=RNa-83a_%gl4~-S7&I%`Z+)GD^LPn$t26<5BF^1`G zs`i_f21gX2ivlD!AVh1ERGUQYy2;V|UavPl*_SBMfL@E}^ih z5RA3vrqvniEv~U_QQGlfd$~ZHKJwA%Ts)1wnpBVWNOjip^{+deYlvbbXN;z~*4vyk zMWZSUy6rhAfglVlz)+1Feh0<5g`Db11U?GPi(O?-Qc(mpeGpZpQOz|!sek?c^7uEk zsUpo?{3Y1rdPy3*l}P+97Pwsa2><8pMcVxv2R%!IJ-#vO6c}-V(qK1mTfI&?#d+6e zE$a@aV)XeVJ{L~pldlzw`e{pIu0y4{wm>~PIo$p2laQ&GytnkkM-}+#3)^#SiGv8n zHOJu@3=!hYoF(^4>6lJZl2I>@`m#QY|Ae{5C$NRH^(j?fE|p&IkTSRFTDI)30IOAR z-T4m3Gk+~BWedX5j!)PZWyoCx8l{cg%ht@6WAD198y8~|Wsz0R zKlJ{K;uXR$L@W`1Jo4xyb~}NB1Nq^Jkzjzc)m?Tgg*xgv%n^7vJEoQCHxI)$Pl6S2 zAH2pa>6zp=&>p6oDYB74A^uH&V_#GYP(ksOSRclQ1q{#I} z<(GWWG^3?3a73cwIvYJw!<-~8jLsu|lqIM+wi60^7zc+HX{qP2jlK0v0rbHRB#Y-H zFXyKF0%wEVcF7ZxWr4~oG@tl}TQmlx*A1;9P6XcE;-`yJ+Ee63WC^X>#nXKt2fA!g z9}hgY8|V4NBc#Df(ncu`?TsbW5B>wo+b<}oZEvIKPENfyG4G~pcX1X4lzQ-^wLw^?#QEX8hEm-qJ{Xf>;Dk_dA`W8-Lf`niL z1oy#0fCPfO1q&YBEx5Z*kOX&2a3{D04^Gg);0_aX@WEYf=XdXat^07-_w>!;p@*KX z?yjnH`qV!A>^2 zY>g}i{k?lX9oS^DlpymMwN~N=!9Y|P;{@u~GWkLS{%x9wV`CmUr&F`f_(Ml2m#i-M z%@4ZHT`>h71&KK(x%qE2AhWDcMxRW?Qg_4ITKW60O;74`q8)l0eCtDJ+VW#NWj=9j}Hl8O`H-9 zm-f3}3(tS+9T&*J%sDt1T%CdO1A8w8BXvYCck7qlA?9EXN5a6L?_AcsZE4f*@jeoC z+tB42snLuEFG3n#s}RfRnYo+fRm;{&$AKm&nlXDN(3RP_1padOz6E9+fj%25eyMm@ zsaf}vDDTj~@B5hGz{Q_ZrUfH{qRx2c8_&yR&6#kA@uinL?CF1!FZv-pZKfZvqUj38 zIYR5gOqCb^Ja4du{2V-BuoYo(Uq~BgHw5ydG??2022KnBf#N#|97HpXr_F!$dxWv{ z3qd!?U|0-P$|IeG;UPhb8RVg9T2sg@XKznSce=GXs7$e8S@PlghWJGF1IB$OhzI(y zg4#Ej%y}0UPYB*ghpY*VVh^tVj347*9SiPV2;tFb+irO-M{k%~Oi-}nN^Kr`l_VA; zBJp4LW&S+E<=-7E0e4KoI2Rpwpl^v%OC*H)I=cmYY7&%_nWEiI1M5u`PXj?NexHW_ z5yUSwu8DB}1E+epkH0~)tSG9g`ZnTvp(4qpRl{gL#w!O3JmuAYElu*(>?yyJsl8G< z--2MF;`bH^ylF%$1`_uP7~#>Ub|n}=T0)%3>xiAG(aV(k^rJtKPLKhITVNhqpQw9ZY+*v^zz6v z#dp0*PbfMgM|r8v>}z-59fKrVEKdEnwSegKogj)F9mX$wK5fQ6{$VSk5m_3HZ+0&* zKIG2xNWEhG9OB)ti0@@EM}*%I@?M1?5j{RbXyAdL+qciV9P=5lOs+j>Se(iBOeFdo z88<1?=;>f&!=koTQlV+E#2TO!0v^~m6Y&=)lhEk~P3&Vpo@IV$qUe75?(LyYU(P^j zrV1HK$pLv7V+kF*H>5sXE{H|mzd8C1{$rRLy3MDPF-!<1lJWeCQl^fM5W>%S&Kwyl zy2DXf=24VGe%)i=W~`&UW|0?WB=KFgtZq0YlSF=+HjsiIu$luU8tlKVWl(>78&Y>{ zBFq5p`|k_l0@CRPzjr>COW_yiRuya*Glqu;k8LFhbZbFX$c6VTcB{1p%oOD(l(j5b z`p-GmO({Y1&(qaRA}%WK%Rgto50(+Kp3`=Jhw_i?N{}Un0cz`w$Bcaw)bjPFbAYH} zsOXCMH^^w17JHFRfirw`HcZ;o2pbLcqkrYIX9;L-1oyeqgoj$Ot*yXH<-HLD{$>ez z^VGZW)pjwk6>ACRZ&4*26Yj182p&18v)o)ljXBrJVyX92qIS86I;1(c1?Z#*X*J?B zsr*32b4kq_ABlAJT{YkZ{gC&k*982ATMy16w?30zDT2~<`D#!(fb-@nZ~L)RzccT1)HgvD1~UZrn5OQ{ z_7g)=^E~>D6QiyL$(T0zRow#b0lV^pd-nC)4m+-RwSE~gdQ>W(wr?s8?({T#T#yWU zBfo}*gBh@sDOYye z;KQ%31AN(HKm@Uh3j!x_rF>w35Hl_MrO#V{d6%V^X$$l;^mAP~#x+DQ zgmI@MK1}x!o&5|#as|tD-5&>XLv&pjAo9N3xsR6Su(#Zn9gXzyeqY%#74YoptJ#vR z@MeQN#DnBMa6V(OqP{@SXX|^5dJu%0AOsikL#Erb*39n47mjfPnU^TwO_T{M7ZDVeOHT@9(ZHIzVj`9otbSWi~hbuV0d~%DD(A!>K!5ijuJ`5X4Omo1mmx3@s9f7z! z_mpUV79RU;c8ioHp|f?;-(=0s)Ps22R9hqY|B4$57!- z)EY>>9Z_ixu0hGX&Ggpd4;?Ot86Fcg>;8O!))<1X%GVWprOVod1dQiIiK_n`(Znv` zhPnjcs&!i<->0u*7q(TthK3r2lZW7l1@t}%yfI^R+aS1cu4ef{nX^_fHQqxApwOZ3 zX+}Fgw%~5i@O;_xQOg-tvK-OQqk`H=zV0use&cc?j0+Q0uJE_P;=cV%D@T(Fh#F@qANXct1C-sn@H|{HSRiUCHeJ*+hN8PPOeDm8h!Y@f2jH03f`G2ME$@+z;K75MB4U!;5(y`^A5UI+@>HOv+!WYQ+Fb*it zIGUwlufA-zca)SUT`?}*82%GW?2&Z((CSxtu)wJzzh%tPz+QsJ z3Z^7XKXiSYWBz!$jEj+jWI-{{PFN4F>F0{J$mZd@Ivb}U{@ri>hbCoX3ql=Ekl`20!*wZqS;Eitvc$3?yNJRQ_qB>T z%zIDU&%OR+nYW~$H@%d)iUYHNwFHTVmG;lAm`0)D$Wij+Y3zdU&ZM9y+hLAOv6TUL zQg3#g%gMWZ%CKK3wY~`75H1L1jVB0w_`pnH?Jn}3uK2^5EF}CCM*Y#YVM)WgKGrN( zB!YUBuyTj)?(JrYf<}c$yN}%&?~Q%D#4JJIo31xPLcd5oEFO#XwPGjsX|j`_fcJn? z_P!!$pwd;}4Q~S05n=CqS@!?hB$|h^Rqlm9fS#R6v`gfhb=9J`LWiFoM~#F($($SLGER7|1epB3cT z6tvG7ui5`pP!(26|9m%uT}L3^94ky)-H&eWDG%lp@6>O5IsZA4;~P+0oa49vJHdB% z{0^KCbk58r83CJ<8uovGGj}`-w{Y|uwW<&Gb2IeAJ+)cXQ1d z>mdwdyhqRc=DxI$out0VPvs{mtohHn?1TXr{fGg;MS4PIPZa1X8mL6nt5K`4_wn@- zjDnO)sT>{mDt@eU#_J&H!!wpvt9Mf_WL2&bRUv{!T!)-zicIkHsBaAxeq`;k! z-upMidI(NcStb`dskAmukGOid+TuA*fACqkfN*$f_$zmPMzXz@cj1Ij1r_AmtiTz0MHkbEcVH$stoQBAW)o9TINt^qWX43K!?fF)B1cMHz$hxaE_(M5?Ke6{|6j>N$bn zAM%ceB8Y4H?d3#hG&trAd)%FW*4t##U^D}aa+Bk=-?+@ml!G>=W0-8mG^ya6wcfUb zg+1_&GdX@buJr==s(&H5+eTUV-C2SrabrBS;u%vH@wkLCVj1p$Z_5XyVT zcibzD@R9cq)lejHcn->Hau9^0hoBZQiEMBX%*Quf+ds?#mzEr8hoCVT z2=v%v8Z>`QnonZ};nB$zkhGH-T~fi+w+`GepECY*GN=w(wg8(C7uB?=rAv_#xo=N+8~wFO;O+Sd42t0DFH|vC>f%or>9?G zZ{7ceOE*43Xt%b?nAabSzn42*3akIUZ|(jxP??4{5DHK!=O;dI!v7MKVX>H+Wrke^ zO8ES0E98w^O&^!X17XS0DZX*t`g4p<)r73bLhN0dh6aWPs|w*spEcp`@HapNDm;oxSMTwx!d4NAtu$RCSW1HGy~&`fl*N>BUb0x*xa@iNDzlFOu!Tjjws8 zil=|y%$U!q`KL|W4_!SE!V^!BjU*u@B~@QH^JRgx(t*ABXuj|$!0I>W!h2i3;fm`L zS<}owgN^J~u-)I8j6<$<1Jat5bsuR|ImX)qkM(iIw{0QeKk)?S1G+IIaXkDUmt?o) zo<~UAffmEie9PJ6;yRhO^uBrd9tMk`V%F@2%lenw10_X@OB^%BiV3ldm5b(AyJ~%R zAaN@x;A)&H`eo>@f1YF{(u;=$tCQ+kF#+k9>Rl9+?08qdm}|aWFi-kyRn>TEI<@-Md9_ zMT*^srH&XJGsKZjs%?&WoSS&Y-Ncsm3QQ#AP-5yCwDa$zvVoT(h> zOXaih>lDV7*lFVAU9y4F#$B@g4=j2FEsQWDyby_h^`Jm$@#9h7j6H%Csmt@_DJ!^q zK(jMT6EGU73YsG})|UnIVDM@56w{P-?f!>SHc1YNV9#IvgAbtG?05+0(=oG+&{(58 zcG%_DIdc@EkZui#x$_f+pNMH45m533BpL!2qci`boT$|washh$NUqK?EqBH;E)(o< z{XA$4C^87|5j_t1&6ua^Zv)aORBMrnB#P#gE8$c|G)~0i|J7}Nzkb^ zADr3i%N(|eSx8hwD}Es2_S4Zc=#=u$4G-jb`71n(fu)InUp)JV&G2M+xoQ}qw z=rw;iU=EV+=_tGNq$8;)_)S*R&uQ7AcU5*gPh*40{NHyQsH6e}$vX23(sWV$tB{nW zn-8th8hTku8&rJ}dqFf(K)tHTwxs^LS?g5{FTrkN-*e_~&SLp6pwC27IK&G-K_rHR zFeW4v{-b&(2%jmRj2uVqrFn@mxQpYF#X}|n$AT$Bi8Yf*lmRCz zI>%|wa6!2HROCE`1lRzD zW;{=JQbP`33-ruYzUeT%J_f0Tz4Ih!pckGM~zC+_G>vNs>f?! z*;YUAsZ^L~XP0e0alLnomUIVY`OxI*{uPY}3G?nCO;n0}`i z1&0tq!p}(lu?R~Sl6Y6kguA2Rt|$=!tK&{-Vz2)$NZF{}Nt9_Inc?K8(?l_QP>10W zo?D`})~qtMak*YkI;dqKC{GmZ=cf#)xS9iH$D!g9-_^>d4GWTPXPjjyw_kaBR=!et zU0pQ(H+h2nXC9TD8D&BruZ_F`Ki~FBOThgN`p(e13+CQDX<52TIl3047u^{3TRl>0 zKv*^|91<^rBKKRvrl$f8tUTyAP19FH6BMR9(j6HiK2dHsOv2fyZ@ z5=_#C@`C#wn_4)aK_*^3#O>mg5TY654CYR8 z?gk@=&v;JrWL0J9xGq_CxzkSu9k)%lBZLNq9$99u%ho4_*&ami(|nAVE+2W@G;e2H z-1n%YyGghLD!wFOY%O{zNkPpa=!{%}c!1t4ErA@JgjQYLd%7A|Q8tDDbdd+7*pG>P zo@Zj{CX0c@2c#3i#<&ROUWP#M#H}b3q(Uk~)jk8;-zWen-DPE=w{e6uawvclEue?% z#)~zw!4vip9n^9vaaK8dgR2U^ibc?q7NK!dWkSFPArC%CZJ+_Kw?bHOsXxC}u$7 zVYG4uUtZwiI=*S~SVrRAWcL?I@F{gwJq=hs`LcuMh_%u>K7Q%-PpbFBhLdLG7^b<~ zGW8H69$k|TJMTB$fG>AUc)AG#E}O5@4>&OXsq_{+3&HGl_B2+vpbKnz(g0;P=bdI_ z*ygp)x*8MFNje9fs;7YALMlGcIMazYzMv>LxTwJMOTu}GzX+l^qezfS%gMxq#85`n zSGOhRSVV9X(_pj#5n#lhOhM0eZri>G0enn=zg3;Jos-Gu2o}e?0Ti=|azJZ*>JL*h z3JR96{qOOH0*o0*T=so}EKZVG z64xdNFgpLa&IECQDWhfI!zhji>XJy1eg5B$6QJ_5Q&ontJ{*`pcp-j}@ZKB{r~M5h zH0585aj_75EMVYiFgD{L-TyVs4E&1*^Pe&|8BqQMKrFz70p?FZRU!sM+_Y^U zSdx)xh3N5AQz>oWAA!G|4IxcJL_jx&yypaC{8NDjdiX0iEFVYie;X*!W;{*cpYO-+ z4UqqY!^OkY-u!3Iz%c?@y0IV^m3R;k00CWq_kuByA`0X}q~`+I=fAF#|3BjA0mXoP z>3`;N#-#|slQ`5S2CO}ApK>qjhFV06w6MoHITq?#_CEsZFE^=uIrT=eoEcMnsrWM( z{3lb0yfWtLM>w4rldpN* zu6xk@fLe*Tw_o^a{YXJddfeo1RA<~3R3Qvo9(0|$;NEoH<{$m^6Q|}7t>%y_^d3`& z-!=*HIDDGX%Dd$BSERi4tphuxW^FfmI_K1G(|1vF@%{B^(epim%@LIV@aEf19@#s_>?>8!7sD>Guwubs5a=_JPq|OOT}g)>BhoJlkPEG5%z9GMP=17)GF#z z!n;3Ex8q+?O3OgvzhDuI5OnQhXBDq}-Z-*(J$-7Db=6;rvY_M@?{Mud9d&Lh_5K8`(gX-qXS3&09mWyPa0`g&f6iefTxAw-WaGLcpr38?6y*rXQ`SmYM4Q0ID(6MzD7-Q@XWW5W|0zT~rxttpV1#j%G^| zJ$Jui`-Pu-xv5Rf(cLnaU>mtw(x0?`kAsPrl^tu8a7f$FOqNri1Hy2@+kk`ntSTH2 zgL4#~MnXtoYt1~g=Q49xN%%ZTw6=M#i}^rjh|-tiVrM1P(TVrl!jbUJqXcJrw?_SN z3Ww;mCeH;sB3txF*3z!Mb|SI|{%|ot?n!&6>Zc(pq1H?mxbd9Z_OZVykBk3w7h$G+ z<*&WsX*TZ(C|^e&X`Ml_Zyrn2>K>8vGdk}QrADu|T$4*FbA%92_BRf36v~uoy|g_$ zBp%_?owqG%o}I#W*>4!%g#)f#S+CXOKGbj154_77LxGIc~kDs|+pr!{cWLMamZ8T0eksn7iZ zwXs((BAEz~CPvM~K4z%d{P$<^kJUA1{JTH$iyW%E`q0hRb;GDJD7Vr-WOW;^f02)_ z*uRndl6`%lP?PG9!gE48$6H?Go^S*W7ap_#lD~8G*^tqWPpIcpdlL<6?wEwkHFMlwUVJgvrQuf!`mznPIYxIf>kLHED-X|4X|2l-Bh za39@v4;Cs@{+Xd{u|cL6R{Mpw%|(EyW!t@efVbkZ=oO}2KGTPQld#nirsTcs+&lN- z>5SmnYWFo3C|{Xtj%Rw)u6e!9B&;M}c+utf!(zg~-F4*3#_g_Ml#t<{qL`4;bmJ@D zy`P)KeyNIyqs~~whr3=6^OY_;kWc9AkLaQ~t0n5_9dpN8edGMG#SJ1T@GCHA7<+!f zdyE#dzfH<}y}zUxeIoq&!nu#zt*aBE>XZD|jXA4@IPk~{$ZlWGan`uGf-#S#vg6`# z)$1-FS@d+@4+Hx4M@MM3GclQ8Vnn-&4m&T|&wthQC<`9^Y{0p%?Q9{}uJgFB&d+$J z!sN}Tk7Bf}U3N{a-{Q8@F+ZV`aZy3c+UP+Va6s86N$}fO`}#0<5ux3K zYmWP5n<-rFLAN|HnCaq|J_iK9dq2ldT+x76hLZnOu7O8U0V;O7#kOK`zTn=m-vW~0 zJ4F9zKZM*G(Yvx~_`n?bl5N4k&23*smL@XSLm7pZ;ymTtY&26+GV; zT;B@DSak@uXjjX0o_=O?#pntbW97Ra%AD>~cle#kL#)fofVU>L`Qg4o;B;uVnms8{ z=}2%_g| zN$ZpDK`fXnEQtuC!euf=1$q?$G*6Om1=nYQ9BT!o@EWK zTN_(to7E}*gzQKHQnftWf~Q|!R){gZdw0kmC*02IzuU>QcrF{~Er}I-0o22Uw;{|- zkAwkWi(1gQ8}>HyX4&#bV9lP&?gG9uT3Pk)!?I5!P4hpV>3C0vlf;h`CA5WBv8%^c z-OB1A!?&j);J;;c)9a1YdfcSEiBcKYr^EqIMMq=nR^+ozl03`yTA>$|kB)QsccFW? zv4F5HCXDeGOX*L(h|=xWMd{YcXZT=@oi+ER_;%%PhjCB7r9?${i$SnrmqvRB%b8*_LJ0Tv z1{O-W_VZBxJ%+GAueZ!22^fAdAn0?IGnBxJydb6>~f z0DbI|=7kD|!Te8;ibitqkl-6xU!%HMwOq0NmWRbu4x> ztQGn55Q)KA4J}jQtjP(PrK|S*(O;jG?+kY&a!}vKZka_Oq4Fd19aA_CJJfSaxxa5; zIo_2r#;)JaadKSrP01B!w-;34zDO5^KGY?v=L>VT?DKgtGR~B|3WCJ`lP_(MZ zzm71zFB17!nTZJiyI%R@^?MFIcj?{_(`29+^w6+Mhf|k2i)Nf|l0)gWvxapw9K@;nx2ULW7>fOESwSP}$7Q!FuKCX%!TbKu zIHJ>l=d-tL@{6RB&#EbnzbmQ0bUkCz`0I{L#*1{k&wbq_Fv*geFAVR7&WrX-x7y0a>Yiaedf|hXr)_5q zkgqOB>|SAcyq})O`0Tpae3=m(Z0_>z!beGxKOiiUioFRIL8LHbaIF^CEE&n(cleZY zq6CzHbew9sZJ$&U+;p@{Q#ra1qA7?OwX?`S-mB7Eht+349D(?vO_ zT}G)_-17qGV&xNzub!=cBGRd^5gsKxpiqs}zAvb&5-HmHb5$$y%eikF-UUBVsx0~J znW&4T%G-in5tB2f)KxA^MOWp^)ck^zyb_DOIx6m{wLm(sBuZH+uN*6@k_-PVuxGkC z9gDr1w*hsOH5LHFPFW)3Gxt+!Lk!p>vBI;_QHHFW7**$PXMmD#Y)1-vXjrL#sqCT}huxfqf=2{X= znKTrtcz;c@Y5FrmF&D!5?%mmvGwj+d+3Z@D=Fx)^K?#Tt2dx?)-asGj5MB?RxCSl1 z>Z9rL_PZQweMaW8-)6t^O&g$ISt4RhF$sh7(_nUx$X(rDU4LwiT)4CZWbDos%Qb-a z>%?|h)<+6%>vw-!@SV75NF-^u7PD{J#bWmFC6PZRu(Ri=AbB&x(tjJ4=H6*h?ulk; zc#pO}3ndTq=4v497mB%`#@Kelw09+xr(1z13pOV@OcHZjo&hdO?CU(D|K#Hf_-!WH zrO~o8X2>`9&g?hc{*(ci8cO@h{m8eTkc8GC1Q0{wyhyyXsDI;j*SZyhY;ze**igU| z{G7}xL#5k(x6zRKp-|WZep>dT#6N09q}lH}!LfS9Sp{5#Onskb_bTxA7hA(z?R;5D z>5(rt-{yf$SL<1HDkXYm>USofyD>Mxo$TTIop5^ z!`8GukG+`AS{~1)DvTK4xq^1Z8fLdIiF%9FPh0Q8ZD2YD%I_MVJ&In@A`3rJ&wZ~F ztNvaGU%pa22qsc{Fh%W${W9U^3Ll%aNX|FxvoY~26!Bk}C?xQ;)(d_6?%mHi#4VRL zTU7DXB{19*S+^_;ojVGtE2~Y1@#Qbk>>B`Ql08t&08;~4WumEqTDw%s2RNf1YRMX}T^wbf~r~XlbPcJD?eO zZ<6cS(r|?vKeU>aGm?E@3SWikQ~(dK;l zpr(lx3=yQxk3XTWf5m4rVaTJ2>C+p5nAEU4Xre=24jIW1GrAGiUFM%k&yp2_R<2O| zxs8U8`tY5o~jIBb6(wKbM;wcpdt&=oM^ z&w37{i^FxCW(Ee#%Fo%d5TmbsxydQ}1l;FYv}zaJU+XpOciid1)%b?0eB^Ait1k%e z1Rh4^S@}BX52H(-XF{DaPn0`6?rse36<47KBU$1|rCmcnlAHwPPGTlPoR{s!aBXBF zTrT8LNhVT_H)MSMLy;o+{#9ZZLC|`#Fxp;gz#`SGu*s4u49?!mvC2{YvitIvCoD_& z7eko@1=-uHo8&>ZPG5QNL(FnF4ssDU&7Iy|Z?36`vUERzde2lcc+RcieP(Z|;I^N3 zvmVFxmcGv`iKyOmY+&7V#yFKkR!K`j;kR2d%x+olnA=~98^wAPNE|@+gyC6FYMDrhCZsH5*{`q?`HUq~>~j@7nx;TP%a;F| z*WW@SwZGC+;IMCc2%wFTLe&QqY}87x&!t$40)a1;9kX;=L zxO&xktqR_(JMWxvu%cm4X&gv6e#UwYO=`B}?#WopZ|9+`;AQztZ^i3b(y@`4#B-?? z4=#~_k`tjQ^5<(;t-oPx+z@cK~|ok-_;Z z_UG1oheZ0X(1leyDetIk+j{ozAHrZAWQEKR=}k0vXP-XEbRgPj4nLDQ84gDj(T4NI zs2>`PwYS78_`|-zhc2xyiDRnFmp5x14q}OfGaFu4p1S&974x!?Ltk}hS6Dh{P&=29 z#B{KxzQaUF-BC8HVDzin`=U5Bt|sYw21Q>!HqjJ_d)5dBT=!#MJ6x`iq$)Q*`SFp< z@#TRc1(Hes)mNlUCD`r*ozfI-_VG%KX)dPU=Kde)Tu4^2M`yvE94w&6d58($@{U)3 zSGX_J1)9zwSMb#Fz5+Oux@}6x1d{h0sc6;%b-O;^Itx8|>l4aLcwTX6SBp6a z{3)Iq$sp@z@m|S^^g3z0q%DoEO^HPct5@9hxy^t~N4sK~m6OBQ<0;1Dq~b^#{+hB^ zmI)vkUIP@_8!#xn^VDW~C27tmNjP4pl&W=|y8Mjl495x1@-T$y;}^=M@}L;r7PFr0 zZ7%~El};Ea*QqNqi>yD z2brp4gk7<-U!&J+&*>b2y@jLpN?GuC9( Xg@15NB+P%8 zgiLN*Z)iM5yMs+CRBDeDWoKntxZY?ivdpqLdkwW3jELl%MQ*l4Bx^yj^_Fk7hx;#A z3brUz4kHQ-5m9CAo$pWNW=;SV?Q>gCamZgv&!rP6jkC9r&ezeeUy96_|UC@u~(;e6d?*8#u zOWCJ#iP&WIrgTb=GF!J%>ClN7WO8z>ajbn8m*d#|Iszf>A|(kv_OF`44yhEB&hqZ%Yd5l4<~KYO{{*Cs z2u62n9z(?p@8TsL&bCIsLe}^kz6%nEyKq$R+RHNl8WbDPG=pe9u(#{+;7Dhs#k~Vx zqY`7S-kvaaJn28)zDN6gJXN;M^0XWi_!SC+SyS=hS^{97FJAD8Zkp0k%+9-7S#4XF zUvR4zE8R!Sa6Ea1VUWx1zKeDe;0)YQ;i1lO_!G!7Suv>3Qirw8AMtB9k9ouAT5re`!umV` zGUJf*v`o{S`k(9$C#a{>ekO2?D#L81+U;xYYGYf?XTWLk5Iq3Pc9H}RP7Fh~%(~Pt zS7o&tckMMV5vUkn`XT(#sqJ2cl-XF!E>Ahb`O}8~^;OS~)Q_MWlZw6L*H@CuW;I?Cupyf>f{#1=wNd+qkEn;R6ID!^p^$(8 zPwaH1*=U}$V3cnJSZqYQ)Oo?W`0n@R9d)fP#;kjB)b%dba#qMQ@olHWY)DKw)kp^7)O--qS3=&j{O`#zEf2e^|m>_255b4$mU9$L1B)75z*wxFV4xg zE!?)V)UZ+@17~~vhr6nmd4q5!VqJhW>3mE&y&RGU#1XxQ%|>_6_&%?UAA0YqK@uvx zS0^&~U3t!gE`7Cc4CbcZ6|?DiBqFXmKGnY=>3R(St*a{l1Bd44*U74RHE%Pxn03Tk z!mWV%RY@a+3+i{d5QnVOB;7t6X9~~T8fSzrz|Ek1Tw{2>o)p++4R_JE^yI03fnF9D z`9&P;;lBxWJzV-yWt<3Hr0ZCs&+;*nrhC6Lh4ZyWC}l&|Ft#}({@UZ=_2PBb3DUg& zP37J%7q^2s-dKU%A8VeHN^j69-Bj#H(%g;2YuJ1rinChId`WbY+8jf`gYO+i9u1kY zt%{NEz_S--qJejl%2l=SA-nwW<5!OCyex_iiq`t7PYRg77N_fG`~#DvToMO}wDjMK z{JqM4Uo$oR{?E!J&(bzJ22XnJ%3Bq@rB!c1qpcLnt0p0!g>g^?(0r{s?MLwgOsmeZ$Qdla`HOqx)10X3(xRBkVp0LsdzQJFg9w(bMQY2@2xU_0ttPI~^L=VR2 zsgIsiHgdt8K<<>M^e%UwE>n*hRC}S3Gg6ZImm9V|SjOz_Z?@R%)i_^%Rib)}DY3|R zpr=<-Qz9y{!!V>e_rBOLQfh*~>V*;DkxR$BvW-C}9t}x78pLHfTrSk>ADP4PxVZy< zp0wR+vwZ=gs_NOBMeoy>DX_0>pALhbIjWA%IZ|r1eO0tajLSSKAl}Ohe;YTIoV~32 z2hM9T-PRnRy?(p@{SFOoc}2(R)5-uIj0M(tcXT|M5=cqR0?pQ^gX_QTauahLCFq*f zGri9@I?Q&?96PX`4|z5PILs9Ig^<)kMxv4RAD%PC0}zks?(OIYLUrY8bMe$sQ{=fI z;R{P3@0l<{fJUhXpk?DaHu?rKzGHS-cq@KaXh{SvW#b$^QZZyIsXgL66lksLmO!2PN)iKy#%UGHg5_XS*D^Sxg2 zSPvubX@2?WM?5U`E6fdiq28-BLG=;fh2jn7YJA~%|E8Q4#><{^&8}QyZE}*^p0TlR z$u643MYIvKm0!}Kti>0Wf9|bXZo^-b8pVRU%b<-yR{2_dwG?<^SZKjw$um8qDDVg8bq}DCi?jKfoD0a#HTT9?g zfAuH3%B5X39mXr!eJ9DSKHvrZZ;aePG;hJp{8GS}#9xPo{^(Ta)$R}V~D<=QvWGrEDmOHR5u zj2&0k%Xy=bC8Er;k3J*E9c^~=oIcWyJFGj~aT*m30UWPqeUJTrVWTz-#Tp$8og)L& zEV?SJlH zKOTIWY*0BQN!9Yl^*rrdH1Ae?ZVJ48UR$}ovMac&r4kUS?UB6~^JwPebfoIj^5%Ms za!bAF!@QN>(mWOPIwod)Vz5G32=2=e1V`JL)inb4358deJv~DYfM;EcbH>w_2^6qg*7mM z<>-FL0m@H@6@G>4I@`Ss zd$c@SqGT%1m4Q+K>N#aLui1P%7HM@RzwL;Mok{cyiJDv9QOvFVI+&p^QW)wl`ZW$w zTVk2hV;jSJbko29kkMpgmXYGz_V?t+!w*mO79z{gnAiia;F_ZgZ2*HMZ>J0mh!ZrG z(*@q31_oce_yQiAd;;JnC)NiFIVL zU&n;vEag!1?))C^M^~ImHynW+hSaR_V6uPc_UhcTdz#Ei<2n^QNP@ahzb|=a+$VM3 zwRN~9wf|WMQoF|Vi^wA#hVZk@vTt>dv{#u>ZFl#K)2tlrichdBw-tKDh%tZ!Ty6Th zR^cwq2V3*RaUMdr@zY}1;j9nc4Y8|hbaA;(_F>W8?EPlz61Ofhu($YesnuoYax?Z#nIoc2aC<2_|PI{YQN&* z?Z8yS+*WBOf+zuDxH|FF(lId`5WEQRU`ZgkJo^l6Brm5)K6CVZ9ed_H3P1`rH9%!! zD1b;p&CC?6yuq|qj%R?+QKtG)l9_}wdZF$}fy{ma^zbhr6(c;W`Viyhg;7)#nr^?w zBg0=Md_Khx3Y_2$YDWe8BC5`cxc6&Yuc^HmwvHT zLICCi4`CMs1sQYs_F>00zJfuY@x-#8-BS_7h(@qolnq@Pl_vJ@-v^8m*_#36wv5@RK*V(i=}9MbOao%W$8Jpp4sj7o7Zq@32TIj zHEwuh!ta`)GW+6B)JG=Vmz|>DN-rj-DEBIi50{$B1yR-ETV4-()$gi;!dEm@&v)9B zu93aOms}y8=|B$Vm$SJ!mIhFhL z536}}$2yZU*Ujyqm*V|5F!8J#6_9q~<;gVA8SW?TkQfPowUxVbuvV^UV_(Tsr^K#5 zp!?<%*UY2?MPjW<>x9tkXx;~R?n~k1mFSP(x!UWaPnL!8(+y)O=Xw7&wki-PFBH?UP9(}w_=K%(Z(p%%E5p7#cW(GSlsCKQuzUN!7_%<) zl}091Z5xeL*ZHx_X;%d1dg!xX6Z(+m8E(zN5YKluQ3^211e^a?ZQmKyR1)x!atd-=PnP+BBCi~g5&z=vhua_eYZqFMDZ*p&rO>=DqNn&bpYdaah4!84n z&cjAHZ`+-YhII9Qa?{xl_AOQ0RgD1BQiCee=cBQ#AN^0R-o!)}gdW@FuLV5&lwUzz zGfI});j1PtTM3gCrjANr-+n=D*T#zogERhN?mYfF-KCcSO`h~CW+Rz1F&(BJ|Y z&5!@l>d6C}PXl7Vch9A`&-9Aw|JN_=Fipn)(ZQ3ejWavC^`tx4F(cKnc*WvOJmlnU&{*VY($D>!_n{!8Fx_7a+&r-3oBmSR1?Upt}>J}pxZrB>%Zz)(b z|7BhtCbA}hAyKn-E5v(~<~BOEU2TEdlRRmxu_7P}GwmLfE>tc(cxjpy=$5=V1iGG1 zGA~mcZ@D8amFIP_xNGbu&`>5`YbR-LVX3_N+{-~0>W7N=%dMnRIvsj5{`rY|aeUNKCIoZRv>9$7Zl#0Y)PvO7Du76N#F zbjo&yHvhAz@yytZ>5vcW`_@GdxotiN+?bbu{NAFU_SK9UWp+BW#Y#)92z`7u9_(SG zdfZdt4TDMbJy4`Gi`l7Ls0%O(erkE4_MpEE7=thFEF){CEho}-?c!-7aiB2%I=jSE zcR1_yXrX&Da1C+cJH-s%;46o{T+p#8ymu%2=L;*$^oZ+;UFU}iA?2*o7a*i@+jwOA zJ8wO3+_6xo@Gq2Pk-aY2IN~doKgZi6C?#C`*-GtWmpXB3%Bi4jY~p%%Q7hj_#aPLT zCr{RjOJewC#B~;8FEgbUFD^K;>^ZU=;&@Z8V`R~UaKu??u3F)1dSJfuGAB@?MdR>% z60FVZ{cglJGb%??54zCYuY>*GO-0T?8KUr;!xPqB!QXxchbH+lB8oPa!Q;*;_0t6< z3?_eD#l~1n-5B>MCF{~)a@HgCTT_#U_-NW)@rW|k=qU({>5%K64(H0iN~&DZcz=$9 zgaeLVmUd>2Stuo7*rSzwWZ5UDS%S3p7wBGUVl>0hkKPJhT(($A9_#UkZDLnhC!D?q zzjVKt&*T21i#n*vd9=8o>95Bz=iVKGI-TgYyl4+au(aEsxd>DPY#0+gu{H59?C-(z zp3eJjL2}NEfL#=5HC&sN#~R)HV^lu=Aj&jobz45sSS(2-aY;O4p68tjF-j4Ofm+xl zz`lulL2?h^t}K*!(OpT6+Er7Nu$%tq@1PUFEY7TCUc5bC)cEBKrkQ_tJG(FB2|k)q zqK}FAdte(=HD3R_V3tnc$;CW)?UxGo#UrC2M;6Vpl-3r@mEv;Oa~(&bNh!5n2T5czGF_)HB;G z{^>Mm%1of@_lvz&T9jyeik2Y zK1;sj?BI6ZX0uPfb_=_PJMy!t>zy@&%i*XGMrw)L0fUI?rdf@dCqu2J7H!hG>QUu) z4V6HSnxdA+LXMQ6Zxc`?DWwRxGj=tK(a%z5x+f8)tzK{tABhavxJsI>oIfa`VXuhLnv8|C=+N7utfAERyISz0oWj#g_h}KfevlgjTQDhu4 z9*OlJ1w-1mygiAhc?d#{z$y2iR1$NGLd*pBmRS5TeW=bo_7c|kL)4!nbfzQQ$a02X z8*3de-D;b{YLs$a4Ck*QPiL8^#u;^_OiUYZDE}>*)d)~)UR$$ke%31g_cv7 zxTDR&y!uNr9hsmiQOacX``+~ESsvi`5CU(Lurys@L2s(f3qoYh1#5U7dY6Z7k?y?a zU$QC}xXoX%@)Z8qV=CqXmOiIUbv*NSl+s3nYS3XN`$=Fjj6lx9ab11S=v|H1$_X~} zJBhjQnJZKeEB8bWw0dMV(u-u?@MPRv(sB>b||_e!1{yXB+H zy2bFNl=-;hcGNaGFcJb7b#6KNR?X9_nyZw{vmLJ&-Iadydh;`0O=&k?rMsZ;g^T<< z4CAgt&hIGA9e7bYL0%c-#y7|tXwwcPp zwP*}Hw4U&H3ecTuv`5N6+9YoY?Thv*Ip{jSYnA41nHJfrHootQ zJ?F*Z7j~>6NDg9^3%e_IoDRYXeKP`%*Pbzw95HQIV0Z8Z9li@15Iv2^mffl4ViY!d|bQ8239JN{e_1qO@!stoQ zBAU}0%M|1)M7+M*Sre#2B4pToKlK_PyyN)!@E`vR*}Iy8A3JaEEXy57gO3AyQ|9Q} zGkyurI7K2wJkVbGtZHEBBlp{j4o)*Kg}U=y%F6+V7w~fDv0>flwfi10Apwx$~Q6p))K0J6%k)KTb`$v(C zLPOnlTU>~@h|_LFw}vb$B z>MSaDoBs-EbthCOsZ+YOrGGd@g(tt%usPdXK|=M`kA1qF^wKC zB>S6ZGFZz4-FtpF`iYWlaX9k_u?&tcCAC+c3OF3)%0$laUFw}x$Jp7(HJ6e{BL)uU za%V$bI*il2lTo7%_~9Q>j0bT)y7UWs;%Y;h@+#MOY7%;L?Ui+6{hhRgFdDh< zQ2!vluqo6LznixNZ*ZdnFOvLg$WiM}+`vD)?(J7hzt)7sP5QF&u2$PM6F$E#Q39X5 z^SF=y^grc3xv}8_SRr6T?fHslAIk(Ge2Vj>685i5QA}Q5Og_iv$mVmXK3zwVv|1dj(Hi`chA337vG1~J|>@5G`*P!*}UN=_6cb}2V~95t@*wmrID&N3<2TxN^CJGvaUbuf1uDAu*0z3G}y{aCdy^G%iF%U;B; zqt3;f#I&-Cp~6ROb;&ay!m4tTxlc+N?ij@Y7+66iyFoo}6v` zs1%z@N1-YgDDAw}_=s@wF7Lgs#Y;5Tx!?#b)QOLb5#7@-nzU6_fzJ4EXdU9}3LC~g zw2Xux#}R6BL@772XI!M%w~eHP{Rv(Gzu0cH8u~8+##7DBNHCxs;Z;UT+9}lLQk(G<51fGlEcUo;LIhZEf-wTa}JL1@=oILR(NO@XseEDnhi0*RGp^(%*ET3&+fp=G& zqCgR_hDQEVQ^JnQ3MyA1R!fjig)t#E%8%)9aTXs8T>1tKYT>PuppqJ=wl(YD1vaQA zYmh>EN?h2$doD7q=<^ZR4Kp7h(@sz-74b8#WgC57Hn2s1X7&feW^yNIy%7E>AcyfF0OB5v;v z(Fx}vjKez+PGWQR1Ac&F(4BCTF(9N~AWU9d-AIH@Ht#h3o^muv|5O?}^R>Zw6m){m z>fwz+ISd2o)we86fegK3wA(^}m4XN)SXL1fO?_tl=k8}hjnnq2rOp^FtnJPX*|_OS zk1CykewF>eyYG&;I#=j05E;Kfw9{;M~u&)jI zN040BXU9TI9S=dBa$<#zxOc2>epAW9^*Ve{~RoScZRGE zfS3?SRBAKRy{r1ypH!oE%^2PmPVkA@4^|w!>hW#~SUi#^#z?$*^kP8p%CP6Ss;jb# z`3@v_<1X%=8)}cC<#|{@{y}s)L8e?gZr^-(jJ3Cu?iAnO#oE0o6g$pCF4O~Em;Ies zjc-JH3uX1Gdofr?r)vM5HSb~Ql}~jvC}6>CZSIuC@NeFcFX5>QWDZq6=EV$__i_Fy z>F~|!2>M-a0H7|uMna%a8W*9~=%sp;Ss1hXpSH+;>Uxfh?Pm01l%y2NW0If;LPMhH zLC0PLqr7G@#o>?mrATV1M=>17q2Pz2G?)={lXn;{h|_mIhEuOZDNiNy|G}qJV_TNM zr-WI))6K9!p2|_#B;__kp$)FLwUD5M=R(=Lm4U-qmzju`n82#;V;VAsd0KcVMbz=P z7yV({jv~YH<8hn*+T}LipW(-?hJU={X9|F$V`;^;21F zxGb8<&&hTj8U&R&u7Eel5^8I?eCaCm{(3Tzsl4ifpEZ6ylC&sJIaWzjOw6DDjWZH& zkH{Fr55Bz;f=t=oKQz84cTWt<2PcUqFNoer)Ygc+4vahg5!#v_fkIg)nO1<;wr%2{ zP~(v#>(_a860vI^1}aCv0CXgRdPKX8UiT=p0@MWSOi=0(4-A~m*_ZFhy%ALKX)eG>6A;NN9~JLXL2 zB;M{m=E#E#AEHb|O=?kaOs3DBzT?yM$U;~t%P%APA#l@wnVFY@_^lw&rWLufW>CLo zp=v>~2op&zufMA$sOWpfb@TwKX9iNsI;oH4NX^l7`!+bkL1I||)-2rfv_opgqsX#u zJ9LbGkHT|Wk9HoVM?7VpDIM8JiaSJQR%oc=f7;|M_Z2RvS`H7C#6(z0sDfD@5KBJ{ zkobqld=$S8dNXFlZ_uKg-q?%%n9KOBNXB1+9y2pfRKd{vA59ht90koly07Tv6oBAm zNCYgOJ0ZyQ2&+(O6vs!-)wvlykgZsgf$J z>c8>Zh=Rjy32k-UaSJkV{_-D>a_ith*_?3mQsroC&J)q27`7NdG6wmH;GFZwgl3C-rV@q|`5DX2c!K79WQ=vnQBOV6^n*A>m2&!To;#IlmizO{PRi5Pz8QNGW=luWW1%67;w?GFziLCJ!rzF29~&Tq?GiRm!%-&CR5BBFkesWijv;q55YMG zgp-BD_ul;&rI-fdiFR}wS#15S5i}9wCD9+@hAY1JDXFmeE^w8)0bv8w>i^#-a!1#2 zOUQ8CE&coOb4Rw}kkhp9b*lT%Yr4rjcvD!`(&Nk;)xwT?gVeKFAa!OudW^Ikntp9M z5vV7sojS$s1?LdtE87r&%$0l;DK8ria+u}V?XUeJ3y{8(Ry^UjyQ^Fq0RT z6;&a>8RB7Hj&2+j7~|?rz!_QJ0oZF~w(NmAORoVA6ty{0z`h*GI#K1MXh$~&${cN8 z%yVfV0%2fr_pRuf633N+Cabh7hX zhsGH`P5p$w=}R`^Xnd>l`T}GTq{4wJS^KJDhf9}Qr;)u3u&y?wt6vMKq>6@}t z-W5z$v?T0qwrMa;xZ9mw#n&slmc+JlgkAh$M~+}MSsiYl<7=vYnR>1S7Y=1ge`)dA&rJ>>ml(yfLp=b(g~1BdjdMr( zSbjoFA*X04?o5$4#@~SaG+6XfIwwpka-AH8RzJk2>};8VbuK0m0*W19KP z@cqQ2&+>(pOoGbWm)2N0TkVy4o5TZQh-2}>E5?|Y_80w{d0#Euhx#eujx69Bk&ek` zB@@=5m6dP*h>nmXm_!}@Scs^QO-&BU?+d#c+pX%j<>t9d`_pF-0IixmZf1zS^3XJ* zH?gb8_a;jVKv6IDN@8OJ0A|l9_cHb?lp#!!53`@@ti(POOY@nzj+X=WCb$onFbf}= zXY^wZ?%M_pMtj~<+@i(wb4l-II*KZ)l%4w`hUjE1xr%1r`3yiuzAHP!j6w18XmfS>S1blu8$qn&_Umpmh z4mM0=U)T!8Ut3%8`_6179H81V9HRt7hSj*tno?Vaty9xqEkxPVo%FD5`ZCvjinA!d zT&}3eE{qt|AHw|0Ese1R`*=Mq7~)YxD14aB|l$B?u3N!oBR8w7eG_2C?!Bk7hVl z&CT#UA8VhuZ$&Urg4gkUC#WHgnuGdIpRxgJv!6}Wg3`GYcGI!f)lDrNADud&nJ>hQ zP*tD2#lm(5YKmk$P*WUPOa5M{snlk|>kd9)k6Z*T=bHa*WJHkgNR&vPiqNN;()7bN zpL;nBtCqnJ4T~lV;!cgzVI{^=c>^K1-jT!lEU#KZjKWNG{-mRMDjwH(r%sO(G52e* zO1o(4A6sSfi~j3lG`~(faZ#L(N9iz!i(#AtI?oHf(~?nvLo4ot#F?(eZ?T^?JBTn+ zLHx>_HCW77ze8_5d_0@klhgqAX}(<%I2-)sU&s7{9;ztDVK(dbYkcMoNp#?W^n9Z| zN@dhwQk#?QU);Z2%#;ek=hq|JOkns!VWu=X;HYJhpltpjpfQQW>>< z=z8bsnip@9H-MXt1bCrRHu8jG<|^@!AFd5KQM^g<>-QZUoJzNdocPQz3{q6=2^LGz#O8+=HRKB`mB2uf=X7p&4%s-~XD zL^(Ns1SE(mcW&VB+XDReVTpe+`*G-a+Cc3F$2h=hzhP{9QfglMh(dW(Fmz~WM?ZK= zU*tOW`gU-com^L->$vV3~j&f^JU{%Fv<)?aQFh~t>aHf6kI_Z z9~YhT*4=|?Zc2D<*@%3Mx|;YT%vnv4-2DpJmXLBolAGMN zSMx+P?fGSz1122kXezUS*=SjIpR5Tp4O?o0e_t%9xaM$fFOnq`jMavdBm~jV;=FR28@q^v0mx!!G+*9DK^qX#Gg_|Eu&mYIYZ&cLI69#(*iZckta^l1$JC%) zA*io0TB|Xfg@|4L^3@%Ia&7isTiH8DM}~DV06@?eBxv#9rO3tXbP4*>+-EEik@|TXHu<5+oNOuH!!aFi} zcxeKiw&%Ap8Xx9x6C+yvLTbP}J2mA~udh}{_F%)G4dLIik@qg0XFooT2fMyE>Q7@p zSf#p_GwOkMJrwc9?pjsedSd;g8$Ms3r~nm8$mq;=*?aY&FaEIShXOOY;ie zwl|};=8w010|@^566xLIk?5ddgYUl$09>kp``uGG_U7=`0<}g|*TYBs1P2;wWPTzB zXagCUJiZ+=!&R{vIbhS%=alP;%kw!I5)^f;^^#e6K@D8Y&!+fecsi`M$^<%YsZ5CB zvIgduI>N(pM+QWr4{C*8XMo!DA>p9d$x>~0u#G>2V0`RB49e>P{M6_J7s+OyZfo(A zFB$PFkdiJ?-eRv)uuq%4d%~vGx=Z30ZxMV;9BEsI&Swr~;aqG92Os+{7{b z?K<{16xCD05T8{qb;K*MX=|lWftzUyThbrey|*9=mW;?RGjHDVkCa(~q=@|ZXfBZ= zm3#iY9P+i;Y2O0@Fyz`aR}ax@XKqctKimEtHEyysVdYhJBuWxdF)CeUt^c&FKrd|S zufkJ=dqJti@O(`szC~tRq(TvZwKuUK1NL}KDwZIYpTUM&*KI$;-QJeNf7W+)KP3ds zy`BQ0yES91Qyb9gGLK7)0?_G$#&+5Flg6so)K#^~j~n{|ocm8BHzx7A<GYubw4H0CZbIT*OAJ@w z`qhgaEiaTKPPK@$63fotsNS!R`Z~IN0Q{wbass#%+@?M8)~Xm2J0(_)q7vG!J-RGA zvMk~#Y#L+PaFf`?Pmv9)r#tz_wSv~qp&?FG+f{kiyZypgzjve;{n4k7_Y)3d7<;lC zXS7u-=$%zslys2Wm=DPKMH`iq-+5AtyZp=3hDB4i<^nIi3;urB;hKX}AwR<@H4b?* z1jF{S-Va#(y8?z3MePekvlv~agGD^byHPox(VpSHSaQfF^D}~|e?`l~wQKC@{d2w7 zZRNpK%cD9whh(ehzs!`U0#kywClb{Q+CKG8dYW?h*2H11C^#gvoh0eQz7kWu6k8w| zVrQXnwcmqK<%4no2u>m*ChCiPW{`7j5u@nElT=_gF#JD?cWVq@I~eJ^Td^QT;dDQD)Y?BK)k!4YpPUkfU8Nc%R*0)HgW-@awd@G1J?ibLe9;d{nPX0m{1EL&rUKu4kx zdrJ-P#@5qRD38OMzgV*UgPBGA?{k~g(+Km<+cXo810oPpPtEznkQk zOZ2kDW95;@oX3I0AkswTJk345g0cnar<&LkF6iDLu^d4NZspb|*ix9+MQf>Z$Irlt zeC>%wnGYLN^{+>~6EymJVOJO;vXix zlv@bX*sz6X+j-yVdm09`pGv$Tykke$t=$*{NZKo$pP1zU4{}<`w5u||Q7QKCyoNU} zU&F0`be4t+WBP&Xwm05>05<6tW3BV)=FHvLQbclJDEg%@>CSX4haO`n4^|Vd)rdAy zw2^qJ0&F#~VCamiN_I}+93bf{I&B*u{yb(n2Ii%g;a9#C)k3aFrSZM~@$3#{`&wHi zDNb;OCm?|MZuhG}&TS04u$1VxPLWu16R^(qtMK$P(GI!b_o(zlpAd;K*eW__Sz_31 zfgPY*E;V&ghwc@lcKdg`gz`-88clS|6O~VDR`_((_(>;U5!i#-@!*TDk>PG;5e&4e2JgxFN;2{`D9(u( zh~RM+^!V3a4Xi))h>H>fcXnkFo$1I!DAAsL8cr%G^c2@ZDZaRF^)N^32G=o?wT$VW z^llQAN&CmmSw2(Tzwc^G?!=-3H~Hdo$A-2tecldU0kY!xXU1-aG(Wf$RYbX;3a+Z% zRtX>I>PhNd({xOh&OIyXcWf3I19q{aH;x_V47;)L@AE_B^zW&SY%PrQ@;H=es;TR= z?-Vj~lMfNih@Es^RbLC60PgLeAv&$vAKyT>CVzKp?Ao&W#jVN-HQkhv2#h`Q=>@!D zMb`E-GtxTDjkp7Hh|l;tUL|wzYqA=BE?p3%`u;k45#(NrtMHucG+5OVgaCfve&(Fv z?g>k?1X5wgMjcDhaD!@91}6(f*M-Lw5B?gR^=f3RSrCYs?wG9H&#AW0@#JS_zi;*S zH3xd(A3jB0w1_>yyKllG9%)Rk2i~iV=nqc! ziDbue!BIJST+qqA)1vJpif=zj7asF=|7&7o>^Z~^o#J>8pw3BOAPOaDhskCK6}%yl zML7H^Cj^N4t}EP_R(KLv|G%88{P0boAN|w>n&GMnwo2g^EFtsLrKq?Q)80=v$GiSC z;a0x6E#rf}>v0gZ=pp0CY6Db63Q}^(-vfQ3t@#;Bx2uZ9b9JbZ3yUHU%8F;QQCFH5 z@DQfeO)%s~9LY$4qVI|L_|Ki9@SfPW&DTiA3a!3@(cUn^s8r`?TUGI}Dz{gWT&`I3D` z^!wS$=;JTNXTnN$@ki8Wcb_T~j8aPYfkmK%=b?MLfhfzE~8CN;*iR-8+&@;)n+bJ*Ih%CH?M)(PHEBM7cH|bsv`QR0FQmE7T8DYZ%5Gj@Ml)Qa+cc+cQ;2-gvlr* wLO { + const alertDiv = document.createElement('div'); + alertDiv.classList.add("alert", `alert-${type}`, "alert-dismissible", "fade", "show", "d-flex", "flex-column", "shadow-sm"); + alertDiv.setAttribute("role", "alert"); + alertDiv.setAttribute("id", id); + alertDiv.style.maxWidth = "320px"; + + alertDiv.innerHTML = [ + `
`, + ` `, + ` `, + ` `, + ` ${errorHeader}`, + ` `, + `
`, + `
`, + `
${message}
`, + ].join(''); + + window.scrollTo(0, 0); + + alertPlaceholder.append(alertDiv); + + setTimeout(function () { + bootstrap.Alert.getOrCreateInstance(document.getElementById(`${id}`)).close(); + }, 5000); +} + +function toggleInteractables(isBlocking, excludedOnNotBlockingIds = [], otherBlockingUpdates = () => {}) { + if (isBlocking) { + loadingContainer.classList.add("d-flex"); + interactiveElems.forEach(elems => { + elems.disabled = true; + }); + window.scrollTo(0, 0); + otherBlockingUpdates(); + return; + } + + setTimeout(() => { + loadingContainer.classList.remove("d-flex"); + interactiveElems.forEach(elems => { + !excludedOnNotBlockingIds.includes(elems.id) ? elems.disabled = false : null; + }); + otherBlockingUpdates(); + }, 250); +} + +function showResetSavedSessionsModal() { + let sessions = localStorage.getItem("sessions"); + if (sessions === null) { + appendAlert('Error!', 'noSavedSessions', `No Saved Sessions Exist!`, 'danger'); + return; + } + sessions = JSON.parse(sessions); + + const resetSavedSessionsModal = new bootstrap.Modal(document.getElementById('resetSavedSessionsModal'), { + focus: true, keyboard: false + }); + + + let select = document.getElementById("delete-session-dropdown"); + select.innerHTML = ""; + Object.keys(sessions).forEach((alias) => { + let option = document.createElement("option"); + option.value = alias; + option.innerHTML = alias; + select.appendChild(option); + }); + + document.getElementById("selected-session").innerText = `"${document.getElementById("delete-session-dropdown").value}"`; + + resetSavedSessionsModal.show(); +} + +function resetSavedSessions() { + bootstrap.Modal.getInstance(document.getElementById("resetSavedSessionsModal")).hide(); + + const sessions = JSON.parse(localStorage.getItem("sessions")); + if (sessions === null) { + appendAlert('Error!', 'noSavedSessions', `No Saved Sessions Exist!`, 'danger'); + return; + } + + const activeTab = document.getElementById("reset-tabs").querySelector(".nav-link.active").getAttribute("id"); + if (activeTab === "delete-one-tab") { + const deleteOneConfirmation = document.getElementById("delete-one-confirmation").value; + if (deleteOneConfirmation !== document.getElementById("delete-session-dropdown").value) { + document.getElementById("resetSavedSessionsModal").querySelectorAll("form").forEach(form => { + form.reset(); + }) + appendAlert('Error!', 'noSavedSessions', `Invalid Confirmation Entry!`, 'danger'); + return; + } + + delete sessions[document.getElementById("delete-session-dropdown").value]; + Object.keys(sessions).length === 0 + ? localStorage.removeItem("sessions") + : localStorage.setItem("sessions", JSON.stringify(sessions)); + + } else { + const deleteAllConfirmation = document.getElementById("delete-all-confirmation").value; + if (deleteAllConfirmation !== "Delete All") { + document.getElementById("resetSavedSessionsModal").querySelectorAll("form").forEach(form => { + form.reset(); + }) + appendAlert('Error!', 'noSavedSessions', `Invalid Confirmation Entry!`, 'danger'); + return; + } + + localStorage.removeItem("sessions"); + } + + appendAlert('Success!', 'resetCookies', `Saved Session Reset Successful!`, 'success'); + setTimeout(() => { + location.reload(); + }, 750); +} + +document.getElementById("close-reset-modal").addEventListener("click", () => { + document.getElementById("resetSavedSessionsModal").querySelectorAll("form").forEach(form => { + form.reset(); + }) +}); + +document.getElementById("delete-session-dropdown").addEventListener("change", () => { + document.getElementById("selected-session").innerText = + `"${document.getElementById("delete-session-dropdown").value}"`; +}); diff --git a/util/gem5-resources-manager/static/js/editor.js b/util/gem5-resources-manager/static/js/editor.js new file mode 100644 index 0000000000..64786da0bd --- /dev/null +++ b/util/gem5-resources-manager/static/js/editor.js @@ -0,0 +1,589 @@ +const diffEditorContainer = document.getElementById("diff-editor"); +var diffEditor; +var originalModel; +var modifiedModel; + +const schemaEditorContainer = document.getElementById("schema-editor"); +var schemaEditor; +var schemaModel; + +const schemaButton = document.getElementById("schema-toggle"); +const editingActionsButtons = Array.from( + document.querySelectorAll("#editing-actions button") +); +var editingActionsState; + +const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); +tooltipTriggerList.forEach(tooltip => { + tooltip.setAttribute("data-bs-trigger", "hover"); +}); +const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); + +require.config({ + paths: { + vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs", + }, +}); +require(["vs/editor/editor.main"], () => { + originalModel = monaco.editor.createModel(`{\n}`, "json"); + modifiedModel = monaco.editor.createModel(`{\n}`, "json"); + diffEditor = monaco.editor.createDiffEditor(diffEditorContainer, { + theme: "vs-dark", + language: "json", + automaticLayout: true, + }); + diffEditor.setModel({ + original: originalModel, + modified: modifiedModel, + }); + fetch("/schema") + .then((res) => res.json()) + .then((data) => { + monaco.languages.json.jsonDefaults.setDiagnosticsOptions({ + trailingCommas: "error", + comments: "error", + validate: true, + schemas: [ + { + uri: "http://json-schema.org/draft-07/schema", + fileMatch: ["*"], + schema: data, + }, + ], + }); + + schemaEditor = monaco.editor.create(schemaEditorContainer, { + theme: "vs-dark", + language: "json", + automaticLayout: true, + readOnly: true, + }); + + schemaModel = monaco.editor.createModel(`{\n}`, "json"); + schemaEditor.setModel(schemaModel); + schemaModel.setValue(JSON.stringify(data, null, 4)); + + schemaEditorContainer.style.display = "none"; + }); +}); + +let clientType = document.getElementById('client-type'); +clientType.textContent = clientType.textContent === "mongodb" ? "MongoDB" : clientType.textContent.toUpperCase(); + +const revisionButtons = [document.getElementById("undo-operation"), document.getElementById("redo-operation")]; +revisionButtons.forEach(btn => { + btn.disabled = true; +}); + +const editorGroupIds = []; +document.querySelectorAll(".editorButtonGroup button, .revisionButtonGroup button") + .forEach(btn => { + editorGroupIds.push(btn.id); + }); + +function checkErrors() { + let errors = monaco.editor.getModelMarkers({ resource: modifiedModel.uri }); + if (errors.length > 0) { + console.log(errors); + let str = ""; + errors.forEach((error) => { + str += error.message + "\n"; + }); + appendAlert('Error!', 'schemaError', { str }, 'danger'); + return true; + } + return false; +} +let didChange = false; + +function update(e) { + e.preventDefault(); + if (checkErrors()) { + return; + } + let json = JSON.parse(modifiedModel.getValue()); + let original_json = JSON.parse(originalModel.getValue()); + + console.log(json); + fetch("/update", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + resource: json, + original_resource: original_json, + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then(async (data) => { + console.log(data); + await addVersions(); + //Select last option + document.getElementById("version-dropdown").value = + json["resource_version"]; + console.log(document.getElementById("version-dropdown").value); + find(e); + }); +} + +function addNewResource(e) { + e.preventDefault(); + if (checkErrors()) { + return; + } + let json = JSON.parse(modifiedModel.getValue()); + console.log(json); + fetch("/insert", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + resource: json, + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then(async (data) => { + console.log(data); + await addVersions(); + //Select last option + document.getElementById("version-dropdown").value = + json["resource_version"]; + console.log(document.getElementById("version-dropdown").value); + find(e); + }); +} + +function addVersion(e) { + e.preventDefault(); + console.log("add version"); + if (checkErrors()) { + return; + } + let json = JSON.parse(modifiedModel.getValue()); + console.log(json["resource_version"]); + fetch("/checkExists", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: json["id"], + resource_version: json["resource_version"], + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then((data) => { + console.log(data["exists"]); + if (data["exists"] == true) { + appendAlert("Error!", "existingResourceVersion", "Resource version already exists!", "danger"); + return; + } else { + fetch("/insert", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + resource: json, + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then(async (data) => { + console.log("added version"); + console.log(data); + await addVersions(); + //Select last option + document.getElementById("version-dropdown").value = + json["resource_version"]; + console.log(document.getElementById("version-dropdown").value); + find(e); + }); + } + }); +} + +function deleteRes(e) { + e.preventDefault(); + console.log("delete"); + let id = document.getElementById("id").value; + let resource_version = JSON.parse(originalModel.getValue())[ + "resource_version" + ]; + let json = JSON.parse(originalModel.getValue()); + console.log(resource_version); + fetch("/delete", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + resource: json, + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then(async (data) => { + console.log(data); + await addVersions(); + //Select first option + document.getElementById("version-dropdown").value = + document.getElementById("version-dropdown").options[0].value; + console.log(document.getElementById("version-dropdown").value); + find(e); + }); +} + +document.getElementById("id").onchange = function () { + console.log("id changed"); + didChange = true; +}; + +async function addVersions() { + let select = document.getElementById("version-dropdown"); + select.innerHTML = "Latest"; + await fetch("/versions", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: document.getElementById("id").value, + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then((data) => { + let select = document.getElementById("version-dropdown"); + if (data.length == 0) { + data = [{ resource_version: "Latest" }]; + } + data.forEach((version) => { + let option = document.createElement("option"); + option.value = version["resource_version"]; + option.innerText = version["resource_version"]; + select.appendChild(option); + }); + }); +} + +function find(e) { + e.preventDefault(); + if (didChange) { + addVersions(); + didChange = false; + } + + closeSchema(); + + toggleInteractables(true, editorGroupIds, () => { + diffEditor.updateOptions({ readOnly: true }); + updateRevisionBtnsDisabledAttr(); + }); + + fetch("/find", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: document.getElementById("id").value, + resource_version: document.getElementById("version-dropdown").value, + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then((data) => { + console.log(data); + toggleInteractables(false, editorGroupIds, () => { + diffEditor.updateOptions({ readOnly: false }); + updateRevisionBtnsDisabledAttr(); + }); + + if (data["exists"] == false) { + fetch("/keys", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + category: document.getElementById("category").value, + id: document.getElementById("id").value, + }), + }) + .then((res) => res.json()) + .then((data) => { + console.log(data) + data["id"] = document.getElementById("id").value; + data["category"] = document.getElementById("category").value; + originalModel.setValue(JSON.stringify(data, null, 4)); + modifiedModel.setValue(JSON.stringify(data, null, 4)); + + document.getElementById("add_new_resource").disabled = false; + document.getElementById("add_version").disabled = true; + document.getElementById("delete").disabled = true; + document.getElementById("update").disabled = true; + }); + } else { + console.log(data); + originalModel.setValue(JSON.stringify(data, null, 4)); + modifiedModel.setValue(JSON.stringify(data, null, 4)); + + document.getElementById("version-dropdown").value = + data.resource_version; + document.getElementById("category").value = data.category; + + document.getElementById("add_new_resource").disabled = true; + document.getElementById("add_version").disabled = false; + document.getElementById("delete").disabled = false; + document.getElementById("update").disabled = false; + } + }); +} + +window.onload = () => { + let ver_dropdown = document.getElementById("version-dropdown"); + let option = document.createElement("option"); + option.value = "Latest"; + option.innerHTML = "Latest"; + ver_dropdown.appendChild(option); + fetch("/categories") + .then((res) => res.json()) + .then((data) => { + console.log(data); + let select = document.getElementById("category"); + data.forEach((category) => { + let option = document.createElement("option"); + option.value = category; + option.innerHTML = category; + select.appendChild(option); + }); + fetch("/keys", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + category: document.getElementById("category").value, + id: "", + }), + }) + .then((res) => res.json()) + .then((data) => { + data["id"] = ""; + data["category"] = document.getElementById("category").value; + originalModel.setValue(JSON.stringify(data, null, 4)); + modifiedModel.setValue(JSON.stringify(data, null, 4)); + document.getElementById("add_new_resource").disabled = false; + }); + }); + + checkExistingSavedSession(); +}; + +const myModal = new bootstrap.Modal("#ConfirmModal", { + keyboard: false, +}); + +let confirmButton = document.getElementById("confirm"); + +function showModal(event, callback) { + event.preventDefault(); + myModal.show(); + confirmButton.onclick = () => { + callback(event); + myModal.hide(); + }; +} + +let editorTitle = document.getElementById("editor-title"); + +function showSchema() { + if (diffEditorContainer.style.display !== "none") { + diffEditorContainer.style.display = "none"; + schemaEditorContainer.classList.add("editor-sizing"); + schemaEditor.setPosition({ column: 1, lineNumber: 1 }); + schemaEditor.revealPosition({ column: 1, lineNumber: 1 }); + schemaEditorContainer.style.display = "block"; + + editingActionsState = editingActionsButtons.map( + (button) => button.disabled + ); + + editingActionsButtons.forEach((btn) => { + btn.disabled = true; + }); + + editorTitle.children[0].style.display = "none"; + editorTitle.children[1].textContent = "Schema (Read Only)"; + + schemaButton.textContent = "Close Schema"; + schemaButton.onclick = closeSchema; + } +} + +function closeSchema() { + if (schemaEditorContainer.style.display !== "none") { + schemaEditorContainer.style.display = "none"; + diffEditorContainer.style.display = "block"; + + editingActionsButtons.forEach((btn, i) => { + btn.disabled = editingActionsState[i]; + }); + + editorTitle.children[0].style.display = "unset"; + editorTitle.children[1].textContent = "Edited"; + + schemaButton.textContent = "Show Schema"; + schemaButton.onclick = showSchema; + } +} + +const saveSessionBtn = document.getElementById("saveSession"); +saveSessionBtn.disabled = true; + +let password = document.getElementById("session-password"); +password.addEventListener("input", () => { + saveSessionBtn.disabled = password.value === ""; +}); + +function showSaveSessionModal() { + const saveSessionModal = new bootstrap.Modal(document.getElementById('saveSessionModal'), { + focus: true, keyboard: false + }); + saveSessionModal.show(); +} + +function saveSession() { + alias = document.getElementById("alias").innerText; + + bootstrap.Modal.getInstance(document.getElementById("saveSessionModal")).hide(); + + let preserveDisabled = []; + document.querySelectorAll(".editorButtonGroup button, .revisionButtonGroup button") + .forEach(btn => { + btn.disabled === true ? preserveDisabled.push(btn.id) : null; + }); + + toggleInteractables(true); + + fetch("/saveSession", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + alias: alias, + password: document.getElementById("session-password").value + }), + }) + .then((res) => { + document.getElementById("saveSessionForm").reset(); + + toggleInteractables(false, preserveDisabled); + + res.json() + .then((data) => { + if (res.status === 400) { + appendAlert('Error!', 'saveSessionError', `${data["error"]}`, 'danger'); + return; + } + + let sessions = JSON.parse(localStorage.getItem("sessions")) || {}; + sessions[alias] = data["ciphertext"]; + localStorage.setItem("sessions", JSON.stringify(sessions)); + + document.getElementById("showSaveSessionModal").innerText = "Session Saved"; + checkExistingSavedSession(); + }) + }) +} + +function executeRevision(event, operation) { + if (!["undo", "redo"].includes(operation)) { + appendAlert("Error!", "invalidRevOp", "Fatal! Invalid Revision Operation!", "danger"); + return; + } + + toggleInteractables(true, editorGroupIds, () => { + diffEditor.updateOptions({ readOnly: true }); + updateRevisionBtnsDisabledAttr(); + }); + fetch(`/${operation}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + alias: document.getElementById("alias").innerText, + }), + }) + .then(() => { + toggleInteractables(false, editorGroupIds, () => { + diffEditor.updateOptions({ readOnly: false }); + updateRevisionBtnsDisabledAttr(); + }); + find(event); + }) +} + +function updateRevisionBtnsDisabledAttr() { + fetch("/getRevisionStatus", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => res.json()) + .then((data) => { + revisionButtons[0].disabled = data.undo; + revisionButtons[1].disabled = data.redo; + }) +} + +function logout() { + toggleInteractables(true); + + fetch("/logout", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + alias: document.getElementById("alias").innerText, + }), + }) + .then((res) => { + toggleInteractables(false); + + if (res.status !== 302) { + res.json() + .then((data) => { + appendAlert('Error!', 'logoutError', `${data["error"]}`, 'danger'); + return; + }) + } + + window.location = res.url; + }) +} + +function checkExistingSavedSession() { + document.getElementById("existing-session-warning").style.display = + document.getElementById("alias").innerText in JSON.parse(localStorage.getItem("sessions") || "{}") + ? "flex" + : "none"; +} + +document.getElementById("close-save-session-modal").addEventListener("click", () => { + document.getElementById("saveSessionModal").querySelector("form").reset(); + saveSessionBtn.disabled = password.value === ""; +}); diff --git a/util/gem5-resources-manager/static/js/index.js b/util/gem5-resources-manager/static/js/index.js new file mode 100644 index 0000000000..1509d2d893 --- /dev/null +++ b/util/gem5-resources-manager/static/js/index.js @@ -0,0 +1,75 @@ +window.onload = () => { + let select = document.getElementById("sessions-dropdown"); + const sessions = JSON.parse(localStorage.getItem("sessions")); + + if (sessions === null) { + document.getElementById("showSavedSessionModal").disabled = true; + return; + } + + Object.keys(sessions).forEach((alias) => { + let option = document.createElement("option"); + option.value = alias; + option.innerHTML = alias; + select.appendChild(option); + }); +} + +const loadSessionBtn = document.getElementById("loadSession"); +loadSessionBtn.disabled = true; + +let password = document.getElementById("session-password"); +password.addEventListener("input", () => { + loadSessionBtn.disabled = password.value === ""; +}); + +document.getElementById("close-load-session-modal").addEventListener("click", () => { + document.getElementById("savedSessionModal").querySelector("form").reset(); +}) + +function showSavedSessionModal() { + const savedSessionModal = new bootstrap.Modal(document.getElementById('savedSessionModal'), { focus: true, keyboard: false }); + savedSessionModal.show(); +} + +function loadSession() { + bootstrap.Modal.getInstance(document.getElementById("savedSessionModal")).hide(); + + const alias = document.getElementById("sessions-dropdown").value; + const session = JSON.parse(localStorage.getItem("sessions"))[alias]; + + if (session === null) { + appendAlert("Error!", "sessionNotFound", "Saved Session Not Found!", "danger"); + return; + } + + toggleInteractables(true); + + fetch("/loadSession", { + method: "POST", + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + password: document.getElementById("session-password").value, + alias: alias, + session: session + }) + }) + .then((res) => { + toggleInteractables(false); + + if (res.status !== 200) { + res.json() + .then((error) => { + document.getElementById("savedSessionModal").querySelector("form").reset(); + appendAlert("Error!", "invalidStatus", `${error["error"]}`, "danger"); + return; + }) + } + + if (res.redirected) { + window.location = res.url; + } + }) +} diff --git a/util/gem5-resources-manager/static/js/login.js b/util/gem5-resources-manager/static/js/login.js new file mode 100644 index 0000000000..b21ffeb458 --- /dev/null +++ b/util/gem5-resources-manager/static/js/login.js @@ -0,0 +1,330 @@ +function handleMongoDBLogin(event) { + event.preventDefault(); + const activeTab = document.getElementById("mongodb-login-tabs").querySelector(".nav-link.active").getAttribute("id"); + + activeTab === "enter-uri-tab" ? handleEnteredURI() : handleGenerateURI(); + + return; +} + +function handleEnteredURI() { + const uri = document.getElementById('uri').value; + const collection = document.getElementById('collection').value; + const database = document.getElementById('database').value; + const alias = document.getElementById('alias').value; + const emptyInputs = [{ type: "Alias", value: alias }, { type: "Collection", value: collection }, { type: "Database", value: database }, { type: "URI", value: uri }]; + let error = false; + + for (let i = 0; i < emptyInputs.length; i++) { + if (emptyInputs[i].value === "") { + appendAlert("Error", `${emptyInputs[i].type}`, `Cannot Proceed Without ${emptyInputs[i].type} Value!`, 'danger'); + error = true; + } + } + + if (error) { + return; + } + + handleMongoURLFetch(uri, collection, database, alias); +} + +function handleGenerateURI() { + const connection = document.getElementById('connection').checked; + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + const collection = document.getElementById('collectionGenerate').value; + const database = document.getElementById('databaseGenerate').value; + const host = document.getElementById('host').value; + const alias = document.getElementById('aliasGenerate').value; + const options = document.getElementById('options').value.split(","); + let generatedURI = ""; + const emptyInputs = [{ type: "Alias", value: alias }, { type: "Host", value: host }, { type: "Collection", value: collection }, { type: "Database", value: database }]; + let error = false; + + for (let i = 0; i < emptyInputs.length; i++) { + if (emptyInputs[i].value === "") { + appendAlert("Error", `${emptyInputs[i].type}`, `Cannot Proceed Without ${emptyInputs[i].type} Value!`, 'danger'); + error = true; + } + } + + if (error) { + return; + } + + generatedURI = connection ? "mongodb+srv://" : "mongodb://"; + if (username && password) { + generatedURI += `${encodeURIComponent(username)}:${encodeURIComponent(password)}@`; + } + + generatedURI += host; + + if (options.length) { + generatedURI += `/?${options.join("&")}`; + } + + handleMongoURLFetch(generatedURI, collection, database, alias); +} + +function handleMongoURLFetch(uri, collection, database, alias) { + toggleInteractables(true); + + fetch("/validateMongoDB", + { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + uri: uri, + collection: collection, + database: database, + alias: alias + }) + }) + .then((res) => { + toggleInteractables(false); + + if (!res.ok) { + res.json() + .then(error => { + appendAlert('Error!', 'mongodbValidationError', `${error.error}`, 'danger'); + }); + return; + } + + res.redirected ? window.location = res.url : appendAlert('Error!', 'invalidRes', 'Invalid Server Response!', 'danger'); + }) +} + +function handleJSONLogin(event) { + event.preventDefault(); + const activeTab = document.getElementById("json-login-tabs").querySelector(".nav-link.active").getAttribute("id"); + if (activeTab === "remote-tab") { + handleRemoteJSON(); + } else if (activeTab === "existing-tab") { + const filename = document.getElementById("existing-dropdown").value; + if (filename !== "No Existing Files") { + toggleInteractables(true); + + fetch(`/existingJSON?filename=${filename}`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + .then((res) => { + toggleInteractables(false); + + if (res.status !== 200) { + appendAlert('Error!', 'invalidURL', 'Invalid JSON File URL!', 'danger'); + } + if (res.redirected) { + window.location = res.url; + } + }) + } + } else { + handleUploadJSON(); + } + return; +} + +function handleRemoteJSON() { + const url = document.getElementById("jsonRemoteURL").value; + const filename = document.getElementById("remoteFilename").value; + const emptyInputs = [{ type: "URL", value: url }, { type: "Filename", value: filename }]; + let error = false; + + for (let i = 0; i < emptyInputs.length; i++) { + if (emptyInputs[i].value === "") { + appendAlert("Error", `${emptyInputs[i].type}`, `Cannot Proceed Without ${emptyInputs[i].type} Value!`, 'danger'); + error = true; + } + } + + if (error) { + return; + } + + const params = new URLSearchParams(); + params.append('filename', filename + ".json"); + params.append('q', url); + + const flask_url = `/validateJSON?${params.toString()}`; + + toggleInteractables(true); + + fetch(flask_url, { + method: 'GET', + }) + .then((res) => { + toggleInteractables(false); + + if (res.status === 400) { + appendAlert('Error!', 'invalidURL', 'Invalid JSON File URL!', 'danger'); + } + + if (res.status === 409) { + const myModal = new bootstrap.Modal(document.getElementById('conflictResolutionModal'), { focus: true, keyboard: false }); + document.getElementById("header-filename").textContent = `"${filename}"`; + myModal.show(); + } + + if (res.redirected) { + window.location = res.url; + } + }) +} + +var filename; + +function handleUploadJSON() { + const jsonFile = document.getElementById("jsonFile"); + const file = jsonFile.files[0]; + + if (jsonFile.value === "") { + appendAlert('Error!', 'emptyUpload', 'Cannot Proceed Without Uploading a File!', 'danger'); + return; + } + + filename = file.name; + + const form = new FormData(); + form.append("file", file); + + toggleInteractables(true); + + fetch("/validateJSON", { + method: 'POST', + body: form + }) + .then((res) => { + toggleInteractables(false); + + if (res.status === 400) { + appendAlert('Error!', 'invalidUpload', 'Invalid JSON File Upload!', 'danger'); + } + + if (res.status === 409) { + const myModal = new bootstrap.Modal(document.getElementById('conflictResolutionModal'), { focus: true, keyboard: false }); + document.getElementById("header-filename").textContent = `"${filename}"`; + myModal.show(); + } + + if (res.redirected) { + window.location = res.url; + } + }) +} + +function saveConflictResolution() { + const conflictResolutionModal = bootstrap.Modal.getInstance(document.getElementById("conflictResolutionModal")); + const selectedValue = document.querySelector('input[name="conflictRadio"]:checked').id; + const activeTab = document.getElementById("json-login-tabs").querySelector(".nav-link.active").getAttribute("id"); + + if (selectedValue === null) { + appendAlert('Error!', 'nullRadio', 'Fatal! Null Radio!', 'danger'); + return; + } + + if (selectedValue === "clearInput") { + if (activeTab === "upload-tab") { + document.getElementById("jsonFile").value = ''; + } + + if (activeTab === "remote-tab") { + document.getElementById('remoteFilename').value = ''; + document.getElementById('jsonRemoteURL').value = ''; + } + + conflictResolutionModal.hide(); + handleConflictResolution("clearInput", filename.split(".")[0]); + return; + } + + if (selectedValue === "openExisting") { + conflictResolutionModal.hide(); + handleConflictResolution("openExisting", filename.split(".")[0]); + return; + } + + if (selectedValue === "overwrite") { + conflictResolutionModal.hide(); + handleConflictResolution("overwrite", filename.split(".")[0]); + return; + } + + if (selectedValue === "newFilename") { + const updatedFilename = document.getElementById("updatedFilename").value; + if (updatedFilename === "") { + appendAlert('Error!', 'emptyFilename', 'Must Enter A New Name!', 'danger'); + return; + } + + if (`${updatedFilename}.json` === filename) { + appendAlert('Error!', 'sameFilenames', 'Cannot Have Same Name as Current!', 'danger'); + return; + } + + conflictResolutionModal.hide(); + handleConflictResolution("newFilename", updatedFilename); + return; + } +} + +function handleConflictResolution(resolution, filename) { + const params = new URLSearchParams(); + params.append('resolution', resolution); + params.append('filename', filename !== "" ? filename + ".json" : ""); + + const flask_url = `/resolveConflict?${params.toString()}`; + toggleInteractables(true); + + fetch(flask_url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + .then((res) => { + toggleInteractables(false); + + if (res.status === 204) { + console.log("Input Cleared, Cached File Deleted, Resources Unset"); + return; + } + + if (res.status !== 200) { + appendAlert('Error!', 'didNotRedirect', 'Server Did Not Redirect!', 'danger'); + return; + } + + if (res.redirected) { + window.location = res.url; + } + }) +} + +window.onload = () => { + if (window.location.pathname === "/login/json") { + fetch('/existingFiles', { + method: 'GET', + }) + .then((res) => res.json()) + .then((data) => { + let select = document.getElementById("existing-dropdown"); + if (data.length === 0) { + data = ["No Existing Files"]; + } + data.forEach((files) => { + let option = document.createElement("option"); + option.value = files; + option.innerHTML = files; + select.appendChild(option); + }); + }); + } +} diff --git a/util/gem5-resources-manager/static/styles/global.css b/util/gem5-resources-manager/static/styles/global.css new file mode 100644 index 0000000000..caa446a60b --- /dev/null +++ b/util/gem5-resources-manager/static/styles/global.css @@ -0,0 +1,231 @@ +@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Mulish:wght@700&display=swap'); + +html, +body { + min-height: 100vh; + margin: 0; +} + +.btn-outline-primary { + --bs-btn-color: #0095AF; + --bs-btn-bg: #FFFFFF; + --bs-btn-border-color: #0095AF; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #0095AF; + --bs-btn-hover-border-color: #0095AF; + --bs-btn-focus-shadow-rgb: 13, 110, 253; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #0095AF; + --bs-btn-active-border-color: #0095AF; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: white; + --bs-btn-disabled-bg: grey; + --bs-btn-disabled-border-color: grey; + --bs-gradient: none; +} + +.btn-box-shadow { + box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; +} + +.calc-main-height { + height: calc(100vh - 81px); +} + +.main-text-semi { + font-family: 'Open Sans', sans-serif; + font-weight: 600; + font-size: 1rem; +} + +.main-text-regular, +.buttonGroup>button, +#markdown-body-styling p, +#markdown-body-styling li { + font-family: 'Open Sans', sans-serif; + font-weight: 400; + font-size: 1rem; +} + +.secondary-text-semi { + font-family: 'Open Sans', sans-serif; + font-weight: 600; + font-size: 1.25rem; +} + +.secondary-text-bold { + font-family: 'Open Sans', sans-serif; + font-weight: 600; + font-size: 1.25rem; +} + +.main-text-bold { + font-family: 'Open Sans', sans-serif; + font-weight: 700; + font-size: 1rem; +} + +.page-title, +#markdown-body-styling h1 { + color: #425469; + font-family: 'Mulish', sans-serif; + font-weight: 700; + font-size: 2.5rem; +} + +.main-panel-container { + max-width: 530px; + padding-top: 5rem; + padding-bottom: 5rem; +} + +.input-shadow, +.form-input-shadow>input { + box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; +} + +.panel-container { + background: rgba(0, 149, 175, 0.50); + border-radius: 1rem; + box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px, rgba(0, 0, 0, 0.35) 0px 5px 15px; + height: 555px; + width: 530px; +} + +.panel-text-styling, +#generate-uri-form>label { + text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.50); + color: white; +} + +.editorContainer { + width: 80%; +} + +.monaco-editor { + position: absolute !important; +} + +.editor-sizing { + min-height: 650px; + height: 75%; + width: 100%; +} + +#liveAlertPlaceholder { + position: absolute; + margin-top: 1rem; + right: 2rem; + margin-left: 2rem; + z-index: 1040; +} + +.alert-dismissible { + padding-right: 1rem; +} + +.reset-nav, +.login-nav { + --bs-nav-link-color: #0095AF; + --bs-nav-link-hover-color: white; + --bs-nav-tabs-link-active-color: #0095AF; +} + +.login-nav-link { + color: white; + text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.50); +} + +.login-nav-link.active { + text-shadow: none; +} + +.navbar-nav>.nav-link:hover { + text-decoration: underline; +} + +.reset-nav-link:hover, +.login-nav-link:hover { + background-color: #0095AF; +} + +.reset-nav-link { + color: black; +} + +.form-check-input:checked { + background-color: #6c6c6c; + border-color: #6c6c6c; +} + +#markdown-body-styling h1 { + color: #425469; +} + +code { + display: inline-table; + overflow-x: auto; + padding: 2px; + color: #333; + background: #f8f8f8; + border: 1px solid #ccc; + border-radius: 3px; +} + +.editor-tooltips { + --bs-tooltip-bg: #0095AF; + --bs-tooltip-opacity: 1; +} + +#loading-container { + display: none; + position: absolute; + right: 2rem; + margin-top: 1rem; +} + +.spinner { + --bs-spinner-width: 2.25rem; + --bs-spinner-height: 2.25rem; + --bs-spinner-border-width: 0.45em; + border-color: #0095AF; + border-right-color: transparent; +} + +#saved-confirmation { + opacity: 0; + transition: opacity 0.5s; +} + +@media (max-width: 991px) { + .editorContainer { + width: 95%; + } +} + +@media (max-width: 425px) { + + .main-text-regular, + .main-text-semi, + .main-text-bold, + .buttonGroup>button, + #markdown-body-styling p { + font-size: 0.875rem; + } + + .secondary-text-semi { + font-size: 1rem; + } + + .page-title, + #markdown-body-styling h1 { + font-size: 2.25rem; + } +} + +@media (min-width: 425px) { + #databaseActions { + max-width: 375px; + } +} diff --git a/util/gem5-resources-manager/templates/404.html b/util/gem5-resources-manager/templates/404.html new file mode 100644 index 0000000000..0a38326b2e --- /dev/null +++ b/util/gem5-resources-manager/templates/404.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} {% block head %} +Page Not Found +{% endblock %} {% block body %} +
+
+

404

+

+ The page you are looking for does not seem to exist. +

+ Home +
+
+{% endblock %} diff --git a/util/gem5-resources-manager/templates/base.html b/util/gem5-resources-manager/templates/base.html new file mode 100644 index 0000000000..3b89f8f4c1 --- /dev/null +++ b/util/gem5-resources-manager/templates/base.html @@ -0,0 +1,96 @@ + + + + + + + + + {% block head %}{% endblock %} + + + +
+
+ Processing... +
+ Processing... +
+
+ + {% block body %}{% endblock %} + + + diff --git a/util/gem5-resources-manager/templates/editor.html b/util/gem5-resources-manager/templates/editor.html new file mode 100644 index 0000000000..813a4d1a4b --- /dev/null +++ b/util/gem5-resources-manager/templates/editor.html @@ -0,0 +1,355 @@ +{% extends 'base.html' %} {% block head %} +Editor + +{% endblock %} {% block body %} + + +
+
+
+
+
+ Database Actions +
+ +
+
+ +
+ + +
+ + + +
+
+
+ Revision Actions +
+
+ + + + + + +
+
+
+
+ Other Actions +
+ + + + + + + +
+
+
+ +
+

{{ client_type }}

+

+ {{ alias }} +

+
+
+

Original

+

Modified

+
+
+
+
+ + + + + + + + + + + + +
+
+
+
+ +{% endblock %} diff --git a/util/gem5-resources-manager/templates/help.html b/util/gem5-resources-manager/templates/help.html new file mode 100644 index 0000000000..957a87b59e --- /dev/null +++ b/util/gem5-resources-manager/templates/help.html @@ -0,0 +1,20 @@ +{% extends 'base.html' %} {% block head %} +Help + +{% endblock %} {% block body %} +
+
+ {{ rendered_html|safe }} +
+
+{% endblock %} diff --git a/util/gem5-resources-manager/templates/index.html b/util/gem5-resources-manager/templates/index.html new file mode 100644 index 0000000000..6321a9e5b6 --- /dev/null +++ b/util/gem5-resources-manager/templates/index.html @@ -0,0 +1,116 @@ +{% extends 'base.html' %} {% block head %} +Resources Manager +{% endblock %} {% block body %} + +
+
+
+
+
+ gem5 +
+
+
+ + + + + + + +
+
+
+
+ +{% endblock %} diff --git a/util/gem5-resources-manager/templates/login/login_json.html b/util/gem5-resources-manager/templates/login/login_json.html new file mode 100644 index 0000000000..98663a304b --- /dev/null +++ b/util/gem5-resources-manager/templates/login/login_json.html @@ -0,0 +1,242 @@ +{% extends 'base.html' %} {% block head %} +JSON Login +{% endblock %} {% block body %} + +
+
+
+
+

JSON

+
+ +
+
+
+
+ +
+ + .json +
+
+ + +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+
+
+ +{% endblock %} diff --git a/util/gem5-resources-manager/templates/login/login_mongodb.html b/util/gem5-resources-manager/templates/login/login_mongodb.html new file mode 100644 index 0000000000..83361b578e --- /dev/null +++ b/util/gem5-resources-manager/templates/login/login_mongodb.html @@ -0,0 +1,189 @@ +{% extends 'base.html' %} {% block head %} +MongoDB Login +{% endblock %} {% block body %} +
+
+
+
+

MongoDB

+
+ +
+
+
+ + + + + + + + +
+
+
+
+
+ Standard +
+ +
+ DNS Seed List +
+ + + + + + + + + + + + + + +
+
+
+
+
+
+ +
+
+
+
+ +{% endblock %} diff --git a/util/gem5-resources-manager/test/__init__.py b/util/gem5-resources-manager/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/util/gem5-resources-manager/test/api_test.py b/util/gem5-resources-manager/test/api_test.py new file mode 100644 index 0000000000..0ff439cd2e --- /dev/null +++ b/util/gem5-resources-manager/test/api_test.py @@ -0,0 +1,722 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import flask +import contextlib +import unittest +from server import app +import server +import json +from bson import json_util +from unittest.mock import patch +import mongomock +from api.mongo_client import MongoDBClient +import requests + + +@contextlib.contextmanager +def captured_templates(app): + """ + This is a context manager that allows you to capture the templates + that are rendered during a test. + """ + recorded = [] + + def record(sender, template, context, **extra): + recorded.append((template, context)) + + flask.template_rendered.connect(record, app) + try: + yield recorded + finally: + flask.template_rendered.disconnect(record, app) + + +class TestAPI(unittest.TestCase): + @patch.object( + MongoDBClient, + "_get_database", + return_value=mongomock.MongoClient().db.collection, + ) + def setUp(self, mock_get_database): + """This method sets up the test environment.""" + self.ctx = app.app_context() + self.ctx.push() + self.app = app + self.test_client = app.test_client() + self.alias = "test" + objects = [] + with open("./test/refs/resources.json", "rb") as f: + objects = json.loads(f.read(), object_hook=json_util.object_hook) + self.collection = mock_get_database() + for obj in objects: + self.collection.insert_one(obj) + + self.test_client.post( + "/validateMongoDB", + json={ + "uri": "mongodb://localhost:27017", + "database": "test", + "collection": "test", + "alias": self.alias, + }, + ) + + def tearDown(self): + """ + This method tears down the test environment. + """ + self.collection.drop() + self.ctx.pop() + + def test_get_helppage(self): + """ + This method tests the call to the help page. + It checks if the call is GET, status code is 200 and if the template + rendered is help.html. + """ + with captured_templates(self.app) as templates: + response = self.test_client.get("/help") + self.assertEqual(response.status_code, 200) + self.assertTrue(templates[0][0].name == "help.html") + + def test_get_mongodb_loginpage(self): + """ + This method tests the call to the MongoDB login page. + It checks if the call is GET, status code is 200 and if the template + rendered is mongoDBLogin.html. + """ + with captured_templates(self.app) as templates: + response = self.test_client.get("/login/mongodb") + self.assertEqual(response.status_code, 200) + self.assertTrue(templates[0][0].name == "login/login_mongodb.html") + + def test_get_json_loginpage(self): + """ + This method tests the call to the JSON login page. + It checks if the call is GET, status code is 200 and if the template + rendered is jsonLogin.html. + """ + with captured_templates(self.app) as templates: + response = self.test_client.get("/login/json") + self.assertEqual(response.status_code, 200) + self.assertTrue(templates[0][0].name == "login/login_json.html") + + def test_get_editorpage(self): + """This method tests the call to the editor page. + It checks if the call is GET, status code is 200 and if the template + rendered is editor.html. + """ + with captured_templates(self.app) as templates: + response = self.test_client.get("/editor?alias=test") + self.assertEqual(response.status_code, 200) + self.assertTrue(templates[0][0].name == "editor.html") + + def test_get_editorpage_invalid(self): + """This method tests the call to the editor page without required + query parameters. + It checks if the call is GET, status code is 404 and if the template + rendered is 404.html. + """ + with captured_templates(self.app) as templates: + response = self.test_client.get("/editor") + self.assertEqual(response.status_code, 404) + self.assertTrue(templates[0][0].name == "404.html") + response = self.test_client.get("/editor?alias=invalid") + self.assertEqual(response.status_code, 404) + self.assertTrue(templates[0][0].name == "404.html") + + def test_default_call(self): + """This method tests the default call to the API.""" + with captured_templates(self.app) as templates: + response = self.test_client.get("/") + self.assertEqual(response.status_code, 200) + self.assertTrue(templates[0][0].name == "index.html") + + def test_default_call_is_not_post(self): + """This method tests that the default call is not a POST.""" + + response = self.test_client.post("/") + self.assertEqual(response.status_code, 405) + + def test_get_categories(self): + """ + The methods tests if the category call returns the same categories as + the schema. + """ + + response = self.test_client.get("/categories") + post_response = self.test_client.post("/categories") + categories = [ + "workload", + "disk-image", + "binary", + "kernel", + "checkpoint", + "git", + "bootloader", + "file", + "directory", + "simpoint", + "simpoint-directory", + "resource", + "looppoint-pinpoint-csv", + "looppoint-json", + ] + self.assertEqual(post_response.status_code, 405) + self.assertEqual(response.status_code, 200) + returnedData = json.loads(response.data) + self.assertTrue(returnedData == categories) + + def test_get_schema(self): + """ + The methods tests if the schema call returns the same schema as the + schema file. + """ + + response = self.test_client.get("/schema") + post_response = self.test_client.post("/schema") + self.assertEqual(post_response.status_code, 405) + self.assertEqual(response.status_code, 200) + returnedData = json.loads(response.data) + schema = {} + schema = requests.get( + "https://resources.gem5.org/gem5-resources-schema.json" + ).json() + self.assertTrue(returnedData == schema) + + def test_insert(self): + """This method tests the insert method of the API.""" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + resource = self.collection.find({"id": "test-resource"}, {"_id": 0}) + + json_resource = json.loads(json_util.dumps(resource[0])) + self.assertTrue(json_resource == test_resource) + + def test_find_no_version(self): + """This method tests the find method of the API.""" + test_id = "test-resource" + test_resource_version = "1.0.0" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + response = self.test_client.post( + "/find", + json={"id": test_id, "resource_version": "", "alias": self.alias}, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + def test_find_not_exist(self): + """This method tests the find method of the API.""" + test_id = "test-resource" + response = self.test_client.post( + "/find", + json={"id": test_id, "resource_version": "", "alias": self.alias}, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == {"exists": False}) + + def test_find_with_version(self): + """This method tests the find method of the API.""" + test_id = "test-resource" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + test_resource["resource_version"] = "1.0.1" + test_resource["description"] = "test-description2" + self.collection.insert_one(test_resource.copy()) + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": "1.0.1", + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + return_json = response.json + self.assertTrue(return_json["description"] == "test-description2") + self.assertTrue(return_json["resource_version"] == "1.0.1") + self.assertTrue(return_json == test_resource) + + def test_delete(self): + """This method tests the delete method of the API.""" + test_id = "test-resource" + test_version = "1.0.0" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + response = self.test_client.post( + "/delete", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Deleted"}) + resource = self.collection.find({"id": "test-resource"}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == []) + + def test_if_resource_exists_true(self): + """This method tests the checkExists method of the API.""" + test_id = "test-resource" + test_version = "1.0.0" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + response = self.test_client.post( + "/checkExists", + json={ + "id": test_id, + "resource_version": test_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"exists": True}) + + def test_if_resource_exists_false(self): + """This method tests the checkExists method of the API.""" + test_id = "test-resource" + test_version = "1.0.0" + response = self.test_client.post( + "/checkExists", + json={ + "id": test_id, + "resource_version": test_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"exists": False}) + + def test_get_resource_versions(self): + """This method tests the getResourceVersions method of the API.""" + test_id = "test-resource" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + test_resource["resource_version"] = "1.0.1" + test_resource["description"] = "test-description2" + self.collection.insert_one(test_resource.copy()) + response = self.test_client.post( + "/versions", json={"id": test_id, "alias": self.alias} + ) + return_json = json.loads(response.data) + self.assertEqual(response.status_code, 200) + self.assertEqual( + return_json, + [{"resource_version": "1.0.1"}, {"resource_version": "1.0.0"}], + ) + + def test_update_resource(self): + """This method tests the updateResource method of the API.""" + test_id = "test-resource" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + original_resource = test_resource.copy() + self.collection.insert_one(test_resource.copy()) + test_resource["description"] = "test-description2" + test_resource["example_usage"] = "test-usage2" + response = self.test_client.post( + "/update", + json={ + "original_resource": original_resource, + "resource": test_resource, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Updated"}) + resource = self.collection.find({"id": test_id}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == [test_resource]) + + def test_keys_1(self): + """This method tests the keys method of the API.""" + response = self.test_client.post( + "/keys", json={"category": "simpoint", "id": "test-resource"} + ) + test_response = { + "category": "simpoint", + "id": "test-resource", + "author": [], + "description": "", + "license": "", + "source_url": "", + "tags": [], + "example_usage": "", + "gem5_versions": [], + "resource_version": "1.0.0", + "simpoint_interval": 0, + "warmup_interval": 0, + } + self.assertEqual(response.status_code, 200) + self.assertEqual(json.loads(response.data), test_response) + + def test_keys_2(self): + """This method tests the keys method of the API.""" + response = self.test_client.post( + "/keys", json={"category": "disk-image", "id": "test-resource"} + ) + test_response = { + "category": "disk-image", + "id": "test-resource", + "author": [], + "description": "", + "license": "", + "source_url": "", + "tags": [], + "example_usage": "", + "gem5_versions": [], + "resource_version": "1.0.0", + } + self.assertEqual(response.status_code, 200) + self.assertEqual(json.loads(response.data), test_response) + + def test_undo(self): + """This method tests the undo method of the API.""" + test_id = "test-resource" + test_resource = { + "category": "disk-image", + "id": "test-resource", + "author": [], + "description": "", + "license": "", + "source_url": "", + "tags": [], + "example_usage": "", + "gem5_versions": [], + "resource_version": "1.0.0", + } + original_resource = test_resource.copy() + # insert resource + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + # update resource + test_resource["description"] = "test-description2" + test_resource["example_usage"] = "test-usage2" + response = self.test_client.post( + "/update", + json={ + "original_resource": original_resource, + "resource": test_resource, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Updated"}) + # check if resource is updated + resource = self.collection.find({"id": test_id}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == [test_resource]) + # undo update + response = self.test_client.post("/undo", json={"alias": self.alias}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Undone"}) + # check if resource is back to original + resource = self.collection.find({"id": test_id}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == [original_resource]) + + def test_redo(self): + """This method tests the undo method of the API.""" + test_id = "test-resource" + test_resource = { + "category": "disk-image", + "id": "test-resource", + "author": [], + "description": "", + "license": "", + "source_url": "", + "tags": [], + "example_usage": "", + "gem5_versions": [], + "resource_version": "1.0.0", + } + original_resource = test_resource.copy() + # insert resource + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + # update resource + test_resource["description"] = "test-description2" + test_resource["example_usage"] = "test-usage2" + response = self.test_client.post( + "/update", + json={ + "original_resource": original_resource, + "resource": test_resource, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Updated"}) + # check if resource is updated + resource = self.collection.find({"id": test_id}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == [test_resource]) + # undo update + response = self.test_client.post("/undo", json={"alias": self.alias}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Undone"}) + # check if resource is back to original + resource = self.collection.find({"id": test_id}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == [original_resource]) + # redo update + response = self.test_client.post("/redo", json={"alias": self.alias}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Redone"}) + # check if resource is updated again + resource = self.collection.find({"id": test_id}, {"_id": 0}) + json_resource = json.loads(json_util.dumps(resource)) + self.assertTrue(json_resource == [test_resource]) + + def test_invalid_alias(self): + test_id = "test-resource" + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + alias = "invalid" + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": alias} + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post( + "/find", + json={"id": test_id, "resource_version": "", "alias": alias}, + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post( + "/delete", json={"resource": test_resource, "alias": alias} + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post( + "/checkExists", + json={"id": test_id, "resource_version": "", "alias": alias}, + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post( + "/versions", json={"id": test_id, "alias": alias} + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post( + "/update", + json={ + "original_resource": test_resource, + "resource": test_resource, + "alias": alias, + }, + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post("/undo", json={"alias": alias}) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post("/redo", json={"alias": alias}) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post( + "/getRevisionStatus", json={"alias": alias} + ) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + response = self.test_client.post("/saveSession", json={"alias": alias}) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json, {"error": "database not found"}) + + def test_get_revision_status_valid(self): + response = self.test_client.post( + "/getRevisionStatus", json={"alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"undo": 1, "redo": 1}) + + @patch.object( + MongoDBClient, + "_get_database", + return_value=mongomock.MongoClient().db.collection, + ) + def test_save_session_load_session(self, mock_get_database): + password = "test" + expected_session = server.databases["test"].save_session() + response = self.test_client.post( + "/saveSession", json={"alias": self.alias, "password": password} + ) + self.assertEqual(response.status_code, 200) + + response = self.test_client.post( + "/loadSession", + json={ + "alias": self.alias, + "session": response.json["ciphertext"], + "password": password, + }, + ) + self.assertEqual(response.status_code, 302) + self.assertEqual( + expected_session, server.databases[self.alias].save_session() + ) + + def test_logout(self): + response = self.test_client.post("/logout", json={"alias": self.alias}) + self.assertEqual(response.status_code, 302) + self.assertNotIn(self.alias, server.databases) diff --git a/util/gem5-resources-manager/test/comprehensive_test.py b/util/gem5-resources-manager/test/comprehensive_test.py new file mode 100644 index 0000000000..4c32087324 --- /dev/null +++ b/util/gem5-resources-manager/test/comprehensive_test.py @@ -0,0 +1,407 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +from server import app +import json +from bson import json_util +import copy +import mongomock +from unittest.mock import patch +from api.mongo_client import MongoDBClient + + +class TestComprehensive(unittest.TestCase): + @patch.object( + MongoDBClient, + "_get_database", + return_value=mongomock.MongoClient().db.collection, + ) + def setUp(self, mock_get_database): + """This method sets up the test environment.""" + self.ctx = app.app_context() + self.ctx.push() + self.app = app + self.test_client = app.test_client() + self.alias = "test" + objects = [] + with open("./test/refs/resources.json", "rb") as f: + objects = json.loads(f.read(), object_hook=json_util.object_hook) + self.collection = mock_get_database() + for obj in objects: + self.collection.insert_one(obj) + + self.test_client.post( + "/validateMongoDB", + json={ + "uri": "mongodb://localhost:27017", + "database": "test", + "collection": "test", + "alias": self.alias, + }, + ) + + def tearDown(self): + """This method tears down the test environment.""" + self.collection.drop() + self.ctx.pop() + + def test_insert_find_update_find(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + original_resource = test_resource.copy() + test_id = test_resource["id"] + test_resource_version = test_resource["resource_version"] + # insert resource + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + # update resource + test_resource["description"] = "test-description-2" + test_resource["author"].append("test-author-2") + response = self.test_client.post( + "/update", + json={ + "original_resource": original_resource, + "resource": test_resource, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Updated"}) + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + def test_find_new_insert(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + test_id = test_resource["id"] + test_resource_version = test_resource["resource_version"] + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"exists": False}) + # insert resource + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + def test_insert_find_new_version_find_older(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + test_id = test_resource["id"] + test_resource_version = test_resource["resource_version"] + # insert resource + response = self.test_client.post( + "/insert", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + # add new version + test_resource_new_version = copy.deepcopy(test_resource) + test_resource_new_version["description"] = "test-description-2" + test_resource_new_version["author"].append("test-author-2") + test_resource_new_version["resource_version"] = "1.0.1" + + response = self.test_client.post( + "/insert", + json={"resource": test_resource_new_version, "alias": self.alias}, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + + # get resource versions + response = self.test_client.post( + "/versions", json={"id": test_id, "alias": self.alias} + ) + return_json = json.loads(response.data) + self.assertEqual(response.status_code, 200) + self.assertEqual( + return_json, + [{"resource_version": "1.0.1"}, {"resource_version": "1.0.0"}], + ) + + resource_version = return_json[1]["resource_version"] + # find older version + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + def test_find_add_new_version_delete_older(self): + test_resource = { + "category": "binary", + "id": "binary-example", + "description": "binary-example documentation.", + "architecture": "ARM", + "is_zipped": False, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": ( + "http://dist.gem5.org/dist/develop/" + "test-progs/hello/bin/arm/linux/hello64-static" + ), + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + test_id = test_resource["id"] + test_resource_version = test_resource["resource_version"] + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + # add new version + test_resource_new_version = copy.deepcopy(test_resource) + test_resource_new_version["description"] = "test-description-2" + test_resource_new_version["resource_version"] = "1.0.1" + + response = self.test_client.post( + "/insert", + json={"resource": test_resource_new_version, "alias": self.alias}, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + + # get resource versions + response = self.test_client.post( + "/versions", json={"id": test_id, "alias": self.alias} + ) + return_json = json.loads(response.data) + self.assertEqual(response.status_code, 200) + self.assertEqual( + return_json, + [{"resource_version": "1.0.1"}, {"resource_version": "1.0.0"}], + ) + # delete older version + response = self.test_client.post( + "/delete", json={"resource": test_resource, "alias": self.alias} + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Deleted"}) + + # get resource versions + response = self.test_client.post( + "/versions", json={"id": test_id, "alias": self.alias} + ) + return_json = json.loads(response.data) + self.assertEqual(response.status_code, 200) + self.assertEqual(return_json, [{"resource_version": "1.0.1"}]) + + def test_find_add_new_version_update_older(self): + test_resource = { + "category": "binary", + "id": "binary-example", + "description": "binary-example documentation.", + "architecture": "ARM", + "is_zipped": False, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": ( + "http://dist.gem5.org/dist/develop/" + "test-progs/hello/bin/arm/linux/hello64-static" + ), + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + original_resource = test_resource.copy() + test_id = test_resource["id"] + test_resource_version = test_resource["resource_version"] + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": test_resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) + + # add new version + test_resource_new_version = copy.deepcopy(test_resource) + test_resource_new_version["description"] = "test-description-2" + test_resource_new_version["resource_version"] = "1.0.1" + + response = self.test_client.post( + "/insert", + json={"resource": test_resource_new_version, "alias": self.alias}, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Inserted"}) + + # get resource versions + response = self.test_client.post( + "/versions", json={"id": test_id, "alias": self.alias} + ) + return_json = json.loads(response.data) + self.assertEqual(response.status_code, 200) + self.assertEqual( + return_json, + [{"resource_version": "1.0.1"}, {"resource_version": "1.0.0"}], + ) + + resource_version = return_json[1]["resource_version"] + + # update older version + test_resource["description"] = "test-description-3" + + response = self.test_client.post( + "/update", + json={ + "original_resource": original_resource, + "resource": test_resource, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json, {"status": "Updated"}) + + # find resource + response = self.test_client.post( + "/find", + json={ + "id": test_id, + "resource_version": resource_version, + "alias": self.alias, + }, + ) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.json == test_resource) diff --git a/util/gem5-resources-manager/test/json_client_test.py b/util/gem5-resources-manager/test/json_client_test.py new file mode 100644 index 0000000000..e08eb18452 --- /dev/null +++ b/util/gem5-resources-manager/test/json_client_test.py @@ -0,0 +1,262 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +from api.json_client import JSONClient +from server import app +import json +from bson import json_util +from unittest.mock import patch +from pathlib import Path +from api.json_client import JSONClient + + +def get_json(): + with open("test/refs/test_json.json", "r") as f: + jsonFile = f.read() + return json.loads(jsonFile) + + +def mockinit(self, file_path): + self.file_path = Path("test/refs/") / file_path + with open(self.file_path, "r") as f: + self.resources = json.load(f) + + +class TestJson(unittest.TestCase): + @classmethod + def setUpClass(cls): + with open("./test/refs/resources.json", "rb") as f: + jsonFile = f.read() + with open("./test/refs/test_json.json", "wb") as f: + f.write(jsonFile) + + @classmethod + def tearDownClass(cls): + Path("./test/refs/test_json.json").unlink() + + @patch.object(JSONClient, "__init__", mockinit) + def setUp(self): + """This method sets up the test environment.""" + with open("./test/refs/test_json.json", "rb") as f: + jsonFile = f.read() + self.original_json = json.loads(jsonFile) + self.json_client = JSONClient("test_json.json") + + def tearDown(self): + """This method tears down the test environment.""" + with open("./test/refs/test_json.json", "w") as f: + json.dump(self.original_json, f, indent=4) + + def test_insertResource(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + response = self.json_client.insert_resource(test_resource) + self.assertEqual(response, {"status": "Inserted"}) + json_data = get_json() + self.assertNotEqual(json_data, self.original_json) + self.assertIn(test_resource, json_data) + + def test_insertResource_duplicate(self): + test_resource = { + "category": "diskimage", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": True, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": ( + "http://dist.gem5.org/dist/develop/images" + "/x86/ubuntu-18-04/x86-ubuntu.img.gz" + ), + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + response = self.json_client.insert_resource(test_resource) + self.assertEqual(response, {"status": "Resource already exists"}) + + def test_find_no_version(self): + expected_response = { + "category": "diskimage", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": True, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": ( + "http://dist.gem5.org/dist/develop/images" + "/x86/ubuntu-18-04/x86-ubuntu.img.gz" + ), + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + response = self.json_client.find_resource( + {"id": expected_response["id"]} + ) + self.assertEqual(response, expected_response) + + def test_find_with_version(self): + expected_response = { + "category": "kernel", + "id": "kernel-example", + "description": "kernel-example documentation.", + "architecture": "RISCV", + "is_zipped": False, + "md5sum": "60a53c7d47d7057436bf4b9df707a841", + "url": ( + "http://dist.gem5.org/dist/develop" + "/kernels/x86/static/vmlinux-5.4.49" + ), + "source": "src/linux-kernel", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + response = self.json_client.find_resource( + { + "id": expected_response["id"], + "resource_version": expected_response["resource_version"], + } + ) + self.assertEqual(response, expected_response) + + def test_find_not_found(self): + response = self.json_client.find_resource({"id": "not-found"}) + self.assertEqual(response, {"exists": False}) + + def test_deleteResource(self): + deleted_resource = { + "category": "diskimage", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": True, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": ( + "http://dist.gem5.org/dist/develop/" + "images/x86/ubuntu-18-04/x86-ubuntu.img.gz" + ), + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + response = self.json_client.delete_resource( + { + "id": deleted_resource["id"], + "resource_version": deleted_resource["resource_version"], + } + ) + self.assertEqual(response, {"status": "Deleted"}) + json_data = get_json() + self.assertNotEqual(json_data, self.original_json) + self.assertNotIn(deleted_resource, json_data) + + def test_updateResource(self): + updated_resource = { + "category": "diskimage", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": True, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": ( + "http://dist.gem5.org/dist/develop/images" + "/x86/ubuntu-18-04/x86-ubuntu.img.gz" + ), + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + original_resource = { + "category": "diskimage", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": True, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": ( + "http://dist.gem5.org/dist/develop/" + "images/x86/ubuntu-18-04/x86-ubuntu.img.gz" + ), + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": ["23.0"], + } + response = self.json_client.update_resource( + { + "original_resource": original_resource, + "resource": updated_resource, + } + ) + self.assertEqual(response, {"status": "Updated"}) + json_data = get_json() + self.assertNotEqual(json_data, self.original_json) + self.assertIn(updated_resource, json_data) + + def test_getVersions(self): + resource_id = "kernel-example" + response = self.json_client.get_versions({"id": resource_id}) + self.assertEqual( + response, + [{"resource_version": "2.0.0"}, {"resource_version": "1.0.0"}], + ) + + def test_checkResourceExists_True(self): + resource_id = "kernel-example" + resource_version = "1.0.0" + response = self.json_client.check_resource_exists( + {"id": resource_id, "resource_version": resource_version} + ) + self.assertEqual(response, {"exists": True}) + + def test_checkResourceExists_False(self): + resource_id = "kernel-example" + resource_version = "3.0.0" + response = self.json_client.check_resource_exists( + {"id": resource_id, "resource_version": resource_version} + ) + self.assertEqual(response, {"exists": False}) diff --git a/util/gem5-resources-manager/test/mongo_client_test.py b/util/gem5-resources-manager/test/mongo_client_test.py new file mode 100644 index 0000000000..761475ead8 --- /dev/null +++ b/util/gem5-resources-manager/test/mongo_client_test.py @@ -0,0 +1,281 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +from server import app, databases +import json +from bson import json_util +import mongomock +from unittest.mock import patch +from api.mongo_client import MongoDBClient + + +class TestApi(unittest.TestCase): + """This is a test class that tests the API.""" + + API_URL = "http://127.0.0.1:5000" + + @patch.object( + MongoDBClient, + "_get_database", + return_value=mongomock.MongoClient().db.collection, + ) + def setUp(self, mock_get_database): + """This method sets up the test environment.""" + objects = [] + with open("./test/refs/resources.json", "rb") as f: + objects = json.loads(f.read(), object_hook=json_util.object_hook) + self.collection = mock_get_database() + for obj in objects: + self.collection.insert_one(obj) + self.mongo_client = MongoDBClient( + "mongodb://localhost:27017", "test", "test" + ) + + def tearDown(self): + """This method tears down the test environment.""" + self.collection.drop() + + def test_insertResource(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + ret_value = self.mongo_client.insert_resource(test_resource) + self.assertEqual(ret_value, {"status": "Inserted"}) + self.assertEqual( + self.collection.find({"id": "test-resource"})[0], test_resource + ) + self.collection.delete_one({"id": "test-resource"}) + + def test_insertResource_duplicate(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources/" + "tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource) + ret_value = self.mongo_client.insert_resource(test_resource) + self.assertEqual(ret_value, {"status": "Resource already exists"}) + + def test_findResource_no_version(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources" + "/tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + ret_value = self.mongo_client.find_resource({"id": "test-resource"}) + self.assertEqual(ret_value, test_resource) + self.collection.delete_one({"id": "test-resource"}) + + def test_findResource_with_version(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources" + "/tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + test_resource["resource_version"] = "2.0.0" + test_resource["description"] = "test-description2" + self.collection.insert_one(test_resource.copy()) + ret_value = self.mongo_client.find_resource( + {"id": "test-resource", "resource_version": "2.0.0"} + ) + self.assertEqual(ret_value, test_resource) + + def test_findResource_not_found(self): + ret_value = self.mongo_client.find_resource({"id": "test-resource"}) + self.assertEqual(ret_value, {"exists": False}) + + def test_deleteResource(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources" + "/tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + ret_value = self.mongo_client.delete_resource( + {"id": "test-resource", "resource_version": "1.0.0"} + ) + self.assertEqual(ret_value, {"status": "Deleted"}) + + self.assertEqual( + json.loads( + json_util.dumps(self.collection.find({"id": "test-resource"})) + ), + [], + ) + + def test_updateResource(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources" + "/tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + original_resource = test_resource.copy() + self.collection.insert_one(test_resource.copy()) + test_resource["author"].append("test-author2") + test_resource["description"] = "test-description2" + ret_value = self.mongo_client.update_resource( + {"original_resource": original_resource, "resource": test_resource} + ) + self.assertEqual(ret_value, {"status": "Updated"}) + self.assertEqual( + self.collection.find({"id": "test-resource"}, {"_id": 0})[0], + test_resource, + ) + + def test_checkResourceExists(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources" + "/tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + ret_value = self.mongo_client.check_resource_exists( + {"id": "test-resource", "resource_version": "1.0.0"} + ) + self.assertEqual(ret_value, {"exists": True}) + + def test_checkResourceExists_not_found(self): + ret_value = self.mongo_client.check_resource_exists( + {"id": "test-resource", "resource_version": "1.0.0"} + ) + self.assertEqual(ret_value, {"exists": False}) + + def test_getVersion(self): + test_resource = { + "category": "diskimage", + "id": "test-resource", + "author": ["test-author"], + "description": "test-description", + "license": "test-license", + "source_url": ( + "https://github.com/gem5/gem5-resources" + "/tree/develop/src/x86-ubuntu" + ), + "tags": ["test-tag", "test-tag2"], + "example_usage": " test-usage", + "gem5_versions": [ + "22.1", + ], + "resource_version": "1.0.0", + } + self.collection.insert_one(test_resource.copy()) + test_resource["resource_version"] = "2.0.0" + test_resource["description"] = "test-description2" + self.collection.insert_one(test_resource.copy()) + ret_value = self.mongo_client.get_versions({"id": "test-resource"}) + self.assertEqual( + ret_value, + [{"resource_version": "2.0.0"}, {"resource_version": "1.0.0"}], + ) diff --git a/util/gem5-resources-manager/test/refs/resources.json b/util/gem5-resources-manager/test/refs/resources.json new file mode 100644 index 0000000000..614f8dc764 --- /dev/null +++ b/util/gem5-resources-manager/test/refs/resources.json @@ -0,0 +1,196 @@ +[ + { + "category": "kernel", + "id": "kernel-example", + "description": "kernel-example documentation.", + "architecture": "RISCV", + "is_zipped": false, + "md5sum": "60a53c7d47d7057436bf4b9df707a841", + "url": "http://dist.gem5.org/dist/develop/kernels/x86/static/vmlinux-5.4.49", + "source": "src/linux-kernel", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "kernel", + "id": "kernel-example", + "description": "kernel-example documentation 2.", + "architecture": "RISCV", + "is_zipped": false, + "md5sum": "60a53c7d47d7057436bf4b9df707a841", + "url": "http://dist.gem5.org/dist/develop/kernels/x86/static/vmlinux-5.4.49", + "source": "src/linux-kernel", + "resource_version": "2.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "diskimage", + "id": "disk-image-example", + "description": "disk-image documentation.", + "architecture": "X86", + "is_zipped": true, + "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", + "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "binary", + "id": "binary-example", + "description": "binary-example documentation.", + "architecture": "ARM", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + + }, + { + "category": "bootloader", + "id": "bootloader-example", + "description": "bootloader documentation.", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "checkpoint", + "id": "checkpoint-example", + "description": "checkpoint-example documentation.", + "architecture": "RISCV", + "is_zipped": false, + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", + "source": null, + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "git", + "id": "git-example", + "description": null, + "is_zipped": false, + "is_tar_archive": true, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "file", + "id": "file-example", + "description": null, + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "source": null, + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "directory", + "id": "directory-example", + "description": "directory-example documentation.", + "is_zipped": false, + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", + "source": null, + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "simpoint-directory", + "id": "simpoint-directory-example", + "description": "simpoint directory documentation.", + "is_zipped": false, + "md5sum": "3fcffe3956c8a95e3fb82e232e2b41fb", + "source": null, + "is_tar_archive": true, + "url": "http://dist.gem5.org/dist/develop/simpoints/x86-print-this-15000-simpoints-20221013.tar", + "simpoint_interval": 1000000, + "warmup_interval": 1000000, + "simpoint_file": "simpoint.simpt", + "weight_file": "simpoint.weight", + "workload_name": "Example Workload", + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "simpoint", + "id": "simpoint-example", + "description": "simpoint documentation.", + "simpoint_interval": 1000000, + "warmup_interval": 23445, + "simpoint_list": [ + 2, + 3, + 4, + 15 + ], + "weight_list": [ + 0.1, + 0.2, + 0.4, + 0.3 + ], + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "looppoint-pinpoint-csv", + "id": "looppoint-pinpoint-csv-resource", + "description": "A looppoint pinpoints csv file.", + "is_zipped": false, + "md5sum": "199ab22dd463dc70ee2d034bfe045082", + "url": "http://dist.gem5.org/dist/develop/pinpoints/x86-matrix-multiply-omp-100-8-global-pinpoints-20230127", + "source": null, + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + }, + { + "category": "looppoint-json", + "id": "looppoint-json-restore-resource-region-1", + "description": "A looppoint json file resource.", + "is_zipped": false, + "region_id": "1", + "md5sum": "a71ed64908b082ea619b26b940a643c1", + "url": "http://dist.gem5.org/dist/develop/looppoints/x86-matrix-multiply-omp-100-8-looppoint-json-20230128", + "source": null, + "resource_version": "1.0.0", + "gem5_versions": [ + "23.0" + ] + } +] From 3105f59544c91c7a832782f227bfcede1460f08c Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Mon, 10 Jul 2023 12:20:50 -0700 Subject: [PATCH 061/693] misc: Update Change-Id Check This updates the change-id code to refer to commit messages in pull requests instead of on pushes. Change-Id: I308f02b4616804b386140d5875a79878eccd721e --- .github/workflows/ci-tests.yaml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 61ba4b5b53..83a1b873d0 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -16,10 +16,30 @@ jobs: - uses: actions/setup-python@v3 - uses: pre-commit/action@v3.0.0 + # ensures we have a change-id in every commit, needed for gerrit + check-for-change-id: + # runs on github hosted runner + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Check for Change-Id + run: | + for commit in $(git rev-list ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}); do + git checkout $commit + if !(git log -1 --pretty=format:"%s" | grep -q "Change-Id: ") + then + echo "One or more of the commits in this pull request is missing a Change-ID, which we require for any changes made to gem5. "\ + "To automatically insert one, run the following:\n f=`git rev-parse --git-dir`/hooks/commit-msg ; mkdir -p $(dirname $f) ; "\ + "curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f\n Then amend the commit with git commit --amend --no-edit, and update your pull request." + exit 1 + fi + done + build-gem5: runs-on: [self-hosted, linux, x64, build] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: pre-commit # only runs if pre-commit passes + needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes outputs: artifactname: ${{ steps.name.outputs.test }} steps: @@ -39,7 +59,7 @@ jobs: unittests-all-opt: runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: pre-commit # only runs if pre-commit passes + needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes timeout-minutes: 60 steps: - uses: actions/checkout@v3 @@ -51,7 +71,7 @@ jobs: testlib-quick: runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, build-gem5] + needs: [pre-commit, build-gem5, check-for-change-id] timeout-minutes: 360 # 6 hours steps: - uses: actions/checkout@v3 From 160681cabf467ea36f33d831a872fa84314b29a6 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 10 Jul 2023 12:28:44 -0700 Subject: [PATCH 062/693] misc: Update version info for develop branch Change-Id: Iecee9e230c1c80f5675ec14bbeba9f7d9e2b8664 --- src/Doxyfile | 2 +- src/base/version.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Doxyfile b/src/Doxyfile index 325040fee0..24d70bbc55 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = gem5 # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = v23.0.0.0 +PROJECT_NUMBER = [DEVELOP-FOR-23.0] # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/src/base/version.cc b/src/base/version.cc index 38f415590a..c7255e91a7 100644 --- a/src/base/version.cc +++ b/src/base/version.cc @@ -32,6 +32,6 @@ namespace gem5 /** * @ingroup api_base_utils */ -const char *gem5Version = "23.0.0.0"; +const char *gem5Version = "DEVELOP-FOR-23.1"; } // namespace gem5 From 4f45f84aa594d44ceab9c54112ec9b1c3bdfc902 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 10 Jul 2023 12:30:54 -0700 Subject: [PATCH 063/693] misc: Revert remove -Werror This reverts commit 6c997b633fb5759bd45ff947626c5228e2c67539. This is so the develop branch gives warnings as errors. Change-Id: I6c8c81d478dc11fb561748dd2f392103b2beff68 --- SConstruct | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SConstruct b/SConstruct index 4fe2f64366..9b25b33783 100755 --- a/SConstruct +++ b/SConstruct @@ -447,6 +447,12 @@ for variant_path in variant_paths: conf.CheckLinkFlag( '-Wl,--thread-count=%d' % GetOption('num_jobs')) + # Treat warnings as errors but white list some warnings that we + # want to allow (e.g., deprecation warnings). + env.Append(CCFLAGS=['-Werror', + '-Wno-error=deprecated-declarations', + '-Wno-error=deprecated', + ]) else: error('\n'.join(( From 05e7a684872bd68b6184f214added574b4c3f4ea Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Mon, 10 Jul 2023 12:41:04 -0700 Subject: [PATCH 064/693] misc: Add runs-on line to CI tests Adds missing line to CI tests Change-Id: I34019d76648dc6025ac89cbec4605f17d2a5e3f7 --- .github/workflows/ci-tests.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 83a1b873d0..85836a264f 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -19,6 +19,7 @@ jobs: # ensures we have a change-id in every commit, needed for gerrit check-for-change-id: # runs on github hosted runner + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 with: From ab0f43d2904303927a2b727e0bca49b216d66255 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Mon, 10 Jul 2023 13:00:04 -0700 Subject: [PATCH 065/693] misc: Update CI tests to only require 1 Change-Id Since commits will be squashed and merged in GitHub, we only require one of the commits to contain a Change-ID within a pull request Change-Id: I0fbb1c0e79009097456193fbe3c6fa20746e4805 --- .github/workflows/ci-tests.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 85836a264f..520767bca0 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -26,16 +26,20 @@ jobs: fetch-depth: 0 - name: Check for Change-Id run: | + # loop through all the commits in the pull request for commit in $(git rev-list ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}); do git checkout $commit - if !(git log -1 --pretty=format:"%s" | grep -q "Change-Id: ") + if (git log -1 --pretty=format:"%s" | grep -q "Change-Id: ") then - echo "One or more of the commits in this pull request is missing a Change-ID, which we require for any changes made to gem5. "\ - "To automatically insert one, run the following:\n f=`git rev-parse --git-dir`/hooks/commit-msg ; mkdir -p $(dirname $f) ; "\ - "curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f\n Then amend the commit with git commit --amend --no-edit, and update your pull request." - exit 1 + # passes as long as at least one change-id exists in the pull request + exit 0 fi done + # if we reach this part, none of the commits had a change-id + echo "None of the commits in this pull request contains a Change-ID, which we require for any changes made to gem5. "\ + "To automatically insert one, run the following:\n f=`git rev-parse --git-dir`/hooks/commit-msg ; mkdir -p $(dirname $f) ; "\ + "curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f\n Then amend the commit with git commit --amend --no-edit, and update your pull request." + exit 1 build-gem5: runs-on: [self-hosted, linux, x64, build] From a2d34a52fc8382965a67d3be6ae0d2c3cf913649 Mon Sep 17 00:00:00 2001 From: Ayaz Akram Date: Wed, 14 Jun 2023 11:03:33 -0700 Subject: [PATCH 066/693] configs: Fix SPEC benchmarks example scripts This small change fixes the gem5_library example scripts for SPEC benchmarks to make them compatible with the latest version of the std library. Change-Id: I3da9745f0ee6b253871e32082e135e0fa4040108 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71738 Tested-by: kokoro Maintainer: Jason Lowe-Power Reviewed-by: Jason Lowe-Power From edc4ff338231ba6ffe5e1501515b18ee63228df0 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Mon, 10 Jul 2023 14:36:27 -0700 Subject: [PATCH 067/693] misc: Include body in check for Change-Id Updates ci-tests.yaml to check the entire commit message for the Change-Id, not just the subject. Change-Id: Ia76c77d096617a6fe76ffea7f2bd8a4295ca14f7 --- .github/workflows/ci-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 520767bca0..c184e482f1 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -29,7 +29,7 @@ jobs: # loop through all the commits in the pull request for commit in $(git rev-list ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}); do git checkout $commit - if (git log -1 --pretty=format:"%s" | grep -q "Change-Id: ") + if (git log -1 --pretty=format:"%B" | grep -q "Change-Id: ") then # passes as long as at least one change-id exists in the pull request exit 0 From 63bdde4f637572117c7b9e77a3489669397829e4 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 10 Jul 2023 15:28:41 -0700 Subject: [PATCH 068/693] arch-riscv: Remove clearLoadReservation This was added due to a bad merge from stable to develop. Change-Id: I7adf9604ee4d6f1cf11c404af5e8e1c071461a4a --- src/arch/riscv/isa.hh | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 352a8eb0cd..8b6239cb69 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -92,13 +92,6 @@ class ISA : public BaseISA return new PCState(new_inst_addr, rv_type); } - void - clearLoadReservation(ContextID cid) override - { - Addr& load_reservation_addr = load_reservation_addrs[cid]; - load_reservation_addr = INVALID_RESERVATION_ADDR; - } - public: RegVal readMiscRegNoEffect(RegIndex idx) const override; RegVal readMiscReg(RegIndex idx) override; @@ -143,12 +136,6 @@ class ISA : public BaseISA RiscvType rvType() const { return rv_type; } - void - clearLoadReservation(ContextID cid) - { - Addr& load_reservation_addr = load_reservation_addrs[cid]; - load_reservation_addr = INVALID_RESERVATION_ADDR; - } }; } // namespace RiscvISA From a43f8e6904693bbfbee4b952981b4a05e20187f1 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 25 Aug 2022 13:51:02 -0700 Subject: [PATCH 069/693] stdlib: Allow passing of func list as exit_event generator Allows for a passing of functions to specify actions to execute on an exit event via the Simulator module in the stdlib. The list of functions must have no manditory arguments and return True if the Simulation is to exit upon the function call's completion. Issue-on: https://gem5.atlassian.net/browse/GEM5-1126 Change-Id: Ia88caf2975227e78243763627acab9e9f89e2a7d Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62691 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/python/gem5/simulate/simulator.py | 84 ++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index 0551745b36..4947b46ebb 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -34,7 +34,7 @@ from m5.util import warn import os import sys from pathlib import Path -from typing import Optional, List, Tuple, Dict, Generator, Union +from typing import Optional, List, Tuple, Dict, Generator, Union, Callable from .exit_event_generators import ( warn_default_decorator, @@ -83,7 +83,10 @@ class Simulator: board: AbstractBoard, full_system: Optional[bool] = None, on_exit_event: Optional[ - Dict[ExitEvent, Generator[Optional[bool], None, None]] + Dict[ + ExitEvent, + Union[Generator[Optional[bool], None, None], List[Callable]], + ] ] = None, expected_execution_order: Optional[List[ExitEvent]] = None, checkpoint_path: Optional[Path] = None, @@ -96,7 +99,9 @@ class Simulator: `is_fullsystem()` function. :param on_exit_event: An optional map to specify the generator to execute on each exit event. The generator may yield a boolean which, - if True, will have the Simulator exit the run loop. + if True, will have the Simulator exit the run loop. A List of functions + may also be used. Each function must be callable with no arguments and + return a boolean specifying if the Simulation should exit the run loop. :param expected_execution_order: May be specified to check the exit events come in a specified order. If the order specified is not encountered (e.g., 'Workbegin', 'Workend', then 'Exit'), an Exception @@ -111,6 +116,9 @@ class Simulator: `on_exit_event` usage notes --------------------------- + With Generators + =============== + The `on_exit_event` parameter specifies a Python generator for each exit event. `next()` is run each time an exit event. The generator may yield a boolean. If this value of this boolean is True @@ -142,6 +150,54 @@ class Simulator: encountered, will dump gem5 statistics the second time an exit event is encountered, and will terminate the Simulator run loop the third time. + With a list of functions + ======================== + + Alternatively, instead of passing a generator per exit event, a list of + functions may be passed. Each function must take no mandatory arguments + and return True if the simulator is to exit after being called. + + An example: + + ``` + def stop_simulation() -> bool: + return True + + def switch_cpus() -> bool: + processor.switch() + return False + + def print_hello() -> None: + # Here we don't explicitly return a boolean, but the simulator + # treats a None return as False. Ergo the Simulation loop is not + # terminated. + print("Hello") + + + simulator = Simulator( + board=board, + on_exit_event = { + ExitEvent.Exit : [ + print_hello, + switch_cpus, + print_hello, + stop_simulation + ], + }, + ) + ``` + + Upon each `EXIT` type exit event the list will function as a queue, + with the top function of the list popped and executed. Therefore, in + this example, the first `EXIT` type exit event will cause `print_hello` + to be executed, and the second `EXIT` type exit event will cause the + `switch_cpus` function to run. The third will execute `print_hello` + again before finally, on the forth exit event will call + `stop_simulation` which will stop the simulation as it returns False. + + Exit Event defaults + =================== + Each exit event has a default behavior if none is specified by the user. These are as follows: @@ -202,7 +258,19 @@ class Simulator: } if on_exit_event: - self._on_exit_event = on_exit_event + self._on_exit_event = {} + for key, value in on_exit_event.items(): + if isinstance(value, Generator): + self._on_exit_event[key] = value + elif isinstance(value, List): + # In instances where we have a list of functions, we + # convert this to a generator. + self._on_exit_event[key] = (func() for func in value) + else: + raise Exception( + f"`on_exit_event` for '{key.value}' event is " + "not a Generator or List[Callable]." + ) else: self._on_exit_event = self._default_on_exit_dict @@ -475,12 +543,12 @@ class Simulator: # If the user has specified their own generator for this exit # event, use it. exit_on_completion = next(self._on_exit_event[exit_enum]) - except StopIteration: + except (StopIteration): # If the user's generator has ended, throw a warning and use # the default generator for this exit event. warn( - "User-specified generator for the exit event " - f"'{exit_enum.value}' has ended. Using the default " + "User-specified generator/function list for the exit " + f"event'{exit_enum.value}' has ended. Using the default " "generator." ) exit_on_completion = next( @@ -496,7 +564,7 @@ class Simulator: self._exit_event_count += 1 # If the generator returned True we will return from the Simulator - # run loop. + # run loop. In the case of a function: if it returned True. if exit_on_completion: return From c9ff8ef57d98739205426511ac9a8470f3bb5fd1 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 26 Aug 2022 17:39:50 -0700 Subject: [PATCH 070/693] stdlib,tests: Add Simulator Exit Event handler tests Change-Id: Ib5f119730299c0f201a14a9e9bb933d23d65ac62 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62751 Reviewed-by: Melissa Jost Tested-by: kokoro Maintainer: Bobby Bruce Reviewed-by: Jason Lowe-Power --- .../gem5/configs/simulator_exit_event_run.py | 147 ++++++++++++++++++ tests/gem5/stdlib/simulator/ref/simout | 8 + .../gem5/stdlib/simulator/test_event_event.py | 68 ++++++++ 3 files changed, 223 insertions(+) create mode 100644 tests/gem5/configs/simulator_exit_event_run.py create mode 100644 tests/gem5/stdlib/simulator/ref/simout create mode 100644 tests/gem5/stdlib/simulator/test_event_event.py diff --git a/tests/gem5/configs/simulator_exit_event_run.py b/tests/gem5/configs/simulator_exit_event_run.py new file mode 100644 index 0000000000..f4e8ab9ce8 --- /dev/null +++ b/tests/gem5/configs/simulator_exit_event_run.py @@ -0,0 +1,147 @@ +# Copyright (c) 2022 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. + +""" +This script is used for testing the event_event handler of the Simulator +module. If the handler is working correctly the following output will be +received: + +``` +The program has started! +About to exit the simulation for the 1 st/nd/rd/th time +Handled exit event. +build/X86/sim/simulate.cc:194: info: Entering event queue @ 780559326. Starting simulation... +About to exit the simulation for the 2 st/nd/rd/th time +Handled exit event. +build/X86/sim/simulate.cc:194: info: Entering event queue @ 854152659. Starting simulation... +About to exit the simulation for the 3 st/nd/rd/th time +Handling the final exit event. We'll exit now. +``` + +By default a generator is passed to define the evit_event. A list of functions +can also be passed. This is enabled by passing the `--list-format` flag. +""" + +from gem5.resources.resource import Resource +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.boards.simple_board import SimpleBoard +from gem5.simulate.simulator import Simulator +from gem5.simulate.exit_event import ExitEvent +from gem5.isas import ISA + +import argparse + +parser = argparse.ArgumentParser( + description="A gem5 script for running simple binaries in SE mode." +) + +parser.add_argument( + "-l", + "--list-format", + action="store_true", + help="Use a list of functions, instead of a generator, for the exit event " + "handler", +) + +parser.add_argument( + "-r", + "--resource-directory", + type=str, + required=False, + help="The directory in which resources will be downloaded or exist.", +) + + +args = parser.parse_args() + +# Setup the system. +cache_hierarchy = NoCache() +memory = SingleChannelDDR3_1600() + +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, + isa=ISA.X86, + num_cores=1, +) + +motherboard = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the workload +# Note: Here we're using the "x86-m5-exit-repeat" resource. This calls an +# `m5_exit(0)` command in an infinite while-loop. +binary = Resource( + "x86-m5-exit-repeat", resource_directory=args.resource_directory +) +motherboard.set_se_binary_workload(binary) + +# Create the exit event handler. Here there are two kinds: either pass a +# generator or a list of functions. In this script they both do the same things +# for testing purposes. + + +def event_handle() -> bool: + print("Handled exit event.") + return False + + +def event_handle_final() -> bool: + print("Handling the final exit event. We'll exit now.") + return True + + +def generator(): + yield event_handle() + yield event_handle() + yield event_handle_final() + + +func_list = [event_handle, event_handle, event_handle_final] + +exit_event_handler = None +if args.list_format: + exit_event_handler = func_list +else: + exit_event_handler = generator() + +assert exit_event_handler is not None + +# Run the simulation +simulator = Simulator( + board=motherboard, + on_exit_event={ + ExitEvent.EXIT: exit_event_handler, + }, +) +simulator.run() diff --git a/tests/gem5/stdlib/simulator/ref/simout b/tests/gem5/stdlib/simulator/ref/simout new file mode 100644 index 0000000000..a58d513213 --- /dev/null +++ b/tests/gem5/stdlib/simulator/ref/simout @@ -0,0 +1,8 @@ +Global frequency set at 1000000000000 ticks per second +The program has started! +About to exit the simulation for the 1 st/nd/rd/th time +Handled exit event. +About to exit the simulation for the 2 st/nd/rd/th time +Handled exit event. +About to exit the simulation for the 3 st/nd/rd/th time +Handling the final exit event. We'll exit now. diff --git a/tests/gem5/stdlib/simulator/test_event_event.py b/tests/gem5/stdlib/simulator/test_event_event.py new file mode 100644 index 0000000000..cb70a5d90e --- /dev/null +++ b/tests/gem5/stdlib/simulator/test_event_event.py @@ -0,0 +1,68 @@ +# Copyright (c) 2022 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 testlib import * + +""" +These tests are designed to test the BaseCPUProcessor. It utilizes the +tests/gem5/configs/simple_binary_run.py to run a simple SE-mode simualation +with different configurations of the BaseCPUProcessor. +""" + +verifiers = (verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref", "simout")),) + + +gem5_verify_config( + name="simulator-exit-event-handler-with-function-list", + verifiers=verifiers, + fixtures=(), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "configs", + "simulator_exit_event_run.py", + ), + config_args=["-l"], + valid_isas=(constants.all_compiled_tag,), + length=constants.quick_tag, +) + +gem5_verify_config( + name="simulator-exit-event-handler-with-generator", + verifiers=verifiers, + fixtures=(), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "configs", + "simulator_exit_event_run.py", + ), + config_args=[], + valid_isas=(constants.all_compiled_tag,), + length=constants.quick_tag, +) From 037e6fe33ca10528add42f1b2280bc3ef87cefe3 Mon Sep 17 00:00:00 2001 From: mbabaie Date: Wed, 14 Jun 2023 12:07:11 -0700 Subject: [PATCH 071/693] misc: update gem5 links This change updates all of the gerrit links to use github. Change-Id: I2a020dafac0bd2ba99b26c6a9cd4f0c585e253f8 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71719 Maintainer: Bobby Bruce Tested-by: kokoro Reviewed-by: Bobby Bruce --- CONTRIBUTING.md | 130 ++++-------------- .../gem5-all-min-dependencies/Dockerfile | 2 +- util/gem5art/artifact/README.md | 2 +- util/gem5art/artifact/setup.py | 4 +- util/gem5art/run/setup.py | 2 +- util/gem5art/tasks/setup.py | 2 +- 6 files changed, 29 insertions(+), 113 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae771d3ffb..c3c4d617d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,8 +67,8 @@ High-level flow for submitting changes | Submit code | +-------------+ -After creating your change to gem5, you can post a review on our Gerrit -code-review site: https://gem5-review.googlesource.com. Before being able to +After creating your change to gem5, you can post a review to git +via a pull request at: https://github.com/gem5/gem5/pulls/. Before being able to submit your code to the mainline of gem5, the code is reviewed by others in the community. Additionally, the maintainer for that part of the code must sign off on it. @@ -77,13 +77,13 @@ Cloning the gem5 repo to contribute =================================== If you plan on contributing, it is strongly encouraged for you to clone the -repository directly, and checkout the `develop` branch from our gerrit instance -at https://gem5.googlesource.com/. +repository directly, and checkout the `develop` branch from our git instance +at https://github.com/gem5/gem5/. To clone the gem5 repository: ``` - git clone https://gem5.googlesource.com/public/gem5 + git clone https://github.com/gem5/gem5/ ``` By default, the stable branch is checked out. The stable branch contains the @@ -156,7 +156,7 @@ The hooks are also automatically installed when gem5 is compiled. When you run a `git commit` command the pre-commit hook will run checks on your committed code. The commit will be blocked if a check fails. -The same checks are run as part of Gerrit's CI tests (those required to obtain +The same checks are run as part of github actions CI tests (those required to obtain a Verified label, necessary for a change to be accepted to the develop branch). Therefore setting up pre-commit in your local gem5 development environment is recommended. @@ -187,8 +187,7 @@ A canonical commit message consists of three parts: less. Leave a blank line between the first short summary line and this detailed description. * Tags describing patch metadata. You are highly recommended to use - tags to acknowledge reviewers for their work. Gerrit will automatically add - most tags. + tags to acknowledge reviewers for their work. Tags are an optional mechanism to store additional metadata about a patch and acknowledge people who reported a bug or reviewed that patch. Tags are @@ -243,7 +242,7 @@ who has contributed a significant amount of code to the file). The up-to-date when you make further changes to files which already have your copyright but with older dates. -Note: If you do not follow these guidelines, the gerrit review site will +Note: If you do not follow these guidelines, the github actions will automatically reject your patch. If this happens, update your changeset descriptions to match the required style and resubmit. The following is a useful git command to update the most recent @@ -263,20 +262,18 @@ See TESTING.md for more information. Posting a review ================ -If you have not signed up for an account on the Gerrit review site -(https://gem5-review.googlesource.com), you first have to create an account. +If you have not signed up for an account on the github +(https://github.com/), you first have to create an account. Setting up an account --------------------- - 1. Go to https://gem5.googlesource.com/ - 2. Click "Sign In" in the upper right corner. Note: You will need a Google - account to contribute. - 3. After signing in, click "Generate Password" and follow the instructions. + 1. Go to https://github.com/ + 2. Click "Sign up" in the upper right corner. Submitting a change ------------------- -In gerrit, to submit a review request, you can simply push your git commits to +In github, to submit a review request, you can simply push your git commits to a special named branch. For more information on git push see https://git-scm.com/docs/git-push. @@ -284,94 +281,13 @@ There are three ways to push your changes to gerrit. Push change to gerrit review ---------------------------- +1. Fork the gem5 repository on GitHub from https://github.com/gem5/gem5/. +2. Create a new branch in your forked repository for your feature or bug fix. +3. Commit your changes to the new branch. +4. Push the branch to your forked repository. +5. Open a pull request from your branch in your forked repository to the main gem5 repository. -``` - git push origin HEAD:refs/for/develop -``` - -Assuming origin is https://gem5.googlesource.com/public/gem5 and you want to -push the changeset at HEAD, this will create a new review request on top of the -develop branch. More generally, - -``` - git push :refs/for/ -``` - -See https://gerrit-review.googlesource.com/Documentation/user-upload.html for -more information. - -Pushing your first change --------------------------- -The first time you push a change you may get the following error: - -``` - remote: ERROR: [fb1366b] missing Change-Id in commit message footer - ... -``` - -Within the error message, there is a command line you should run. For every new -clone of the git repo, you need to run the following command to automatically -insert the change id in the the commit (all on one line). - -``` - curl -Lo `git rev-parse --git-dir`/hooks/commit-msg \ - https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; \ - chmod +x `git rev-parse --git-dir`/hooks/commit-msg -``` - -If you receive the above error, simply run this command and then amend your -changeset. - -``` - git commit --amend -``` - -Push change to gerrit as a Work In Progress -------------------------------------------- - -It is acceptable to push commits as "Work In Progress" (WIP) changes within -gerrit. WIP changes are publicly visible though no one will be able to review -the changes or be directly notified they have been submitted. WIP changes can -be useful for backing up code currently under-development or for sharing -incomplete code with the wider community (i.e., the link to the gerrit change -may be shared, and others may download the change, comment on it, and track -alterations over time). - -See https://gerrit-review.googlesource.com/Documentation/intro-user.html#wip -for details on WIP gerrit changes. - -To push a change as a WIP: - -``` - git push origin HEAD:refs/for/develop%wip -``` - -Once you have pushed your change as a WIP, you can log onto [gerrit]( -https://gem5-review.googlesource.com) and view it. Once you're happy with the -change you can add reviewers which shall move your change from WIP status -to be considered for submission by the wider gem5 community. Switching from a -WIP to a regular change does not notify the gem5 community, via the gem5-dev -mailing-list, that a change has been submitted (as would occur if a change were -submitted directly for review). It is therefore important to include reviewers -and CC those who you wish to view the change (they will be notified -automatically via email). - -Push change bypassing gerrit ------------------------------ - -Only maintainers can bypass gerrit review. This should very rarely be used. - -``` - git push origin HEAD:refs/heads/develop -``` - -Other gerrit push options -------------------------- - -There are a number of options you can specify when uploading your changes to -gerrit (e.g., reviewers, labels). The gerrit documentation has more -information. -https://gerrit-review.googlesource.com/Documentation/user-upload.html +We will continue to use the “develop” branch for development, so please ensure your pull requests are for the gem5 develop branch. Pull requests to the stable branch will be blocked. Branches ======== @@ -413,8 +329,8 @@ development.** Reviewing patches ================= -Reviewing patches is done on our gerrit instance at -https://gem5-review.googlesource.com/. +Reviewing patches is done on our github instance at +https://github.com/gem5/gem5/pulls/. After logging in with your Google account, you will be able to comment, review, and push your own patches as well as review others' patches. All gem5 users are @@ -550,7 +466,7 @@ into the stable branch after two weeks, thus marking the new release. 3. The staging branch will have the full suite of gem5 tests run on it to ensure all tests pass and the to-be-released code is in a decent state. 4. If a user submits a changeset to the staging branch, it will be considered -and undergo the standard Gerrit review process. However, only alterations that +and undergo the standard github review process. However, only alterations that cannot wait until the following release will be accepted for submission into the branch (i.e., submissions to the staging branch for "last minute" inclusions to the release should be of a high priority, such as a critical bug @@ -585,7 +501,7 @@ permitted, the following steps will be taken: 1. A new branch with the prefix "hotfix-" will be created from the stable branch. Only gem5 maintainers can create branches. If a non-maintainer requires the creation of a hotfix branch then they should contact a gem5 maintainer. -2. The change shall be submitted to the hotfix branch via gerrit. Full review, +2. The change shall be submitted to the hotfix branch via github. Full review, as with any other change, will be required. 3. Once fully submitted, the hotfix branch shall be merged into both the develop and the stable branch by a gem5 maintainer. diff --git a/util/dockerfiles/gem5-all-min-dependencies/Dockerfile b/util/dockerfiles/gem5-all-min-dependencies/Dockerfile index da5613e1a1..b28b674fa7 100644 --- a/util/dockerfiles/gem5-all-min-dependencies/Dockerfile +++ b/util/dockerfiles/gem5-all-min-dependencies/Dockerfile @@ -26,7 +26,7 @@ FROM gcr.io/gem5-test/ubuntu-22.04_min-dependencies:latest as source RUN apt -y update && apt -y install git -RUN git clone -b develop https://gem5.googlesource.com/public/gem5 /gem5 +RUN git clone -b develop https://github.com/gem5/gem5/ /gem5 WORKDIR /gem5 RUN scons -j`nproc` build/ALL/gem5.fast diff --git a/util/gem5art/artifact/README.md b/util/gem5art/artifact/README.md index aae297332a..86e30abcd0 100644 --- a/util/gem5art/artifact/README.md +++ b/util/gem5art/artifact/README.md @@ -51,7 +51,7 @@ gem5_binary = Artifact.registerArtifact( inputs = [gem5_repo,], documentation = ''' Default gem5 binary compiled for the X86 ISA. - This was built from the main gem5 repo (gem5.googlesource.com) without + This was built from the main gem5 repo (https://github.com/gem5/gem5/) without any modifications. We recently updated to the current gem5 master which has a fix for memory channel address striping. ''' diff --git a/util/gem5art/artifact/setup.py b/util/gem5art/artifact/setup.py index 869603db4b..78247eb16d 100755 --- a/util/gem5art/artifact/setup.py +++ b/util/gem5art/artifact/setup.py @@ -56,8 +56,8 @@ setup( install_requires=["pymongo"], python_requires=">=3.6", project_urls={ - "Bug Reports": "https://gem5.atlassian.net/", - "Source": "https://gem5.googlesource.com/", + "Bug Reports": "https://github.com/gem5/issues/", + "Source": "https://github.com/gem5/gem5/", "Documentation": "https://www.gem5.org/documentation/gem5art", }, ) diff --git a/util/gem5art/run/setup.py b/util/gem5art/run/setup.py index d17124bd1f..1ab51b5c2d 100755 --- a/util/gem5art/run/setup.py +++ b/util/gem5art/run/setup.py @@ -57,7 +57,7 @@ setup( python_requires=">=3.6", project_urls={ "Bug Reports": "https://gem5.atlassian.net/", - "Source": "https://gem5.googlesource.com/", + "Source": "https://github.com/gem5/gem5/", "Documentation": "https://www.gem5.org/documentation/gem5art", }, scripts=["bin/gem5art-getruns"], diff --git a/util/gem5art/tasks/setup.py b/util/gem5art/tasks/setup.py index 7bcfc642ae..290c68a17a 100755 --- a/util/gem5art/tasks/setup.py +++ b/util/gem5art/tasks/setup.py @@ -58,7 +58,7 @@ setup( python_requires=">=3.6", project_urls={ "Bug Reports": "https://gem5.atlassian.net/", - "Source": "https://gem5.googlesource.com/", + "Source": "https://github.com/gem5/gem5/", "Documentation": "https://www.gem5.org/documentation/gem5art", }, ) From eb07d3fcf4095aedda7faa50184c2228d5053ccd Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Wed, 28 Jun 2023 10:16:52 -0700 Subject: [PATCH 072/693] misc: Update documentation and links for GitHub This changes mentions of googlesource and Gerrit to instead link to the gem5 GitHub repository, and updates the documentation to reflect the GitHub review process. Change-Id: I5dc1d9fcf6b96f9e5116802f938b7e3bb5b09567 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/71878 Maintainer: Bobby Bruce Tested-by: kokoro Reviewed-by: Bobby Bruce --- CONTRIBUTING.md | 40 ++-------------- TESTING.md | 47 +++++++++++++++++-- configs/example/gem5_library/arm-hello.py | 2 +- .../riscv-hello-save-checkpoint.py | 2 +- .../gem5_library/dramsys/arm-hello-dramsys.py | 2 +- configs/example/gem5_library/riscv-fs.py | 2 +- ext/sst/README.md | 2 +- tests/weekly.sh | 2 +- 8 files changed, 54 insertions(+), 45 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3c4d617d2..b41a73a4a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,12 +14,12 @@ several reasons to do this: * You will have the satisfaction of contributing back to the community. The main method for contributing code to gem5 is via our code review website: -https://gem5-review.googlesource.com/. This documents describes the details of +https://github.com/gem5/gem5/pulls/. This documents describes the details of how to create code changes, upload your changes, have your changes reviewed, and finally push your changes to gem5. More information can be found from the following sources: * http://gem5.org/contributing - * https://gerrit-review.googlesource.com/Documentation/index.html + * https://docs.github.com/en/pull-requests * https://git-scm.com/book @@ -277,9 +277,7 @@ In github, to submit a review request, you can simply push your git commits to a special named branch. For more information on git push see https://git-scm.com/docs/git-push. -There are three ways to push your changes to gerrit. - -Push change to gerrit review +Push changes to GitHub ---------------------------- 1. Fork the gem5 repository on GitHub from https://github.com/gem5/gem5/. 2. Create a new branch in your forked repository for your feature or bug fix. @@ -296,35 +294,7 @@ By default, contributions to gem5 should be made on the develop branch. The stable branch is maintained as a stable release branch (i.e., it can be pulled to obtain the latest official release of gem5). Creation of additional branches is generally discouraged due to their tendency to bloat git repositories with -abandoned code. However, the creation of new branches is permitted for -development of a specific feature or improvement if one or more of the -following criteria are met: - -1. The feature/improvement is likely to be of a large size, consisting of many -commits, with little logic in these commits being contributed separately. -2. The feature/improvement will be developed over a long period of time. -3. There is sufficient reason that a feature/improvement should not be part -of the next gem5 release (e.g., the change should be held within a feature -branch until ready for the next release, at which point it will be merged -into the develop branch). - -If a branch is required it can only be created by a project maintainer. -Therefore, if a gem5 contributor desires a separate branch for their work, they -should request one from the maintainer of the component the work relates to -(see MAINTAINERS for the list of maintainers and the components they are -responsible for). **The maintainer shall use their discretion to determine -whether the creation of a branch is necessary**. If approved, the maintainer -shall create the branch which the contributor may then use. - -Development on a branch within Gerrit functions in exactly the same way as -contributing to the develop branch. When contributors to a branch are -satisfied, they should create a merge commit into the develop branch. The -maintainer should then be notified that the branch they created can now be -deleted. - -**Abandonment of changes within branches may result in these branches being -removed from the repository. All branches within a repo should be under active -development.** +abandoned code. Reviewing patches ================= @@ -332,7 +302,7 @@ Reviewing patches Reviewing patches is done on our github instance at https://github.com/gem5/gem5/pulls/. -After logging in with your Google account, you will be able to comment, review, +After logging in with your GitHub account, you will be able to comment, review, and push your own patches as well as review others' patches. All gem5 users are encouraged to review patches. The only requirement to review patches is to be polite and respectful of others. diff --git a/TESTING.md b/TESTING.md index 146aeac8b1..50cc9bea3e 100644 --- a/TESTING.md +++ b/TESTING.md @@ -18,8 +18,8 @@ To build and run all the unit tests: scons build/ALL/unittests.opt ``` -All unit tests should be run prior to posting a patch to -https://gem5-review.googlesource.com +All unit tests should be run prior to creating a pull request at +https://github.com/gem5/gem5/pulls/ To compile and run just one set of tests (e.g. those declared within `src/base/bitunion.test.cc`): @@ -60,8 +60,8 @@ cd tests ./main.py run ``` -The above is the *minumum* you should run before posting a patch to -https://gem5-review.googlesource.com +The above is the *minumum* you should run before posting a pull request to +https://github.com/gem5/gem5/pulls/ ## Running tests from multiple directories @@ -260,3 +260,42 @@ suites in parallel, supply the `-t ` flag to the run command. For example, to run up to three test suites at the same time:: ./main.py run --skip-build -t 3 + +## Running Tests within GitHub Actions + +To run these tests within GitHub Actions, we use the format of running +tests by directory as shown above in the "Running Tests from Multiple +Directories" section. These tests are run within workflow files, +which can be found in the .github directory of this repository. +You can learn more about workflows +[here](https://docs.github.com/en/actions/using-workflows/about-workflows). + +Each workflow is made up of individual jobs, where each job is a set +of tests that is executed on a runner within GitHub. In each +workflow, each version of gem5.opt needed is first built, and then +stored as an artifact for main.py to use. + +There are two sets of runners within the gem5 repository: builders and +runners. The builders have more resources available to allow for a +quicker compilation of gem5, while the runners have less, and are +meant to only run tests. + +After the gem5 artifact has been uploaded, a runner can then download +the versions needed for their tests. For example, in the daily-tests.yaml, +in order to run the multi_isa tests, you need artifacts of ARM, RISCV, +and VEGA_X86. + +## Adding Tests to GitHub Actions + +In order to add new tests to our GitHub Actions testing infastructure, +follow the format currently shown in the existing workflows. If the +new tests were added to an already existing directory (ex. A very-long +test in the gem5_library_example_tests), it will automatically be +included into the weekly testing, since weekly-tests.yaml already +contains a job for the gem5_library_example_tests. + +However, if a new directory is added to the tests, you need to manually +add a new step to the GitHub workflows. This would consist of both a +step to build whatever version of gem5 was required if it wasn't +already included in the file, as well as a step to run main.py +in the given directory after downloading the gem5 artifact. diff --git a/configs/example/gem5_library/arm-hello.py b/configs/example/gem5_library/arm-hello.py index d66eee5790..b4180f11eb 100644 --- a/configs/example/gem5_library/arm-hello.py +++ b/configs/example/gem5_library/arm-hello.py @@ -80,7 +80,7 @@ board = SimpleBoard( board.set_se_binary_workload( # The `Resource` class reads the `resources.json` file from the gem5 # resources repository: - # https://gem5.googlesource.com/public/gem5-resource. + # https://github.com/gem5/gem5-resources. # Any resource specified in this file will be automatically retrieved. # At the time of writing, this file is a WIP and does not contain all # resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096 diff --git a/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py b/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py index 159c4b76e1..439d2054fa 100644 --- a/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py @@ -97,7 +97,7 @@ board = SimpleBoard( board.set_se_binary_workload( # The `Resource` class reads the `resources.json` file from the gem5 # resources repository: - # https://gem5.googlesource.com/public/gem5-resource. + # https://github.com/gem5/gem5-resources. # Any resource specified in this file will be automatically retrieved. # At the time of writing, this file is a WIP and does not contain all # resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096 diff --git a/configs/example/gem5_library/dramsys/arm-hello-dramsys.py b/configs/example/gem5_library/dramsys/arm-hello-dramsys.py index 8b25a36396..ae0f51ad40 100644 --- a/configs/example/gem5_library/dramsys/arm-hello-dramsys.py +++ b/configs/example/gem5_library/dramsys/arm-hello-dramsys.py @@ -74,7 +74,7 @@ board = SimpleBoard( board.set_se_binary_workload( # The `Resource` class reads the `resources.json` file from the gem5 # resources repository: - # https://gem5.googlesource.com/public/gem5-resource. + # https://github.com/gem5/gem5-resources. # Any resource specified in this file will be automatically retrieved. # At the time of writing, this file is a WIP and does not contain all # resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096 diff --git a/configs/example/gem5_library/riscv-fs.py b/configs/example/gem5_library/riscv-fs.py index e3e2bc75e1..e4dce027e3 100644 --- a/configs/example/gem5_library/riscv-fs.py +++ b/configs/example/gem5_library/riscv-fs.py @@ -27,7 +27,7 @@ """ This example runs a simple linux boot. It uses the 'riscv-disk-img' resource. It is built with the sources in `src/riscv-fs` in [gem5 resources]( -https://gem5.googlesource.com/public/gem5-resources). +https://github.com/gem5/gem5-resources). Characteristics --------------- diff --git a/ext/sst/README.md b/ext/sst/README.md index 1f37cb4c44..fb998b5e18 100644 --- a/ext/sst/README.md +++ b/ext/sst/README.md @@ -78,7 +78,7 @@ the `bbl-busybox-boot-exit` resource, which contains an m5 binary, and `m5 exit` will be called upon the booting process reaching the early userspace. More information about building a bootloader containing a Linux Kernel and a customized workload is available at -[https://gem5.googlesource.com/public/gem5-resources/+/refs/heads/stable/src/riscv-boot-exit-nodisk/]. +[https://github.com/gem5/gem5-resources/tree/stable/src/riscv-boot-exit-nodisk]. ## Running an example simulation (Arm) diff --git a/tests/weekly.sh b/tests/weekly.sh index 9c7ebdf76d..2bfd33741d 100755 --- a/tests/weekly.sh +++ b/tests/weekly.sh @@ -94,7 +94,7 @@ rm -rf ${gem5_root}/m5out coAuthorsDBLP.graph 1k_128k.gr result.out # Moreover, DNNMark builds a library and thus doesn't have a binary, so we # need to build it before we run it. # Need to pull this first because HACC's docker requires this path to exist -git clone https://gem5.googlesource.com/public/gem5-resources \ +git clone https://github.com/gem5/gem5-resources \ "${gem5_root}/gem5-resources" From 35763bdfb2550b74262e040e9cdf9f458ec3ecf4 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Tue, 17 Jan 2023 13:57:23 +0800 Subject: [PATCH 073/693] arch: Add setRegOperand in VecRegOperand VecRegOperand also need setRegOperand method to write back execution result. Change-Id: Ie50606014827c14a7219558dd003eb4747231649 Co-authored-by: Xuan Hu Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67292 Reviewed-by: Giacomo Travaglini Reviewed-by: Bobby Bruce Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/isa_parser/operand_types.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arch/isa_parser/operand_types.py b/src/arch/isa_parser/operand_types.py index 174a54cd4c..113cc2f982 100755 --- a/src/arch/isa_parser/operand_types.py +++ b/src/arch/isa_parser/operand_types.py @@ -372,6 +372,7 @@ class VecRegOperand(RegOperand): def makeWrite(self): return f""" + xc->setRegOperand(this, {self.dest_reg_idx}, &tmp_d{self.dest_reg_idx}); if (traceData) {{ traceData->setData({self.reg_class}, &tmp_d{self.dest_reg_idx}); }} From c634b23305ed4e26ca0efa41b859ca7e3da11ee6 Mon Sep 17 00:00:00 2001 From: Luming Wang Date: Tue, 23 May 2023 22:32:12 +0800 Subject: [PATCH 074/693] sim,python: follow the new CPython startup sequence Currently, gem5 suffers from several bugs related to Python interpreter's locale encoding issues. gem5 will crash when the working directory contains Non-ASCII characters. The reason is that Python 3.8+ introduces a new interpreter startup sequence [1]. The startup sequence consists of three phases: 1. Python core runtime preinitialization 2. Python core runtime initialization 3. Main interpreter configuration Stage 1 determining the encodings used for system interfaces. However, gem5 doesn't preinitialize the Python interpreter. Thus, the locale settings do not take effect. This patch preinitialize the Python for Python 3.8+. Also, this patch avoid the use of `Py_SetProgramName`, which is deprecated since Python 3.11[3]. [1] https://peps.python.org/pep-0432/ [2] https://peps.python.org/pep-0587/ [3] https://docs.python.org/3/c-api/init.html#c.Py_SetProgramName Change-Id: I08a2ec6ab2b39a95ab194909932c8fc578c745ce Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70898 Tested-by: kokoro Reviewed-by: Bobby Bruce Maintainer: Bobby Bruce Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Reviewed-by: Roger Chang --- src/python/gem5py.cc | 15 +++++++++++++++ src/sim/main.cc | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/python/gem5py.cc b/src/python/gem5py.cc index f2d87596f0..37ddee2e7c 100644 --- a/src/python/gem5py.cc +++ b/src/python/gem5py.cc @@ -51,6 +51,21 @@ namespace py = pybind11; int main(int argc, const char **argv) { +#if PY_VERSION_HEX >= 0x03080000 + // Preinitialize Python for Python 3.8+ + // This ensures that the locale configuration takes effect + PyStatus status; + PyPreConfig preconfig; + PyPreConfig_InitPythonConfig(&preconfig); + + preconfig.utf8_mode = 1; + + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } +#endif + py::scoped_interpreter guard; // Embedded python doesn't set up sys.argv, so we'll do that ourselves. diff --git a/src/sim/main.cc b/src/sim/main.cc index 81a691d15d..1c42891816 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -50,6 +50,7 @@ main(int argc, char **argv) // Initialize gem5 special signal handling. initSignals(); +#if PY_VERSION_HEX < 0x03080000 // Convert argv[0] to a wchar_t string, using python's locale and cleanup // functions. std::unique_ptr program( @@ -59,6 +60,23 @@ main(int argc, char **argv) // This can help python find libraries at run time relative to this binary. // It's probably not necessary, but is mostly harmless and might be useful. Py_SetProgramName(program.get()); +#else + // Preinitialize Python for Python 3.8+ + // This ensures that the locale configuration takes effect + PyStatus status; + + PyConfig config; + PyConfig_InitPythonConfig(&config); + + /* Set the program name. Implicitly preinitialize Python. */ + status = PyConfig_SetBytesString(&config, &config.program_name, + argv[0]); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); + return 1; + } +#endif py::scoped_interpreter guard(true, argc, argv); From 73afee1e0d25646bb8b42b610f2ffdd43b6aaed4 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Mon, 27 Feb 2023 15:48:23 +0000 Subject: [PATCH 075/693] base: Provide stl_helpers::operator<< for more types This operator can be safely brought in scope when needed with "using stl_helpers::operator<<". In order to provide a specialization for operator<< with stl_helpers-enabled types without loosing the hability to use it with other types, a dual-dispatch mechanism is used. The only entry point in the system is through a primary dispatch function that won't resolve for non-helped types. Then, recursive calls go through the secondary dispatch interface that sort between helped and non-helped types. Helped typed will enter the system back through the primary dispatch interface while other types will look for operator<< through regular lookup, especially ADL. Change-Id: I1609dd6e85e25764f393458d736ec228e025da32 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67666 Reviewed-by: Daniel Carvalho Tested-by: kokoro Maintainer: Bobby Bruce --- src/base/stl_helpers.hh | 57 +----- src/base/stl_helpers/SConscript | 1 + src/base/stl_helpers/ostream_helpers.hh | 192 +++++++++++++++++++ src/base/stl_helpers/ostream_helpers.test.cc | 66 +++++++ 4 files changed, 263 insertions(+), 53 deletions(-) create mode 100644 src/base/stl_helpers/ostream_helpers.hh create mode 100644 src/base/stl_helpers/ostream_helpers.test.cc diff --git a/src/base/stl_helpers.hh b/src/base/stl_helpers.hh index 1d19f56676..b70eea9992 100644 --- a/src/base/stl_helpers.hh +++ b/src/base/stl_helpers.hh @@ -26,59 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BASE_STL_HELPERS_HH__ -#define __BASE_STL_HELPERS_HH__ +#ifndef BASE_STL_HELPERS_HH +#define BASE_STL_HELPERS_HH -#include -#include -#include -#include -#include - -#include "base/compiler.hh" #include "base/stl_helpers/hash_helpers.hh" +#include "base/stl_helpers/ostream_helpers.hh" -namespace gem5 -{ - -namespace stl_helpers -{ - -template -struct IsHelpedContainer : public std::false_type {}; - -template -struct IsHelpedContainer> : public std::true_type {}; - -template -constexpr bool IsHelpedContainerV = IsHelpedContainer::value; - -/** - * Write out all elements in an stl container as a space separated - * list enclosed in square brackets - * - * @ingroup api_base_utils - */ - -template -std::enable_if_t, std::ostream &> -operator<<(std::ostream& out, const T &t) -{ - out << "[ "; - bool first = true; - auto printer = [&first, &out](const auto &elem) { - if (first) - out << elem; - else - out << " " << elem; - }; - std::for_each(t.begin(), t.end(), printer); - out << " ]"; - out << std::flush; - return out; -} - -} // namespace stl_helpers -} // namespace gem5 - -#endif // __BASE_STL_HELPERS_HH__ +#endif // BASE_STL_HELPERS_HH diff --git a/src/base/stl_helpers/SConscript b/src/base/stl_helpers/SConscript index 1143dc2d42..7328cf066a 100644 --- a/src/base/stl_helpers/SConscript +++ b/src/base/stl_helpers/SConscript @@ -26,3 +26,4 @@ Import('*') GTest('hash_helpers.test', 'hash_helpers.test.cc') +GTest('ostream_helpers.test', 'ostream_helpers.test.cc') diff --git a/src/base/stl_helpers/ostream_helpers.hh b/src/base/stl_helpers/ostream_helpers.hh new file mode 100644 index 0000000000..a1c92e1ed1 --- /dev/null +++ b/src/base/stl_helpers/ostream_helpers.hh @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2023 Arteris, Inc. and its applicable licensors and + * affiliates. + * 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. + */ + +#ifndef BASE_STL_HELPERS_OSTREAM_HELPERS_HH +#define BASE_STL_HELPERS_OSTREAM_HELPERS_HH + +#include +#include +#include +#include + +#include "base/type_traits.hh" +#include "magic_enum/magic_enum.hh" + +namespace gem5::stl_helpers +{ + +namespace opExtract_impl +{ + +/* + * In order to provide a specialization for operator<< with stl_helpers-enabled + * types + * without loosing the hability to use it with other types, a dual-dispatch + * mechanism is used. The only entry point in the system is through a primary + * dispatch function that won't resolve for non-helped types. Then, recursive + * calls go through the secondary dispatch interface that sort between helped + * and non-helped types. Helped typed will enter the system back through the + * primary dispatch interface while other types will look for operator<< + * through regular lookup, especially ADL. + */ + +template +std::ostream& +opExtractSecDisp(std::ostream& os, const T& v); + +template +std::enable_if_t, +std::ostream&> +opExtractPrimDisp(std::ostream& os, const E& e) +{ + return os << magic_enum::enum_name(e); +} + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const std::tuple& p) +{ + std::apply([&](auto&&... e) { + std::size_t n{0}; + os << '('; + ((opExtractSecDisp(os, e) << (++n != sizeof...(T) ? ", " : "")), ...); + os << ')'; + }, p); + return os; +} + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const std::pair& p) +{ + return opExtractPrimDisp(os, std::tie(p.first, p.second)); +} + +template +std::enable_if_t, std::ostream&> +opExtractPrimDisp(std::ostream& os, const T& v) +{ + os << "[ "; + for (auto& e: v) { + opExtractSecDisp(os, e) << ", "; + } + return os << ']'; +} + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const std::optional& o) +{ + if (o) { + return opExtractSecDisp(os, *o); + } else { + return os << '-'; + } +} + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, T* p); + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const std::shared_ptr& p) +{ + return opExtractPrimDisp(os, p.get()); +} + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const std::unique_ptr& p) +{ + return opExtractPrimDisp(os, p.get()); +} + +template +constexpr bool isOpExtractNativelySupported = false; + +template +constexpr bool isOpExtractNativelySupported() << std::declval())>> = true; + +template +constexpr bool isOpExtractHelped = false; + +template +constexpr bool isOpExtractHelped(), + std::declval()))>> + = true; + +template +constexpr bool needsDispatch = + isOpExtractHelped && !isOpExtractNativelySupported; + +template +std::ostream& +opExtractPrimDisp(std::ostream& os, T* p) +{ + if (!p) { + return os << "nullptr"; + } + if constexpr (isOpExtractHelped || isOpExtractNativelySupported) { + os << '(' << p << ": "; + opExtractSecDisp(os, *p); + return os << ')'; + } else { + return os << p; + } +} + +template +std::ostream& +opExtractSecDisp(std::ostream& os, const T& v) +{ + if constexpr (needsDispatch) { + return opExtractPrimDisp(os, v); + } else { + return os << v; + } +} + +} // namespace opExtract_impl + +// Add "using stl_helpers::operator<<" in the scope where you want to use it. +template +std::enable_if_t, std::ostream&> +operator<<(std::ostream& os, const T& v) +{ + return opExtract_impl::opExtractPrimDisp(os, v); +} + +} // namespace gem5::stl_helpers + +#endif // BASE_STL_HELPERS_OSTREAM_HELPERS_HH diff --git a/src/base/stl_helpers/ostream_helpers.test.cc b/src/base/stl_helpers/ostream_helpers.test.cc new file mode 100644 index 0000000000..19a1ece27e --- /dev/null +++ b/src/base/stl_helpers/ostream_helpers.test.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Arteris, Inc. and its applicable licensors and + * affiliates. 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. + */ + +#include + +#include +#include +#include +#include + +#include "base/stl_helpers/ostream_helpers.hh" + +using gem5::stl_helpers::operator<<; + +TEST(OstreamHelpers, pair) { + auto p = std::make_pair(1, 2); + std::ostringstream os; + os << p; + EXPECT_EQ(os.str(), "(1, 2)"); +} + +TEST(OstreamHelpers, tuple) { + auto t = std::make_tuple(true, + std::make_pair("Hello", std::string_view("World")), '!'); + std::ostringstream os; + os << t; + EXPECT_EQ(os.str(), "(1, (Hello, World), !)"); +} + +TEST(OstreamHelpers, vector) { + auto v = std::vector{"abc", "defg", "hijklm", "\n"}; + std::ostringstream os; + os << v; + EXPECT_EQ(os.str(), "[ abc, defg, hijklm, \n, ]"); +} + +TEST(OstreamHelpers, map) { + auto m = std::map{{'a', 0}, {'b', 1}, {'c', 2}, {'d', 3}}; + std::ostringstream os; + os << m; + EXPECT_EQ(os.str(), "[ (a, 0), (b, 1), (c, 2), (d, 3), ]"); +} From 753933d47172d931f577120ce3c930cee71ecfe3 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 11 Jul 2023 14:35:03 -0700 Subject: [PATCH 076/693] gpu-compute, tests: Fix GPU_X86 compilation, add compiler tests (#64) * gpu-compute: Remove use of 'std::random_shuffle' This was deprecated in C++14 and removed in C++17. This has been replaced with std::random. This has been implemented to ensure reproducible results despite (pseudo)random behavior. Change-Id: Idd52bc997547c7f8c1be88f6130adff8a37b4116 * dev-amdgpu: Add missing 'overrides' This causes warnings/errors in some compilers. Change-Id: I36a3548943c030d2578c2f581c8985c12eaeb0ae * dev: Fix Linux specific includes to be portable This allows for compilation in non-linux systems (e.g., Mac OS). Change-Id: Ib6c9406baf42db8caaad335ebc670c1905584ea2 * tests: Add 'VEGA_X86' build target to compiler-tests.sh Change-Id: Icbf1d60a096b1791a4718a7edf17466f854b6ae5 * tests: Add 'GCN3_X86' build target to compiler-tests.sh Change-Id: Ie7c9c20bb090f8688e48c8619667312196a7c123 --- .github/workflows/compiler-tests.yaml | 2 +- src/arch/amdgpu/vega/insts/instructions.hh | 4 ++-- src/cpu/testers/gpu_ruby_test/address_manager.cc | 11 +++++++++-- src/dev/hsa/kfd_ioctl.h | 5 +++-- tests/compiler-tests.sh | 2 ++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 52569e2e01..938bd03e6f 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -35,7 +35,7 @@ jobs: latest-compilers-all-gem5-builds: strategy: matrix: - gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base] + gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, GCN3_X86] image: [gcc-version-12, clang-version-14] opts: [.opt] runs-on: [self-hosted, linux, x64, run] diff --git a/src/arch/amdgpu/vega/insts/instructions.hh b/src/arch/amdgpu/vega/insts/instructions.hh index d45a84c7b8..0e4ec04764 100644 --- a/src/arch/amdgpu/vega/insts/instructions.hh +++ b/src/arch/amdgpu/vega/insts/instructions.hh @@ -31534,8 +31534,8 @@ namespace VegaISA } // getOperandSize void execute(GPUDynInstPtr) override; - void initiateAcc(GPUDynInstPtr gpuDynInst); - void completeAcc(GPUDynInstPtr gpuDynInst); + void initiateAcc(GPUDynInstPtr gpuDynInst) override; + void completeAcc(GPUDynInstPtr gpuDynInst) override; }; // Inst_DS__DS_OR_B32 class Inst_DS__DS_XOR_B32 : public Inst_DS diff --git a/src/cpu/testers/gpu_ruby_test/address_manager.cc b/src/cpu/testers/gpu_ruby_test/address_manager.cc index 37f74203f7..049ba86e51 100644 --- a/src/cpu/testers/gpu_ruby_test/address_manager.cc +++ b/src/cpu/testers/gpu_ruby_test/address_manager.cc @@ -32,6 +32,8 @@ #include "cpu/testers/gpu_ruby_test/address_manager.hh" #include +#include +#include #include "base/intmath.hh" #include "base/logging.hh" @@ -58,8 +60,13 @@ AddressManager::AddressManager(int n_atomic_locs, int n_normal_locs_per_atomic) randAddressMap[i] = (Addr)((i + 128) << floorLog2(sizeof(Value))); } - // randomly shuffle randAddressMap - std::random_shuffle(randAddressMap.begin(), randAddressMap.end()); + // randomly shuffle randAddressMap. The seed is determined by the random_mt + // gem5 rng. This allows for deterministic randomization. + std::shuffle( + randAddressMap.begin(), + randAddressMap.end(), + std::default_random_engine(random_mt.random(0,UINT_MAX)) + ); // initialize atomic locations // first and last normal location per atomic location diff --git a/src/dev/hsa/kfd_ioctl.h b/src/dev/hsa/kfd_ioctl.h index c953787dc8..b7997c40fc 100644 --- a/src/dev/hsa/kfd_ioctl.h +++ b/src/dev/hsa/kfd_ioctl.h @@ -23,9 +23,10 @@ #ifndef KFD_IOCTL_H_INCLUDED #define KFD_IOCTL_H_INCLUDED +#include +#include + #include -#include -#include namespace gem5 { diff --git a/tests/compiler-tests.sh b/tests/compiler-tests.sh index f5d4bb189f..1f180eb5fa 100755 --- a/tests/compiler-tests.sh +++ b/tests/compiler-tests.sh @@ -58,6 +58,8 @@ builds=("ALL" "POWER" "RISCV" "SPARC" + "GCN3_X86" + "VEGA_X86" "X86" "X86_MI_example" "X86_MOESI_AMD_Base") From 2a880053bbc1cf794d4488f006defee2818f2dc8 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Wed, 12 Jul 2023 20:24:18 +0200 Subject: [PATCH 077/693] Sanitizer libraries static linking (#70) * scons: Fix sanitizer lib link for clang Change-Id: I2441466c5c9343afd938185b8ec5047d4e95ac70 * scons: Statically link libubsan when using sanitizers with gcc Change-Id: I362a1fb87771454ad94e439847a85d19108f375a --------- Co-authored-by: Gabriel Busnot --- SConstruct | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 9b25b33783..32e0c36e09 100755 --- a/SConstruct +++ b/SConstruct @@ -562,10 +562,14 @@ for variant_path in variant_paths: if sanitizers: sanitizers = ','.join(sanitizers) if env['GCC'] or env['CLANG']: + libsan = ( + ['-static-libubsan', '-static-libasan'] + if env['GCC'] + else ['-static-libsan'] + ) env.Append(CCFLAGS=['-fsanitize=%s' % sanitizers, '-fno-omit-frame-pointer'], - LINKFLAGS=['-fsanitize=%s' % sanitizers, - '-static-libasan']) + LINKFLAGS=['-fsanitize=%s' % sanitizers] + libsan) if main["BIN_TARGET_ARCH"] == "x86_64": # Sanitizers can enlarge binary size drammatically, north of From 552ae9a1a2fecd693007b7802670d865ca718743 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 13 Jul 2023 10:26:02 -0700 Subject: [PATCH 078/693] misc: Merge v23.0.0.1 Hotfix into develop (#65) * gpu-compute: Remove use of 'std::random_shuffle' This was deprecated in C++14 and removed in C++17. This has been replaced with std::random. This has been implemented to ensure reproducible results despite (pseudo)random behavior. Change-Id: Idd52bc997547c7f8c1be88f6130adff8a37b4116 * dev-amdgpu: Add missing 'overrides' This causes warnings/errors in some compilers. Change-Id: I36a3548943c030d2578c2f581c8985c12eaeb0ae * dev: Fix Linux specific includes to be portable This allows for compilation in non-linux systems (e.g., Mac OS). Change-Id: Ib6c9406baf42db8caaad335ebc670c1905584ea2 * gpu-compute: Add missing include in dispatcher.cc Due to some cherry-picking onto the release-staging branch, there was a missing "sim/sim_exit.hh" include in "src/gpu-compute/dispatcher.cc". This was causing compilation errors. This is being added to the v23.0.0 release as a hotfix. Change-Id: I1043ecf5c41ad6afc0e91311b196f4801646002f Issue-on: https://gem5.atlassian.net/browse/GEM5-1332 * misc: Update version to v23.0.0.1 Change-Id: I3bbcfd4dd9798149b37d4a2824fe63652e29786c * misc: Update RELEASE-NOTES.md for v23.0.0.1 hotfix Change-Id: Ieced7f693a8cbef586324dfe7ce826da16d9a3c3 --- RELEASE-NOTES.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 0c158ee245..1a72428fc1 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,15 @@ +# Version 23.0.0.1 + +**[HOTFIX]** Fixes compilation of `GCN3_X86` and `VEGA_X85`. + +This hotfix release: + +* Removes the use of 'std::random_shuffle'. +This is a deprecated function in C++17 and has been removed in C++20. +* Adds missing 'overrides' in "src/arch/amdgpu/vega/insts/instructions.hh". +* Fixes Linux specific includes, allowing for compilation on non-linux systems. +* Adds a missing include in "src/gpu-compute/dispatcher.cc". + # Version 23.0 This release has approximately 500 contributions from 50 unique contributors. From 18470b474726fdb2ab79deb5c4d290398d3079ec Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 13 Jul 2023 18:57:51 +0100 Subject: [PATCH 079/693] arch-arm: Fix assert fail when UQRSHL shiftAmt==0 (#75) When shiftAmt is 0 for a UQRSHL instruction, the code called bits() with incorrect arguments. This fixes a left-shift of 0 to be a NOP/mov, as required. Change-Id: Ic86ca40ac42bfb767a09e8c65a53cec56382a008 Co-authored-by: Marton Erdos --- src/arch/arm/isa/insts/neon64.isa | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arch/arm/isa/insts/neon64.isa b/src/arch/arm/isa/insts/neon64.isa index 6608f61688..a3b79be912 100644 --- a/src/arch/arm/isa/insts/neon64.isa +++ b/src/arch/arm/isa/insts/neon64.isa @@ -3403,7 +3403,7 @@ let {{ destElem = (srcElem1 >> shiftAmt); } destElem += rBit; - } else { + } else if (shiftAmt > 0) { if (shiftAmt >= sizeof(Element) * 8) { if (srcElem1 != 0) { destElem = mask(sizeof(Element) * 8); @@ -3421,6 +3421,8 @@ let {{ destElem = srcElem1 << shiftAmt; } } + } else { + destElem = srcElem1; } FpscrQc = fpscr; ''' From bc99a6e3467fb064c28f3055d8e5ad7350275083 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 14 Jul 2023 06:31:34 -0700 Subject: [PATCH 080/693] tests: Improve Pyunit tests gem5 Resources' downloads (#79) * tests: Remove large files from resource specialization tests These tests were downloading resources (but not actually using them) to ensure the `obtain_resources` function returned the correct specialization and was parsing the data correctly. As these resources were never used, this patch removes the downloading of large files in this case, replacing them with smaller binaries. Change-Id: I7b33aa6be8ec65b296b470cd50b128c084f2b71f * tests: Rename 'looppoint-json...' example specailization Appending '-example' to the end avoids any name clashes. 'looppoint-json-restore-resources-region-1' shares this ID with a real resources in gem5 Resources. Change-Id: I9853e97cb71e768c46ad173b5a497609f4acc3b2 * tests: Remove disk image download from Workload Checks This download is big and unecessary (the workload is never run as part of the test). This patch changes this test to instead download a small binary in it's palce (again, this does not matter as this is never actually run as a disk image). Change-Id: I74034ebcf5f2501917847c258570e88a8f653a5d * tests: Update IDs in Pyunit Workload checks Some of these IDs clash with real workloads/resources in gem5 Resources. To avoid any possible clashes or confusions, all the mock resources/workloads in this suite of tests has been renamed with '-example' appending on the end of the ID. Change-Id: Ifd907b2321416bf05e8c4e646024d179da2ca487 --- .../pyunit_resource_specialization.py | 2 +- .../stdlib/resources/pyunit_workload_checks.py | 2 +- .../refs/resource-specialization.json | 18 +++++++++--------- .../stdlib/resources/refs/workload-checks.json | 16 ++++++++-------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py index f2088db8ef..93b83019b9 100644 --- a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py +++ b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py @@ -278,7 +278,7 @@ class ResourceSpecializationSuite(unittest.TestCase): Looppoint JSON file.""" resource = obtain_resource( - resource_id="looppoint-json-restore-resource-region-1", + resource_id="looppoint-json-restore-resource-region-1-example", resource_directory=self.get_resource_dir(), resource_version="1.0.0", gem5_version="develop", diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index b59e09d4fe..b374e7a8d3 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -65,7 +65,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): function="set_se_binary_workload", parameters={ "binary": obtain_resource( - "x86-hello64-static", gem5_version="develop" + "x86-hello64-static-example", gem5_version="develop" ), "arguments": ["hello", 6], }, diff --git a/tests/pyunit/stdlib/resources/refs/resource-specialization.json b/tests/pyunit/stdlib/resources/refs/resource-specialization.json index 414bf73b11..9a92204765 100644 --- a/tests/pyunit/stdlib/resources/refs/resource-specialization.json +++ b/tests/pyunit/stdlib/resources/refs/resource-specialization.json @@ -19,9 +19,9 @@ "id": "disk-image-example", "description": "disk-image documentation.", "architecture": "X86", - "is_zipped": true, - "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", - "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "is_zipped": false, + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", "source": "src/x86-ubuntu", "root_partition": "1", "resource_version": "1.0.0", @@ -64,9 +64,9 @@ "description": "checkpoint-example documentation.", "architecture": "RISCV", "is_zipped": false, - "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", "source": null, "is_tar_archive": true, + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", "resource_version": "1.0.0", "gem5_versions": [ @@ -93,8 +93,8 @@ "id": "file-example", "description": null, "is_zipped": false, - "md5sum": "2efd144c11829ab18d54eae6371e120a", - "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", + "md5sum": "71b2cb004fe2cda4556f0b1a38638af6", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/arm/linux/hello64-static", "source": null, "resource_version": "1.0.0", "gem5_versions": [ @@ -106,10 +106,10 @@ "category": "directory", "id": "directory-example", "description": "directory-example documentation.", - "is_zipped": false, - "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", "source": null, + "is_zipped": false, "is_tar_archive": true, + "md5sum": "3a57c1bb1077176c4587b8a3bf4f8ace", "url": "http://dist.gem5.org/dist/develop/checkpoints/riscv-hello-example-checkpoint.tar", "resource_version": "1.0.0", "gem5_versions": [ @@ -177,7 +177,7 @@ }, { "category": "looppoint-json", - "id": "looppoint-json-restore-resource-region-1", + "id": "looppoint-json-restore-resource-region-1-example", "description": "A looppoint json file resource.", "is_zipped": false, "region_id": "1", diff --git a/tests/pyunit/stdlib/resources/refs/workload-checks.json b/tests/pyunit/stdlib/resources/refs/workload-checks.json index dcb8577619..bf954059c5 100644 --- a/tests/pyunit/stdlib/resources/refs/workload-checks.json +++ b/tests/pyunit/stdlib/resources/refs/workload-checks.json @@ -1,7 +1,7 @@ [ { "category": "kernel", - "id": "x86-linux-kernel-5.2.3", + "id": "x86-linux-kernel-5.2.3-example", "description": "The linux kernel (v5.2.3), compiled to X86.", "architecture": "X86", "is_zipped": false, @@ -15,12 +15,12 @@ }, { "category": "disk-image", - "id": "x86-ubuntu-18.04-img", + "id": "x86-ubuntu-18.04-img-example", "description": "A disk image containing Ubuntu 18.04 for x86..", "architecture": "X86", - "is_zipped": true, - "md5sum": "90e363abf0ddf22eefa2c7c5c9391c49", - "url": "http://dist.gem5.org/dist/develop/images/x86/ubuntu-18-04/x86-ubuntu.img.gz", + "is_zipped": false, + "md5sum": "dbf120338b37153e3334603970cebd8c", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/x86/linux/hello64-static", "source": "src/x86-ubuntu", "root_partition": "1", "resource_version": "1.0.0", @@ -34,8 +34,8 @@ "description": "Description of workload here", "function": "set_kernel_disk_workload", "resources": { - "kernel": "x86-linux-kernel-5.2.3", - "disk-image": "x86-ubuntu-18.04-img" + "kernel": "x86-linux-kernel-5.2.3-example", + "disk-image": "x86-ubuntu-18.04-img-example" }, "additional_params": { "readfile_contents": "echo 'Boot successful'; m5 exit" @@ -47,7 +47,7 @@ }, { "category": "binary", - "id": "x86-hello64-static", + "id": "x86-hello64-static-example", "description": "A 'Hello World!' binary.", "architecture": "X86", "is_zipped": false, From b2fcc558d8a467aa517b62023b976c7f7365d82b Mon Sep 17 00:00:00 2001 From: Mahyar Samani Date: Fri, 14 Jul 2023 07:33:21 -0700 Subject: [PATCH 081/693] stdlib: Deviding range for linear multicore. (#63) This patch changes the way memory ranges are devided when using multiple cores for linear traffic. The current state assigns the same range to multiple linear generators so all the cores start generating the same trace. This patch devides the overall range assigned to the generator ([min_addr:max_addr]) between the cores. Change-Id: I49f69b3d61b590899f8d54ee3be997ad22d7fa9b Co-authored-by: Jason Lowe-Power Co-authored-by: mkjost0 <50555529+mkjost0@users.noreply.github.com> Co-authored-by: Bobby R. Bruce --- .../components/processors/abstract_generator.py | 16 ++++++++++++++++ .../components/processors/complex_generator.py | 8 +++++--- .../components/processors/linear_generator.py | 10 +++++++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/python/gem5/components/processors/abstract_generator.py b/src/python/gem5/components/processors/abstract_generator.py index ff5387dd14..30e8f17970 100644 --- a/src/python/gem5/components/processors/abstract_generator.py +++ b/src/python/gem5/components/processors/abstract_generator.py @@ -35,6 +35,22 @@ from ..boards.abstract_board import AbstractBoard from typing import List +def partition_range( + min_addr: int, max_addr: int, num_partitions: int +) -> List[tuple]: + assert ( + isinstance(min_addr, int) + and isinstance(max_addr, int) + and isinstance(num_partitions, int) + ) + assert ((max_addr - min_addr) % num_partitions) == 0 + chunk_size = int((max_addr - min_addr) / num_partitions) + return [ + (min_addr + chunk_size * i, min_addr + chunk_size * (i + 1)) + for i in range(num_partitions) + ] + + class AbstractGenerator(AbstractProcessor): """The abstract generator It defines the external interface of every generator component. diff --git a/src/python/gem5/components/processors/complex_generator.py b/src/python/gem5/components/processors/complex_generator.py index b113640ae7..81b94f0c14 100644 --- a/src/python/gem5/components/processors/complex_generator.py +++ b/src/python/gem5/components/processors/complex_generator.py @@ -27,6 +27,7 @@ from ...utils.override import overrides from .complex_generator_core import ComplexGeneratorCore from .abstract_generator import AbstractGenerator +from .abstract_generator import partition_range from typing import Iterator, List, Any @@ -76,13 +77,14 @@ class ComplexGenerator(AbstractGenerator): :param data_limit: The amount of data in bytes to read/write by the generator before stopping generation. """ - for core in self.cores: + ranges = partition_range(min_addr, max_addr, len(self.cores)) + for i, core in enumerate(self.cores): core.add_linear( duration, rate, block_size, - min_addr, - max_addr, + ranges[i][0], + ranges[i][1], rd_perc, data_limit, ) diff --git a/src/python/gem5/components/processors/linear_generator.py b/src/python/gem5/components/processors/linear_generator.py index 90fe62e7d6..32587d40c2 100644 --- a/src/python/gem5/components/processors/linear_generator.py +++ b/src/python/gem5/components/processors/linear_generator.py @@ -27,6 +27,7 @@ from ...utils.override import overrides from .linear_generator_core import LinearGeneratorCore from .abstract_generator import AbstractGenerator +from .abstract_generator import partition_range from typing import List @@ -91,17 +92,20 @@ class LinearGenerator(AbstractGenerator): The helper function to create the cores for the generator, it will use the same inputs as the constructor function. """ + + ranges = partition_range(min_addr, max_addr, num_cores) + return [ LinearGeneratorCore( duration=duration, rate=rate, block_size=block_size, - min_addr=min_addr, - max_addr=max_addr, + min_addr=ranges[i][0], + max_addr=ranges[i][1], rd_perc=rd_perc, data_limit=data_limit, ) - for _ in range(num_cores) + for i in range(num_cores) ] @overrides(AbstractGenerator) From 52d9259396af6d56047f1c72c049f8c43b5d8030 Mon Sep 17 00:00:00 2001 From: rogerchang23424 <32214817+rogerchang23424@users.noreply.github.com> Date: Fri, 14 Jul 2023 23:48:43 +0800 Subject: [PATCH 082/693] arch-riscv: Fix clearLoadReservation merge (#81) The previous change (https://gem5-review.googlesource.com/c/public/gem5/+/71818) makes the clearLoadReservation be RISC-V only. Change-Id: I5df1a7fa688489d57fff8da937e3c8addfe4c299 --- src/arch/generic/isa.hh | 1 - src/arch/riscv/isa.hh | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/arch/generic/isa.hh b/src/arch/generic/isa.hh index 58f66fc99b..e9e4d95d7b 100644 --- a/src/arch/generic/isa.hh +++ b/src/arch/generic/isa.hh @@ -70,7 +70,6 @@ class BaseISA : public SimObject public: virtual PCStateBase *newPCState(Addr new_inst_addr=0) const = 0; virtual void clear() {} - virtual void clearLoadReservation(ContextID cid) {} virtual RegVal readMiscRegNoEffect(RegIndex idx) const = 0; virtual RegVal readMiscReg(RegIndex idx) = 0; diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 8b6239cb69..31001c04b4 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -136,6 +136,12 @@ class ISA : public BaseISA RiscvType rvType() const { return rv_type; } + void + clearLoadReservation(ContextID cid) + { + Addr& load_reservation_addr = load_reservation_addrs[cid]; + load_reservation_addr = INVALID_RESERVATION_ADDR; + } }; } // namespace RiscvISA From f8f5dd98bf937f8052654ebccb9cf80355ee5bf2 Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Mon, 17 Jul 2023 10:17:47 -0700 Subject: [PATCH 083/693] mem-ruby: Added WIB State to VIPER TCC Cache (#67) Added WIB (Waiting on Writethrough Ack; Will be Bypassed) state which is transitioned to when a dirty line in the TCC is evicted in a bypassed read. Previously, we were transitioning to invalid. While a WI (Waiting on Writethrough Ack) state exists, transitions from it on WBAck deallocates the TBE, which contains SLC bit information needed to trigger the Bypass event when the read response from the directory comes in. Without this change, WB acknowledgements from the directory in read bypass evicts (with the SLC bit set) were being treated as if they were read responses, leading to an invalid transition panic. Change-Id: I703c3fe8af0366856552bb677810cb1a8f2896de --- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 32 +++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index a59589870d..df3aa1ebca 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -81,6 +81,7 @@ machine(MachineType:TCC, "TCC Cache") I, AccessPermission:Invalid, desc="Invalid"; IV, AccessPermission:Busy, desc="Waiting for Data"; WI, AccessPermission:Busy, desc="Waiting on Writethrough Ack"; + WIB, AccessPermission:Busy, desc="Waiting on Writethrough Ack; Will be Bypassed"; A, AccessPermission:Busy, desc="Invalid waiting on atomici Data"; } @@ -289,7 +290,14 @@ machine(MachineType:TCC, "TCC Cache") is_slc_set := tbe.isSLCSet; } - if (is_slc_set) { + // Whether the SLC bit is set or not, WB acks should invoke the + // WBAck event. For cases where a read response will follow a + // WBAck (A read bypass evict on a dirty line), the line's TLB + // will not be deallocated on WBAck, and the SLC bit will be + // checked when the read response is received. + if (in_msg.Type == CoherenceResponseType:NBSysWBAck) { + trigger(Event:WBAck, in_msg.addr, cache_entry, tbe); + } else if (is_slc_set) { // If the SLC bit is set, the response needs to bypass the cache // and should not be allocated an entry. trigger(Event:Bypass, in_msg.addr, cache_entry, tbe); @@ -300,8 +308,6 @@ machine(MachineType:TCC, "TCC Cache") Addr victim := L2cache.cacheProbe(in_msg.addr); trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); } - } else if (in_msg.Type == CoherenceResponseType:NBSysWBAck) { - trigger(Event:WBAck, in_msg.addr, cache_entry, tbe); } else { error("Unexpected Response Message to Core"); } @@ -699,6 +705,12 @@ machine(MachineType:TCC, "TCC Cache") // woken up st_stallAndWaitRequest; } + transition(WIB, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} { + // by putting the stalled requests in a buffer, we reduce resource contention + // since they won't try again every cycle and will instead only try again once + // woken up + st_stallAndWaitRequest; + } transition(A, {RdBlk, WrVicBlk, WrVicBlkBack}) { //TagArrayRead} { // by putting the stalled requests in a buffer, we reduce resource contention // since they won't try again every cycle and will instead only try again once @@ -751,7 +763,7 @@ machine(MachineType:TCC, "TCC Cache") // Transition to be called when a read request with SLC flag set arrives at // entry in state W. It evicts and invalidates the cache entry before // forwarding the request to global memory - transition(W, RdBypassEvict, I) {TagArrayRead} { + transition(W, RdBypassEvict, WIB) {TagArrayRead} { p_profileMiss; t_allocateTBE; wb_writeBack; @@ -763,7 +775,7 @@ machine(MachineType:TCC, "TCC Cache") // Transition to be called when a read request with SLC flag set arrives at // entry in state M. It evicts and invalidates the cache entry before // forwarding the request to global memory to main memory - transition(M, RdBypassEvict, I) {TagArrayRead} { + transition(M, RdBypassEvict, WIB) {TagArrayRead} { p_profileMiss; t_allocateTBE; wb_writeBack; @@ -785,7 +797,7 @@ machine(MachineType:TCC, "TCC Cache") // Transition to be called when a read request with SLC flag arrives at entry // in transient state. The request stalls until the pending transition is complete. - transition({WI, IV}, RdBypassEvict) { + transition({WI, WIB, IV}, RdBypassEvict) { st_stallAndWaitRequest; } @@ -900,7 +912,7 @@ transition(I, Atomic, A) {TagArrayRead} { i_invL2; } - transition({A, IV, WI}, L2_Repl) { + transition({A, IV, WI, WIB}, L2_Repl) { i_invL2; } @@ -919,7 +931,7 @@ transition(I, Atomic, A) {TagArrayRead} { pp_popProbeQueue; } - transition({A, IV, WI}, PrbInv) { + transition({A, IV, WI, WIB}, PrbInv) { pi_sendProbeResponseInv; pp_popProbeQueue; } @@ -974,4 +986,8 @@ transition(I, Atomic, A) {TagArrayRead} { wada_wakeUpAllDependentsAddr; pr_popResponseQueue; } + + transition(WIB, WBAck,I) { + pr_popResponseQueue; + } } From 442923c414d5d3f3d94d462ed0f9baae83db177f Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Mon, 17 Jul 2023 10:41:51 -0700 Subject: [PATCH 084/693] Add feature to output citations automatically based on configuration (#90) This change adds a new file to m5out which is citations.bib. This file will contain the citations to the papers which describe the aspects of the gem5 simulator that the simulation uses. In other words, each simulation configuration could generate a different bib file referencing different works. Each SimObject can now have a set of citations associated with it. After the system is built (in `instantiate`), the citations.bib file is created by parsing all SimObjects that have been instantiated and taking the union of their associated citations. This commit is not meant to add all citations, but to act as an example for others to add more citations to gem5. Change-Id: Icd5c46fd9ee44adbeec1fea162657f5716f7e5ef Signed-off-by: Jason Lowe-Power --- src/gpu-compute/GPU.py | 33 ++++ src/mem/DRAMSim2.py | 21 ++ src/mem/DRAMSys.py | 29 +++ src/mem/DRAMsim3.py | 23 +++ src/mem/MemCtrl.py | 22 +++ src/mem/ruby/network/garnet/GarnetNetwork.py | 38 ++++ src/python/SConscript | 1 + src/python/m5/SimObject.py | 4 + src/python/m5/citations.py | 191 +++++++++++++++++++ src/python/m5/simulate.py | 3 + 10 files changed, 365 insertions(+) create mode 100644 src/python/m5/citations.py diff --git a/src/gpu-compute/GPU.py b/src/gpu-compute/GPU.py index c64a6b791d..d2b9e98362 100644 --- a/src/gpu-compute/GPU.py +++ b/src/gpu-compute/GPU.py @@ -27,6 +27,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.citations import add_citation from m5.defines import buildEnv from m5.params import * from m5.proxy import * @@ -356,3 +357,35 @@ class StorageClassType(Enum): "SC_ARG", "SC_NONE", ] + + +add_citation( + ComputeUnit, + """@inproceedings{Gutierrez:2018:amdgpu, + author = {Anthony Gutierrez and + Bradford M. Beckmann and + Alexandru Dutu and + Joseph Gross and + Michael LeBeane and + John Kalamatianos and + Onur Kayiran and + Matthew Poremba and + Brandon Potter and + Sooraj Puthoor and + Matthew D. Sinclair and + Mark Wyse and + Jieming Yin and + Xianwei Zhang and + Akshay Jain and + Timothy G. Rogers}, + title = {Lost in Abstraction: Pitfalls of Analyzing GPUs at the Intermediate + Language Level}, + booktitle = {{IEEE} International Symposium on High Performance Computer Architecture, + {HPCA} 2018, Vienna, Austria, February 24-28, 2018}, + pages = {608--619}, + publisher = {{IEEE} Computer Society}, + year = {2018}, + url = {https://doi.org/10.1109/HPCA.2018.00058}, + doi = {10.1109/HPCA.2018.00058} +}""", +) diff --git a/src/mem/DRAMSim2.py b/src/mem/DRAMSim2.py index 364a0d794b..14c85312fe 100644 --- a/src/mem/DRAMSim2.py +++ b/src/mem/DRAMSim2.py @@ -33,6 +33,8 @@ # (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 citations import add_citation + from m5.params import * from m5.objects.AbstractMemory import * @@ -56,3 +58,22 @@ class DRAMSim2(AbstractMemory): ) traceFile = Param.String("", "Output file for trace generation") enableDebug = Param.Bool(False, "Enable DRAMSim2 debug output") + + +add_citation( + DRAMSim2, + """@article{Rosenfeld:2011:dramsim2, + author = {Paul Rosenfeld and + Elliott Cooper{-}Balis and + Bruce L. Jacob}, + title = {DRAMSim2: {A} Cycle Accurate Memory System Simulator}, + journal = {{IEEE} Compututer Architecture Letters}, + volume = {10}, + number = {1}, + pages = {16--19}, + year = {2011}, + url = {https://doi.org/10.1109/L-CA.2011.4}, + doi = {10.1109/L-CA.2011.4} +} +""", +) diff --git a/src/mem/DRAMSys.py b/src/mem/DRAMSys.py index c7d69a0ae4..9f84dbc1de 100644 --- a/src/mem/DRAMSys.py +++ b/src/mem/DRAMSys.py @@ -24,6 +24,8 @@ # (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.citations import add_citation + from m5.SimObject import * from m5.params import * from m5.proxy import * @@ -41,3 +43,30 @@ class DRAMSys(AbstractMemory): configuration = Param.String("Path to the DRAMSys configuration") resource_directory = Param.String("Path to the DRAMSys resource directory") recordable = Param.Bool(True, "Whether DRAMSys should record a trace file") + + +add_citation( + DRAMSys, + """@inproceedings{Steiner:2020:dramsys4, + author = {Lukas Steiner and + Matthias Jung and + Felipe S. Prado and + Kirill Bykov and + Norbert Wehn}, + editor = {Alex Orailoglu and + Matthias Jung and + Marc Reichenbach}, + title = {DRAMSys4.0: {A} Fast and Cycle-Accurate SystemC/TLM-Based {DRAM} Simulator}, + booktitle = {Embedded Computer Systems: Architectures, Modeling, and Simulation + - 20th International Conference, {SAMOS} 2020, Samos, Greece, July + 5-9, 2020, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = {12471}, + pages = {110--126}, + publisher = {Springer}, + year = {2020}, + url = {https://doi.org/10.1007/978-3-030-60939-9\_8}, + doi = {10.1007/978-3-030-60939-9\_8} +} +""", +) diff --git a/src/mem/DRAMsim3.py b/src/mem/DRAMsim3.py index 40f61608d8..0ca0077a85 100644 --- a/src/mem/DRAMsim3.py +++ b/src/mem/DRAMsim3.py @@ -33,6 +33,8 @@ # (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.citations import add_citation + from m5.params import * from m5.objects.AbstractMemory import * @@ -54,3 +56,24 @@ class DRAMsim3(AbstractMemory): filePath = Param.String( "ext/dramsim3/DRAMsim3/", "Directory to prepend to file names" ) + + +add_citation( + DRAMsim3, + """@article{Li:2020:dramsim3, + author = {Shang Li and + Zhiyuan Yang and + Dhiraj Reddy and + Ankur Srivastava and + Bruce L. Jacob}, + title = {DRAMsim3: {A} Cycle-Accurate, Thermal-Capable {DRAM} Simulator}, + journal = {{IEEE} Compututer Architecture Letters}, + volume = {19}, + number = {2}, + pages = {110--113}, + year = {2020}, + url = {https://doi.org/10.1109/LCA.2020.2973991}, + doi = {10.1109/LCA.2020.2973991} +} +""", +) diff --git a/src/mem/MemCtrl.py b/src/mem/MemCtrl.py index 549616ccba..62e4d97b26 100644 --- a/src/mem/MemCtrl.py +++ b/src/mem/MemCtrl.py @@ -41,6 +41,7 @@ from m5.params import * from m5.proxy import * from m5.objects.QoSMemCtrl import * +from m5.citations import add_citation # Enum for memory scheduling algorithms, currently First-Come # First-Served and a First-Row Hit then First-Come First-Served @@ -99,3 +100,24 @@ class MemCtrl(QoSMemCtrl): command_window = Param.Latency("10ns", "Static backend latency") disable_sanity_check = Param.Bool(False, "Disable port resp Q size check") + + +add_citation( + MemCtrl, + """@inproceedings{Hansson:2014:dram-controller, + author = {Andreas Hansson and + Neha Agarwal and + Aasheesh Kolli and + Thomas F. Wenisch and + Aniruddha N. Udipi}, + title = {Simulating {DRAM} controllers for future system architecture exploration}, + booktitle = {2014 {IEEE} International Symposium on Performance Analysis of Systems + and Software, {ISPASS} 2014, Monterey, CA, USA, March 23-25, 2014}, + pages = {201--210}, + publisher = {{IEEE} Computer Society}, + year = {2014}, + url = {https://doi.org/10.1109/ISPASS.2014.6844484}, + doi = {10.1109/ISPASS.2014.6844484} +} +""", +) diff --git a/src/mem/ruby/network/garnet/GarnetNetwork.py b/src/mem/ruby/network/garnet/GarnetNetwork.py index 128118309c..bf5a0bad33 100644 --- a/src/mem/ruby/network/garnet/GarnetNetwork.py +++ b/src/mem/ruby/network/garnet/GarnetNetwork.py @@ -28,6 +28,7 @@ # Author: Tushar Krishna # +from m5.citations import add_citation from m5.params import * from m5.proxy import * from m5.objects.Network import RubyNetwork @@ -83,3 +84,40 @@ class GarnetRouter(BasicRouter): width = Param.UInt32( Parent.ni_flit_size, "bit width supported by the router" ) + + +add_citation( + GarnetNetwork, + """@inproceedings{Bharadwaj:2020:kite, + author = {Srikant Bharadwaj and + Jieming Yin and + Bradford M. Beckmann and + Tushar Krishna}, + title = {Kite: {A} Family of Heterogeneous Interposer Topologies Enabled via + Accurate Interconnect Modeling}, + booktitle = {57th {ACM/IEEE} Design Automation Conference, {DAC} 2020, San Francisco, + CA, USA, July 20-24, 2020}, + pages = {1--6}, + publisher = {{IEEE}}, + year = {2020}, + url = {https://doi.org/10.1109/DAC18072.2020.9218539}, + doi = {10.1109/DAC18072.2020.9218539} +} +@inproceedings{Agarwal:2009:garnet, + author = {Niket Agarwal and + Tushar Krishna and + Li{-}Shiuan Peh and + Niraj K. Jha}, + title = {{GARNET:} {A} detailed on-chip network model inside a full-system + simulator}, + booktitle = {{IEEE} International Symposium on Performance Analysis of Systems + and Software, {ISPASS} 2009, April 26-28, 2009, Boston, Massachusetts, + USA, Proceedings}, + pages = {33--42}, + publisher = {{IEEE} Computer Society}, + year = {2009}, + url = {https://doi.org/10.1109/ISPASS.2009.4919636}, + doi = {10.1109/ISPASS.2009.4919636} +} +""", +) diff --git a/src/python/SConscript b/src/python/SConscript index ea9d3d4021..eaaea203f0 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -311,6 +311,7 @@ PySource('gem5.utils.multiprocessing', PySource('', 'importer.py') PySource('m5', 'm5/__init__.py') PySource('m5', 'm5/SimObject.py') +PySource('m5', 'm5/citations.py') PySource('m5', 'm5/core.py') PySource('m5', 'm5/debug.py') PySource('m5', 'm5/event.py') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 08105d8833..f2c1b30def 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -47,6 +47,8 @@ import m5 from m5.util import * from m5.util.pybind import * +from m5.citations import gem5_citations + # Use the pyfdt and not the helper class, because the fdthelper # relies on the SimObject definition from m5.ext.pyfdt import pyfdt @@ -215,6 +217,8 @@ class MetaSimObject(type): cls._instantiated = False # really instantiated, cloned, or subclassed cls._init_called = False # Used to check if __init__ overridden + cls._citations = gem5_citations # Default to gem5's citations + # We don't support multiple inheritance of sim objects. If you want # to, you must fix multidict to deal with it properly. Non sim-objects # are ok, though diff --git a/src/python/m5/citations.py b/src/python/m5/citations.py new file mode 100644 index 0000000000..1ac8e08145 --- /dev/null +++ b/src/python/m5/citations.py @@ -0,0 +1,191 @@ +# Copyright (c) 2023 The Regents of The University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from pathlib import Path +from typing import Type + +import m5.options + + +def add_citation(sim_obj_cls: Type["SimObject"], citation: str): + """Add a citation to a SimObject class. + + :param sim_obj_cls: The SimObject class to add the citation to. + :param citation: The citation to add. Should be bibtex compatible + entry or entries + + This function will encode the citation into the SimObject class and it + will be included in the citations in the output directory when the + SimObject is used. If you have multiple citations, then you should include + one multiline string with all of the citations. + """ + + sim_obj_cls._citations += citation + + +def gather_citations(root: "SimObject"): + """Based on the root SimObject, walk the object hierarchy and gather all + of the citations together and then print them to citations.bib in the + output directory. + """ + + citations = {} + for obj in root.descendants(): + loc = 0 + while loc >= 0: + key, cite, loc = _get_next_key_entry(obj._citations, loc) + # If a key repeats, then just overwrite it + citations[key] = cite + + with open(Path(m5.options.outdir) / "citations.bib", "w") as output: + output.writelines(citations.values()) + + +def _get_next_key_entry(citations: str, loc: int = 0): + """Return the key, the citation, and the end of the citation location""" + + start = citations.find("@", loc) + key_start = citations.find("{", start) + key_end = citations.find(",", key_start) + end = citations.find("@", start + 1) + if end == -1: + end = len(citations) + next = -1 + else: + next = end + + return citations[key_start:key_end], citations[start:end], next + + +gem5_citations = """@article{Binkert:2011:gem5, + author = {Nathan L. Binkert and + Bradford M. Beckmann and + Gabriel Black and + Steven K. Reinhardt and + Ali G. Saidi and + Arkaprava Basu and + Joel Hestness and + Derek Hower and + Tushar Krishna and + Somayeh Sardashti and + Rathijit Sen and + Korey Sewell and + Muhammad Shoaib Bin Altaf and + Nilay Vaish and + Mark D. Hill and + David A. Wood}, + title = {The gem5 simulator}, + journal = {{SIGARCH} Comput. Archit. News}, + volume = {39}, + number = {2}, + pages = {1--7}, + year = {2011}, + url = {https://doi.org/10.1145/2024716.2024718}, + doi = {10.1145/2024716.2024718} +} +@article{Lowe-Power:2020:gem5-20, + author = {Jason Lowe{-}Power and + Abdul Mutaal Ahmad and + Ayaz Akram and + Mohammad Alian and + Rico Amslinger and + Matteo Andreozzi and + Adri{\`{a}} Armejach and + Nils Asmussen and + Srikant Bharadwaj and + Gabe Black and + Gedare Bloom and + Bobby R. Bruce and + Daniel Rodrigues Carvalho and + Jer{\'{o}}nimo Castrill{\'{o}}n and + Lizhong Chen and + Nicolas Derumigny and + Stephan Diestelhorst and + Wendy Elsasser and + Marjan Fariborz and + Amin Farmahini Farahani and + Pouya Fotouhi and + Ryan Gambord and + Jayneel Gandhi and + Dibakar Gope and + Thomas Grass and + Bagus Hanindhito and + Andreas Hansson and + Swapnil Haria and + Austin Harris and + Timothy Hayes and + Adrian Herrera and + Matthew Horsnell and + Syed Ali Raza Jafri and + Radhika Jagtap and + Hanhwi Jang and + Reiley Jeyapaul and + Timothy M. Jones and + Matthias Jung and + Subash Kannoth and + Hamidreza Khaleghzadeh and + Yuetsu Kodama and + Tushar Krishna and + Tommaso Marinelli and + Christian Menard and + Andrea Mondelli and + Tiago M{\"{u}}ck and + Omar Naji and + Krishnendra Nathella and + Hoa Nguyen and + Nikos Nikoleris and + Lena E. Olson and + Marc S. Orr and + Binh Pham and + Pablo Prieto and + Trivikram Reddy and + Alec Roelke and + Mahyar Samani and + Andreas Sandberg and + Javier Setoain and + Boris Shingarov and + Matthew D. Sinclair and + Tuan Ta and + Rahul Thakur and + Giacomo Travaglini and + Michael Upton and + Nilay Vaish and + Ilias Vougioukas and + Zhengrong Wang and + Norbert Wehn and + Christian Weis and + David A. Wood and + Hongil Yoon and + {\'{E}}der F. Zulian}, + title = {The gem5 Simulator: Version 20.0+}, + journal = {CoRR}, + volume = {abs/2007.03152}, + year = {2020}, + url = {https://arxiv.org/abs/2007.03152}, + eprinttype = {arXiv}, + eprint = {2007.03152} +} +""" diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 587bfa0202..70ed11a9b6 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -51,6 +51,7 @@ from . import SimObject from . import ticks from . import objects from . import params +from .citations import gather_citations from m5.util.dot_writer import do_dot, do_dvfs_dot from m5.util.dot_writer_ruby import do_ruby_dot @@ -164,6 +165,8 @@ def instantiate(ckpt_dir=None): # a checkpoint, If so, this call will shift them to be at a valid time. updateStatEvents() + gather_citations(root) + need_startup = True From 6062214d873c7db0deaf2e289c0afbbdb5d58175 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 17 Jul 2023 10:42:28 -0700 Subject: [PATCH 085/693] util: Add "Improving stability" sec to github-vagrant-runner (#87) Change-Id: I9812a21523b5b29bd7f570df4f1e90dbeabea085 --- util/github-runners-vagrant/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/github-runners-vagrant/README.md b/util/github-runners-vagrant/README.md index 86b9e1da87..7d0f116260 100644 --- a/util/github-runners-vagrant/README.md +++ b/util/github-runners-vagrant/README.md @@ -97,6 +97,20 @@ If you wish to destroy all the VMs you can run: **Note:** This script assumes "VAGRANT_HOME" is set to the CWD. +## Improving stability + +Occasionally GitHub runner services, or VMs, go down. This is often silent and +usually only noticable from going to the GitHub repo page "settings" -> "actions" -> "runners" and observing the status. +When the VMs or the service stop working they need restarted. +To do so you can sun `./vm_manager.sh`. This will cycle through the VMs and execute a `vagrant up` command. +This does one of three things depending on the state of the VM: + +1. If the VM is down this will bring the VM back online and start the GitHub runner service. +2. If the VM is up but the GitHub runner service is down, this will start the GitHub runner service. +3. If the VM is up and the GitHub runner service is running (i.e., everything is fine) then this does nothing. + +Given there is no harm in running this command frequently, we recommend setting up a cron job to automatically execute `./vm_manager.sh` every few hours. + ## Troubleshooting ### The default libvirt disk image storage pool is on the wrong drive From efa1d87addd9caff066a12cc0472164f1c5dd7f5 Mon Sep 17 00:00:00 2001 From: KaiBatley <68886332+KaiBatley@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:42:40 -0500 Subject: [PATCH 086/693] configs: fix GPU's default number of HW barrier/CU (#92) AMD GCN3 and Vega GPUs assume a max of 16 WG/CU. Any GPU WG with more than 1 WF requires a hardware barrier to allow WFs in the WG to synchronize locally. However, currently the default gem5 GPU configuration assumes only 4 barriers per CU, which artificially prevents applications with > 4 WG/CU that could run simultaneously from running simultaneously. This fix resolves this by updating the default number of hardware barriers per CU to 16, which mimics the support described in slide 39 here: https://www.olcf.ornl.gov/wp-content/uploads/2019/10/ ORNL_Application_Readiness_Workshop-AMD_GPU_Basics.pdf Change-Id: Ib7636a13359d998e676c1790f436a83ce88cbfc0 --- src/gpu-compute/GPU.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpu-compute/GPU.py b/src/gpu-compute/GPU.py index d2b9e98362..1b6c6a7494 100644 --- a/src/gpu-compute/GPU.py +++ b/src/gpu-compute/GPU.py @@ -131,7 +131,7 @@ class ComputeUnit(ClockedObject): # Wavefront size is 64. This is configurable, however changing # this value to anything other than 64 will likely cause errors. wf_size = Param.Int(64, "Wavefront size (in work items)") - num_barrier_slots = Param.Int(4, "Number of barrier slots in a CU") + num_barrier_slots = Param.Int(16, "Number of barrier slots in a CU") num_SIMDs = Param.Int(4, "number of SIMD units per CU") num_scalar_cores = Param.Int(1, "number of Scalar cores per CU") num_scalar_mem_pipes = Param.Int( From 162f2e2dba069ad3df7d488136f07536d54b7795 Mon Sep 17 00:00:00 2001 From: wmin0 Date: Tue, 18 Jul 2023 06:29:05 +0800 Subject: [PATCH 087/693] scons: Use pkgconfig to get correct Protobuf dependency (#68) Latest protobuf library depends on abseil libraries. We should rely on pkgconfig to give us correct dependency. We still keep the old check as fallback. Change-Id: I529ea1f61e5bbc16b2520ab1badff3d8264f1c33 --- src/proto/SConsopts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/proto/SConsopts b/src/proto/SConsopts index 6b5b25d0ce..fab29bc235 100644 --- a/src/proto/SConsopts +++ b/src/proto/SConsopts @@ -50,14 +50,6 @@ with gem5_scons.Configure(main) as conf: warning('protoc version', min_protoc_version, 'or newer required.\n' 'Installed version:', protoc_version[1]) else: - # Attempt to determine the appropriate include path and - # library path using pkg-config, that means we also need to - # check for pkg-config. Note that it is possible to use - # protobuf without the involvement of pkg-config. Later on we - # check go a library config check and at that point the test - # will fail if libprotobuf cannot be found. - if conf.env['HAVE_PKG_CONFIG']: - conf.CheckPkgConfig('protobuf', '--cflags', '--libs-only-L') conf.env['HAVE_PROTOC'] = True # If we have the protobuf compiler, also make sure we have the @@ -65,9 +57,11 @@ with gem5_scons.Configure(main) as conf: # automatically added to the LIBS environment variable. After # this, we can use the HAVE_PROTOBUF flag to determine if we have # got both protoc and libprotobuf available. - conf.env['CONF']['HAVE_PROTOBUF'] = conf.env['HAVE_PROTOC'] and \ + conf.env['CONF']['HAVE_PROTOBUF'] = conf.env['HAVE_PROTOC'] and ( + (conf.env['HAVE_PKG_CONFIG'] and + conf.CheckPkgConfig('protobuf', '--cflags', '--libs')) or conf.CheckLibWithHeader('protobuf', 'google/protobuf/message.h', - 'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;') + 'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;')) # If we have the compiler but not the library, print another warning. if main['HAVE_PROTOC'] and not main['CONF']['HAVE_PROTOBUF']: From f80015ea1827148fc539ebd98cc39d187ca161b4 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 17 Jul 2023 15:30:35 -0700 Subject: [PATCH 088/693] misc: Update README/README.md (#71) * misc: Update README to README.md This change converts the text-based README to markdown. This works better with modern source-control systems, most notably, GitHub. The README.md has been broken down into sections to better organize the document. This section now included expanded information on Reporting bugs and Requesting Features. Due to renaming 'README' to 'README.md', this code was generating the following for "info.py": ``` README.md = "" ``` As '.' is used to access member variables/methods in python. To fix this "infopy.oy" now replaces "." with "_". As such the generated in in "info.py" is now: ``` README_MD = "" This puts GitHub Discussions and GitHub Issues towards the top of the list. This is to incentivize their usage. Change-Id: I18018ba23493f43861544497f23ec59f1e8debe1 --------- Co-authored-by: Jason Lowe-Power --- README | 43 --------------------- README.md | 90 +++++++++++++++++++++++++++++++++++++++++++ build_tools/infopy.py | 6 ++- src/SConscript | 2 +- 4 files changed, 96 insertions(+), 45 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index 5803372a98..0000000000 --- a/README +++ /dev/null @@ -1,43 +0,0 @@ -This is the gem5 simulator. - -The main website can be found at http://www.gem5.org - -A good starting point is http://www.gem5.org/about, and for -more information about building the simulator and getting started -please see http://www.gem5.org/documentation and -http://www.gem5.org/documentation/learning_gem5/introduction. - -To build gem5, you will need the following software: g++ or clang, -Python (gem5 links in the Python interpreter), SCons, zlib, m4, and lastly -protobuf if you want trace capture and playback support. Please see -http://www.gem5.org/documentation/general_docs/building for more details -concerning the minimum versions of these tools. - -Once you have all dependencies resolved, type 'scons -build//gem5.opt' where CONFIG is one of the options in build_opts like -ARM, NULL, MIPS, POWER, SPARC, X86, Garnet_standalone, etc. This will build an -optimized version of the gem5 binary (gem5.opt) with the the specified -configuration. See http://www.gem5.org/documentation/general_docs/building for -more details and options. - -The main source tree includes these subdirectories: - - build_opts: pre-made default configurations for gem5 - - build_tools: tools used internally by gem5's build process. - - configs: example simulation configuration scripts - - ext: less-common external packages needed to build gem5 - - include: include files for use in other programs - - site_scons: modular components of the build system - - src: source code of the gem5 simulator - - system: source for some optional system software for simulated systems - - tests: regression tests - - util: useful utility programs and files - -To run full-system simulations, you may need compiled system firmware, kernel -binaries and one or more disk images, depending on gem5's configuration and -what type of workload you're trying to run. Many of those resources can be -downloaded from http://resources.gem5.org, and/or from the git repository here: -https://gem5.googlesource.com/public/gem5-resources/ - -If you have questions, please send mail to gem5-users@gem5.org - -Enjoy using gem5 and please share your modifications and extensions. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..bd6db2fbd7 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +# The gem5 Simulator + +This is the repository for the gem5 simulator. It contains the full source code +for the simulator and all tests and regressions. + +The gem5 simulator is a modular platform for computer-system architecture +research, encompassing system-level architecture as well as processor +microarchitecture. It is primarily used to evaluate new hardware designs, +system software changes, and compile-time and run-time system optimizations. + +The main website can be found at . + +## Getting started + +A good starting point is , and for +more information about building the simulator and getting started +please see and +. + +## Building gem5 + +To build gem5, you will need the following software: g++ or clang, +Python (gem5 links in the Python interpreter), SCons, zlib, m4, and lastly +protobuf if you want trace capture and playback support. Please see + for more details +concerning the minimum versions of these tools. + +Once you have all dependencies resolved, execute +`scons build/ALL/gem5.opt` to build an optimized version of the gem5 binary +(`gem5.opt`) containing all gem5 ISAs. If you only wish to compile gem5 to +include a single ISA, you can replace `ALL` with the name of the ISA. Valid +options include `ARM`, `NULL`, `MIPS`, `POWER`, `SPARC`, and `X86` The complete +list of options can be found in the build_opts directory. + +See https://www.gem5.org/documentation/general_docs/building for more +information on building gem5. + +## The Source Tree + +The main source tree includes these subdirectories: + +* build_opts: pre-made default configurations for gem5 +* build_tools: tools used internally by gem5's build process. +* configs: example simulation configuration scripts +* ext: less-common external packages needed to build gem5 +* include: include files for use in other programs +* site_scons: modular components of the build system +* src: source code of the gem5 simulator. The C++ source, Python wrappers, and Python standard library are found in this directory. +* system: source for some optional system software for simulated systems +* tests: regression tests +* util: useful utility programs and files + +## gem5 Resources + +To run full-system simulations, you may need compiled system firmware, kernel +binaries and one or more disk images, depending on gem5's configuration and +what type of workload you're trying to run. Many of these resources can be +obtained from . + +More information on gem5 Resources can be found at +. + +## Getting Help, Reporting bugs, and Requesting Features + +We provide a variety of channels for users and developers to get help, report +bugs, requests features, or engage in community discussions. Below +are a few of the most common we recommend using. + +* **GitHub Discussions**: A GitHub Discussions page. This can be used to start +discussions or ask questions. Available at +. +* **GitHub Issues**: A GitHub Issues page for reporting bugs or requesting +features. Available at . +* **Jira Issue Tracker**: A Jira Issue Tracker for reporting bugs or requesting +features. Available at . +* **Slack**: A Slack server with a variety of channels for the gem5 community +to engage in a variety of discussions. Please visit + to join. +* **gem5-users@gem5.org**: A mailing list for users of gem5 to ask questions +or start discussions. To join the mailing list please visit +. +* **gem5-dev@gem5.org**: A mailing list for developers of gem5 to ask questions +or start discussions. To join the mailing list please visit +. + +## Contributing to gem5 + +We hope you enjoy using gem5. When appropriate we advise charing your +contributions to the project. can help you +get started. Additional information can be found in the CONTRIBUTING.md file. diff --git a/build_tools/infopy.py b/build_tools/infopy.py index 4f15f24f98..8a4e013388 100644 --- a/build_tools/infopy.py +++ b/build_tools/infopy.py @@ -51,7 +51,11 @@ args = parser.parse_args() code = code_formatter() for source in args.files: - src = os.path.basename(source) + # We replace the "."s in the file name with underscores to make + # it a valid python identifier. With the dot, "README.md" would generate + # `README.md = "..."` which is not valid as `md` is not a property of + # `README`. + src = os.path.basename(source).replace(".", "_") with open(source, "r") as f: data = "".join(f) code("${src} = ${{repr(data)}}") diff --git a/src/SConscript b/src/SConscript index f54a881f72..481f6522e5 100644 --- a/src/SConscript +++ b/src/SConscript @@ -615,7 +615,7 @@ PySource('m5', 'python/m5/defines.py') # Generate a file that wraps the basic top level files gem5py_env.Command('python/m5/info.py', - [ File('#/COPYING'), File('#/LICENSE'), File('#/README'), + [ File('#/COPYING'), File('#/LICENSE'), File('#/README.md'), "${GEM5PY}", "${INFOPY_PY}" ], MakeAction('"${GEM5PY}" "${INFOPY_PY}" "${TARGET}" ' '${SOURCES[:-2]}', From 6fb72d84e171de3cd575b442f392ebdf4c4e08fc Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Tue, 18 Jul 2023 00:32:04 +0200 Subject: [PATCH 089/693] base: Find lsb set generalization and optimization (#76) * base: Generalize findLsbSet to std::bitset * base: Split builtin and fallback implementations of findLsbSet * base: Add more unit testing for findLsbSet Change-Id: Id75dfb7d306c9a8228fa893798b1b867137465a9 --------- Co-authored-by: Gabriel Busnot --- src/base/bitfield.hh | 99 +++++++++++++++++++++++++++++---------- src/base/bitfield.test.cc | 18 +++++++ 2 files changed, 91 insertions(+), 26 deletions(-) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index eecea02981..8d3721b08a 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -41,9 +41,12 @@ #ifndef __BASE_BITFIELD_HH__ #define __BASE_BITFIELD_HH__ +#include #include +#include #include #include +#include #include namespace gem5 @@ -303,40 +306,84 @@ findMsbSet(uint64_t val) return msb; } +namespace { +template +constexpr bool +hasBuiltinCtz() { +#if defined(__has_builtin) && __has_builtin(__builtin_ctz) + return sizeof(unsigned long long) >= sizeof(T); +#else + return false; +#endif +} + +int +findLsbSetFallback(uint64_t val) { + // Create a mask with val's trailing zeros flipped to 1, lsb set flipped to + // 0 and the rest unchanged. This effectively is equivalent to doing -1. + // e.g.: 0101000 - 1 = 0100111 + // ^^^^ ^^^^ + auto mask = val - 1; + // This will create a mask of ones from lsb set to last bit + // e.g.: 0101000 ^ 0100111 = 00001111 + // ^^^^ ^^^^ + auto masked = val ^ mask; + // Shift that mask to that there is 1s only where there was 0s after the + // lsb set before + // e.g.: 00001111 >> 1 = 00000111 (val is 0101000 in the example) + auto ones = masked >> 1; + // Number of bit set is the lsb set. This operation should be optimized by + // the compiler without unsing intrinsics. This operation will become + // constexpr starting from C++23. In the meantime, that fallback should not + // be used much in favor of the constexpr intrinsic + return std::bitset(ones).count(); +} +} + /** * Returns the bit position of the LSB that is set in the input + * That function will either use a builting that exploit a "count trailing + * zeros" instruction or use a bit-fidling algorithm explained bellow. * * @ingroup api_bitfield */ constexpr int -findLsbSet(uint64_t val) +findLsbSet(uint64_t val) { + if (val == 0) return 64; + + if constexpr (hasBuiltinCtz()) { + return __builtin_ctzll(val); + } else { + return findLsbSetFallback(val); + } +} + + +template +constexpr int +findLsbSet(std::bitset bs) { - int lsb = 0; - if (!val) - return sizeof(val) * 8; - if (!bits(val, 31, 0)) { - lsb += 32; - val >>= 32; + if constexpr (N <= 64) { + return findLsbSet(bs.to_ullong()); + } else { + if (bs.none()) return N; + // Mask of ones + constexpr std::bitset mask(std::numeric_limits::max()); + // Is the lsb set in the rightmost 64 bits ? + auto nextQword{bs & mask}; + int i{0}; + while (nextQword.none()) { + // If no, shift by 64 bits and repeat + i += 64; + bs >>= 64; + nextQword = bs & mask; + } + // If yes, account for the bumber of 64-bit shifts and add the + // remaining using the uint64_t implementation. Store in intermediate + // variable to ensure valid conversion from ullong to uint64_t. + uint64_t remaining{nextQword.to_ullong()}; + return i + findLsbSet(remaining); } - if (!bits(val, 15, 0)) { - lsb += 16; - val >>= 16; - } - if (!bits(val, 7, 0)) { - lsb += 8; - val >>= 8; - } - if (!bits(val, 3, 0)) { - lsb += 4; - val >>= 4; - } - if (!bits(val, 1, 0)) { - lsb += 2; - val >>= 2; - } - if (!bits(val, 0, 0)) - lsb += 1; - return lsb; } /** diff --git a/src/base/bitfield.test.cc b/src/base/bitfield.test.cc index 1711ea68bf..94cff8e155 100644 --- a/src/base/bitfield.test.cc +++ b/src/base/bitfield.test.cc @@ -316,6 +316,7 @@ TEST(BitfieldTest, FindLsb) { uint64_t val = (1ULL << 63) + (1 << 1); EXPECT_EQ(1, findLsbSet(val)); + EXPECT_EQ(1, findLsbSetFallback(val)); } TEST(BitfieldTest, FindLsbZero) @@ -323,6 +324,23 @@ TEST(BitfieldTest, FindLsbZero) EXPECT_EQ(64, findLsbSet(0)); } +TEST(BitfieldTest, FindLsbGeneralized) +{ + static constexpr size_t N{1000}; + std::bitset bs{0}; + EXPECT_EQ(findLsbSet(bs), N); + for (size_t i{0}; i < N ; ++i) { + bs = std::bitset{1} << i; + ASSERT_EQ(findLsbSet(bs), i); + } + + const auto leadingOne = std::bitset{1} << (N-1); + for (size_t i{0}; i < N ; ++i) { + bs = leadingOne | (std::bitset{1} << i); + ASSERT_EQ(findLsbSet(bs), i); + } +} + /* * The following tests "popCount(X)". popCount counts the number of bits set to * one. From 424350f446fe5965ca44de68acb4b8cd3441fe6a Mon Sep 17 00:00:00 2001 From: Melissa Jost <50555529+mkjost0@users.noreply.github.com> Date: Tue, 18 Jul 2023 10:27:32 -0700 Subject: [PATCH 090/693] misc: Update CI test workflow (#88) * misc: Update CI test workflow This updates our CI tests to clean the runners after every workflow, to make sure no hanging files cause problems for future tests Change-Id: Iff6a702bbc2e86a31e4c18ef9764a3cfd3af2f7d * misc: Update scheduled workflows to clean runners This updates our scheduled tests to clean up any remaining files after running tests to avoid anything hanging for future runs. Change-Id: Icfdd5a0559337ad0e62d108a47f4e5a12e0db677 * misc: Fix spacing in workflow files Some commands were incorrectly spaced Change-Id: Id340dc77bfb5c5d579b5f1e5b3ddeabea4a35ea8 --- .github/workflows/ci-tests.yaml | 5 + .github/workflows/daily-tests.yaml | 139 +++++++++++++++++++++------- .github/workflows/weekly-tests.yaml | 20 ++++ 3 files changed, 132 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index c184e482f1..5e11903a0f 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -102,4 +102,9 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 5fab058b79..a7d92a2ada 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -290,6 +290,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-fs: @@ -330,6 +335,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-gem5_library_example_tests: @@ -370,6 +380,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-gpu: @@ -405,6 +420,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-insttest_se: @@ -440,36 +460,46 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." # kvm tests don't work on github actions - # testlib-long-kvm-fork-tests: - # runs-on: [self-hosted, linux, x64, run] - # container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - # needs: build-gem5 - # timeout-minutes: 1440 # 24 hours - # steps: - # - uses: actions/checkout@v3 - # with: - # # Scheduled workflows run on the default branch by default. We - # # therefore need to explicitly checkout the develop branch. - # ref: develop - # - uses: actions/download-artifact@v3 - # with: - # name: ${{ env.artifact-name }} - # path: build/ALL/gem5.opt - # - run: chmod u+x build/ALL/gem5.opt - # - name: long kvm-fork-tests - # working-directory: ${{ github.workspace }}/tests - # run: ./main.py run gem5/kvm-fork-tests --length=long --skip-build -vv -t $(nproc) - # - uses: actions/upload-artifact@v3 - # env: - # MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - # with: - # name: ${{ env.MY_STEP_VAR }} - # path: tests/testing-results - # retention-days: 7 - # - run: echo "This job's status is ${{ job.status }}." +# testlib-long-kvm-fork-tests: +# runs-on: [self-hosted, linux, x64, run] +# container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest +# needs: build-gem5 +# timeout-minutes: 1440 # 24 hours +# steps: +# - uses: actions/checkout@v3 +# with: +# # Scheduled workflows run on the default branch by default. We +# # therefore need to explicitly checkout the develop branch. +# ref: develop +# - uses: actions/download-artifact@v3 +# with: +# name: ${{ env.artifact-name }} +# path: build/ALL/gem5.opt +# - run: chmod u+x build/ALL/gem5.opt +# - name: long kvm-fork-tests +# working-directory: ${{ github.workspace }}/tests +# run: ./main.py run gem5/kvm-fork-tests --length=long --skip-build -vv -t $(nproc) +# - uses: actions/upload-artifact@v3 +# env: +# MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} +# with: +# name: ${{ env.MY_STEP_VAR }} +# path: tests/testing-results +# retention-days: 7 +# - name: Clean runner +# run: +# rm -rf ./* || true +# rm -rf ./.??* || true +# rm -rf ~/.cache || true +# - run: echo "This job's status is ${{ job.status }}." # testlib-long-kvm-switch-tests: # runs-on: [self-hosted, linux, x64, run] @@ -477,11 +507,11 @@ jobs: # needs: build-gem5 # timeout-minutes: 1440 # 24 hours # steps: - # - uses: actions/checkout@v3 - # with: - # # Scheduled workflows run on the default branch by default. We - # # therefore need to explicitly checkout the develop branch. - # ref: develop + # - uses: actions/checkout@v3 + # with: + # # Scheduled workflows run on the default branch by default. We + # # therefore need to explicitly checkout the develop branch. + # ref: develop # - uses: actions/download-artifact@v3 # with: # name: ${{ env.artifact-name }} @@ -497,6 +527,11 @@ jobs: # name: ${{ env.MY_STEP_VAR }} # path: tests/testing-results # retention-days: 7 + # - name: Clean runner + # run: + # rm -rf ./* || true + # rm -rf ./.??* || true + # rm -rf ~/.cache || true # - run: echo "This job's status is ${{ job.status }}." testlib-long-learning_gem5: @@ -532,6 +567,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-m5_threads: @@ -567,6 +607,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-memory: @@ -602,6 +647,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-multi_isa: @@ -647,6 +697,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-replacement-policies: @@ -682,6 +737,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-riscv-boot-tests: @@ -717,6 +777,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-stdlib: @@ -762,6 +827,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-long-x86-boot-tests: @@ -797,6 +867,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." # This runs the SST-gem5 integration compilation and tests it with diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 4c3f6b55bc..dd81555f00 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -67,6 +67,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." @@ -103,6 +108,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-very-long-parsec-benchmarks: @@ -138,6 +148,11 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." testlib-very-long-x86-boot-tests: @@ -173,4 +188,9 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." From 8450b93f8e4a939fba6e075b225c07f112a5a72b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 18 Jul 2023 10:27:48 -0700 Subject: [PATCH 091/693] misc: Add bug report template (#85) * misc: Add Bug Report Issue Template Change-Id: I3acf7a1991f889462c0f2604d251dead563846c2 * misc: Cleanup bug_report.md * Inform the reader to use codeblocks where approproate. * Inform the reader they should include the Python configuraiton script and state parameters passed. Change-Id: Ib0b8e9a6d3ed199c435917acfdf958073d4faa04 --- .github/ISSUE_TEMPLATE/bug_report.md | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..179a37ac0b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,62 @@ +--- +name: Bug report +about: Create a report to help us find and fix the bug +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Affects version** +State which version of gem5 this bug was found in. If on the develop branch state the Commit revision ID you are working. + +**gem5 Modifications** +If you have modified gem5 in some way please state, to the best of your ability, how it has been modified. + +**To Reproduce** +Steps to reproduce the behavior. Please assume starting from a clean repository: +1. Compile gem5 with command ... +2. Execute the simulation with... + +If writing code, or a terminal command, use code blocks. Either an inline code block, \`scons build/ALL/gem5.opt\` (enclosed in two \`) or a multi-line codeblock: + + +\`\`\` + +int x=2; + +int y=3' + +print(x+y); + +\`\`\` + +If possible, please include the Python configuration script used and state clearly any parameters passed. + +**Terminal Output** +If applicable, add the terminal output here. If long, only include the relevant lines. +Please put the terminal output in code blocks. I.e.: + +\`\`\` + +#Terminal output here# + +\`\`\` + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Host Operating System** +Ubuntu 22.04, Mac OS X, etc. + +**Host ISA** +ARM, X86, RISC-V, etc. + +**Compiler used** +State which compiler was used to compile gem5. Please include the compiler version. + +**Additional information** +Add any other information which does not fit in the previous sections but may be of use in fixing this bug. From 65fc9a6bfaf625e2eab3aea82380fcb7a23cd3b8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 18 Jul 2023 10:28:09 -0700 Subject: [PATCH 092/693] misc: Drop older compilers and Ubuntu 18.04 (#80) * tests,util-docker,misc: Drop compiler support for GCC 7 Change-Id: I8b17b77c92b88e78a8cb6d38cd5f045dbe80a643 * tests,util-docker,misc: Drop compiler support for clang 6.0 Change-Id: Ie3b6bfe889ad1d119cee0c9ffb04c5996517922e * util-docker,tests,misc: Remove Ubuntu 18.04 support 18.04 is no longer supported. This patch removes specific 18.04 compiler tests and removes our 18.04 dockerfiles. Images will no longer be produced for specific 18.04 tasks. Compiler images for GCC and Clang, which used 18.04 have been updated to use 20.04. Change-Id: I6338ab47af3287a25a557dbbeaeebcfccfdec9fc --- .github/workflows/compiler-tests.yaml | 2 +- tests/compiler-tests.sh | 2 - util/dockerfiles/docker-compose.yaml | 27 ++-------- .../ubuntu-18.04_all-dependencies/Dockerfile | 39 -------------- .../ubuntu-18.04_clang-version/Dockerfile | 53 ------------------- .../ubuntu-18.04_gcc-version/Dockerfile | 49 ----------------- 6 files changed, 5 insertions(+), 167 deletions(-) delete mode 100644 util/dockerfiles/ubuntu-18.04_all-dependencies/Dockerfile delete mode 100644 util/dockerfiles/ubuntu-18.04_clang-version/Dockerfile delete mode 100644 util/dockerfiles/ubuntu-18.04_gcc-version/Dockerfile diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 938bd03e6f..3b5ed1c901 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -16,7 +16,7 @@ jobs: all-compilers: strategy: matrix: - image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, gcc-version-7, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, clang-version-6.0, ubuntu-18.04_all-dependencies, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] + image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] runs-on: [self-hosted, linux, x64, run] timeout-minutes: 2880 # 48 hours diff --git a/tests/compiler-tests.sh b/tests/compiler-tests.sh index 1f180eb5fa..a7ae397eac 100755 --- a/tests/compiler-tests.sh +++ b/tests/compiler-tests.sh @@ -18,7 +18,6 @@ images=("gcc-version-12" "gcc-version-10" "gcc-version-9" "gcc-version-8" - "gcc-version-7" "clang-version-14" "clang-version-13" "clang-version-12" @@ -27,7 +26,6 @@ images=("gcc-version-12" "clang-version-9" "clang-version-8" "clang-version-7" - "clang-version-6.0" # The following checks our support for Ubuntu 18.04, 20.04, and 22.04. "ubuntu-18.04_all-dependencies" "ubuntu-20.04_all-dependencies" diff --git a/util/dockerfiles/docker-compose.yaml b/util/dockerfiles/docker-compose.yaml index 39579962b1..e2d327b0b2 100644 --- a/util/dockerfiles/docker-compose.yaml +++ b/util/dockerfiles/docker-compose.yaml @@ -21,11 +21,6 @@ services: context: systemc-2.3.3 dockerfile: Dockerfile image: gcr.io/gem5-test/systemc-env:latest - ubuntu-18.04_all-dependencies: - build: - context: ubuntu-18.04_all-dependencies - dockerfile: Dockerfile - image: gcr.io/gem5-test/ubuntu-18.04_all-dependencies:latest ubuntu-20.04_all-dependencies: build: context: ubuntu-20.04_all-dependencies @@ -41,16 +36,9 @@ services: context: ubuntu-22.04_min-dependencies dockerfile: Dockerfile image: gcr.io/gem5-test/ubuntu-22.04_min-dependencies:latest - gcc-7: - build: - context: ubuntu-18.04_gcc-version - dockerfile: Dockerfile - args: - - version=7 - image: gcr.io/gem5-test/gcc-version-7:latest gcc-8: build: - context: ubuntu-18.04_gcc-version + context: ubuntu-20.04_gcc-version dockerfile: Dockerfile args: - version=8 @@ -83,30 +71,23 @@ services: args: - version=12 image: gcr.io/gem5-test/gcc-version-12:latest - clang-6: - build: - context: ubuntu-18.04_clang-version - dockerfile: Dockerfile - args: - - version=6.0 - image: gcr.io/gem5-test/clang-version-6.0:latest clang-7: build: - context: ubuntu-18.04_clang-version + context: ubuntu-20.04_clang-version dockerfile: Dockerfile args: - version=7 image: gcr.io/gem5-test/clang-version-7:latest clang-8: build: - context: ubuntu-18.04_clang-version + context: ubuntu-20.04_clang-version dockerfile: Dockerfile args: - version=8 image: gcr.io/gem5-test/clang-version-8:latest clang-9: build: - context: ubuntu-18.04_clang-version + context: ubuntu-20.04_clang-version dockerfile: Dockerfile args: - version=9 diff --git a/util/dockerfiles/ubuntu-18.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-18.04_all-dependencies/Dockerfile deleted file mode 100644 index 629fc5d614..0000000000 --- a/util/dockerfiles/ubuntu-18.04_all-dependencies/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2020 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 ubuntu:18.04 - -RUN apt -y update && apt -y upgrade && \ - apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ - libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ - python3-dev python3 doxygen libboost-all-dev \ - libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config \ - python3-pip python3-venv - -RUN pip3 install black mypy pre-commit - -RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 10 -RUN update-alternatives --install /usr/bin/python python /usr/bin/python2 1 diff --git a/util/dockerfiles/ubuntu-18.04_clang-version/Dockerfile b/util/dockerfiles/ubuntu-18.04_clang-version/Dockerfile deleted file mode 100644 index 3d9c3a7c12..0000000000 --- a/util/dockerfiles/ubuntu-18.04_clang-version/Dockerfile +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2020 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 ubuntu:18.04 - -# Valid version values: -# 3.9 -# 4.0 -# 5.0 -# 6.0 -# 7 -# 8 -# 9 -ARG version - -RUN apt -y update && apt -y upgrade && \ - apt -y install git m4 scons zlib1g zlib1g-dev clang-${version} \ - libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ - python3-dev python3 doxygen make - -RUN apt-get --purge -y remove gcc - -RUN update-alternatives --install \ - /usr/bin/clang++ clang++ /usr/bin/clang++-${version} 100 -RUN update-alternatives --install \ - /usr/bin/clang clang /usr/bin/clang-${version} 100 -RUN update-alternatives --install \ - /usr/bin/c++ c++ /usr/bin/clang++-${version} 100 -RUN update-alternatives --install \ - /usr/bin/cc cc /usr/bin/clang-${version} 100 diff --git a/util/dockerfiles/ubuntu-18.04_gcc-version/Dockerfile b/util/dockerfiles/ubuntu-18.04_gcc-version/Dockerfile deleted file mode 100644 index 3e94e8d0e6..0000000000 --- a/util/dockerfiles/ubuntu-18.04_gcc-version/Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2020 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 ubuntu:18.04 - -# Valid version values: -# 4.8 -# 5 -# 6 -# 7 -# 8 -ARG version - -RUN apt -y update && apt -y upgrade && \ - apt -y install git m4 scons zlib1g zlib1g-dev gcc-multilib \ - libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ - python3-dev python3 doxygen wget zip gcc-${version} \ - g++-${version} make - -RUN update-alternatives --install \ - /usr/bin/g++ g++ /usr/bin/g++-${version} 100 -RUN update-alternatives --install \ - /usr/bin/gcc gcc /usr/bin/gcc-${version} 100 -RUN update-alternatives --install \ - /usr/bin/c++ c++ /usr/bin/g++-${version} 100 -RUN update-alternatives --install \ - /usr/bin/cc cc /usr/bin/gcc-${version} 100 From 573523c07a658dc8988567eea8f6e9a15fc11d4f Mon Sep 17 00:00:00 2001 From: Lingkang Date: Wed, 19 Jul 2023 05:00:57 +0800 Subject: [PATCH 093/693] python: fix fatal in main.py (github #78) (#93) * python: fix fatal in main.py (github #78) Issue-On: https://github.com/gem5/gem5/issues/78 * python: fix fatal in main.py (github #78) Issue-On: https://github.com/gem5/gem5/issues/78 Change-Id: I80855b05168a067ddd7706ad9fd7e71e75bfd3b1 --------- Co-authored-by: Jason Lowe-Power --- src/python/m5/main.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/python/m5/main.py b/src/python/m5/main.py index ddcb024f8b..e07e9562ab 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -348,13 +348,14 @@ def interact(scope): def _check_tracing(): - import m5 import _m5.core + from .util import fatal + if _m5.core.TRACING_ON: return - m5.fatal("Tracing is not enabled. Compile with TRACING_ON") + fatal("Tracing is not enabled. Compile with TRACING_ON") def main(): @@ -369,7 +370,7 @@ def main(): from . import stats from . import trace - from .util import inform, fatal, panic, isInteractive + from .util import inform, panic, isInteractive from m5.util.terminal_formatter import TerminalFormatter options, arguments = parse_options() From 4d9bd7dedf3b0615e62095659c93d68c3d6cb680 Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Wed, 19 Jul 2023 02:07:39 -0700 Subject: [PATCH 094/693] base: Added missing backup dummy __has_builtin definition (#99) Added dummy definition of __has_builtin to bitfield.hh's hasBuiltinCtz, which is already being done in popCount. Change-Id: I4a1760a142209462bb807c6df4bc868284b6f5f3 --- src/base/bitfield.hh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 8d3721b08a..c2eeb1fb55 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -310,6 +310,13 @@ namespace { template constexpr bool hasBuiltinCtz() { +// Since the defined(__has_builtin) in the subsequent #if statement +// won't short-circuit the macro expansion of +// __has_builtin(__builtin_ctz), we must explicitly define it as zero +// if it's undefined to avoid a preprocessor error. +#ifndef __has_builtin +# define __has_builtin(foo) 0 +#endif #if defined(__has_builtin) && __has_builtin(__builtin_ctz) return sizeof(unsigned long long) >= sizeof(T); #else From 4c4419296b8430d754a96da0eaae731c594f4d06 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Wed, 19 Jul 2023 17:45:29 +0200 Subject: [PATCH 095/693] base: Unit tests miscellaneous patches (#73) * base: Fix Memoizer constructor parameter type * base: switch from new to mk_unq in amo.test.cc * base: Fix memory management in IniFile * base: Fix memory management in Trie * sim: Fix out-of-bounds access in CheckpointIn::setDir Change-Id: Iac50bbf01b6d7acc458c786da8ac371582a4ce09 --------- Co-authored-by: Gabriel Busnot --- src/base/amo.test.cc | 74 ++++++++++++++++++------------ src/base/inifile.cc | 105 +++++++++++++++++++------------------------ src/base/inifile.hh | 23 +++++----- src/base/memoizer.hh | 2 +- src/base/trie.hh | 64 +++++++++++--------------- src/sim/serialize.cc | 5 ++- 6 files changed, 135 insertions(+), 138 deletions(-) diff --git a/src/base/amo.test.cc b/src/base/amo.test.cc index 10e5540da4..e511117eea 100644 --- a/src/base/amo.test.cc +++ b/src/base/amo.test.cc @@ -64,9 +64,10 @@ TEST(AmoTest, AtomicOpMin) std::string test_string_smaller = "apple"; std::string test_string_bigger = "cat"; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpMin(10); - TypedAtomicOpFunctor *amo_op_string = - new AtomicOpMin("base"); + std::unique_ptr> amo_op_int = + std::make_unique>(10); + std::unique_ptr> amo_op_string = + std::make_unique>("base"); amo_op_int->execute(&test_int_smaller); amo_op_int->execute(&test_int_bigger); amo_op_string->execute(&test_string_smaller); @@ -85,9 +86,10 @@ TEST(AmoTest, AtomicOpMax) std::string test_string_smaller = "apple"; std::string test_string_bigger = "cat"; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpMax(10); - TypedAtomicOpFunctor *amo_op_string = - new AtomicOpMax("base"); + std::unique_ptr> amo_op_int = + std::make_unique>(10); + std::unique_ptr> amo_op_string = + std::make_unique>("base"); amo_op_int->execute(&test_int_smaller); amo_op_int->execute(&test_int_bigger); amo_op_string->execute(&test_string_smaller); @@ -104,8 +106,10 @@ TEST(AmoTest, AtomicOpDec) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpDec(); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpDec(); + std::unique_ptr> amo_op_int = + std::make_unique>(); + std::unique_ptr> amo_op_char = + std::make_unique>(); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -118,8 +122,10 @@ TEST(AmoTest, AtomicOpInc) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpInc(); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpInc(); + std::unique_ptr> amo_op_int = + std::make_unique>(); + std::unique_ptr> amo_op_char = + std::make_unique>(); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -132,8 +138,10 @@ TEST(AmoTest, AtomicOpSub) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpSub(2); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpSub('a'); + std::unique_ptr> amo_op_int = + std::make_unique>(2); + std::unique_ptr> amo_op_char = + std::make_unique>('a'); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -146,8 +154,10 @@ TEST(AmoTest, AtomicOpAdd) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpAdd(2); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpAdd(2); + std::unique_ptr> amo_op_int = + std::make_unique>(2); + std::unique_ptr> amo_op_char = + std::make_unique>(2); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -160,8 +170,10 @@ TEST(AmoTest, AtomicOpExch) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpExch(2); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpExch('a'); + std::unique_ptr> amo_op_int = + std::make_unique>(2); + std::unique_ptr> amo_op_char = + std::make_unique>('a'); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -174,8 +186,10 @@ TEST(AmoTest, AtomicOpXor) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpXor(2); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpXor('a'); + std::unique_ptr> amo_op_int = + std::make_unique>(2); + std::unique_ptr> amo_op_char = + std::make_unique>('a'); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -188,8 +202,10 @@ TEST(AmoTest, AtomicOpOr) int test_int = 8; bool test_bool = true; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpOr(2); - TypedAtomicOpFunctor *amo_op_bool = new AtomicOpOr(false); + std::unique_ptr> amo_op_int = + std::make_unique>(2); + std::unique_ptr> amo_op_bool = + std::make_unique>(false); amo_op_int->execute(&test_int); amo_op_bool->execute(&test_bool); @@ -202,8 +218,10 @@ TEST(AmoTest, AtomicOpAnd) int test_int = 10; char test_char = 'c'; - TypedAtomicOpFunctor *amo_op_int = new AtomicOpAnd(6); - TypedAtomicOpFunctor *amo_op_char = new AtomicOpAnd('a'); + std::unique_ptr> amo_op_int = + std::make_unique>(6); + std::unique_ptr> amo_op_char = + std::make_unique>('a'); amo_op_int->execute(&test_int); amo_op_char->execute(&test_char); @@ -215,8 +233,8 @@ TEST(AmoTest, AtomicGeneric2Op) { int test_int = 9; - TypedAtomicOpFunctor *amo_op_int = - new AtomicGeneric2Op(9, multiply2Op); + std::unique_ptr> amo_op_int = + std::make_unique>(9, multiply2Op); amo_op_int->execute(&test_int); EXPECT_EQ(test_int, 81); @@ -226,8 +244,8 @@ TEST(AmoTest, AtomicGeneric3Op) { int test_int = 2; - TypedAtomicOpFunctor *amo_op_int = - new AtomicGeneric3Op(4, 3, multiply3Op); + std::unique_ptr> amo_op_int = + std::make_unique>(4, 3, multiply3Op); amo_op_int->execute(&test_int); EXPECT_EQ(test_int, 24); @@ -239,8 +257,8 @@ TEST(AmoTest, AtomicGenericPair3Op) std::array a = {6, 3}; std::array c = {10, 8}; - TypedAtomicOpFunctor *amo_op_int = - new AtomicGenericPair3Op(a, c, addSubColumns); + std::unique_ptr> amo_op_int = + std::make_unique>(a, c, addSubColumns); amo_op_int->execute(&test_int); EXPECT_EQ(test_int, 10); diff --git a/src/base/inifile.cc b/src/base/inifile.cc index 8c0662d0e3..23253e9df5 100644 --- a/src/base/inifile.cc +++ b/src/base/inifile.cc @@ -42,17 +42,6 @@ namespace gem5 IniFile::IniFile() {} -IniFile::~IniFile() -{ - SectionTable::iterator i = table.begin(); - SectionTable::iterator end = table.end(); - - while (i != end) { - delete (*i).second; - ++i; - } -} - bool IniFile::load(const std::string &file) { @@ -82,15 +71,15 @@ IniFile::Section::addEntry(const std::string &entryName, if (ei == table.end()) { // new entry - table[entryName] = new Entry(value); + table.emplace(entryName, value); } else if (append) { // append new reult to old entry - ei->second->appendValue(value); + ei->second.appendValue(value); } else { // override old entry - ei->second->setValue(value); + ei->second.setValue(value); } } @@ -120,39 +109,42 @@ IniFile::Section::add(const std::string &assignment) IniFile::Entry * +IniFile::Section::findEntry(const std::string &entryName) +{ + return const_cast( + std::as_const(*this).findEntry(entryName)); +} + +const IniFile::Entry * IniFile::Section::findEntry(const std::string &entryName) const { referenced = true; - EntryTable::const_iterator ei = table.find(entryName); + auto ei = table.find(entryName); - return (ei == table.end()) ? NULL : ei->second; + return (ei == table.end()) ? nullptr : &ei->second; } IniFile::Section * IniFile::addSection(const std::string §ionName) { - SectionTable::iterator i = table.find(sectionName); - - if (i != table.end()) { - return i->second; - } - else { - // new entry - Section *sec = new Section(); - table[sectionName] = sec; - return sec; - } + return &table[sectionName]; } - IniFile::Section * +IniFile::findSection(const std::string §ionName) +{ + return const_cast( + std::as_const(*this).findSection(sectionName)); +} + +const IniFile::Section * IniFile::findSection(const std::string §ionName) const { - SectionTable::const_iterator i = table.find(sectionName); + auto i = table.find(sectionName); - return (i == table.end()) ? NULL : i->second; + return (i == table.end()) ? nullptr : &i->second; } @@ -215,11 +207,11 @@ bool IniFile::find(const std::string §ionName, const std::string &entryName, std::string &value) const { - Section *section = findSection(sectionName); + auto* section = findSection(sectionName); if (section == NULL) return false; - Entry *entry = section->findEntry(entryName); + auto* entry = section->findEntry(entryName); if (entry == NULL) return false; @@ -232,7 +224,7 @@ bool IniFile::entryExists(const std::string §ionName, const std::string &entryName) const { - Section *section = findSection(sectionName); + auto* section = findSection(sectionName); if (!section) return false; @@ -248,13 +240,13 @@ IniFile::sectionExists(const std::string §ionName) const bool -IniFile::Section::printUnreferenced(const std::string §ionName) +IniFile::Section::printUnreferenced(const std::string §ionName) const { bool unref = false; bool search_unref_entries = false; std::vector unref_ok_entries; - Entry *entry = findEntry("unref_entries_ok"); + auto* entry = findEntry("unref_entries_ok"); if (entry != NULL) { tokenize(unref_ok_entries, entry->getValue(), ' '); if (unref_ok_entries.size()) { @@ -262,10 +254,9 @@ IniFile::Section::printUnreferenced(const std::string §ionName) } } - for (EntryTable::iterator ei = table.begin(); - ei != table.end(); ++ei) { - const std::string &entryName = ei->first; - entry = ei->second; + for (auto& ei: table) { + const std::string &entryName = ei.first; + entry = &ei.second; if (entryName == "unref_section_ok" || entryName == "unref_entries_ok") @@ -294,32 +285,29 @@ IniFile::Section::printUnreferenced(const std::string §ionName) void IniFile::getSectionNames(std::vector &list) const { - for (SectionTable::const_iterator i = table.begin(); - i != table.end(); ++i) - { - list.push_back((*i).first); + for (auto& entry: table) { + auto& sectionName = entry.first; + list.push_back(sectionName); } } bool -IniFile::printUnreferenced() +IniFile::printUnreferenced() const { bool unref = false; - for (SectionTable::iterator i = table.begin(); - i != table.end(); ++i) { - const std::string §ionName = i->first; - Section *section = i->second; + for (auto& entry: table) { + auto& [sectionName, section] = entry; - if (!section->isReferenced()) { - if (section->findEntry("unref_section_ok") == NULL) { + if (!section.isReferenced()) { + if (section.findEntry("unref_section_ok") == NULL) { std::cerr << "Section " << sectionName << " not referenced." << std::endl; unref = true; } } else { - if (section->printUnreferenced(sectionName)) { + if (section.printUnreferenced(sectionName)) { unref = true; } } @@ -330,12 +318,11 @@ IniFile::printUnreferenced() void -IniFile::Section::dump(const std::string §ionName) +IniFile::Section::dump(const std::string §ionName) const { - for (EntryTable::iterator ei = table.begin(); - ei != table.end(); ++ei) { - std::cout << sectionName << ": " << (*ei).first << " => " - << (*ei).second->getValue() << "\n"; + for (auto& ei: table) { + std::cout << sectionName << ": " << ei.first << " => " + << ei.second.getValue() << "\n"; } } @@ -344,7 +331,7 @@ IniFile::dump() { for (SectionTable::iterator i = table.begin(); i != table.end(); ++i) { - i->second->dump(i->first); + i->second.dump(i->first); } } @@ -364,9 +351,9 @@ void IniFile::visitSection(const std::string §ionName, IniFile::VisitSectionCallback cb) { - const auto& section = *table.at(sectionName); + const auto& section = table.at(sectionName); for (const auto& pair : section) { - cb(pair.first, pair.second->getValue()); + cb(pair.first, pair.second.getValue()); } } diff --git a/src/base/inifile.hh b/src/base/inifile.hh index 72f1df7b05..d17193d5bf 100644 --- a/src/base/inifile.hh +++ b/src/base/inifile.hh @@ -72,7 +72,7 @@ class IniFile } /// Has this entry been used? - bool isReferenced() { return referenced; } + bool isReferenced() const { return referenced; } /// Fetch the value. const std::string &getValue() const; @@ -94,7 +94,7 @@ class IniFile class Section { /// EntryTable type. Map of strings to Entry object pointers. - typedef std::unordered_map EntryTable; + typedef std::unordered_map EntryTable; EntryTable table; ///< Table of entries. mutable bool referenced; ///< Has this section been used? @@ -107,7 +107,7 @@ class IniFile } /// Has this section been used? - bool isReferenced() { return referenced; } + bool isReferenced() const { return referenced; } /// Add an entry to the table. If an entry with the same name /// already exists, the 'append' parameter is checked If true, @@ -125,24 +125,25 @@ class IniFile /// Find the entry with the given name. /// @retval Pointer to the entry object, or NULL if none. - Entry *findEntry(const std::string &entryName) const; + Entry *findEntry(const std::string &entryName); + const Entry *findEntry(const std::string &entryName) const; /// Print the unreferenced entries in this section to cerr. /// Messages can be suppressed using "unref_section_ok" and /// "unref_entries_ok". /// @param sectionName Name of this section, for use in output message. /// @retval True if any entries were printed. - bool printUnreferenced(const std::string §ionName); + bool printUnreferenced(const std::string §ionName) const; /// Print the contents of this section to cout (for debugging). - void dump(const std::string §ionName); + void dump(const std::string §ionName) const; EntryTable::const_iterator begin() const; EntryTable::const_iterator end() const; }; /// SectionTable type. Map of strings to Section object pointers. - typedef std::unordered_map SectionTable; + typedef std::unordered_map SectionTable; protected: /// Hash of section names to Section object pointers. @@ -155,15 +156,13 @@ class IniFile /// Look up section with the given name. /// @retval Pointer to section object, or NULL if not found. - Section *findSection(const std::string §ionName) const; + Section *findSection(const std::string §ionName); + const Section *findSection(const std::string §ionName) const; public: /// Constructor. IniFile(); - /// Destructor. - ~IniFile(); - /// Load parameter settings from given istream. This is a helper /// function for load(string) and loadCPP(), which open a file /// and then pass it here. @@ -206,7 +205,7 @@ class IniFile /// Print unreferenced entries in object. Iteratively calls /// printUnreferend() on all the constituent sections. - bool printUnreferenced(); + bool printUnreferenced() const; /// Dump contents to cout. For debugging. void dump(); diff --git a/src/base/memoizer.hh b/src/base/memoizer.hh index c3390887b7..4d3816e9ea 100644 --- a/src/base/memoizer.hh +++ b/src/base/memoizer.hh @@ -85,7 +85,7 @@ class Memoizer using ret_type = Ret; using args_type = std::tuple; - constexpr Memoizer(Ret _func(Args...)) + constexpr Memoizer(Ret (*_func)(Args...)) : func(_func) { validateMemoizer(); diff --git a/src/base/trie.hh b/src/base/trie.hh index 477bfbde14..47d60b7632 100644 --- a/src/base/trie.hh +++ b/src/base/trie.hh @@ -70,7 +70,7 @@ class Trie Value *value; Node *parent; - Node *kids[2]; + std::unique_ptr kids[2]; Node(Key _key, Key _mask, Value *_val) : key(_key & _mask), mask(_mask), value(_val), @@ -83,16 +83,8 @@ class Trie void clear() { - if (kids[1]) { - kids[1]->clear(); - delete kids[1]; - kids[1] = NULL; - } - if (kids[0]) { - kids[0]->clear(); - delete kids[0]; - kids[0] = NULL; - } + kids[1].reset(); + kids[0].reset(); } void @@ -188,9 +180,9 @@ class Trie return node; if (node->kids[0] && node->kids[0]->matches(key)) - node = node->kids[0]; + node = node->kids[0].get(); else if (node->kids[1] && node->kids[1]->matches(key)) - node = node->kids[1]; + node = node->kids[1].get(); else node = NULL; } @@ -225,8 +217,8 @@ class Trie // Walk past all the nodes this new node will be inserted after. They // can be ignored for the purposes of this function. Node *node = &head; - while (goesAfter(&node, node->kids[0], key, new_mask) || - goesAfter(&node, node->kids[1], key, new_mask)) + while (goesAfter(&node, node->kids[0].get(), key, new_mask) || + goesAfter(&node, node->kids[1].get(), key, new_mask)) {} assert(node); @@ -239,14 +231,13 @@ class Trie } for (unsigned int i = 0; i < 2; i++) { - Node *&kid = node->kids[i]; - Node *new_node; + auto& kid = node->kids[i]; if (!kid) { // No kid. Add a new one. - new_node = new Node(key, new_mask, val); + auto new_node = std::make_unique(key, new_mask, val); new_node->parent = node; - kid = new_node; - return new_node; + kid = std::move(new_node); + return kid.get(); } // Walk down the leg until something doesn't match or we run out @@ -266,23 +257,23 @@ class Trie continue; // At the point we walked to above, add a new node. - new_node = new Node(key, cur_mask, NULL); + auto new_node = std::make_unique(key, cur_mask, nullptr); new_node->parent = node; - kid->parent = new_node; - new_node->kids[0] = kid; - kid = new_node; + kid->parent = new_node.get(); + new_node->kids[0] = std::move(kid); + kid = std::move(new_node); // If we ran out of bits, the value goes right here. if (cur_mask == new_mask) { - new_node->value = val; - return new_node; + kid->value = val; + return kid.get(); } // Still more bits to deal with, so add a new node for that path. - new_node = new Node(key, new_mask, val); - new_node->parent = kid; - kid->kids[1] = new_node; - return new_node; + new_node = std::make_unique(key, new_mask, val); + new_node->parent = kid.get(); + kid->kids[1] = std::move(new_node); + return kid->kids[1].get(); } panic("Reached the end of the Trie insert function!\n"); @@ -332,23 +323,22 @@ class Trie if (node->kids[0]) node->kids[0]->parent = parent; // Figure out which kid we are, and update our parent's pointers. - if (parent->kids[0] == node) - parent->kids[0] = node->kids[0]; - else if (parent->kids[1] == node) - parent->kids[1] = node->kids[0]; + if (parent->kids[0].get() == node) + parent->kids[0] = std::move(node->kids[0]); + else if (parent->kids[1].get() == node) + parent->kids[1] = std::move(node->kids[0]); else panic("Trie: Inconsistent parent/kid relationship.\n"); // Make sure if the parent only has one kid, it's kid[0]. if (parent->kids[1] && !parent->kids[0]) { - parent->kids[0] = parent->kids[1]; - parent->kids[1] = NULL; + parent->kids[0] = std::move(parent->kids[1]); + parent->kids[1] = nullptr; } // If the parent has less than two kids and no cargo and isn't the // root, delete it too. if (!parent->kids[1] && !parent->value && parent->parent) remove(parent); - delete node; return val; } diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 2b1bd35f16..0f722a017e 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -145,8 +145,11 @@ CheckpointIn::setDir(const std::string &name) // appears to have a format placeholder in it. currentDirectory = (name.find("%") != std::string::npos) ? csprintf(name, curTick()) : name; - if (currentDirectory[currentDirectory.size() - 1] != '/') + auto isEmptyPath = currentDirectory.empty(); + auto endsWithSlash = !isEmptyPath && currentDirectory.back() == '/'; + if (!endsWithSlash) { currentDirectory += "/"; + } return currentDirectory; } From 5d2edca1e36189052739250c25471c285746665b Mon Sep 17 00:00:00 2001 From: rogerchang23424 Date: Thu, 20 Jul 2023 02:14:27 +0800 Subject: [PATCH 096/693] arch-riscv: Set default check alignment True (#98) Raise misaligned trap if effective address if not aligned by default Change-Id: I634aa7ddbf5282fc583316fc77ab1e37bfe415e3 --- src/arch/riscv/RiscvISA.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index e2381fd158..bb9a05babe 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -53,6 +53,6 @@ class RiscvISA(BaseISA): cxx_header = "arch/riscv/isa.hh" check_alignment = Param.Bool( - False, "whether to check memory access alignment" + True, "whether to check memory access alignment" ) riscv_type = Param.RiscvType("RV64", "RV32 or RV64") From 566308dad9101bfd9e7ead7f453a96f97e3af8d6 Mon Sep 17 00:00:00 2001 From: rogerchang23424 Date: Fri, 21 Jul 2023 00:35:45 +0800 Subject: [PATCH 097/693] scons: Add extra parent dir to CPPPATH if --no-duplicate-sources (#104) In the previous version of gem5, the source files of extra directories will copy to build directory for compilation. It will not be a problem if the extra directories include *.h(*.hh) from the other extra directories. After the patch applied from the change (https://gem5-review.googlesource.com/c/public/gem5/+/68758). The source files of extra directories will not copy to the build directory unless the user compiles gem5 with "--duplicate-sources". It will cause the compilation error if the code includes a header file from other repositories. For example, assume we want to compile gem5 with "foo/bar1" and "foo/bar2" repositories and they are gem5-independent. There are some header files in "foo/bar1/a.h" "foo/bar1/b.h" and "foo/bar2/d.h". If the code "foo/bar1/sample.c" tries to include the file "foo/bar2/d.h". They usually include the file by declare "#include bar2/d.h" in foo/bar1/sample.c. It can work if --duplicate-sources is specified in gem5 build because they will copy to /bar1 and /bar2 respectively, and -I is specified by default whether duplicate_sources or not. It will raise the compilation error if the user does not specify it. The change is aimed to let the situation work without duplicate-sources specified by adding parent extra directory, and adding them before the extra directories. If the --duplicate-sources specified, it will not add parent extra directories to avoid repeat include paths. Change-Id: I461e1dcb8266d785f1f38eeff77f9d515d47c03d --- src/SConscript | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/SConscript b/src/SConscript index 481f6522e5..62ae807b55 100644 --- a/src/SConscript +++ b/src/SConscript @@ -536,6 +536,14 @@ Export('DebugFormatFlag') # the corresponding build directory to pick up generated include # files. env.Append(CPPPATH=Dir('.')) +parent_dir_set = set() + +for extra_dir in extras_dir_list: + parent_dir_set.add(str(Dir(extra_dir).Dir('..').abspath)) + +if not GetOption('duplicate_sources'): + for parent_dir in parent_dir_set: + env.Append(CPPPATH=Dir(parent_dir)) for extra_dir in extras_dir_list: env.Append(CPPPATH=Dir(extra_dir)) From 1705853b12df627d0e7279ef2acbd01dd1291838 Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Thu, 20 Jul 2023 09:48:08 -0700 Subject: [PATCH 098/693] mem-ruby: Added support for non-system-scope atomics in VIPER (#101) Added support for performing non-SLC-set atomics in the TCC. Previously, all atomics were being passed on by the TCC to the directory. With this change, atomics will only be passed on if the SLC bit is set or if the line isn't present or available in the TCC. If a non-SLC atomic is passed on to the directory because it is not present in the TCC, the atomic will be performed on the return path on the Data event. To accommodate the directory not performing the atomic in this case, this change also passes the SLC bit on to the directory. The previously-named "Atomic" action has been renamed to "AtomicPassOn", with the new "Atomic" corresponding to an atomic performed directly in the TCC. Change-Id: Ibf92f71ddceb38bd1b0da70b0a786cc4c3cf2669 --- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 123 ++++++++++++++++---- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 8 +- 2 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index df3aa1ebca..a83bee0fa5 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -61,6 +61,7 @@ machine(MachineType:TCC, "TCC Cache") WrVicBlkBack, desc="L1 Write Through(dirty cache)"; WrVicBlkEvict, desc="L1 Write Through(dirty cache) and evict"; Atomic, desc="Atomic Op"; + AtomicPassOn, desc="Atomic Op Passed on to Directory"; AtomicDone, desc="AtomicOps Complete"; AtomicNotDone, desc="AtomicOps not Complete"; Data, desc="data messgae"; @@ -355,11 +356,17 @@ machine(MachineType:TCC, "TCC Cache") trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe); } } else if (in_msg.Type == CoherenceRequestType:Atomic) { - // Currently the Atomic requests do not have GLC/SLC bit handing - // support. The assert ensures that the requests do not have - // these set, and therefore do not expect to bypass the cache - assert(!in_msg.isSLCSet); - trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); + // If the request is system-level, or if the address isn't in the cache, + // then send the request to the directory. Since non-SLC atomics won't be + // performed by the directory, TCC will perform the atomic on the return path + // on Event:Data. + // The action will invalidate the cache line if SLC is set and the address is + // in the cache. + if(in_msg.isSLCSet || !presentOrAvail(in_msg.addr)) { + trigger(Event:AtomicPassOn, in_msg.addr, cache_entry, tbe); + } else { + trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); + } } else if (in_msg.Type == CoherenceRequestType:RdBlk) { if (in_msg.isSLCSet) { // If SLC bit is set, the request needs to go directly to memory. @@ -502,6 +509,22 @@ machine(MachineType:TCC, "TCC Cache") } action(ar_sendAtomicResponse, "ar", desc="send Atomic Ack") { + peek(coreRequestNetwork_in, CPURequestMsg) { + enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { + out_msg.addr := address; + out_msg.Type := CoherenceResponseType:TDSysResp; + out_msg.Destination.clear(); + out_msg.Destination.add(in_msg.Requestor); + out_msg.Sender := machineID; + out_msg.MessageSize := MessageSizeType:Response_Data; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; + } + } + } + + action(bar_sendBypassedAtomicResponse, "bar", desc="send bypassed Atomic Ack") { peek(responseFromNB_in, ResponseMsg) { enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { out_msg.addr := address; @@ -614,6 +637,8 @@ machine(MachineType:TCC, "TCC Cache") out_msg.Type := CoherenceRequestType:Atomic; out_msg.Dirty := true; out_msg.writeMask.orMask(in_msg.writeMask); + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } } } @@ -688,6 +713,10 @@ machine(MachineType:TCC, "TCC Cache") triggerQueue_in.dequeue(clockEdge()); } + action(pa_performAtomic, "pa", desc="Perform atomic") { + cache_entry.DataBlk.atomicPartial(cache_entry.DataBlk, cache_entry.writeMask); + } + // END ACTIONS // BEGIN TRANSITIONS @@ -699,7 +728,7 @@ machine(MachineType:TCC, "TCC Cache") // Stalling transitions do NOT check the tag array...and if they do, // they can cause a resource stall deadlock! - transition(WI, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} { + transition(WI, {RdBlk, WrVicBlk, Atomic, AtomicPassOn, WrVicBlkBack}) { //TagArrayRead} { // by putting the stalled requests in a buffer, we reduce resource contention // since they won't try again every cycle and will instead only try again once // woken up @@ -717,18 +746,21 @@ machine(MachineType:TCC, "TCC Cache") // woken up st_stallAndWaitRequest; } - transition(IV, {WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} { + + transition(IV, {WrVicBlk, Atomic, AtomicPassOn, WrVicBlkBack}) { //TagArrayRead} { // by putting the stalled requests in a buffer, we reduce resource contention // since they won't try again every cycle and will instead only try again once // woken up st_stallAndWaitRequest; } + transition({M, V}, RdBlk) {TagArrayRead, DataArrayRead} { p_profileHit; sd_sendData; ut_updateTag; p_popRequestQueue; } + transition(W, RdBlk, WI) {TagArrayRead, DataArrayRead} { t_allocateTBE; wb_writeBack; @@ -801,21 +833,21 @@ machine(MachineType:TCC, "TCC Cache") st_stallAndWaitRequest; } - transition(V, Atomic, A) {TagArrayRead} { + transition(V, Atomic, M) {TagArrayRead, DataArrayWrite} { p_profileHit; - i_invL2; - t_allocateTBE; - at_atomicThrough; - ina_incrementNumAtomics; + wdb_writeDirtyBytes; + pa_performAtomic; + ar_sendAtomicResponse; p_popRequestQueue; } -transition(I, Atomic, A) {TagArrayRead} { + transition(I, Atomic, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} { p_profileMiss; - i_invL2; - t_allocateTBE; - at_atomicThrough; - ina_incrementNumAtomics; + a_allocateBlock; + ut_updateTag; + wdb_writeDirtyBytes; + pa_performAtomic; + ar_sendAtomicResponse; p_popRequestQueue; } @@ -827,7 +859,45 @@ transition(I, Atomic, A) {TagArrayRead} { st_stallAndWaitRequest; } - transition({M, W}, Atomic, WI) {TagArrayRead} { + transition({M, W}, Atomic) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + p_profileHit; + wdb_writeDirtyBytes; + pa_performAtomic; + ar_sendAtomicResponse; + p_popRequestQueue; + } + + // The following atomic pass on actions will send the request to the directory, + // and are triggered when an atomic request is received that is not in TCC, + // and/or if SLC is set. + + transition(V, AtomicPassOn, A) {TagArrayRead} { + p_profileHit; + i_invL2; + t_allocateTBE; + at_atomicThrough; + ina_incrementNumAtomics; + p_popRequestQueue; + } + + transition(I, AtomicPassOn, A) {TagArrayRead} { + p_profileMiss; + i_invL2; + t_allocateTBE; + at_atomicThrough; + ina_incrementNumAtomics; + p_popRequestQueue; + } + + transition(A, AtomicPassOn) { + p_profileMiss; + // by putting the stalled requests in a buffer, we reduce resource contention + // since they won't try again every cycle and will instead only try again once + // woken up + st_stallAndWaitRequest; + } + + transition({M, W}, AtomicPassOn, WI) {TagArrayRead} { t_allocateTBE; wb_writeBack; // after writing back the current line, we need to wait for it to be done @@ -946,6 +1016,18 @@ transition(I, Atomic, A) {TagArrayRead} { dt_deallocateTBE; } + transition(A, Bypass) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + bar_sendBypassedAtomicResponse; + dna_decrementNumAtomics; + pr_popResponseQueue; + } + + transition(WI, Bypass, I) { + pr_popResponseQueue; + wada_wakeUpAllDependentsAddr; + dt_deallocateTBE; + } + transition(IV, Data, V) {TagArrayRead, TagArrayWrite, DataArrayWrite} { a_allocateBlock; ut_updateTag; @@ -956,9 +1038,10 @@ transition(I, Atomic, A) {TagArrayRead} { dt_deallocateTBE; } - transition(A, Data) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + transition(A, Data, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} { a_allocateBlock; - ar_sendAtomicResponse; + pa_performAtomic; + bar_sendBypassedAtomicResponse; dna_decrementNumAtomics; pr_popResponseQueue; } diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index 4dd03a19c0..fd0cca5782 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -161,6 +161,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") uint64_t probe_id, desc="probe id for lifetime profiling"; WriteMask writeMask, desc="outstanding write through mask"; int Len, desc="Length of memory request for DMA"; + bool isSLCSet, desc="Bypass L1 and L2 Cache"; } structure(TBETable, external="yes") { @@ -975,6 +976,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.atomicData := true; tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; + tbe.isSLCSet := in_msg.isSLCSet; } tbe.Dirty := false; if (in_msg.Type == CoherenceRequestType:WriteThrough) { @@ -995,7 +997,11 @@ machine(MachineType:Directory, "AMD Baseline protocol") action(wd_writeBackData, "wd", desc="Write back data if needed") { if (tbe.wtData || tbe.atomicData || tbe.Dirty == false) { - if (tbe.atomicData) { + // If SLC is not set, the atomic is handled in the L2 + // Atomic needs to be done at the L3 only if this is + // not the case + + if (tbe.atomicData && tbe.isSLCSet) { tbe.DataBlk.atomicPartial(tbe.DataBlk, tbe.writeMask); } enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) { From f7da973f34cd81f117019680c2816f6db000ae94 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Thu, 20 Jul 2023 10:34:44 -0700 Subject: [PATCH 099/693] cpu-kvm: Make using perf when using KVM CPU optional (#95) * cpu-kvm: Add a variable signifying whether we are using perf Change-Id: Iaa081e364f85c863f781723b5524d267724ed0e4 Signed-off-by: Hoa Nguyen * cpu-kvm: Making it clear the functionalities are specific to KVM Change-Id: I982426f294d90655227dc15337bf73c42a260ded Signed-off-by: Hoa Nguyen * cpu-kvm: Make perf optional Change-Id: I8973c2a96575383976cea7ca3fda478f83e95c3f Signed-off-by: Hoa Nguyen * configs: Add an example config of using KVM without perf Change-Id: Ic69fa7dac4f1a2c8fe23712b0fa77b5b22c5f2df Signed-off-by: Hoa Nguyen * Apply suggestions from code review Co-authored-by: Jason Lowe-Power * misc: Add an example to the panic Change-Id: Ic1fdfb955e5d8b9ad1d4f0a2bf30fa8050deba70 Signed-off-by: Hoa Nguyen * misc: Add warning of not using perf when using KVM CPU Change-Id: I96c0832fb48c63a79773665ca6228da778ef0497 Signed-off-by: Hoa Nguyen * misc: Fix stuff Change-Id: Ib407ae7407955b695f0e0f2718324f41bb0d768f Signed-off-by: Hoa Nguyen * misc: style fix Change-Id: I7275942e43f46140fdd52c975f76abb3c81b8b0a Signed-off-by: Hoa Nguyen --------- Signed-off-by: Hoa Nguyen Co-authored-by: Jason Lowe-Power --- .../x86-ubuntu-run-with-kvm-no-perf.py | 138 ++++++++++++++++++ src/cpu/kvm/BaseKvmCPU.py | 5 + src/cpu/kvm/base.cc | 84 ++++++++--- src/cpu/kvm/base.hh | 7 +- src/cpu/kvm/perfevent.cc | 16 +- 5 files changed, 221 insertions(+), 29 deletions(-) create mode 100644 configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py diff --git a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py new file mode 100644 index 0000000000..1c65357921 --- /dev/null +++ b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py @@ -0,0 +1,138 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" + +This script demonstrates how to use KVM CPU without perf. +This simulation boots Ubuntu 18.04 using 2 KVM CPUs without using perf. + +Usage +----- + +``` +scons build/X86/gem5.opt -j`nproc` +./build/X86/gem5.opt configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py +``` +""" + +from gem5.utils.requires import requires +from gem5.components.boards.x86_board import X86Board +from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import ( + MESITwoLevelCacheHierarchy, +) +from gem5.components.memory.single_channel import SingleChannelDDR4_2400 +from gem5.components.processors.simple_switchable_processor import ( + SimpleSwitchableProcessor, +) +from gem5.components.processors.cpu_types import CPUTypes +from gem5.isas import ISA +from gem5.coherence_protocol import CoherenceProtocol +from gem5.simulate.simulator import Simulator +from gem5.simulate.exit_event import ExitEvent +from gem5.resources.workload import Workload + +# This simulation requires using KVM with gem5 compiled for X86 simulation +# and with MESI_Two_Level cache coherence protocol. +requires( + isa_required=ISA.X86, + coherence_protocol_required=CoherenceProtocol.MESI_TWO_LEVEL, + kvm_required=True, +) + +from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import ( + MESITwoLevelCacheHierarchy, +) + +cache_hierarchy = MESITwoLevelCacheHierarchy( + l1d_size="32KiB", + l1d_assoc=8, + l1i_size="32KiB", + l1i_assoc=8, + l2_size="512KiB", + l2_assoc=16, + num_l2_banks=1, +) + +# Main memory +memory = SingleChannelDDR4_2400(size="3GiB") + +# This is a switchable CPU. We first boot Ubuntu using KVM, then the guest +# will exit the simulation by calling "m5 exit" (see the `command` variable +# below, which contains the command to be run in the guest after booting). +# Upon exiting from the simulation, the Exit Event handler will switch the +# CPU type (see the ExitEvent.EXIT line below, which contains a map to +# a function to be called when an exit event happens). +processor = SimpleSwitchableProcessor( + starting_core_type=CPUTypes.KVM, + switch_core_type=CPUTypes.TIMING, + isa=ISA.X86, + num_cores=2, +) + +# Here we tell the KVM CPU (the starting CPU) not to use perf. +for proc in processor.start: + proc.core.usePerf = False + +# Here we setup the board. The X86Board allows for Full-System X86 simulations. +board = X86Board( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Here we set the Full System workload. +# The `set_kernel_disk_workload` function for the X86Board takes a kernel, a +# disk image, and, optionally, a command to run. + +# This is the command to run after the system has booted. The first `m5 exit` +# will stop the simulation so we can switch the CPU cores from KVM to timing +# and continue the simulation to run the echo command, sleep for a second, +# then, again, call `m5 exit` to terminate the simulation. After simulation +# has ended you may inspect `m5out/system.pc.com_1.device` to see the echo +# output. +command = ( + "m5 exit;" + + "echo 'This is running on Timing CPU cores.';" + + "sleep 1;" + + "m5 exit;" +) + +workload = Workload("x86-ubuntu-18.04-boot") +workload.set_parameter("readfile_contents", command) +board.set_workload(workload) + +simulator = Simulator( + board=board, + on_exit_event={ + # Here we want override the default behavior for the first m5 exit + # exit event. Instead of exiting the simulator, we just want to + # switch the processor. The 2nd m5 exit after will revert to using + # default behavior where the simulator run will exit. + ExitEvent.EXIT: (func() for func in [processor.switch]) + }, +) +simulator.run() diff --git a/src/cpu/kvm/BaseKvmCPU.py b/src/cpu/kvm/BaseKvmCPU.py index f958e8126c..610663fa41 100644 --- a/src/cpu/kvm/BaseKvmCPU.py +++ b/src/cpu/kvm/BaseKvmCPU.py @@ -64,6 +64,11 @@ class BaseKvmCPU(BaseCPU): def support_take_over(cls): return True + usePerf = Param.Bool( + True, + "Use perf for gathering statistics from the guest and providing " + "statistic-related functionalities", + ) useCoalescedMMIO = Param.Bool(False, "Use coalesced MMIO (EXPERIMENTAL)") usePerfOverflow = Param.Bool( False, "Use perf event overflow counters (EXPERIMENTAL)" diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc index e22e1628d2..eaa771d8cf 100644 --- a/src/cpu/kvm/base.cc +++ b/src/cpu/kvm/base.cc @@ -71,12 +71,15 @@ BaseKvmCPU::BaseKvmCPU(const BaseKvmCPUParams ¶ms) alwaysSyncTC(params.alwaysSyncTC), threadContextDirty(true), kvmStateDirty(false), + usePerf(params.usePerf), vcpuID(-1), vcpuFD(-1), vcpuMMapSize(0), _kvmRun(NULL), mmioRing(NULL), pageSize(sysconf(_SC_PAGE_SIZE)), tickEvent([this]{ tick(); }, "BaseKvmCPU tick", false, Event::CPU_Tick_Pri), activeInstPeriod(0), + hwCycles(nullptr), + hwInstructions(nullptr), perfControlledByTimer(params.usePerfOverflow), hostFactor(params.hostFactor), stats(this), ctrInsts(0) @@ -96,6 +99,22 @@ BaseKvmCPU::BaseKvmCPU(const BaseKvmCPUParams ¶ms) thread->setStatus(ThreadContext::Halted); tc = thread->getTC(); threadContexts.push_back(tc); + + if ((!usePerf) && perfControlledByTimer) { + panic("KVM: invalid combination of parameters: cannot use " + "perfControlledByTimer without usePerf\n"); + } + + // If we use perf, we create new PerfKVMCounters + if (usePerf) { + hwCycles = std::unique_ptr(new PerfKvmCounter()); + hwInstructions = std::unique_ptr(new PerfKvmCounter()); + } else { + inform("Using KVM CPU without perf. The stats related to the number " + "of cycles and instructions executed by the KVM CPU will not " + "be updated. The stats should not be used for performance " + "evaluation."); + } } BaseKvmCPU::~BaseKvmCPU() @@ -248,7 +267,7 @@ BaseKvmCPU::restartEqThread() setupCounters(); if (p.usePerfOverflow) { - runTimer.reset(new PerfKvmTimer(hwCycles, + runTimer.reset(new PerfKvmTimer(*hwCycles, KVM_KICK_SIGNAL, p.hostFactor, p.hostFreq)); @@ -424,8 +443,10 @@ BaseKvmCPU::notifyFork() vcpuFD = -1; _kvmRun = NULL; - hwInstructions.detach(); - hwCycles.detach(); + if (usePerf) { + hwInstructions->detach(); + hwCycles->detach(); + } } } @@ -690,7 +711,9 @@ BaseKvmCPU::kvmRunDrain() uint64_t BaseKvmCPU::getHostCycles() const { - return hwCycles.read(); + if (usePerf) + return hwCycles->read(); + return 0; } Tick @@ -746,21 +769,26 @@ BaseKvmCPU::kvmRun(Tick ticks) // Get hardware statistics after synchronizing contexts. The KVM // state update might affect guest cycle counters. uint64_t baseCycles(getHostCycles()); - uint64_t baseInstrs(hwInstructions.read()); + uint64_t baseInstrs = 0; + if (usePerf) { + baseInstrs = hwInstructions->read(); + } // Arm the run timer and start the cycle timer if it isn't // controlled by the overflow timer. Starting/stopping the cycle // timer automatically starts the other perf timers as they are in // the same counter group. runTimer->arm(ticks); - if (!perfControlledByTimer) - hwCycles.start(); + if (usePerf && (!perfControlledByTimer)) { + hwCycles->start(); + } ioctlRun(); runTimer->disarm(); - if (!perfControlledByTimer) - hwCycles.stop(); + if (usePerf && (!perfControlledByTimer)) { + hwCycles->stop(); + } // The control signal may have been delivered after we exited // from KVM. It will be pending in that case since it is @@ -771,7 +799,10 @@ BaseKvmCPU::kvmRun(Tick ticks) const uint64_t hostCyclesExecuted(getHostCycles() - baseCycles); const uint64_t simCyclesExecuted(hostCyclesExecuted * hostFactor); - const uint64_t instsExecuted(hwInstructions.read() - baseInstrs); + uint64_t instsExecuted = 0; + if (usePerf) { + instsExecuted = hwInstructions->read() - baseInstrs; + } ticksExecuted = runTimer->ticksFromHostCycles(hostCyclesExecuted); /* Update statistics */ @@ -1288,13 +1319,14 @@ BaseKvmCPU::setupCounters() // We might be re-attaching counters due threads being // re-initialised after fork. - if (hwCycles.attached()) - hwCycles.detach(); + if (usePerf) { + if (hwCycles->attached()) { + hwCycles->detach(); + } - hwCycles.attach(cfgCycles, - 0); // TID (0 => currentThread) - - setupInstCounter(); + hwCycles->attach(cfgCycles, 0); // TID (0 => currentThread) + setupInstCounter(); + } } bool @@ -1344,10 +1376,16 @@ BaseKvmCPU::setupInstStop() void BaseKvmCPU::setupInstCounter(uint64_t period) { + // This function is for setting up instruction counter using perf + if (!usePerf) { + return; + } + // No need to do anything if we aren't attaching for the first // time or the period isn't changing. - if (period == activeInstPeriod && hwInstructions.attached()) + if (period == activeInstPeriod && hwInstructions->attached()) { return; + } PerfKvmCounterConfig cfgInstructions(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); @@ -1366,15 +1404,15 @@ BaseKvmCPU::setupInstCounter(uint64_t period) // We need to detach and re-attach the counter to reliably change // sampling settings. See PerfKvmCounter::period() for details. - if (hwInstructions.attached()) - hwInstructions.detach(); - assert(hwCycles.attached()); - hwInstructions.attach(cfgInstructions, + if (hwInstructions->attached()) + hwInstructions->detach(); + assert(hwCycles->attached()); + hwInstructions->attach(cfgInstructions, 0, // TID (0 => currentThread) - hwCycles); + *hwCycles); if (period) - hwInstructions.enableSignals(KVM_KICK_SIGNAL); + hwInstructions->enableSignals(KVM_KICK_SIGNAL); activeInstPeriod = period; } diff --git a/src/cpu/kvm/base.hh b/src/cpu/kvm/base.hh index 7bbf393f9b..3cf70a0bef 100644 --- a/src/cpu/kvm/base.hh +++ b/src/cpu/kvm/base.hh @@ -653,6 +653,9 @@ class BaseKvmCPU : public BaseCPU */ bool kvmStateDirty; + /** True if using perf; False otherwise*/ + bool usePerf; + /** KVM internal ID of the vCPU */ long vcpuID; @@ -763,7 +766,7 @@ class BaseKvmCPU : public BaseCPU * PerfKvmTimer (see perfControlledByTimer) to trigger exits from * KVM. */ - PerfKvmCounter hwCycles; + std::unique_ptr hwCycles; /** * Guest instruction counter. @@ -776,7 +779,7 @@ class BaseKvmCPU : public BaseCPU * @see setupInstBreak * @see scheduleInstStop */ - PerfKvmCounter hwInstructions; + std::unique_ptr hwInstructions; /** * Does the runTimer control the performance counters? diff --git a/src/cpu/kvm/perfevent.cc b/src/cpu/kvm/perfevent.cc index f9c317da41..c5e33abf82 100644 --- a/src/cpu/kvm/perfevent.cc +++ b/src/cpu/kvm/perfevent.cc @@ -173,12 +173,20 @@ PerfKvmCounter::attach(PerfKvmCounterConfig &config, { if (errno == EACCES) { - panic("PerfKvmCounter::attach recieved error EACCESS\n" + panic("PerfKvmCounter::attach received error EACCESS.\n" " This error may be caused by a too restrictive setting\n" - " in the file '/proc/sys/kernel/perf_event_paranoid'\n" - " The default value was changed to 2 in kernel 4.6\n" + " in the file '/proc/sys/kernel/perf_event_paranoid'.\n" + " The default value was changed to 2 in kernel 4.6.\n" " A value greater than 1 prevents gem5 from making\n" - " the syscall to perf_event_open"); + " the syscall to perf_event_open.\n" + " Alternatively, you can set the usePerf flag of the KVM\n" + " CPU to False. Setting this flag to False will limit some\n" + " functionalities of KVM CPU, such as counting the number of\n" + " cycles and the number of instructions, as well as the\n" + " ability of exiting to gem5 after a certain amount of cycles\n" + " or instructions when using KVM CPU. An example can be found\n" + " here, configs/example/gem5_library/" + "x86-ubuntu-run-with-kvm-no-perf.py."); } panic("PerfKvmCounter::attach failed (%i)\n", errno); } From 2a6d39aa888b9f39f8b775a317267b7a904fce4a Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Thu, 20 Jul 2023 10:43:32 -0700 Subject: [PATCH 100/693] misc: Split up tests in daily-tests.yaml This splits up the gem5 library example tests by Suite UID, as right now running them together uses the runner for a long period of time. It is important to note that doing this means additional tests from this directory will need to be manually added, such as the kvm tests. Change-Id: Ib2a0aca08f9b51b60e9dd0528324372cf2d98c05 --- .github/workflows/daily-tests.yaml | 188 ++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 3 deletions(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index a7d92a2ada..87059dd2ae 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -342,7 +342,9 @@ jobs: rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." - testlib-long-gem5_library_example_tests: + # split library example tests into runs based on Suite UID + # so that they don't hog the runners for too long + testlib-long-gem5_library_example_tests_x86_ubuntu_run_ALL_x86_64_opt: runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] @@ -363,9 +365,189 @@ jobs: name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} path: build/ALL_MESI_Two_Level - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - name: long gem5_library_example_tests + - name: long gem5_library_example_tests_x86_ubuntu_run_ALL_x86_64_opt working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/gem5_library_example_tests --length=long --skip-build -vv -t $(nproc) + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt --length=long --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-gem5_library_example_tests_riscv_ubuntu_run_ALL_x86_64_opt: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt + - name: long gem5_library_example_tests_riscv_ubuntu_run_ALL_x86_64_opt + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt --length=long --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-gem5_library_example_tests_lupv_example_ALL_x86_64_opt: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt + - name: long gem5_library_example_tests_lupv_example_ALL_x86_64_opt + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-lupv-example-ALL-x86_64-opt --length=long --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-gem5_library_example_tests_arm_ubuntu_run_test_ALL_x86_64_opt: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt + - name: long gem5_library_example_tests_arm_ubuntu_run_test_ALL_x86_64_opt + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt --length=long --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true + - run: echo "This job's status is ${{ job.status }}." + + testlib-long-gem5_library_example_tests_riscvmatched_hello_ALL_x86_64_opt: + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt + - name: long gem5_library_example_tests_riscvmatched_hello_ALL_x86_64_opt + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-riscvmatched-hello-ALL-x86_64-opt --length=long --skip-build -vv - name: create zip of results if: success() || failure() run: | From 3c6563d6f7cf35f5e801b7a1dc9363619bb55239 Mon Sep 17 00:00:00 2001 From: Kunal Pai <62979320+kunpai@users.noreply.github.com> Date: Thu, 20 Jul 2023 12:00:49 -0700 Subject: [PATCH 101/693] stdlib: Change resource compatibility warning (#91) * stdlib: Change resource compatibility warning If the gem5 version is "develop", the warning will not be thrown. Change-Id: Id2be1c4323c6ca06c5503c2885c1608f8d119420 * stdlib: Change resource compatibility warning If the gem5 version is "develop", the warning will not be thrown. Change-Id: Id2be1c4323c6ca06c5503c2885c1608f8d119420 * tests: Edit obtain_resources warning test Since we are editing the warning message for the develop branch, the test removes the warning message as well. Change-Id: I90882340188360bb3435344cdc14b324412c6c0e --------- Co-authored-by: Jason Lowe-Power --- .../resources/client_api/client_wrapper.py | 22 ++++++++++--------- .../pyunit_obtain_resources_check.py | 6 ----- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index d2baabc52d..ccb92cfb20 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -285,19 +285,21 @@ class ClientWrapper: return False if ( gem5_version + and not gem5_version.upper().startswith("DEVELOP") and not self._get_resources_compatible_with_gem5_version( [resource], gem5_version=gem5_version ) ): - warn( - f"Resource {resource['id']} with version " - f"{resource['resource_version']} is not known to be compatible" - f" with gem5 version {gem5_version}. " - "This may cause problems with your simulation. " - "This resource's compatibility " - "with different gem5 versions can be found here: " - "https://resources.gem5.org" - f"/resources/{resource['id']}/versions" - ) + if not gem5_version.upper().startswith("DEVELOP"): + warn( + f"Resource {resource['id']} with version " + f"{resource['resource_version']} is not known to be compatible" + f" with gem5 version {gem5_version}. " + "This may cause problems with your simulation. " + "This resource's compatibility " + "with different gem5 versions can be found here: " + "https://resources.gem5.org" + f"/resources/{resource['id']}/versions" + ) return False return True diff --git a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py index b1eda4e6ed..8c08cd88d5 100644 --- a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py @@ -110,12 +110,6 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_directory=self.get_resource_dir(), resource_version="1.5.0", ) - self.assertTrue( - f"warn: Resource test-binary-resource with version 1.5.0 is not known to be compatible with gem5 version {core.gem5Version}. " - "This may cause problems with your simulation. This resource's compatibility with different gem5 versions can be found here: " - f"https://resources.gem5.org/resources/test-binary-resource/versions" - in f.getvalue() - ) resource = obtain_resource( resource_id="test-binary-resource", From 29832849f7412aa145a5a83800d0527fb1f12bf1 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Thu, 20 Jul 2023 13:23:16 -0700 Subject: [PATCH 102/693] cpu-minor: Check pc valid before printing In https://gem5-review.googlesource.com/c/public/gem5/+/52047 inst.pc was changed from an object to a pointer. It is possible that this pointer is null (e.g., if there is an interrupt and there is a bubble). Make sure to check that it's not null before printing. I believe that other places this pointer is dereferenced without an explicit null check are safe, but I'm not certain. Change-Id: Idbe246cfdb62d4d75416d41b451fb3c076233bbc Signed-off-by: Jason Lowe-Power --- src/cpu/minor/dyn_inst.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cpu/minor/dyn_inst.cc b/src/cpu/minor/dyn_inst.cc index 68415ecd09..6ff5ed6b5e 100644 --- a/src/cpu/minor/dyn_inst.cc +++ b/src/cpu/minor/dyn_inst.cc @@ -112,6 +112,11 @@ MinorDynInst::reportData(std::ostream &os) const std::ostream & operator <<(std::ostream &os, const MinorDynInst &inst) { + if (!inst.pc) { + os << inst.id << " pc: 0x???????? (bubble)"; + return os; + } + os << inst.id << " pc: 0x" << std::hex << inst.pc->instAddr() << std::dec << " ("; @@ -169,7 +174,7 @@ MinorDynInst::minorTraceInst(const Named &named_object) const { if (isFault()) { minorInst(named_object, "id=F;%s addr=0x%x fault=\"%s\"\n", - id, pc->instAddr(), fault->name()); + id, pc ? pc->instAddr() : 0, fault->name()); } else { unsigned int num_src_regs = staticInst->numSrcRegs(); unsigned int num_dest_regs = staticInst->numDestRegs(); @@ -209,7 +214,7 @@ MinorDynInst::minorTraceInst(const Named &named_object) const minorInst(named_object, "id=%s addr=0x%x inst=\"%s\" class=%s" " flags=\"%s\"%s%s\n", - id, pc->instAddr(), + id, pc ? pc->instAddr() : 0, (staticInst->opClass() == No_OpClass ? "(invalid)" : staticInst->disassemble(0,NULL)), enums::OpClassStrings[staticInst->opClass()], From 427b4d596eae9a123ce46611803cefb44e45fef2 Mon Sep 17 00:00:00 2001 From: Adwaith R Krishna Date: Fri, 21 Jul 2023 02:26:31 +0530 Subject: [PATCH 103/693] mem-garnet: Fix packet_id val in flit (#72) Change-Id: I163b5a32972783bf2e99f3383b9f86776577b727 Co-authored-by: Bobby R. Bruce --- src/mem/ruby/network/garnet/flit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/ruby/network/garnet/flit.cc b/src/mem/ruby/network/garnet/flit.cc index d31d826c93..21e6dcdc33 100644 --- a/src/mem/ruby/network/garnet/flit.cc +++ b/src/mem/ruby/network/garnet/flit.cc @@ -51,7 +51,7 @@ flit::flit(int packet_id, int id, int vc, int vnet, RouteInfo route, int size, m_enqueue_time = curTime; m_dequeue_time = curTime; m_time = curTime; - m_packet_id = id; + m_packet_id = packet_id; m_id = id; m_vnet = vnet; m_vc = vc; From 573573b5ba04d5022ea58045e2dc3ba7183eebb2 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 20 Jul 2023 15:04:06 -0700 Subject: [PATCH 104/693] base: Add `maybe_unused` to `findLsbSetFallback` When compiling with clang-14 I received the following error: ``` src/base/bitfield.hh:328:1: error: function 'findLsbSetFallback' is not needed and will not be emitted [-Werror,-Wunneeded-internal-declaration] ``` This function was introduced in PR #76. This fixes this compiler warning/error by using `[[maybe_unused]]`. Change-Id: I0b99eab0a9e42ee1687e7a0594a5a7bf9588b422 --- src/base/bitfield.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index c2eeb1fb55..29f8929065 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -324,6 +324,7 @@ hasBuiltinCtz() { #endif } +[[maybe_unused]] int findLsbSetFallback(uint64_t val) { // Create a mask with val's trailing zeros flipped to 1, lsb set flipped to From 01623fac68d18fd96eaf981798f75e39d75ea260 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 20 Jul 2023 23:08:39 -0700 Subject: [PATCH 105/693] stdlib,configs,tests: Remove deprecated Resource classes usage (#102) * stdlib,configs,tests: Remove `Resource` class use This class is deprecated, but was still used in various example configuration scriots and tests. This patch replaces it with the `obtain_resource` function. Change-Id: I0c89bf17783ccaaafc18072aaeefb5d1e207bc55 * configs: Remove `CustomDiskImageResource` use The class is deprecated but was still used in the SPEC example scripts. This patch replaces it with the `DiskImageResource` class. Change-Id: Ie0697fe59a3d737b05eb45ff3bc964f42b0387e0 * configs,tests: Remove `CustomResource` use This class is deprecated but was still used in example scripts and mentioned, incorrectly, in comments in the pyunit tests. This patch removes these. Change-Id: Icb6d02f47a5b72cd58551e5dcd59cc72d6a91a01 * stdlib: Remove '\' in Workload docstring example This example shows how to use the Workload. The backslash is not correct Python and would fail if used in this way. Co-authored-by: Jason Lowe-Power --------- Co-authored-by: Jason Lowe-Power --- configs/example/gem5_library/arm-hello.py | 4 ++-- .../checkpoints/riscv-hello-restore-checkpoint.py | 6 +++--- .../checkpoints/riscv-hello-save-checkpoint.py | 4 ++-- .../gem5_library/dramsys/arm-hello-dramsys.py | 4 ++-- configs/example/gem5_library/power-hello.py | 4 ++-- configs/example/gem5_library/riscv-fs.py | 6 +++--- configs/example/gem5_library/riscvmatched-hello.py | 4 ++-- .../example/gem5_library/x86-gapbs-benchmarks.py | 6 +++--- configs/example/gem5_library/x86-npb-benchmarks.py | 6 +++--- .../example/gem5_library/x86-parsec-benchmarks.py | 6 +++--- .../gem5_library/x86-spec-cpu2006-benchmarks.py | 6 ++---- .../gem5_library/x86-spec-cpu2017-benchmarks.py | 10 ++++------ configs/example/lupv/run_lupv.py | 6 +++--- configs/example/sst/riscv_fs.py | 4 ++-- src/python/gem5/resources/workload.py | 14 ++++++++------ src/python/gem5/utils/multiprocessing/README.md | 4 ++-- tests/gem5/configs/arm_boot_exit_run.py | 8 ++++---- tests/gem5/configs/boot_kvm_fork_run.py | 6 +++--- tests/gem5/configs/boot_kvm_switch_exit.py | 6 +++--- tests/gem5/configs/parsec_disk_run.py | 6 +++--- tests/gem5/configs/simple_binary_run.py | 6 ++++-- tests/gem5/configs/simulator_exit_event_run.py | 4 ++-- tests/gem5/to_tick/configs/tick-exit.py | 4 ++-- tests/gem5/to_tick/configs/tick-to-max.py | 4 ++-- .../stdlib/resources/pyunit_workload_checks.py | 8 ++++---- 25 files changed, 73 insertions(+), 73 deletions(-) diff --git a/configs/example/gem5_library/arm-hello.py b/configs/example/gem5_library/arm-hello.py index b4180f11eb..721d71c2cb 100644 --- a/configs/example/gem5_library/arm-hello.py +++ b/configs/example/gem5_library/arm-hello.py @@ -43,7 +43,7 @@ scons build/ARM/gem5.opt from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard @@ -84,7 +84,7 @@ board.set_se_binary_workload( # Any resource specified in this file will be automatically retrieved. # At the time of writing, this file is a WIP and does not contain all # resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096 - Resource("arm-hello64-static") + obtain_resource("arm-hello64-static") ) # Lastly we run the simulation. diff --git a/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py b/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py index 60a7dd0f59..9f9bf839a6 100644 --- a/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py @@ -48,7 +48,7 @@ scons build/RISCV/gem5.opt from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard @@ -89,8 +89,8 @@ board = SimpleBoard( # configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py board.set_se_binary_workload( # the workload should be the same as the save-checkpoint script - Resource("riscv-hello"), - checkpoint=Resource("riscv-hello-example-checkpoint-v23"), + obtain_resource("riscv-hello"), + checkpoint=obtain_resource("riscv-hello-example-checkpoint-v23"), ) simulator = Simulator( diff --git a/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py b/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py index 439d2054fa..234153a57f 100644 --- a/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py @@ -46,7 +46,7 @@ scons build/RISCV/gem5.opt import argparse from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard @@ -101,7 +101,7 @@ board.set_se_binary_workload( # Any resource specified in this file will be automatically retrieved. # At the time of writing, this file is a WIP and does not contain all # resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096 - Resource("riscv-hello") + obtain_resource("riscv-hello") ) # Lastly we run the simulation. diff --git a/configs/example/gem5_library/dramsys/arm-hello-dramsys.py b/configs/example/gem5_library/dramsys/arm-hello-dramsys.py index ae0f51ad40..ae2b4bb5b6 100644 --- a/configs/example/gem5_library/dramsys/arm-hello-dramsys.py +++ b/configs/example/gem5_library/dramsys/arm-hello-dramsys.py @@ -35,7 +35,7 @@ correctly. If this is not done correctly this script will run with error. from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.memory import DRAMSysDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard @@ -78,7 +78,7 @@ board.set_se_binary_workload( # Any resource specified in this file will be automatically retrieved. # At the time of writing, this file is a WIP and does not contain all # resources. Jira ticket: https://gem5.atlassian.net/browse/GEM5-1096 - Resource("arm-hello64-static") + obtain_resource("arm-hello64-static") ) # Lastly we run the simulation. diff --git a/configs/example/gem5_library/power-hello.py b/configs/example/gem5_library/power-hello.py index cf31778945..59020643e0 100644 --- a/configs/example/gem5_library/power-hello.py +++ b/configs/example/gem5_library/power-hello.py @@ -43,7 +43,7 @@ scons build/POWER/gem5.opt from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.memory import SingleChannelDDR4_2400 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard @@ -75,7 +75,7 @@ board = SimpleBoard( cache_hierarchy=cache_hierarchy, ) -board.set_se_binary_workload(Resource("power-hello")) +board.set_se_binary_workload(obtain_resource("power-hello")) # Lastly we run the simulation. simulator = Simulator(board=board) diff --git a/configs/example/gem5_library/riscv-fs.py b/configs/example/gem5_library/riscv-fs.py index e4dce027e3..8a0de6c688 100644 --- a/configs/example/gem5_library/riscv-fs.py +++ b/configs/example/gem5_library/riscv-fs.py @@ -48,7 +48,7 @@ from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierar from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator # Run a check to ensure the right version of gem5 is being used. @@ -79,8 +79,8 @@ board = RiscvBoard( # Set the Full System workload. board.set_kernel_disk_workload( - kernel=Resource("riscv-bootloader-vmlinux-5.10"), - disk_image=Resource("riscv-disk-img"), + kernel=obtain_resource("riscv-bootloader-vmlinux-5.10"), + disk_image=obtain_resource("riscv-disk-img"), ) simulator = Simulator(board=board) diff --git a/configs/example/gem5_library/riscvmatched-hello.py b/configs/example/gem5_library/riscvmatched-hello.py index e7b4cf7128..a11ec39159 100644 --- a/configs/example/gem5_library/riscvmatched-hello.py +++ b/configs/example/gem5_library/riscvmatched-hello.py @@ -37,7 +37,7 @@ scons build/RISCV/gem5.opt ``` """ -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard from gem5.isas import ISA @@ -49,7 +49,7 @@ requires(isa_required=ISA.RISCV) board = RISCVMatchedBoard() # set the hello world riscv binary as the board workload -board.set_se_binary_workload(Resource("riscv-hello")) +board.set_se_binary_workload(obtain_resource("riscv-hello")) # run the simulation with the RISCV Matched board simulator = Simulator(board=board, full_system=False) diff --git a/configs/example/gem5_library/x86-gapbs-benchmarks.py b/configs/example/gem5_library/x86-gapbs-benchmarks.py index b85ce6e7e8..c20d2ea4cc 100644 --- a/configs/example/gem5_library/x86-gapbs-benchmarks.py +++ b/configs/example/gem5_library/x86-gapbs-benchmarks.py @@ -63,7 +63,7 @@ from gem5.components.processors.simple_switchable_processor import ( from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent @@ -203,10 +203,10 @@ board.set_kernel_disk_workload( # The x86 linux kernel will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. # gapbs benchamarks was tested with kernel version 4.19.83 - kernel=Resource("x86-linux-kernel-4.19.83"), + kernel=obtain_resource("x86-linux-kernel-4.19.83"), # The x86-gapbs image will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. - disk_image=Resource("x86-gapbs"), + disk_image=obtain_resource("x86-gapbs"), readfile_contents=command, ) diff --git a/configs/example/gem5_library/x86-npb-benchmarks.py b/configs/example/gem5_library/x86-npb-benchmarks.py index cffba5a294..47a62b9fa5 100644 --- a/configs/example/gem5_library/x86-npb-benchmarks.py +++ b/configs/example/gem5_library/x86-npb-benchmarks.py @@ -60,7 +60,7 @@ from gem5.components.processors.simple_switchable_processor import ( from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator from gem5.simulate.simulator import ExitEvent @@ -204,10 +204,10 @@ board.set_kernel_disk_workload( # The x86 linux kernel will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. # npb benchamarks was tested with kernel version 4.19.83 - kernel=Resource("x86-linux-kernel-4.19.83"), + kernel=obtain_resource("x86-linux-kernel-4.19.83"), # The x86-npb image will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. - disk_image=Resource("x86-npb"), + disk_image=obtain_resource("x86-npb"), readfile_contents=command, ) diff --git a/configs/example/gem5_library/x86-parsec-benchmarks.py b/configs/example/gem5_library/x86-parsec-benchmarks.py index aaffec8edc..15f063be92 100644 --- a/configs/example/gem5_library/x86-parsec-benchmarks.py +++ b/configs/example/gem5_library/x86-parsec-benchmarks.py @@ -59,7 +59,7 @@ from gem5.components.processors.simple_switchable_processor import ( from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent @@ -185,10 +185,10 @@ board.set_kernel_disk_workload( # The x86 linux kernel will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. # PARSEC benchamarks were tested with kernel version 4.19.83 - kernel=Resource("x86-linux-kernel-4.19.83"), + kernel=obtain_resource("x86-linux-kernel-4.19.83"), # The x86-parsec image will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. - disk_image=Resource("x86-parsec"), + disk_image=obtain_resource("x86-parsec"), readfile_contents=command, ) diff --git a/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py b/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py index 10d5da0adb..63a7b6b236 100644 --- a/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py +++ b/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py @@ -65,7 +65,7 @@ from gem5.components.processors.simple_switchable_processor import ( from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import Resource, CustomDiskImageResource +from gem5.resources.resource import Resource, DiskImageResource from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent @@ -261,9 +261,7 @@ board.set_kernel_disk_workload( # 5.4.49 kernel=Resource("x86-linux-kernel-4.19.83"), # The location of the x86 SPEC CPU 2017 image - disk_image=CustomDiskImageResource( - args.image, root_partition=args.partition - ), + disk_image=DiskImageResource(args.image, root_partition=args.partition), readfile_contents=command, ) diff --git a/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py b/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py index cb5f5d19e3..348c26f1ff 100644 --- a/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py +++ b/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py @@ -63,7 +63,7 @@ from gem5.components.processors.simple_switchable_processor import ( from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import Resource, CustomDiskImageResource +from gem5.resources.resource import obtain_resource, DiskImageResource from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent @@ -268,18 +268,16 @@ except FileExistsError: command = f"{args.benchmark} {args.size} {output_dir}" -# For enabling CustomResource, we pass an additional parameter to mount the +# For enabling DiskImageResource, we pass an additional parameter to mount the # correct partition. board.set_kernel_disk_workload( # The x86 linux kernel will be automatically downloaded to the # `~/.cache/gem5` directory if not already present. # SPEC CPU2017 benchamarks were tested with kernel version 4.19.83 - kernel=Resource("x86-linux-kernel-4.19.83"), + kernel=obtain_resource("x86-linux-kernel-4.19.83"), # The location of the x86 SPEC CPU 2017 image - disk_image=CustomDiskImageResource( - args.image, root_partition=args.partition - ), + disk_image=DiskImageResource(args.image, root_partition=args.partition), readfile_contents=command, ) diff --git a/configs/example/lupv/run_lupv.py b/configs/example/lupv/run_lupv.py index d92ea3fa3f..e106d051e7 100644 --- a/configs/example/lupv/run_lupv.py +++ b/configs/example/lupv/run_lupv.py @@ -42,7 +42,7 @@ from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.utils.requires import requires -from gem5.resources.resource import Resource, CustomResource +from gem5.resources.resource import obtain_resource import argparse @@ -98,8 +98,8 @@ board = LupvBoard( # Set the Full System workload. board.set_kernel_disk_workload( - kernel=Resource("riscv-lupio-linux-kernel"), - disk_image=Resource("riscv-lupio-busybox-img"), + kernel=obtain_resource("riscv-lupio-linux-kernel"), + disk_image=obtain_resource("riscv-lupio-busybox-img"), ) diff --git a/configs/example/sst/riscv_fs.py b/configs/example/sst/riscv_fs.py index fc8f8618c4..77db9e4dbe 100644 --- a/configs/example/sst/riscv_fs.py +++ b/configs/example/sst/riscv_fs.py @@ -29,7 +29,7 @@ from m5.objects import * from os import path # For downloading the disk image -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource import argparse @@ -139,7 +139,7 @@ cpu_clock_rate = args.cpu_clock_rate memory_size = args.memory_size # Try downloading the Resource -bbl_resource = Resource("riscv-boot-exit-nodisk") +bbl_resource = obtain_resource("riscv-boot-exit-nodisk") bbl_path = bbl_resource.get_local_path() system = System() diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index 0798b891ab..5b25bf879f 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -52,7 +52,7 @@ class AbstractWorkload: workload = CustomWorkload( function = "set_se_binary_workload", parameters = { - "binary" : Resource("x86-print-this"), + "binary" : obtain_resource("x86-print-this"), "arguments" : ["hello", 6] }, ) @@ -64,7 +64,7 @@ class AbstractWorkload: ```py board.set_se_binary_workload( - binary = Resource("x86-print-this"), + binary = obtain_resource("x86-print-this"), arguments = ["hello", 6], ) ``` @@ -121,7 +121,7 @@ class CustomWorkload(AbstractWorkload): workload = CustomWorkload( function = "set_se_binary_workload", parameters = { - "binary" : Resource("x86-print-this"), + "binary" : obtain_resource("x86-print-this"), "arguments" : ["hello", 6] }, ) @@ -148,7 +148,9 @@ class Workload(AbstractWorkload): # Optionally we can override a parameter in the workload. In this example # we are going to run this workload with a difference kernel. - workload.set_parameter("kernel", Resource("arm64-linux-kernel-4.14.134")) + workload.set_parameter("kernel", + obtain_resource("arm64-linux-kernel-4.14.134") + ) # We then set this workload to the board. board.set_workload(workload) @@ -193,8 +195,8 @@ class Workload(AbstractWorkload): ```python board.set_kernel_disk_workload( - kernel = Resource("x86-linux-kernel-5.4.49"), - disk-image = Resource("x86-ubuntu-18.04-img"), + kernel = obtain_resource("x86-linux-kernel-5.4.49"), + disk-image = obtain_resource("x86-ubuntu-18.04-img"), readfile_contents = "m5_exit; echo 'hello'; m5_exit", ) ``` diff --git a/src/python/gem5/utils/multiprocessing/README.md b/src/python/gem5/utils/multiprocessing/README.md index da2116c44c..c6b0406e54 100644 --- a/src/python/gem5/utils/multiprocessing/README.md +++ b/src/python/gem5/utils/multiprocessing/README.md @@ -48,8 +48,8 @@ def run_sim(name): from gem5.simulate.simulator import Simulator board = X86DemoBoard() board.set_kernel_disk_workload( - kernel=Resource("x86-linux-kernel-5.4.49"), - disk_image=Resource("x86-ubuntu-18.04-img"), + kernel=obtain_resource("x86-linux-kernel-5.4.49"), + disk_image=obtain_resource("x86-ubuntu-18.04-img"), ) simulator = Simulator(board=board) simulator.run(max_ticks=10000000) diff --git a/tests/gem5/configs/arm_boot_exit_run.py b/tests/gem5/configs/arm_boot_exit_run.py index a8ea6eeea7..ffb41459f5 100644 --- a/tests/gem5/configs/arm_boot_exit_run.py +++ b/tests/gem5/configs/arm_boot_exit_run.py @@ -36,7 +36,7 @@ Characteristics from gem5.isas import ISA from m5.objects import ArmDefaultRelease from gem5.utils.requires import requires -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator from m5.objects import VExpress_GEM5_Foundation from gem5.coherence_protocol import CoherenceProtocol @@ -199,15 +199,15 @@ board = ArmBoard( # Set the Full System workload. board.set_kernel_disk_workload( - kernel=Resource( + kernel=obtain_resource( "arm64-linux-kernel-5.4.49", resource_directory=args.resource_directory, ), - bootloader=Resource( + bootloader=obtain_resource( "arm64-bootloader-foundation", resource_directory=args.resource_directory, ), - disk_image=Resource( + disk_image=obtain_resource( "arm64-ubuntu-20.04-img", resource_directory=args.resource_directory, ), diff --git a/tests/gem5/configs/boot_kvm_fork_run.py b/tests/gem5/configs/boot_kvm_fork_run.py index 84e273d842..cb6d1b44e1 100644 --- a/tests/gem5/configs/boot_kvm_fork_run.py +++ b/tests/gem5/configs/boot_kvm_fork_run.py @@ -55,7 +55,7 @@ from gem5.components.processors.cpu_types import ( from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.runtime import get_runtime_coherence_protocol from gem5.utils.requires import requires @@ -179,10 +179,10 @@ kernel_args = motherboard.get_default_kernel_args() + [args.kernel_args] # Set the Full System workload. motherboard.set_kernel_disk_workload( - kernel=Resource( + kernel=obtain_resource( "x86-linux-kernel-5.4.49", resource_directory=args.resource_directory ), - disk_image=Resource( + disk_image=obtain_resource( "x86-ubuntu-18.04-img", resource_directory=args.resource_directory ), readfile_contents=dedent( diff --git a/tests/gem5/configs/boot_kvm_switch_exit.py b/tests/gem5/configs/boot_kvm_switch_exit.py index 1347e68ba4..2d21261161 100644 --- a/tests/gem5/configs/boot_kvm_switch_exit.py +++ b/tests/gem5/configs/boot_kvm_switch_exit.py @@ -45,7 +45,7 @@ from gem5.components.processors.cpu_types import ( from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.runtime import get_runtime_coherence_protocol from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent @@ -165,10 +165,10 @@ kernal_args = motherboard.get_default_kernel_args() + [args.kernel_args] # Set the Full System workload. motherboard.set_kernel_disk_workload( - kernel=Resource( + kernel=obtain_resource( "x86-linux-kernel-5.4.49", resource_directory=args.resource_directory ), - disk_image=Resource( + disk_image=obtain_resource( "x86-ubuntu-18.04-img", resource_directory=args.resource_directory ), # The first exit signals to switch processors. diff --git a/tests/gem5/configs/parsec_disk_run.py b/tests/gem5/configs/parsec_disk_run.py index 5c2fa75f65..a0911d46e3 100644 --- a/tests/gem5/configs/parsec_disk_run.py +++ b/tests/gem5/configs/parsec_disk_run.py @@ -37,7 +37,7 @@ Notes import m5.stats -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.boards.x86_board import X86Board from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.simple_switchable_processor import ( @@ -205,10 +205,10 @@ command = ( ) board.set_kernel_disk_workload( - kernel=Resource( + kernel=obtain_resource( "x86-linux-kernel-5.4.49", resource_directory=args.resource_directory ), - disk_image=Resource( + disk_image=obtain_resource( "x86-parsec", resource_directory=args.resource_directory ), readfile_contents=command, diff --git a/tests/gem5/configs/simple_binary_run.py b/tests/gem5/configs/simple_binary_run.py index f5e097eaae..1ad4897415 100644 --- a/tests/gem5/configs/simple_binary_run.py +++ b/tests/gem5/configs/simple_binary_run.py @@ -30,7 +30,7 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.processors.cpu_types import ( get_cpu_types_str_set, get_cpu_type_from_str, @@ -135,7 +135,9 @@ motherboard = SimpleBoard( ) # Set the workload -binary = Resource(args.resource, resource_directory=args.resource_directory) +binary = obtain_resource( + args.resource, resource_directory=args.resource_directory +) motherboard.set_se_binary_workload(binary, arguments=args.arguments) # Run the simulation diff --git a/tests/gem5/configs/simulator_exit_event_run.py b/tests/gem5/configs/simulator_exit_event_run.py index f4e8ab9ce8..c34cfe3ec9 100644 --- a/tests/gem5/configs/simulator_exit_event_run.py +++ b/tests/gem5/configs/simulator_exit_event_run.py @@ -45,7 +45,7 @@ By default a generator is passed to define the evit_event. A list of functions can also be passed. This is enabled by passing the `--list-format` flag. """ -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache @@ -101,7 +101,7 @@ motherboard = SimpleBoard( # Set the workload # Note: Here we're using the "x86-m5-exit-repeat" resource. This calls an # `m5_exit(0)` command in an infinite while-loop. -binary = Resource( +binary = obtain_resource( "x86-m5-exit-repeat", resource_directory=args.resource_directory ) motherboard.set_se_binary_workload(binary) diff --git a/tests/gem5/to_tick/configs/tick-exit.py b/tests/gem5/to_tick/configs/tick-exit.py index 9b412cbfb6..4f13d723fa 100644 --- a/tests/gem5/to_tick/configs/tick-exit.py +++ b/tests/gem5/to_tick/configs/tick-exit.py @@ -28,7 +28,7 @@ """ -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.isas import ISA from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.boards.simple_board import SimpleBoard @@ -76,7 +76,7 @@ motherboard = SimpleBoard( ) # Set the workload -binary = Resource( +binary = obtain_resource( "x86-hello64-static", resource_directory=args.resource_directory ) motherboard.set_se_binary_workload(binary) diff --git a/tests/gem5/to_tick/configs/tick-to-max.py b/tests/gem5/to_tick/configs/tick-to-max.py index 2b679df412..89396915cf 100644 --- a/tests/gem5/to_tick/configs/tick-to-max.py +++ b/tests/gem5/to_tick/configs/tick-to-max.py @@ -33,7 +33,7 @@ run before, at, or after the running of `simulator.run`. time. """ -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.isas import ISA from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.boards.simple_board import SimpleBoard @@ -97,7 +97,7 @@ motherboard = SimpleBoard( ) # Set the workload -binary = Resource( +binary = obtain_resource( "x86-hello64-static", resource_directory=args.resource_directory ) motherboard.set_se_binary_workload(binary) diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index b374e7a8d3..ef7c3caba1 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -72,14 +72,14 @@ class CustomWorkloadTestSuite(unittest.TestCase): ) def test_get_function_str(self) -> None: - # Tests `CustomResource.get_function_str` + # Tests `CustomWorkload.get_function_str` self.assertEqual( "set_se_binary_workload", self.custom_workload.get_function_str() ) def test_get_parameters(self) -> None: - # Tests `CustomResource.get_parameter` + # Tests `CustomWorkload.get_parameter` parameters = self.custom_workload.get_parameters() self.assertTrue(isinstance(parameters, Dict)) @@ -95,7 +95,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): self.assertEquals(6, parameters["arguments"][1]) def test_add_parameters(self) -> None: - # Tests `CustomResource.set_parameter` for the case where we add a new + # Tests `CustomWorkload.set_parameter` for the case where we add a new # parameter value. self.custom_workload.set_parameter("test_param", 10) @@ -109,7 +109,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): del self.custom_workload.get_parameters()["test_param"] def test_override_parameter(self) -> None: - # Tests `CustomResource.set_parameter` for the case where we override + # Tests `CustomWorkload.set_parameter` for the case where we override # a parameter's value. old_value = self.custom_workload.get_parameters()["binary"] From 75b6fa5ad11e93f37a97a9388ddbf2d787457938 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Fri, 21 Jul 2023 20:11:09 +0200 Subject: [PATCH 106/693] base: Ostream helpers (iterable, tuple, pair, enum, pointers, optional) (#77) * base: Enable stl_helpers::operator<< in _formatString The string format (%s) eventually relies on bare operator<< to display any type T. This gives the opportunity to use the helpers in stl_helpers. This patch enables printing enums, pairs, tuples, vectors, maps and others in a PRINTF debug macro without any extra manual operation. Change-Id: I8ac85133ebadcb95354598c1cfe687d8fffb89e2 * base: Add Printer util class to force use of operator<< helpers Wrapping any value in a Printer instance before using operator<< will force the use of stl_helpers::operator<<. Change-Id: I7b505194eeabc3e0721effd9b5ce98f9e151b807 * base: Fix typo in ostream_helpers.hh Change-Id: I283a5414f3add4f18649b77153dcbcc8661bc81e * base: Disambiguate null optional representation in ostream helper Change-Id: I5b093555688566cc405248d3a448a8f3efa67888 * base: Add unit test for std::optional ostream helper Change-Id: I6fb9ced5e6461de5685638a162b5534e10710e20 * base: Ostream helpers Printer unit test Change-Id: I11db89e85fd40c12bceecb41cadee78b8e871d7b * base: Unit test for ostream helpers for pointers and smart ptr Change-Id: Ifa87e8b69fdd9a4869250ab40311f352e8f54ed9 * base: Coding style fix in ostream_helpers.test.cc Change-Id: I095c7048fad35e63f979aa601bfc8cde65c9077b * base: Test shared_ptr in ostream_helpers.test.cc Change-Id: I553df0614f1dd6eef2061c4dc1794af8c543b78f --------- Co-authored-by: Gabriel Busnot --- src/base/cprintf_formats.hh | 3 ++ src/base/stl_helpers/ostream_helpers.hh | 36 +++++++++++-- src/base/stl_helpers/ostream_helpers.test.cc | 54 +++++++++++++++++++- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 4a64780c4a..e4c1048e01 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -34,6 +34,8 @@ #include #include +#include "base/stl_helpers.hh" + namespace gem5 { @@ -221,6 +223,7 @@ template static inline void _formatString(std::ostream &out, const T &data, Format &fmt) { + using stl_helpers::operator<<; if (fmt.width > 0) { std::stringstream foo; foo << data; diff --git a/src/base/stl_helpers/ostream_helpers.hh b/src/base/stl_helpers/ostream_helpers.hh index a1c92e1ed1..680d55f23c 100644 --- a/src/base/stl_helpers/ostream_helpers.hh +++ b/src/base/stl_helpers/ostream_helpers.hh @@ -41,6 +41,19 @@ namespace gem5::stl_helpers { +/* + * Wrap any object in a Printer object to force using a opExtract_impl printing + * function. This is not required for types that do not already enable + * operator<< in another namespace. However, to enable the special printing + * function for, e.g., raw pointers, those must be wrapped in a Printer. + */ +template +struct Printer +{ + Printer(const T& value): value{value} {} + const T& value; +}; + namespace opExtract_impl { @@ -51,7 +64,7 @@ namespace opExtract_impl * mechanism is used. The only entry point in the system is through a primary * dispatch function that won't resolve for non-helped types. Then, recursive * calls go through the secondary dispatch interface that sort between helped - * and non-helped types. Helped typed will enter the system back through the + * and non-helped types. Helped types will enter the system back through the * primary dispatch interface while other types will look for operator<< * through regular lookup, especially ADL. */ @@ -106,7 +119,7 @@ opExtractPrimDisp(std::ostream& os, const std::optional& o) if (o) { return opExtractSecDisp(os, *o); } else { - return os << '-'; + return os << "(-)"; } } @@ -128,6 +141,10 @@ opExtractPrimDisp(std::ostream& os, const std::unique_ptr& p) return opExtractPrimDisp(os, p.get()); } +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const Printer& p); + template constexpr bool isOpExtractNativelySupported = false; @@ -166,6 +183,18 @@ opExtractPrimDisp(std::ostream& os, T* p) } } +template +std::ostream& +opExtractPrimDisp(std::ostream& os, const Printer& p) +{ + if constexpr (isOpExtractHelped) { + return opExtractPrimDisp(os, p.value); + } else { + return os << p.value; + } +} + + template std::ostream& opExtractSecDisp(std::ostream& os, const T& v) @@ -179,7 +208,8 @@ opExtractSecDisp(std::ostream& os, const T& v) } // namespace opExtract_impl -// Add "using stl_helpers::operator<<" in the scope where you want to use it. +// use the Printer wrapper or add "using stl_helpers::operator<<" in the scope +// where you want to use that operator<<. template std::enable_if_t, std::ostream&> operator<<(std::ostream& os, const T& v) diff --git a/src/base/stl_helpers/ostream_helpers.test.cc b/src/base/stl_helpers/ostream_helpers.test.cc index 19a1ece27e..84c936f4a8 100644 --- a/src/base/stl_helpers/ostream_helpers.test.cc +++ b/src/base/stl_helpers/ostream_helpers.test.cc @@ -34,9 +34,9 @@ #include "base/stl_helpers/ostream_helpers.hh" -using gem5::stl_helpers::operator<<; TEST(OstreamHelpers, pair) { + using gem5::stl_helpers::operator<<; auto p = std::make_pair(1, 2); std::ostringstream os; os << p; @@ -44,6 +44,7 @@ TEST(OstreamHelpers, pair) { } TEST(OstreamHelpers, tuple) { + using gem5::stl_helpers::operator<<; auto t = std::make_tuple(true, std::make_pair("Hello", std::string_view("World")), '!'); std::ostringstream os; @@ -52,6 +53,7 @@ TEST(OstreamHelpers, tuple) { } TEST(OstreamHelpers, vector) { + using gem5::stl_helpers::operator<<; auto v = std::vector{"abc", "defg", "hijklm", "\n"}; std::ostringstream os; os << v; @@ -59,8 +61,58 @@ TEST(OstreamHelpers, vector) { } TEST(OstreamHelpers, map) { + using gem5::stl_helpers::operator<<; auto m = std::map{{'a', 0}, {'b', 1}, {'c', 2}, {'d', 3}}; std::ostringstream os; os << m; EXPECT_EQ(os.str(), "[ (a, 0), (b, 1), (c, 2), (d, 3), ]"); } + +TEST(OstreamHelpers, optional) { + using gem5::stl_helpers::operator<<; + auto m = std::make_optional(42); + std::ostringstream os; + os << m; + EXPECT_EQ(os.str(), "42"); + os.str(""); + m.reset(); + os << m; + EXPECT_EQ(os.str(), "(-)"); +} + +TEST(OstreamHelpers, printer) { + std::string hello = "Hello"; + std::ostringstream os; + os << hello; + EXPECT_EQ(os.str(), hello); + + std::ostringstream os2; + os2 << gem5::stl_helpers::Printer(hello); + EXPECT_EQ(os2.str(), "[ H, e, l, l, o, ]"); +} + + +TEST(OstreamHelpers, pointers) { + auto helped_representation = [](const auto& val) { + std::ostringstream os; + os << gem5::stl_helpers::Printer(val); + return os.str(); + }; + auto expected_representation = [&](const auto& ptr) { + using gem5::stl_helpers::operator<<; + std::ostringstream os; + auto* raw_ptr = &*ptr; + os << '(' << raw_ptr << ": " << *ptr << ')'; + return os.str(); + }; + + int x = 42; + auto* ptr = &x; + EXPECT_EQ(helped_representation(ptr), expected_representation(ptr)); + + auto uptr = std::make_unique("Hello, World!"); + EXPECT_EQ(helped_representation(uptr), expected_representation(uptr)); + + auto sptr = std::make_shared>(); + EXPECT_EQ(helped_representation(sptr), expected_representation(sptr)); +} From 0dd43346226150330ee3e969b338c31e1e6d21c2 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Fri, 21 Jul 2023 12:36:24 -0700 Subject: [PATCH 107/693] misc: Add workflow to close stale issues (#96) Create a new workflow file that will hold jobs that are for managing the repository, issues, prs, etc. This changeset then adds a job to close issues that have been open for 30 days without a response someone marks the issue as "needs details." Change-Id: I23b9b6aa5fa67f205e116c88d5449cb69f53b6f9 Signed-off-by: Jason Lowe-Power --- .github/workflows/utils.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/utils.yaml diff --git a/.github/workflows/utils.yaml b/.github/workflows/utils.yaml new file mode 100644 index 0000000000..91d0bf1722 --- /dev/null +++ b/.github/workflows/utils.yaml @@ -0,0 +1,19 @@ +# This workflow file contains miscellaneous tasks to manage the repository. +name: Utils for Repository +on: + schedule: + - cron: '30 1 * * *' + workflow_dispatch: + +jobs: + # This job runs the stale action to close issues that have been inactive for 30 days. + # It is scheduled to run every day at 1:30 AM UTC. + close-stale-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v8.0.0 + with: + close-issue-message: 'This issue is being closed because it has been inactive waiting for response for 30 days. If this is still an issue, please open a new issue and reference this one.' + days-before-stale: 21 + days-before-close: 7 + any-of-labels: 'needs details' From 6a360bd1bba85db4e21afac771ebfb52ccdae0b0 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 21 Jul 2023 15:53:12 -0700 Subject: [PATCH 108/693] misc: Update ci-tests.yaml to always clean runner Adds line to make sure the runners are always cleaned whether or not the previous tests pass Change-Id: I980c0232305999fb3548464ea1b6eaeca7bcdbd6 --- .github/workflows/ci-tests.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 5e11903a0f..9894716665 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -103,6 +103,7 @@ jobs: path: output.zip retention-days: 7 - name: Clean runner + if: success() || failure() run: rm -rf ./* || true rm -rf ./.??* || true From 984499329d5b70c1841c39e545878303b4a5ddd5 Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Sun, 23 Jul 2023 13:57:06 -0700 Subject: [PATCH 109/693] mem-ruby,configs: Add GLC Atomic Latency VIPER Parameter (#110) Added a GLC atomic latency parameter (glc-atomic-latency) used when enqueueing response messages regarding atomics directly performed in the TCC. This latency is added in addition to the L2 response latency (TCC_latency). This represents the latency of performing an atomic within the L2. With this change, the TCC response queue will receive enqueues with varying latencies as GLC atomic responses will have this added GLC atomic latency while data responses will not. To accommodate this in light of the queue having strict FIFO ordering (which would be violated here), this change also adds an optional parameter bypassStrictFIFO to the SLICC enqueue function which allows overriding strict FIFO requirements for individual messages on a case-by-case basis. This parameter is only being used in the TCC's atomic response enqueue call. Change-Id: Iabd52cbd2c0cc385c1fb3fe7bcd0cc64bdb40aac --- configs/ruby/GPU_VIPER.py | 4 ++++ src/mem/ruby/network/MessageBuffer.cc | 11 +++++++--- src/mem/ruby/network/MessageBuffer.hh | 6 +++++- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 3 ++- src/mem/slicc/ast/EnqueueStatementAST.py | 26 +++++++++++++++++++----- src/mem/slicc/parser.py | 8 ++++++-- 6 files changed, 46 insertions(+), 12 deletions(-) diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index ee8d570498..1e95964a40 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -489,6 +489,9 @@ def define_options(parser): help="Size of the mandatory queue in the GPU scalar " "cache controller", ) + parser.add_argument( + "--glc-atomic-latency", type=int, default=1, help="GLC Atomic Latency" + ) def construct_dirs(options, system, ruby_system, network): @@ -875,6 +878,7 @@ def construct_tccs(options, system, ruby_system, network): tcc_cntrl.create(options, ruby_system, system) tcc_cntrl.l2_request_latency = options.gpu_to_dir_latency tcc_cntrl.l2_response_latency = options.TCC_latency + tcc_cntrl.glc_atomic_latency = options.glc_atomic_latency tcc_cntrl_nodes.append(tcc_cntrl) tcc_cntrl.WB = options.WB_L2 tcc_cntrl.number_of_TBEs = 2560 * options.num_compute_units diff --git a/src/mem/ruby/network/MessageBuffer.cc b/src/mem/ruby/network/MessageBuffer.cc index 9a6500978e..9a4439a538 100644 --- a/src/mem/ruby/network/MessageBuffer.cc +++ b/src/mem/ruby/network/MessageBuffer.cc @@ -62,7 +62,8 @@ MessageBuffer::MessageBuffer(const Params &p) m_max_dequeue_rate(p.max_dequeue_rate), m_dequeues_this_cy(0), m_time_last_time_size_checked(0), m_time_last_time_enqueue(0), m_time_last_time_pop(0), - m_last_arrival_time(0), m_strict_fifo(p.ordered), + m_last_arrival_time(0), m_last_message_strict_fifo_bypassed(false), + m_strict_fifo(p.ordered), m_randomization(p.randomization), m_allow_zero_latency(p.allow_zero_latency), m_routing_priority(p.routing_priority), @@ -214,7 +215,8 @@ random_time() } void -MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta) +MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta, + bool bypassStrictFIFO) { // record current time incase we have a pop that also adjusts my size if (m_time_last_time_enqueue < current_time) { @@ -252,7 +254,8 @@ MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta) // Check the arrival time assert(arrival_time >= current_time); - if (m_strict_fifo) { + if (m_strict_fifo && + !(bypassStrictFIFO || m_last_message_strict_fifo_bypassed)) { if (arrival_time < m_last_arrival_time) { panic("FIFO ordering violated: %s name: %s current time: %d " "delta: %d arrival_time: %d last arrival_time: %d\n", @@ -266,6 +269,8 @@ MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta) m_last_arrival_time = arrival_time; } + m_last_message_strict_fifo_bypassed = bypassStrictFIFO; + // compute the delay cycles and set enqueue time Message* msg_ptr = message.get(); assert(msg_ptr != NULL); diff --git a/src/mem/ruby/network/MessageBuffer.hh b/src/mem/ruby/network/MessageBuffer.hh index 279599340a..03a0454433 100644 --- a/src/mem/ruby/network/MessageBuffer.hh +++ b/src/mem/ruby/network/MessageBuffer.hh @@ -123,7 +123,8 @@ class MessageBuffer : public SimObject const MsgPtr &peekMsgPtr() const { return m_prio_heap.front(); } - void enqueue(MsgPtr message, Tick curTime, Tick delta); + void enqueue(MsgPtr message, Tick curTime, Tick delta, + bool bypassStrictFIFO = false); // Defer enqueueing a message to a later cycle by putting it aside and not // enqueueing it in this cycle @@ -271,6 +272,9 @@ class MessageBuffer : public SimObject uint64_t m_msg_counter; int m_priority_rank; + + bool m_last_message_strict_fifo_bypassed; + const bool m_strict_fifo; const MessageRandomization m_randomization; const bool m_allow_zero_latency; diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index a83bee0fa5..31fc484973 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -36,6 +36,7 @@ machine(MachineType:TCC, "TCC Cache") bool WB; /*is this cache Writeback?*/ Cycles l2_request_latency := 50; Cycles l2_response_latency := 20; + Cycles glc_atomic_latency := 0; // From the TCPs or SQCs MessageBuffer * requestFromTCP, network="From", virtual_network="1", vnet_type="request"; @@ -510,7 +511,7 @@ machine(MachineType:TCC, "TCC Cache") action(ar_sendAtomicResponse, "ar", desc="send Atomic Ack") { peek(coreRequestNetwork_in, CPURequestMsg) { - enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { + enqueue(responseToCore_out, ResponseMsg, l2_response_latency + glc_atomic_latency, true) { out_msg.addr := address; out_msg.Type := CoherenceResponseType:TDSysResp; out_msg.Destination.clear(); diff --git a/src/mem/slicc/ast/EnqueueStatementAST.py b/src/mem/slicc/ast/EnqueueStatementAST.py index 148cc3a223..e9bda61911 100644 --- a/src/mem/slicc/ast/EnqueueStatementAST.py +++ b/src/mem/slicc/ast/EnqueueStatementAST.py @@ -31,12 +31,21 @@ from slicc.symbols import Var class EnqueueStatementAST(StatementAST): - def __init__(self, slicc, queue_name, type_ast, lexpr, statements): + def __init__( + self, + slicc, + queue_name, + type_ast, + lexpr, + bypass_strict_fifo, + statements, + ): super().__init__(slicc) self.queue_name = queue_name self.type_ast = type_ast self.latexpr = lexpr + self.bypass_strict_fifo = bypass_strict_fifo self.statements = statements def __repr__(self): @@ -76,10 +85,17 @@ class EnqueueStatementAST(StatementAST): if self.latexpr != None: ret_type, rcode = self.latexpr.inline(True) - code( - "(${{self.queue_name.var.code}}).enqueue(" - "out_msg, clockEdge(), cyclesToTicks(Cycles($rcode)));" - ) + if self.bypass_strict_fifo != None: + bypass_strict_fifo_code = self.bypass_strict_fifo.inline(False) + code( + "(${{self.queue_name.var.code}}).enqueue(" + "out_msg, clockEdge(), cyclesToTicks(Cycles($rcode)), $bypass_strict_fifo_code);" + ) + else: + code( + "(${{self.queue_name.var.code}}).enqueue(" + "out_msg, clockEdge(), cyclesToTicks(Cycles($rcode)));" + ) else: code( "(${{self.queue_name.var.code}}).enqueue(out_msg, " diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index 155eb07f7a..d84eab211c 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -633,11 +633,15 @@ class SLICC(Grammar): def p_statement__enqueue(self, p): "statement : ENQUEUE '(' var ',' type ')' statements" - p[0] = ast.EnqueueStatementAST(self, p[3], p[5], None, p[7]) + p[0] = ast.EnqueueStatementAST(self, p[3], p[5], None, None, p[7]) def p_statement__enqueue_latency(self, p): "statement : ENQUEUE '(' var ',' type ',' expr ')' statements" - p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9]) + p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], None, p[9]) + + def p_statement__enqueue_latency_bypass_strict_fifo(self, p): + "statement : ENQUEUE '(' var ',' type ',' expr ',' expr ')' statements" + p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9], p[11]) def p_statement__defer_enqueueing(self, p): "statement : DEFER_ENQUEUEING '(' var ',' type ')' statements" From 7dba30209a40265fd91be90cc766da67f39591a4 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 17 Jul 2023 12:35:03 +0100 Subject: [PATCH 110/693] arch-arm: Hook TLBIOS instructions to the TlbiShareable obj FEAT_TLBIOS has been introduced by a recent patch [1] which was however missing to include the outer shareable case in the Msr disambiguation switch. Which meant the TLBIOS instructions were decoded as normal MSR instructions, with no effect whatsoever on the TLBs [1]: https://gem5-review.googlesource.com/c/public/gem5/+/70567 Change-Id: I41665a4634fbe0ee8cc30dbc5d88d63103082ae9 Signed-off-by: Giacomo Travaglini --- src/arch/arm/isa/formats/aarch64.isa | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/arch/arm/isa/formats/aarch64.isa b/src/arch/arm/isa/formats/aarch64.isa index 47d509e808..68a741a831 100644 --- a/src/arch/arm/isa/formats/aarch64.isa +++ b/src/arch/arm/isa/formats/aarch64.isa @@ -545,21 +545,37 @@ namespace Aarch64 return new Tlbi64LocalHub( machInst, miscReg, rt); case MISCREG_TLBI_ALLE3IS: + case MISCREG_TLBI_ALLE3OS: case MISCREG_TLBI_ALLE2IS: + case MISCREG_TLBI_ALLE2OS: case MISCREG_TLBI_ALLE1IS: + case MISCREG_TLBI_ALLE1OS: case MISCREG_TLBI_VMALLS12E1IS: + case MISCREG_TLBI_VMALLS12E1OS: case MISCREG_TLBI_VMALLE1IS: + case MISCREG_TLBI_VMALLE1OS: case MISCREG_TLBI_VAE3IS_Xt: + case MISCREG_TLBI_VAE3OS_Xt: case MISCREG_TLBI_VALE3IS_Xt: + case MISCREG_TLBI_VALE3OS_Xt: case MISCREG_TLBI_VAE2IS_Xt: + case MISCREG_TLBI_VAE2OS_Xt: case MISCREG_TLBI_VALE2IS_Xt: + case MISCREG_TLBI_VALE2OS_Xt: case MISCREG_TLBI_VAE1IS_Xt: + case MISCREG_TLBI_VAE1OS_Xt: case MISCREG_TLBI_VALE1IS_Xt: + case MISCREG_TLBI_VALE1OS_Xt: case MISCREG_TLBI_ASIDE1IS_Xt: + case MISCREG_TLBI_ASIDE1OS_Xt: case MISCREG_TLBI_VAAE1IS_Xt: + case MISCREG_TLBI_VAAE1OS_Xt: case MISCREG_TLBI_VAALE1IS_Xt: + case MISCREG_TLBI_VAALE1OS_Xt: case MISCREG_TLBI_IPAS2E1IS_Xt: + case MISCREG_TLBI_IPAS2E1OS_Xt: case MISCREG_TLBI_IPAS2LE1IS_Xt: + case MISCREG_TLBI_IPAS2LE1OS_Xt: return new Tlbi64ShareableHub( machInst, miscReg, rt, dec.dvmEnabled); default: From 00b2846109300c16919f20489d9e2e7f0fc32066 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 25 Jul 2023 19:43:24 -0700 Subject: [PATCH 111/693] misc: Update TESTING.md for subset selection This change: 1. Removes the 'Specifying a subset of tests to run' section. This section is no longer useful since tests are no longer divided up so neatly by tags as they once were. 2. Adds a section outlining the 'quick', 'long' and 'very-long' tests and how they may be selected and run. Change-Id: I61370dd80cc925a15d1a22755faa7d62e810862f --- TESTING.md | 63 +++++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/TESTING.md b/TESTING.md index 50cc9bea3e..0f65c2b322 100644 --- a/TESTING.md +++ b/TESTING.md @@ -77,54 +77,35 @@ arguments: This will load every test in directory1 and directory2 (and their subdirectories). -## Specifying a subset of tests to run +## 'quick', 'long', and 'very-long' tests -You can use the tag query interface to specify the exact tests you want to run. -For instance, if you want to run only with `gem5.opt`, you can use +There are three categoties of tests which may be run from the "tests" directory: -```shell -./main.py run --variant opt +1. **'quick' tests**. This suite of tests are designed to finish execution in a few hours, inclusive of compilation of gem5. +We run these as part of our continuous integration tests on pull requests made to our repository. +These tests all utilize a binary build `scons build/ALL/gem5.opt`, and thus only rely on a single compilation for the tests to run. +2. **'long' tests**. This suite of tests are designed to finish execution in around 12 hours. +They incorporate longer running tests which are unsuitable to run as part of the 'quick' tests. +We run these daily via a scheduled job. +3. **'very-long' tests**. This suite of tests are designed to finish execution in days. +They incorporate tests which are too long to run frequntly +We run these daily via a scheduled job. + +When executing `./main.py run` the 'quick' tests are executed. +To run the 'long' tests execute: + +```sh +./main.py run --length=long ``` -Or, if you want to just run quick tests with the `gem5.opt` binary: +and to run the 'very-long' tests execute: -```shell -./main.py run --length quick --variant opt +```sh +./main.py run --length=very-long ``` - -To view all of the available tags, use - -```shell -./main.py list --all-tags -``` - -The output is split into tag *types* (e.g., isa, variant, length) and the -tags for each type are listed after the type name. - -Note that when using the isa tag type, tests were traditionally sorted based -on what compilation it required. However, as tests have switched to all be -compiled under the ALL compilation, which includes all ISAs so one doesn't -need to compile each one individually, using the isa tag for ISAs other than -ALL has become a less optimal way of searching for tests. It would instead -be better to run subsets of tests based on their directories, as described -above. - -You can specify "or" between tags within the same type by using the tag flag -multiple times. For instance, to run everything that is tagged "opt" or "fast" -use - -```shell -./main.py run --variant opt --variant fast -``` - -You can also specify "and" between different types of tags by specifying more -than one type on the command line. For instance, this will only run tests with -both the "ALL" and "opt" tags. - -```shell -./main.py run --isa All --variant opt -``` +In most cases we recommend running the 'quick' tests for most changes. +Only in some cases, such as contributions which significantly change the codebase, do we recommend running the 'long' or 'very-long' suite. ## Running tests in batch From 2846df946a7795fb2b6adecf5f10773e75d9326a Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 25 Jul 2023 19:50:17 -0700 Subject: [PATCH 112/693] misc: Remove test binary sections from TESTING.md These sections are very out-of-date and confusing. Change-Id: I61aae0686f38671e46412e27ea516a5e06f4e6f2 --- TESTING.md | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/TESTING.md b/TESTING.md index 0f65c2b322..6ff79570bd 100644 --- a/TESTING.md +++ b/TESTING.md @@ -194,44 +194,6 @@ test library executes each python file it finds searching for tests. It's okay if the file causes an exception. This means there are no tests in that file (e.g., it's not a new-style test). - -## Binary test applications - -The code for some test binaries that are run in the gem5 guest during -testing can be found in `tests/test-progs`. -There's one directory per test application. -The source code is under the `source` directory. - -You may have a `bin` directory as well. -The `bin` directory is automatically created when running the test case that -uses the test binary. -This is not the case when a test is run via the --bin-path option. -In that scenario a bin directory will be created in the selected path -rather than in `tests/test-progs`. -The binary is downloaded from the gem5 servers the first -time it is referenced by a test. - -Some other tests (like Linux-boot) don't have sources inside gem5 and -are simply downloaded from gem5 servers. - -## Updating the test binaries - -The test infrastructure should check with the gem5 servers to ensure you have -the latest binaries. However, if you believe your binaries are out of date, -simply delete the `bin` directory and they will be re-downloaded to your local -machine. - -## Building (new-style) test binaries - -In each `src/` directory under `tests/test-progs`, there is a Makefile. -This Makefile downloads a docker image and builds the test binary for some ISA -(e.g., Makefile.x86 builds the binary for x86). Additionally, if you run `make -upload` it will upload the binaries to the gem5 server, if you have access to -modify the binaries. *If you need to modify the binaries for updating a test or -adding a new test and you don't have access to the gem5 server, contact a -maintainer (see MAINTAINERS).* - - ## Running Tests in Parallel Whimsy has support for parallel testing baked in. This system supports From cb987155147afdcbf1426f1aa895b2356f842db4 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 25 Jul 2023 20:04:43 -0700 Subject: [PATCH 113/693] misc: Add 'testing resources' sec to TESTING.md Change-Id: Ie8a9c9200461d4f9e272dea75de1755b1b18aceb --- TESTING.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/TESTING.md b/TESTING.md index 6ff79570bd..2c0ab0b3ab 100644 --- a/TESTING.md +++ b/TESTING.md @@ -7,7 +7,7 @@ gem5's testing infrastructure has the following goals: * Fast execution in the simple case * High coverage of gem5 code -# Running unit tests +## Running unit tests gem5 comes with unit tests, created using the Google Test framework. These can be built through SCons. @@ -41,7 +41,7 @@ To run a specific test function (e.g., BitUnionData.NormalBitfield): ./build/ALL/base/bitunion.test.opt --gtest_filter=BitUnionData.NormalBitfield ``` -# Running system-level tests +## Running system-level tests Within the `tests` directory we have system-level tests. These tests run the gem5 framework against various hardware configurations, with different @@ -77,7 +77,7 @@ arguments: This will load every test in directory1 and directory2 (and their subdirectories). -## 'quick', 'long', and 'very-long' tests +### 'quick', 'long', and 'very-long' tests There are three categoties of tests which may be run from the "tests" directory: @@ -107,7 +107,7 @@ and to run the 'very-long' tests execute: In most cases we recommend running the 'quick' tests for most changes. Only in some cases, such as contributions which significantly change the codebase, do we recommend running the 'long' or 'very-long' suite. -## Running tests in batch +### Running tests in batch The testing infrastructure provides the two needed methods to run tests in batch. First, you can list all of the tests based on the same tags as above in @@ -141,7 +141,7 @@ run more than one uid, you must call `./main.py` multiple times. Currently, you must specify `--skip-build` if you want to run a single suite or run in batch mode. Otherwise, you will build gem5 for all architectures. -## Rerunning failed tests +### Rerunning failed tests While developing software a common practice is to run tests, make a change, and assert that the tests still pass. If tests fail you'll likely want to @@ -159,7 +159,7 @@ using the `rerun` command. ./main.py rerun ``` -## If something goes wrong +### If something goes wrong The first step is to turn up the verbosity of the output using `-v`. This will allow you to see what tests are running and why a test is failing. @@ -167,7 +167,7 @@ allow you to see what tests are running and why a test is failing. If a test fails, the temporary directory where the gem5 output was saved is kept and the path to the directory is printed in the terminal. -## Debugging the testing infrastructure +### Debugging the testing infrastructure Every command takes an option for the verbosity. `-v`, `-vv`, `-vvv` will increase the verbosity level. If something isn't working correctly, you can @@ -178,7 +178,7 @@ contains the base code for tests, suites, fixtures, etc. The code in tests/gem5 is *gem5-specific* code. For the most part, the code in tests/gem5 extends the structures in ext/testlib. -## Common errors +### Common errors You may see a number of lines of output during test discovery that look like the following: @@ -194,7 +194,7 @@ test library executes each python file it finds searching for tests. It's okay if the file causes an exception. This means there are no tests in that file (e.g., it's not a new-style test). -## Running Tests in Parallel +### Running Tests in Parallel Whimsy has support for parallel testing baked in. This system supports running multiple suites at the same time on the same computer. To run @@ -204,6 +204,13 @@ For example, to run up to three test suites at the same time:: ./main.py run --skip-build -t 3 +### Testing resources + +By default binaries and testing resources are obtained via the [gem5 resources infrastructure](https://www.gem5.org/documentation/general_docs/gem5_resources/). +The downloaded resources are cached in "tests/gem5/resources". +The resources are cached to avoid re-downloading when tests are run multiple times, though some of these resources, such as disk images, are large. +It is therefore recommended you remove the "tests/gem5/resources" directory when you are done testing. + ## Running Tests within GitHub Actions To run these tests within GitHub Actions, we use the format of running From 56a9bec6021391c9a0799bbdcff4d517f6761140 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 25 Jul 2023 20:22:00 -0700 Subject: [PATCH 114/693] misc: Update GitHub Actions text in TESTING.md This change simplifies the explanation of how GitHub actions works. Change-Id: Ia1540008463b8584f172c40ca7b4826cbbf95eb7 --- TESTING.md | 42 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/TESTING.md b/TESTING.md index 2c0ab0b3ab..f92d6abda6 100644 --- a/TESTING.md +++ b/TESTING.md @@ -213,39 +213,15 @@ It is therefore recommended you remove the "tests/gem5/resources" directory when ## Running Tests within GitHub Actions -To run these tests within GitHub Actions, we use the format of running -tests by directory as shown above in the "Running Tests from Multiple -Directories" section. These tests are run within workflow files, -which can be found in the .github directory of this repository. -You can learn more about workflows -[here](https://docs.github.com/en/actions/using-workflows/about-workflows). +These tests outlined here are run as part of [GitHub Actions](https://github.com/features/actions). +These are outlined in [workflow files](https://docs.github.com/en/actions/using-workflows/about-workflows), which can be found in the repo's ".github" directory. +Each workflow is made up of individual jobs where ecch job consists of a series of steps which are executed within a [GitHub Runner](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners). -Each workflow is made up of individual jobs, where each job is a set -of tests that is executed on a runner within GitHub. In each -workflow, each version of gem5.opt needed is first built, and then -stored as an artifact for main.py to use. +### Adding Tests to GitHub Actions -There are two sets of runners within the gem5 repository: builders and -runners. The builders have more resources available to allow for a -quicker compilation of gem5, while the runners have less, and are -meant to only run tests. +To ensure tests added are run in GitHub Actions you may need to modify the worklfow files. +For tests run via `./main.py` we split up the tests via the subdirectories in "tests/gem5". +For example, all tests under "test/gem5/cpu_tests" are run as one job. +Therefore tests added to existing directories are likely to be included, but modifications to the workflow files may be needed if new directories are added. -After the gem5 artifact has been uploaded, a runner can then download -the versions needed for their tests. For example, in the daily-tests.yaml, -in order to run the multi_isa tests, you need artifacts of ARM, RISCV, -and VEGA_X86. - -## Adding Tests to GitHub Actions - -In order to add new tests to our GitHub Actions testing infastructure, -follow the format currently shown in the existing workflows. If the -new tests were added to an already existing directory (ex. A very-long -test in the gem5_library_example_tests), it will automatically be -included into the weekly testing, since weekly-tests.yaml already -contains a job for the gem5_library_example_tests. - -However, if a new directory is added to the tests, you need to manually -add a new step to the GitHub workflows. This would consist of both a -step to build whatever version of gem5 was required if it wasn't -already included in the file, as well as a step to run main.py -in the given directory after downloading the gem5 artifact. +We strongly recommend that when adding or ammending tests, that contributors check the ".github/workflows" files to ensure the tests they specify will be run as intended. From 949119b5bbb5a92e6ec707135d26721f780255b9 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 25 Jul 2023 20:34:11 -0700 Subject: [PATCH 115/693] misc: Add Pyunit Test info to TESTING.md Change-Id: Ibff77963653600ac7c9d706edca882d95e5c47df --- TESTING.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/TESTING.md b/TESTING.md index f92d6abda6..19965157fb 100644 --- a/TESTING.md +++ b/TESTING.md @@ -7,9 +7,9 @@ gem5's testing infrastructure has the following goals: * Fast execution in the simple case * High coverage of gem5 code -## Running unit tests +## Running the CPP unit tests -gem5 comes with unit tests, created using the Google Test framework. These can +gem5 comes with unit tests for CPP, created using the Google Test framework. These can be built through SCons. To build and run all the unit tests: @@ -41,9 +41,30 @@ To run a specific test function (e.g., BitUnionData.NormalBitfield): ./build/ALL/base/bitunion.test.opt --gtest_filter=BitUnionData.NormalBitfield ``` +## Running the Python unit tests + +gem5 comes with Python unit tests. +These are built using the [Python unit testing framework](https://docs.python.org/3/library/unittest.html). +These tests can be found in "tests/gem5/pyunit". + +To run these tests a gem5 binary must first be compiled. +We recommend, `build/ALL/gem5.opt`: + +```sh +scons build/ALL/gem5.opt -j {number of compilation threads} +``` + +Then the Pyunit tests may be executed using: + +```sh +./build/ALL/gem5.opt tests/run_pyunit.py +``` + +**Note**: These tests are also run via the 'quick' system-level tests, explained below. + ## Running system-level tests -Within the `tests` directory we have system-level tests. These tests run +Within the "tests/gem5" directory we have system-level tests. These tests run the gem5 framework against various hardware configurations, with different ISAs, then verify the simulations execute correctly. These should be seen as high-level, coarse-grained tests to compliment the unit-tests. From 256729a40c0fadb69a413cf4f539e96187636b50 Mon Sep 17 00:00:00 2001 From: Atri Bhattacharyya Date: Wed, 26 Jul 2023 17:34:24 +0200 Subject: [PATCH 116/693] mem: Make functional request a response when satisfied by queue In the memory controller, MemCtrl::MemoryPort::recvFunctional, when the functional request is satisfied by the ctrl-response queue, correctly make the packet a response. This change mirrors AbstractMemory::functionalAccess, which uses Packet::makeResponse() after satisfying the request. Change-Id: I47917062d3270915a97eed2c9fade66ba17019eb --- src/mem/mem_ctrl.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mem/mem_ctrl.cc b/src/mem/mem_ctrl.cc index 9a3600f331..97c7741abd 100644 --- a/src/mem/mem_ctrl.cc +++ b/src/mem/mem_ctrl.cc @@ -1496,6 +1496,11 @@ MemCtrl::MemoryPort::recvFunctional(PacketPtr pkt) // calls recvAtomic() and throws away the latency; we can save a // little here by just not calculating the latency. ctrl.recvFunctional(pkt); + } else { + // The packet's request is satisfied by the queue, but queue + // does not call makeResponse. + // Here, change the packet to the corresponding response + pkt->makeResponse(); } pkt->popLabel(); From ce8e1b6aaabb21ec40e88bb72c668d56607892af Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 26 Jul 2023 10:52:07 -0700 Subject: [PATCH 117/693] tests: Deprecate Gerrit/Jenkins testing scripts These testing scripts are no longer used since moving to GitHub. The Nightly (now refered to as "Daily" tests), the Weekly Tests, Compiler Tests and the CI (Kokoro, pre-commit) tests are run via the GitHub Actions infrastructure. Their setup is described via Workflow files in ".github/workflows". To run tests locally please consult the "TESTING.md" file. These scripts may still be useful to reference and are therefore being moved into a deprecated state. Change-Id: Ie75c2f4f1179eb73d0f45ba0b259e8d79aa02ace --- tests/{ => deprecated}/compiler-tests.sh | 0 tests/{ => deprecated}/jenkins/gem5art-tests.sh | 0 tests/{ => deprecated}/jenkins/presubmit-stage2.sh | 0 tests/{ => deprecated}/jenkins/presubmit.cfg | 0 tests/{ => deprecated}/jenkins/presubmit.sh | 0 tests/{ => deprecated}/nightly.sh | 0 tests/{ => deprecated}/weekly.sh | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename tests/{ => deprecated}/compiler-tests.sh (100%) rename tests/{ => deprecated}/jenkins/gem5art-tests.sh (100%) rename tests/{ => deprecated}/jenkins/presubmit-stage2.sh (100%) rename tests/{ => deprecated}/jenkins/presubmit.cfg (100%) rename tests/{ => deprecated}/jenkins/presubmit.sh (100%) rename tests/{ => deprecated}/nightly.sh (100%) rename tests/{ => deprecated}/weekly.sh (100%) diff --git a/tests/compiler-tests.sh b/tests/deprecated/compiler-tests.sh similarity index 100% rename from tests/compiler-tests.sh rename to tests/deprecated/compiler-tests.sh diff --git a/tests/jenkins/gem5art-tests.sh b/tests/deprecated/jenkins/gem5art-tests.sh similarity index 100% rename from tests/jenkins/gem5art-tests.sh rename to tests/deprecated/jenkins/gem5art-tests.sh diff --git a/tests/jenkins/presubmit-stage2.sh b/tests/deprecated/jenkins/presubmit-stage2.sh similarity index 100% rename from tests/jenkins/presubmit-stage2.sh rename to tests/deprecated/jenkins/presubmit-stage2.sh diff --git a/tests/jenkins/presubmit.cfg b/tests/deprecated/jenkins/presubmit.cfg similarity index 100% rename from tests/jenkins/presubmit.cfg rename to tests/deprecated/jenkins/presubmit.cfg diff --git a/tests/jenkins/presubmit.sh b/tests/deprecated/jenkins/presubmit.sh similarity index 100% rename from tests/jenkins/presubmit.sh rename to tests/deprecated/jenkins/presubmit.sh diff --git a/tests/nightly.sh b/tests/deprecated/nightly.sh similarity index 100% rename from tests/nightly.sh rename to tests/deprecated/nightly.sh diff --git a/tests/weekly.sh b/tests/deprecated/weekly.sh similarity index 100% rename from tests/weekly.sh rename to tests/deprecated/weekly.sh From 62df5ae35fef5f7617e76842d18217b8421dad06 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Tue, 25 Jul 2023 17:25:51 -0700 Subject: [PATCH 118/693] misc: Refactor daily-tests.yaml This changes the daily tests to use a matrix in order to run tests. It also includes forces the cleaning step to run regardless of success or failure. With this refactoring, now all builds of gem5 must finish before any tests run, and all tests download all artifacts from all the build runs. Change-Id: I16e1bc9acaf619feb85fba53eb6129e7df3fe409 --- .github/workflows/daily-tests.yaml | 1026 ++-------------------------- 1 file changed, 65 insertions(+), 961 deletions(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 87059dd2ae..6ef933da68 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -8,1033 +8,136 @@ on: - cron: '0 7 * * *' jobs: -# building all necessary versions of gem5 + name-artifacts: + runs-on: ubuntu-latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v2 + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S-")" >> $GITHUB_OUTPUT + build-gem5: + strategy: + matrix: + # NULL is in quotes since it is considered a keyword in yaml files + image: [ALL, ALL_CHI, ARM, ALL_MSI, ALL_MESI_Two_Level, "NULL", NULL_MI_example, RISCV, VEGA_X86] + # this allows us to pass additional command line parameters + # the default is to add -j $(nproc), but some images + # require more specifications when built + include: + - command-line: -j $(nproc) + - image: ALL_CHI + command-line: --default=ALL PROTOCOL=CHI -j $(nproc) + - image: ALL_MSI + command-line: --default=ALL PROTOCOL=MSI -j $(nproc) + - image: ALL_MESI_Two_Level + command-line: --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) + - image: NULL_MI_example + command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) runs-on: [self-hosted, linux, x64, build] + needs: name-artifacts container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} steps: - uses: actions/checkout@v3 with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL" >> $GITHUB_OUTPUT - name: Build gem5 - run: | - scons build/ALL/gem5.opt -j $(nproc) + run: scons build/${{ matrix.image }}/gem5.opt ${{ matrix.command-line }} - uses: actions/upload-artifact@v3 with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/ALL/gem5.opt + name: ${{ needs.name-artifacts.outputs.build-name }}${{ matrix.image }} + path: build/${{ matrix.image }}/gem5.opt retention-days: 5 - run: echo "This job's status is ${{ job.status }}." - build-gem5-ALL_CHI: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL_CHI" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/ALL_CHI/gem5.opt --default=ALL PROTOCOL=CHI -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/ALL_CHI/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-ARM: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ARM" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/ARM/gem5.opt -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/ARM/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-ALL_MSI: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL_MSI" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/ALL_MSI/gem5.opt --default=ALL PROTOCOL=MSI -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/ALL_MSI/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-ALL_MESI_Two_Level: - runs-on: [self-hosted, linux, x64, build,] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL_MESI_Two_Level" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/ALL_MESI_Two_Level/gem5.opt --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/ALL_MESI_Two_Level/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-NULL: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-NULL" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/NULL/gem5.opt -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/NULL/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-NULL_MI_example: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-NULL_MI_example" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/NULL_MI_example/gem5.opt --default=NULL PROTOCOL=MI_example -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/NULL_MI_example/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-RISCV: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-RISCV" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/RISCV/gem5.opt -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/RISCV/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-VEGA_X86: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-VEGA_X86" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/VEGA_X86/gem5.opt -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/VEGA_X86/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - - # This runs the unit tests for the build/ALL/unittests.debug build. - unittests-all-debug: + # this builds both unittests.fast and unittests.debug + unittests-fast-debug: + strategy: + matrix: + type: [fast, debug] runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest timeout-minutes: 60 - steps: - uses: actions/checkout@v3 with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. ref: develop - - name: ALL/unittests.debug UnitTests - run: | - ls - scons build/ALL/unittests.debug -j $(nproc) + - name: ALL/unittests.${{ matrix.type }} UnitTests + run: scons build/ALL/unittests.${{ matrix.type }} -j $(nproc) - # This runs the unit tests for the build/ALL/unittests.fast build. - unittests-all-fast: + # start running all of the long tests + testlib-long-tests: + strategy: + matrix: + test-type: [arm-boot-tests, fs, gem5_library_example_tests, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement-policies, riscv-boot-tests, stdlib, x86-boot-tests] runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - timeout-minutes: 60 - - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - name: ALL/unittests.fast UnitTests - run: | - ls - scons build/ALL/unittests.fast -j $(nproc) - -# start running all of the long tests - testlib-long-arm-boot-tests: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ALL_CHI] - timeout-minutes: 1440 # 24 hours + needs: [name-artifacts, build-gem5] + timeout-minutes: 1440 # 24 hours for entire matrix to run steps: - uses: actions/checkout@v3 with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. ref: develop + # download all artifacts for each test + # since long tests can't start until the build matrix completes, + # we download all artifacts from the build for each test + # in this matrix - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}ALL path: build/ALL - run: chmod u+x build/ALL/gem5.opt - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5-ALL_CHI.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}ALL_CHI path: build/ALL_CHI - run: chmod u+x build/ALL_CHI/gem5.opt - - name: long arm-boot-tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/arm-boot-tests --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-fs: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ARM] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ARM.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}ARM path: build/ARM - run: chmod u+x build/ARM/gem5.opt - - name: long fs - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/fs --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - # split library example tests into runs based on Suite UID - # so that they don't hog the runners for too long - testlib-long-gem5_library_example_tests_x86_ubuntu_run_ALL_x86_64_opt: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} - path: build/ALL_MESI_Two_Level - - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - name: long gem5_library_example_tests_x86_ubuntu_run_ALL_x86_64_opt - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt --length=long --skip-build -vv - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-gem5_library_example_tests_riscv_ubuntu_run_ALL_x86_64_opt: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} - path: build/ALL_MESI_Two_Level - - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - name: long gem5_library_example_tests_riscv_ubuntu_run_ALL_x86_64_opt - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt --length=long --skip-build -vv - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-gem5_library_example_tests_lupv_example_ALL_x86_64_opt: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} - path: build/ALL_MESI_Two_Level - - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - name: long gem5_library_example_tests_lupv_example_ALL_x86_64_opt - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-lupv-example-ALL-x86_64-opt --length=long --skip-build -vv - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-gem5_library_example_tests_arm_ubuntu_run_test_ALL_x86_64_opt: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} - path: build/ALL_MESI_Two_Level - - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - name: long gem5_library_example_tests_arm_ubuntu_run_test_ALL_x86_64_opt - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt --length=long --skip-build -vv - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-gem5_library_example_tests_riscvmatched_hello_ALL_x86_64_opt: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-ALL_MESI_Two_Level] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ALL_MESI_Two_Level.outputs.build-name}} - path: build/ALL_MESI_Two_Level - - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - name: long gem5_library_example_tests_riscvmatched_hello_ALL_x86_64_opt - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-gem5-library-example-riscvmatched-hello-ALL-x86_64-opt --length=long --skip-build -vv - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-gpu: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5, build-gem5-VEGA_X86] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-VEGA_X86.outputs.build-name}} - path: build/VEGA_X86 - - run: chmod u+x build/VEGA_X86/gem5.opt - - name: long gpu - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/gpu --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-insttest_se: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: long insttest_se - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/insttest_se --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - -# kvm tests don't work on github actions -# testlib-long-kvm-fork-tests: -# runs-on: [self-hosted, linux, x64, run] -# container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest -# needs: build-gem5 -# timeout-minutes: 1440 # 24 hours -# steps: -# - uses: actions/checkout@v3 -# with: -# # Scheduled workflows run on the default branch by default. We -# # therefore need to explicitly checkout the develop branch. -# ref: develop -# - uses: actions/download-artifact@v3 -# with: -# name: ${{ env.artifact-name }} -# path: build/ALL/gem5.opt -# - run: chmod u+x build/ALL/gem5.opt -# - name: long kvm-fork-tests -# working-directory: ${{ github.workspace }}/tests -# run: ./main.py run gem5/kvm-fork-tests --length=long --skip-build -vv -t $(nproc) -# - uses: actions/upload-artifact@v3 -# env: -# MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} -# with: -# name: ${{ env.MY_STEP_VAR }} -# path: tests/testing-results -# retention-days: 7 -# - name: Clean runner -# run: -# rm -rf ./* || true -# rm -rf ./.??* || true -# rm -rf ~/.cache || true -# - run: echo "This job's status is ${{ job.status }}." - - # testlib-long-kvm-switch-tests: - # runs-on: [self-hosted, linux, x64, run] - # container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - # needs: build-gem5 - # timeout-minutes: 1440 # 24 hours - # steps: - # - uses: actions/checkout@v3 - # with: - # # Scheduled workflows run on the default branch by default. We - # # therefore need to explicitly checkout the develop branch. - # ref: develop - # - uses: actions/download-artifact@v3 - # with: - # name: ${{ env.artifact-name }} - # path: build/ALL/gem5.opt - # - run: chmod u+x build/ALL/gem5.opt - # - name: long kvm-switch-tests - # working-directory: ${{ github.workspace }}/tests - # run: ./main.py run gem5/kvm-switch-tests --length=long --skip-build -vv -t $(nproc) - # - uses: actions/upload-artifact@v3 - # env: - # MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - # with: - # name: ${{ env.MY_STEP_VAR }} - # path: tests/testing-results - # retention-days: 7 - # - name: Clean runner - # run: - # rm -rf ./* || true - # rm -rf ./.??* || true - # rm -rf ~/.cache || true - # - run: echo "This job's status is ${{ job.status }}." - - testlib-long-learning_gem5: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5-ALL_MSI - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ALL_MSI.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}ALL_MSI path: build/ALL_MSI - run: chmod u+x build/ALL_MSI/gem5.opt - - name: long learning_gem5 - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/learning_gem5 --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-m5_threads: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: long m5_threads - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/m5threads_test_atomic --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-memory: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5-NULL - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop + name: ${{needs.name-artifacts.outputs.build-name}}ALL_MESI_Two_Level + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5-NULL.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}NULL path: build/NULL - run: chmod u+x build/NULL/gem5.opt - - name: long memory - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/memory --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-multi_isa: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5-ARM, build-gem5-VEGA_X86, build-gem5-RISCV] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5-ARM.outputs.build-name}} - path: build/ARM - - run: chmod u+x build/ARM/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-VEGA_X86.outputs.build-name}} - path: build/VEGA_X86 - - run: chmod u+x build/VEGA_X86/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-RISCV.outputs.build-name}} - path: build/RISCV - - run: chmod u+x build/RISCV/gem5.opt - - name: long multi_isa - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/multi_isa --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-replacement-policies: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5-NULL_MI_example - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-NULL_MI_example.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}NULL_MI_example path: build/NULL_MI_example - run: chmod u+x build/NULL_MI_example/gem5.opt - - name: long replacement-policies - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/replacement-policies --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-riscv-boot-tests: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: long riscv-boot-tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/riscv-boot-tests --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-stdlib: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5-ARM, build-gem5-VEGA_X86, build-gem5-RISCV] - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-ARM.outputs.build-name}} - path: build/ARM - - run: chmod u+x build/ARM/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-VEGA_X86.outputs.build-name}} - path: build/VEGA_X86 - - run: chmod u+x build/VEGA_X86/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5-RISCV.outputs.build-name}} + name: ${{needs.name-artifacts.outputs.build-name}}RISCV path: build/RISCV - run: chmod u+x build/RISCV/gem5.opt - - name: long stdlib - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/stdlib --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-long-x86-boot-tests: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 - timeout-minutes: 1440 # 24 hours - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: long x86-boot-tests + name: ${{needs.name-artifacts.outputs.build-name}}VEGA_X86 + path: build/VEGA_X86 + - run: chmod u+x build/VEGA_X86/gem5.opt + # run test + - name: long ${{ matrix.test-type }} tests working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/x86-boot-tests --length=long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/${{ matrix.image }} --length=long --skip-build -vv -t $(nproc) - name: create zip of results if: success() || failure() run: | @@ -1050,6 +153,7 @@ jobs: path: output.zip retention-days: 7 - name: Clean runner + if: success() || failure() run: rm -rf ./* || true rm -rf ./.??* || true From 7371dd51b9c324f1a52aaac40aeaf60d5ade9931 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Tue, 25 Jul 2023 17:38:54 -0700 Subject: [PATCH 119/693] misc: Move gem5 library example tests into a matrix This moves the gem5 library example tests into a separate matrix, so they can run on separate runners Change-Id: Ie9f51b5bae9e7e424d1c98b545b4cf92b481a2fb --- .github/workflows/daily-tests.yaml | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 6ef933da68..0384bfeadb 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -160,6 +160,52 @@ jobs: rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." + # split library example tests into runs based on Suite UID + # so that they don't hog the runners for too long + testlib-long-gem5_library_example_tests: + runs-on: [self-hosted, linux, x64, run] + strategy: + matrix: + test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: build-gem5 + timeout-minutes: 1440 # 24 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ALL + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: long ${{ matrix.test-type }} gem5_library_example_tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-${{ matrix.test-type }} --length=long --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - name: Clean runner + if: success() || failure() + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true + - run: echo "This job's status is ${{ job.status }}." + # This runs the SST-gem5 integration compilation and tests it with # ext/sst/sst/example.py. sst-test: From ff7e67ee9340992fe405135b6b70243a44982c57 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 26 Jul 2023 21:15:53 -0500 Subject: [PATCH 120/693] cpu: Set SLC bit for GPU tester This fixes #131 by reverting to the old behavior of performing all atomics at the system level. To do this the SLC bit needs to be set for all atomic requests. Change-Id: I63f4e449be1b02c933832d09700237f8c8026f4c --- src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc b/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc index ae4078ee6c..0fcfba7a37 100644 --- a/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc +++ b/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc @@ -189,6 +189,7 @@ GpuWavefront::issueAtomicOps() AtomicOpFunctorPtr(amo_op)); req->setPaddr(address); req->setReqInstSeqNum(tester->getActionSeqNum()); + req->setCacheCoherenceFlags(Request::SLC_BIT); // set protocol-specific flags setExtraRequestFlags(req); From 9ec7a1c14a1aa232533bbf1899ff2f21b462af26 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 26 Jul 2023 19:20:13 -0700 Subject: [PATCH 121/693] util: Ignore line length check for #include pragma in C/C++ files The length of the path of the #include pragma can be more than 79-character long. Change-Id: Id72250c166370c7f456bd1f7d05589a49c14c33d Signed-off-by: Hoa Nguyen --- src/sst/sst_responder_interface.hh | 2 +- util/style/verifiers.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sst/sst_responder_interface.hh b/src/sst/sst_responder_interface.hh index 0e827abfdc..eb9c72ef64 100644 --- a/src/sst/sst_responder_interface.hh +++ b/src/sst/sst_responder_interface.hh @@ -30,7 +30,7 @@ #include -#include "mem/port.hh" +#include "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamem/port.hh" /** * SSTResponderInterface provides an interface specified gem5's expectations diff --git a/util/style/verifiers.py b/util/style/verifiers.py index dbcce1c764..7a88e59789 100644 --- a/util/style/verifiers.py +++ b/util/style/verifiers.py @@ -424,7 +424,11 @@ class LineLength(LineVerifier): test_name = "line length" opt_name = "length" - def check_line(self, line, **kwargs): + def check_line(self, line, language, **kwargs): + # Ignore line length check for include pragmas of C/C++. + if language in {"C", "C++"}: + if line.startswith("#include"): + return True return style.normalized_len(line) <= 79 def fix(self, filename, regions=all_regions, **kwargs): From bd82e6f1a7de72ac59991145ca8e35902107ac2e Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 26 Jul 2023 19:56:06 -0700 Subject: [PATCH 122/693] learning-gem5: Add a missing override Change-Id: I9acebe6f3096b499fa2c69b6d757373431f63c71 Signed-off-by: Hoa Nguyen --- src/learning_gem5/part2/hello_object.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/learning_gem5/part2/hello_object.hh b/src/learning_gem5/part2/hello_object.hh index c34dde304d..05c6dde4d6 100644 --- a/src/learning_gem5/part2/hello_object.hh +++ b/src/learning_gem5/part2/hello_object.hh @@ -69,7 +69,7 @@ class HelloObject : public SimObject * SimObjects have been constructed. It is called after the user calls * simulate() for the first time. */ - void startup(); + void startup() override; }; } // namespace gem5 From f19945e9cbcf742611125fc357210d10d59a76f2 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 26 Jul 2023 21:29:00 -0700 Subject: [PATCH 123/693] ext: Remove the test Change-Id: I5c174ad388f63e7846dab5d9497ab2faa73ca6f7 Signed-off-by: Hoa Nguyen --- src/sst/sst_responder_interface.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sst/sst_responder_interface.hh b/src/sst/sst_responder_interface.hh index eb9c72ef64..0e827abfdc 100644 --- a/src/sst/sst_responder_interface.hh +++ b/src/sst/sst_responder_interface.hh @@ -30,7 +30,7 @@ #include -#include "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamem/port.hh" +#include "mem/port.hh" /** * SSTResponderInterface provides an interface specified gem5's expectations From 415a6eb9d474cf7bd2e5db62a640d67bee74dbcc Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Wed, 26 Jul 2023 23:46:20 -0700 Subject: [PATCH 124/693] misc: Add missing dependency to daily tests The refactoring to the daily tests was missing the dependency on the 'name-artifacts' job, which is necessary for downloading all the gem5 artifacts. This adds it in so the tests run as expected. Change-Id: I0d71ab147395f41c881f2b24597bc07006e1f9c0 --- .github/workflows/daily-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 0384bfeadb..679dba2978 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -168,7 +168,7 @@ jobs: matrix: test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 + needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours steps: - uses: actions/checkout@v3 From dcf3c4ba98a607136a8041f80135ffbfe689db7c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 26 Jul 2023 17:17:33 -0700 Subject: [PATCH 125/693] misc: Sync CONTRIBUTING.md with website This change syncs the repo's contributing documentation with that of the website's contributing documentation: https://www.gem5.org/contributing From now on we'll attempt to keep the repo's CONTRIBUTING.md documentation in sync with that on the website. Change-Id: I2c91e6dd5cd7a9b642377878b007d7da3f0ee2ad --- CONTRIBUTING.md | 725 +++++++++++++++++++++++------------------------- 1 file changed, 349 insertions(+), 376 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b41a73a4a6..208c9444e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,425 +1,390 @@ -If you've made changes to gem5 that might benefit others, we strongly encourage -you to contribute those changes to the public gem5 repository. There are -several reasons to do this: - * Share your work with others, so that they can benefit from new functionality. - * Support the scientific principle by enabling others to evaluate your - suggestions without having to guess what you did. - * Once your changes are part of the main repo, you no longer have to merge - them back in every time you update your local repo. This can be a huge time - saving! - * Once your code is in the main repo, other people have to make their changes - work with your code, and not the other way around. - * Others may build on your contributions to make them even better, or extend - them in ways you did not have time to do. - * You will have the satisfaction of contributing back to the community. +This document serves as a guide to contributing to gem5. +The following subsections outline, in order, the steps involved in contributing +to the gem5 project. -The main method for contributing code to gem5 is via our code review website: -https://github.com/gem5/gem5/pulls/. This documents describes the details of -how to create code changes, upload your changes, have your changes -reviewed, and finally push your changes to gem5. More information can be found -from the following sources: - * http://gem5.org/contributing - * https://docs.github.com/en/pull-requests - * https://git-scm.com/book +## Determining what you can contribute +The easiest way to see how you can contribute to gem5 is to check our Jira +issue tracker: or GitHub issue tracker: +. -High-level flow for submitting changes -====================================== +Browse these open issues and see if there are any which you are capable of +handling. When you find a task you are happy to carry out, verify no one else +is presently assigned, then leave a comment asking if you may assign yourself +this task. Though not mandatory, we +advise first-time contributors do this so developers more familiar with the +task may give advice on how best to implement the necessary changes. - +-------------+ - | Make change | - +------+------+ - | - | - v - +-------------+ - | Run tests |<--------------+ - +------+------+ | - | | - | | - v | - +------+------+ | - | Post review | | - +------+------+ | - | | - v | - +--------+---------+ | - | Wait for reviews | | - +--------+---------+ | - | | - | | - v | - +----+----+ No +------+------+ - |Reviewers+--------->+ Update code | - |happy? | +------+------+ - +----+----+ ^ - | | - | Yes | - v | - +----+-----+ No | - |Maintainer+----------------+ - |happy? | - +----+-----+ - | - | Yes - v - +------+------+ - | Submit code | - +-------------+ +Once a developers has replied to your comment (and given any advice they may +have), you may officially assign yourself the task. This helps the gem5 +development community understand which parts of the project are presently being +worked on. -After creating your change to gem5, you can post a review to git -via a pull request at: https://github.com/gem5/gem5/pulls/. Before being able to -submit your code to the mainline of gem5, the code is reviewed by others in the -community. Additionally, the maintainer for that part of the code must sign off -on it. +**If, for whatever reason, you stop working on a task, please unassign +yourself from the task.** -Cloning the gem5 repo to contribute -=================================== +## Obtaining the git repo -If you plan on contributing, it is strongly encouraged for you to clone the -repository directly, and checkout the `develop` branch from our git instance -at https://github.com/gem5/gem5/. +The gem5 git repository is hosted at . +**Please note: contributions made to other gem5 repos +will not be considered. Please contribute to +exclusively.** -To clone the gem5 repository: +To pull the gem5 git repo: -``` - git clone https://github.com/gem5/gem5/ +```sh +git clone https://github.com/gem5/gem5 ``` -By default, the stable branch is checked out. The stable branch contains the -latest released version of gem5. To obtain code still under-development (and -which contributions can be made): +If you wish to use gem5 and never contribute, this is fine. However, to +contribute, we use the [GitHub Pull-Request model](https://docs.github.com/en/pull-requests), and therefore recommend [Forking the gem5 repository](https://docs.github.com/en/get-started/quickstart/fork-a-repo) prior to contributing. -``` -cd gem5 -git checkout --track origin/develop +### Forking + +Please consult the [GitHub documentation on Forking a GitHub repository](https://docs.github.com/en/get-started/quickstart/fork-a-repo). +As we will be working atop the `develop` branch, please ensure you Fork all the repository's branches, not just the `stable` branch. + +This will create your own forked version of the gem5 repo on your own GitHub account. +You may then obtain it locally using: + +```sh +git clone https://github.com/{your github account}/gem5 ``` -Changes should be made to this develop branch. Changes to the stable branch -will be blocked. Once a change on the develop branch is properly incorporated -into the gem5 repo it will be merged into the stable branch upon the next -release of gem5. New releases of gem5 occur three times a year. Ergo, changes -made to the develop branch should appear on the stable branch within three to -four months as part of a stable release. +### stable / develop branch -Other gem5 repositories ------------------------ +When cloned the git repo will have the `stable` branch checked-out by default. The +`stable` branch is the gem5 stable release branch. I.e., the HEAD +of this branch contains the latest stable release of gem5. (execute `git tag` +on the `stable` branch to see the list of stable releases. A particular +release may be checked out by executing `git checkout `). As the +`stable` branch only contains officially released gem5 code **contributors +should not develop changes on top of the `stable` branch** they should instead +**develop changes on top of the `develop` branch**. -There are a few repositories other than the main gem5 development repository. +To switch to the `develop` branch: - * public/m5threads: The code for a pthreads implementation that works with - gem5's syscall emulation mode. - * public/gem5-resources: Resources to enable computer architecture research - with gem5. See the README.md file in the gem5-resources repository for more - information. - * public/gem5-website: The gem5.org website source. See the README.md file in - the gem5-website repository for more information. +```sh +git switch develop +``` -Making changes to gem5 -====================== +The develop `branch` is merged into the `stable` branch upon a gem5 release. +Therefore, any changes you make exist on the develop branch until the next release. -It is strongly encouraged to use git branches when making changes to gem5. -Additionally, keeping changes small and concise and only have a single logical -change per commit. +We strongly recommend creating your own local branches to do changes. +The flow of development works best if `develop` and `stable` are not modified directly. +This helps keep your changes organized across different branches in your forked repository. +The following example will create a new branch, from `develop`, called `new-feature`: -Unlike our previous flow with Mercurial and patch queues, when using git, you -will be committing changes to your local branch. By using separate branches in -git, you will be able to pull in and merge changes from mainline and simply -keep up with upstream changes. +```sh +git switch -c new-feature +``` -We use a rebase-always model for contributions to the develop branch of gem5. -In this model, the changes are rebased on top of the tip of develop instead of -merged. This means that to contribute, you will have to frequently rebase any -feature branches on top of develop. If you see a "merge conflict" in gerrit, it -can often be solved with a simple rebase. To find out more information about -rebasing and git, see the [git book]. +## Making modifications -[git book]: https://git-scm.com/book/en/v2/Git-Branching-Rebasing +### C/CPP +Different tasks will require the project to be modified in different ways. +Though, in all cases, our style-guide must be adhered to. The full C/C++ style +guide is outlined [here](/documentation/general_docs/development/coding_style). -Setting up pre-commit ---------------------- +As a high-level overview: -To help ensure the gem5 style guide is maintained, we use [pre-commit]( -https://pre-commit.com) to run checks on changes to be contributed. +* Lines must not exceed 79 characters in length. +* There should be no trailing white-space on any line. +* Indentations must be 4 spaces (no tab characters). +* Class names must use upper camel case (e.g., `ThisIsAClass`). +* Class member variables must use lower camel case (e.g., +`thisIsAMemberVariable`). +* Class member variables with their own public accessor must start with an +underscore (e.g., `_variableWithAccessor`). +* Local variables must use snake case (e.g., `this_is_a_local_variable`). +* Functions must use lower camel case (e.g., `thisIsAFunction`) +* Function parameters must use snake case. +* Macros must be in all caps with underscores (e.g., `THIS_IS_A_MACRO`). +* Function declaration return types must be on their own line. +* Function brackets must be on their own line. +* `for`/`if`/`while` branching operations must be followed by a white-space +before the conditional statement (e.g., `for (...)`). +* `for`/`if`/`while` branching operations' opening bracket must be on the +same line, with the closing bracket on its own line (e.g., +`for (...) {\n ... \n}\n`). There should be a space between the condition(s) +and the opening bracket. +* C++ access modifies must be indented by two spaces, with method/variables +defined within indented by four spaces. -To setup pre-commit, run the following in your gem5 directory to install the -pre-commit and commit message hooks. +Below is a simple toy example of how a class should be formatted: + +```C++ +#DEFINE EXAMPLE_MACRO 7 +class ExampleClass +{ + private: + int _fooBar; + int barFoo; + + public: + int + getFooBar() + { + return _fooBar; + } + + int + aFunction(int parameter_one, int parameter_two) + { + int local_variable = 0; + if (true) { + int local_variable = parameter_one + parameter_two + barFoo + + EXAMPLE_MACRO; + } + return local_variable; + } + +} +``` + +### Python + +We use [Python Black](https://github.com/psf/black) to format our Python code +to the correct style. To install: + +```sh +pip install black +``` + +Then run on modified/added python files using: + +```sh +black +``` + +For variable/method/etc. naming conventions, please follow the [PEP 8 naming +convention recommendations]( +https://peps.python.org/pep-0008/#naming-conventions). While we try our best to +enforce naming conventions across the gem5 project, we are aware there are +instances where they are not. In such cases please **follow the convention +of the code you are modifying**. + +### Using pre-commit + +To help enforce our style guide we use use [pre-commit]( +https://pre-commit.com). pre-commit is a git hook and, as such, must be +explicitly installed by a gem5 developer. + +To install the gem5 pre-commit checks, execute the following in the gem5 +directory: ```sh pip install pre-commit -pre-commit install -t pre-commit -t commit-msg +pre-commit install ``` -The hooks are also automatically installed when gem5 is compiled. +Once installed pre-commit will run checks on modified code prior to running the +`git commit` command (see [our section on committing](#committing) for more +details on committing your changes). If these tests fail you will not be able to +commit. -When you run a `git commit` command the pre-commit hook will run checks on your -committed code. The commit will be blocked if a check fails. +These same pre-commit checks are run as part our CI checks (those +which must pass in order for a change to be merged into the develop branch). It +is therefore strongly recommended that developers install pre-commit to catch +style errors early. -The same checks are run as part of github actions CI tests (those required to obtain -a Verified label, necessary for a change to be accepted to the develop branch). -Therefore setting up pre-commit in your local gem5 development environment is -recommended. +## Compiling and running tests -You can automatically format files to pass the pre-commit tests by running: +The minimum criteria for a change to be submitted is that the code is +compilable and the test cases pass. + +The following command both compiles the project and runs our "quick" +system-level checks: ```sh -pre-commit run --files +cd tests +./main.py run ``` -Requirements for change descriptions ------------------------------------- -To help reviewers and future contributors more easily understand and track -changes, we require all change descriptions be strictly formatted. +**Note: These tests can take several hours to build and execute. `main.py` may +be run on multiple threads with the `-j` flag. E.g.: `python main.py run +-j6`.** -A canonical commit message consists of three parts: - * A short summary line describing the change. This line starts with one or - more keywords (found in the MAINTAINERS file) separated by commas followed - by a colon and a description of the change. This short description is - written in the imperative mood, and should say what happens when the patch - is applied. Keep it short and simple. Write it in sentence case preferably - not ending in a period. This line should be no more than 65 characters long - since version control systems usually add a prefix that causes line-wrapping - for longer lines. - * (Optional, but highly recommended) A detailed description. This describes - what you have done and why. If the change isn't obvious, you might want to - motivate why it is needed. Lines need to be wrapped to 72 characters or - less. Leave a blank line between the first short summary line and this - detailed description. - * Tags describing patch metadata. You are highly recommended to use - tags to acknowledge reviewers for their work. +The unit tests should also pass. To run the unit tests: -Tags are an optional mechanism to store additional metadata about a patch and -acknowledge people who reported a bug or reviewed that patch. Tags are -generally appended to the end of the commit message in the order they happen. -We currently use the following tags: - * Signed-off-by: Added by the author and the submitter (if different). - This tag is a statement saying that you believe the patch to be correct and - have the right to submit the patch according to the license in the affected - files. Similarly, if you commit someone else's patch, this tells the rest - of the world that you have have the right to forward it to the main - repository. If you need to make any changes at all to submit the change, - these should be described within hard brackets just before your - Signed-off-by tag. By adding this line, the contributor certifies the - contribution is made under the terms of the Developer Certificate of Origin - (DCO) [https://developercertificate.org/]. - * Reviewed-by: Used to acknowledge patch reviewers. It's generally considered - good form to add these. Added automatically. - * Reported-by: Used to acknowledge someone for finding and reporting a bug. - * Reviewed-on: Link to the review request corresponding to this patch. Added - automatically. - * Change-Id: Used by Gerrit to track changes across rebases. Added - automatically with a commit hook by git. - * Tested-by: Used to acknowledge people who tested a patch. Sometimes added - automatically by review systems that integrate with CI systems. - * Issue-On: Used to link a commit to an issue in gem5's [issue tracker]. The - format should be https://gem5.atlassian.net/browse/GEM5- - -[issue tracker]: https://gem5.atlassian.net/ - -Other than the "Signed-off-by", "Issue-On", "Reported-by", and "Tested-by" -tags, you generally don't need to add these manually as they are added -automatically by Gerrit. - -It is encouraged for the author of the patch and the submitter to add a -Signed-off-by tag to the commit message. By adding this line, the contributor -certifies the contribution is made under the terms of the Developer Certificate -of Origin (DCO) [https://developercertificate.org/]. - -If your change relates to a [Jira Issue](https://gem5.atlassian.net), it is -advised that you provide a link to the issue in the commit message (or messages -if the Jira Issue relates to multiple commits). Though optional, doing this -can help reviewers understand the context of a change. - -It is imperative that you use your real name and your real email address in -both tags and in the author field of the changeset. - -For significant changes, authors are encouraged to add copyright information -and their names at the beginning of the file. The main purpose of the author -names on the file is to track who is most knowledgeable about the file (e.g., -who has contributed a significant amount of code to the file). The -`util/update-copyright.py` helper script can help to keep your copyright dates -up-to-date when you make further changes to files which already have your -copyright but with older dates. - -Note: If you do not follow these guidelines, the github actions will -automatically reject your patch. -If this happens, update your changeset descriptions to match the required style -and resubmit. The following is a useful git command to update the most recent -commit (HEAD). - -``` - git commit --amend +```sh +scons build/NULL/unittests.opt ``` -Running tests -============= +To compile an individual gem5 binary: -Before posting a change to the code review site, you should always run the -quick tests! -See TESTING.md for more information. - -Posting a review -================ - -If you have not signed up for an account on the github -(https://github.com/), you first have to create an account. - -Setting up an account ---------------------- - 1. Go to https://github.com/ - 2. Click "Sign up" in the upper right corner. - -Submitting a change -------------------- - -In github, to submit a review request, you can simply push your git commits to -a special named branch. For more information on git push see -https://git-scm.com/docs/git-push. - -Push changes to GitHub ----------------------------- -1. Fork the gem5 repository on GitHub from https://github.com/gem5/gem5/. -2. Create a new branch in your forked repository for your feature or bug fix. -3. Commit your changes to the new branch. -4. Push the branch to your forked repository. -5. Open a pull request from your branch in your forked repository to the main gem5 repository. - -We will continue to use the “develop” branch for development, so please ensure your pull requests are for the gem5 develop branch. Pull requests to the stable branch will be blocked. - -Branches -======== - -By default, contributions to gem5 should be made on the develop branch. The -stable branch is maintained as a stable release branch (i.e., it can be pulled -to obtain the latest official release of gem5). Creation of additional branches -is generally discouraged due to their tendency to bloat git repositories with -abandoned code. - -Reviewing patches -================= - -Reviewing patches is done on our github instance at -https://github.com/gem5/gem5/pulls/. - -After logging in with your GitHub account, you will be able to comment, review, -and push your own patches as well as review others' patches. All gem5 users are -encouraged to review patches. The only requirement to review patches is to be -polite and respectful of others. - -There are multiple labels in Gerrit that can be applied to each review detailed -below. - * Code-review: This is used by any gem5 user to review patches. When reviewing - a patch you can give it a score of -2 to +2 with the following semantics. - * -2: This blocks the patch. You believe that this patch should never be - committed. This label should be very rarely used. - * -1: You would prefer this is not merged as is - * 0: No score - * +1: This patch seems good, but you aren't 100% confident that it should be - pushed. - * +2: This is a good patch and should be pushed as is. - * Maintainer: Currently only PMC members are maintainers. At least one - maintainer must review your patch and give it a +1 before it can be merged. - * Verified: This is automatically generated from the continuous integrated - (CI) tests. Each patch must receive at least a +1 from the CI tests before - the patch can be merged. The patch will receive a +1 if gem5 builds and - runs, and it will receive a +2 if the stats match. - * Style-Check: This is automatically generated and tests the patch against the - gem5 code style - (http://www.gem5.org/documentation/general_docs/development/coding_style/). - The patch must receive a +1 from the style checker to be pushed. - -Note: Whenever the patch creator updates the patch all reviewers must re-review -the patch. There is no longer a "Fix it, then Ship It" option. - -Once you have received reviews for your patch, you will likely need to make -changes. To do this, you should update the original git changeset. Then, you -can simply push the changeset again to the same Gerrit branch to update the -review request. - -``` - git push origin HEAD:refs/for/develop +```sh +scons build/ALL/gem5.opt ``` -Committing changes -================== +This compiles a gem5 binary containing "ALL" ISA targets. For more information +on building gem5 please consult our [building documentation]( +/documentation/general_docs/building). -Each patch must meet the following criteria to be merged: - * At least one review with +2 - * At least one maintainer with +1 - * At least +1 from the CI tests (gem5 must build and run) - * At least +1 from the style checker +## Committing -Once a patch meets the above criteria, the submitter of the patch will be able -to merge the patch by pressing the "Submit" button on Gerrit. When the patch is -submitted, it is merged into the public gem5 branch. +When you feel your change is done, you may commit. Start by adding the changed +files: -Review moderation and guidelines --------------------------------- +```Shell +git add +``` -Once a change is submitted, reviewers shall review the change. This may require -several iterations before a merge. Comments from reviewers may include -questions, and requests for alterations to the change prior to merging. The -overarching philosophy in managing this process is that there should be -politeness and clear communication between all parties at all times, and, -whenever possible, permission should be asked before doing anything that may -inconvenience another party. Included below are some guidelines we expect -contributors and reviewers to follow. +Make sure these changes are being added to your forked repository. +Then commit using: - * In all forms of communication, contributors and reviewers must be polite. - Comments seen as being needlessly hostile or dismissive will not be - tolerated. - * Change contributors should respond to, or act upon, each item of feedback - given by reviewers. If there is disagreement with a piece of - feedback, a sufficiently detailed reason for this disagreement should - be given. Polite discussion, and sharing of information and expertise - is strongly encouraged. - * Contributors are advised to assign reviewers when submitting a change. - Anyone who contributes to gem5 can be assigned as a reviewer. However, - all changes must be accepted by at least one maintainer prior to a - merge, ergo assigning of at least one maintainer as a reviewer is - strongly recommended. Please see MAINTAINERS for a breakdown of - gem5 maintainers and which components they claim responsibility for. - Maintainers should be chosen based on which components the change is - targeting. Assigning of reviewers is not strictly enforced, though not - assigning reviewers may slow the time in which a change is reviewed. - * If a contributor posts a change and does not receive any reviews after two - working days (excluding regional holidays), it is acceptable to "prod" - reviewers. This can be done by adding a reply to the changeset review - (e.g., "Would it be possible for someone to review my change?"). If the - contributor has yet to assign reviewers, they are strongly advised to do so. - Reviewers will get notified when assigned to referee a change. - * By default, the original contributor is assumed to own a change. I.e., - they are assumed to be the sole party to submit patchsets. If someone - other than the original contributor wishes to submit patchsets to a - change on the original contributor's behalf, they should first ask - permission. If two working days pass without a response, a patchset may be - submitted without permission. Permission does not need to be asked to submit - a patchset consisting of minor, inoffensive, changes such a typo and format - fixes. - * Once a change is ready to merge, it enters a "Ready to Submit" state. The - original contributor should merge their change at this point, assuming they - are content with the commit in its present form. After two working days, a - reviewer may message a contributor to remind them of the change being in a - "Ready to Submit" state and ask if they can merge the change on the - contributors behalf. If a further two working days elapse without a - response, the reviewer may merge without permission. A contributor may keep - a change open for whatever reason though this should be communicated to the - reviewer when asked. - * After a month of inactivity from a contributor on an active change, a - reviewer may post a message on the change reminding the submitter, and - anyone else watching the change, of its active status and ask if they are - still interested in eventually merging the change. After two weeks of no - response the reviewer reserves the right to abandon the change under the - assumption there is no longer interest. - * The final arbiter in any dispute between reviewers and/or contributors - is the PMC (PMC members are highlighted in MAINTAINERS). Disputes requiring - intervention by the PMC are undesirable. Attempts should be made to resolve - disagreements via respectful and polite discourse before being escalated to - this level. +```Shell +git commit +``` -Releases -======== +The commit message must adhere to our style. The first line of the commit is +the "header". The header starts with a tag (or tags, separated by a comma), +then a colon. Which tags are used depend on which components of gem5 +you have modified. **Please refer to the [MAINTAINERS.yaml]( +https://github.com/gem5/gem5/blob/stable/MAINTAINERS.yaml) for +a comprehensive list of accepted tags**. After this colon a short description +of the commit must be provided. **This header line must not exceed 65 +characters**. + +After this, a more detailed description of the commit can be added. This is +inserted below the header, separated by an empty line. Including a description +is optional but it's strongly recommended. The description may span multiple +lines, and multiple paragraphs. **No line in the description may exceed 72 +characters.** + +To improve the navigability of the gem5 project we would appreciate if commit +messages include a link to the relevant Jira issue/issues. + +Below is an example of how a gem5 commit message should be formatted: + +``` +test,base: This commit tests some classes in the base component + +This is a more detailed description of the commit. This can be as long +as is necessary to adequately describe the change. + +A description may spawn multiple paragraphs if desired. + +Jira Issue: https://gem5.atlassian.net/browse/GEM5-186 +``` + +If you feel the need to change your commit, add the necessary files then +_amend_ the changes to the commit using: + +```sh +git commit --amend +``` + +This will give you opportunity to edit the commit message. + +You may continue to add more commits as a chain of commits to be included in the pull-request. +However, we recommend that pull-requests are kept small and focused. +For example, if you wish to add a different feature or fix a different bug, we recommend doing so in another pull requests. + +## Keeping your forked and local repositories up-to-date + +While working on your contribution, we recommend keeping your forked repository in-sync with the source gem5 repository. +To do so, regularly [Sync your fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork). +This can be done via the GitHub web interface and, if so, you should `git pull` on top of your local `stable` and `develop` branches to ensure your local repository is in-sync. +To do so from the command line: + +```sh +# Add the main gem5 repository as a remote on your local repository. This only +# needs done once. +git remote add upstream https://github.com/gem5/gem5.git + +git fetch upstream # Obtain the latest from the gem5 repo. +git switch develop # Switch to the develop branch. +git merge upstream/develop # Merge the latest changes into the develop branch. +git push # Push to develop to your forked repo. +git switch stable # Switch to the stable branch. +git merge upstream/stable # Merge the latest changes into the stable branch. +git push # Push the changes to stable to your forked repo. +``` + +As our local branch work atop the `develop` branch, once we've synced our forked repository, we can rebase our local branch on top of the `develop` branch. +Assuming our local branch is called `new-feature`: + +```sh +git switch develop # Switching back to the develop branch. +git pull # Ensuring we have the latest from the forked repository. +git switch new-feature # Switching back to our local branch. +git rebase develop # Rebasing our local branch on top of the develop branch. +``` + +Conflicts may need resolved between your branch and new changes. + +## Pushing and creating a pull request + +Once you have completed your changes locally, you can push to your forked gem5 repository. +Assuming the branch we are working on is `new-feature`: + +```sh +git switch new-feature # Ensure we are on the 'new-feature' branch. +git push --set-upstream origin new-feature +``` + +Now, via the GitHub web interface, you can [create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) of your changes from your forked repository's branch into the gem5 `develop` branch. + +## Passing the checks + +Once you have created a pull request, the gem5 Continuous Integration (CI) tests will run. +These run a series of checks to ensure your changes are valid. +These must pass before your changes can be merged into the gem5 `develop` branch. + +In addition to the CI tests, your changes will be reviewed by the gem5 community. +Your pull-request must have the approval of at least one community member prior to being merged. + +Once your pull-request has passed all the CI tests and has been approved by at least one community member, it will be merged a gem5 maintainer will do a [Merge](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges) on the pull-request. +The gem5 maintainers are individuals granted the ability to merge pull requests into the gem5 `develop` branch. + + +### Making iterative improvements based on feedback + +A reviewer will ask questions and post suggestions on GitHub. You should read +these comments and answer these questions. **All communications between +reviewers and contributors should be done in a polite manner. Rude and/or +dismissive remarks will not be tolerated.** + +When you understand what changes are required make amendments to the pull +request by adding patches to the same branch and then pushing to the forked repository. +A git "force push" (i.e., `git push --force`) is also acceptable if you wish to alter the commits locally in order to make the changes. +We encourage contributors to help keep our `git log` clean and readable. +We recommend that users rebase their changes frequently on top of the develop branch, squash their commits where appropriate (e.g., in cases where there are many small fix commits to a change in the same PR) then force push changes to keep their PR commits concise. + +Once pushed to the forked repository, the pull request will automatically update with your changes. +The reviewer will then re-review your changes and, if necessary, ask for further changes, or approve your pull-request. + +## Reviewing other contributions + +We encourage all gem5 developers to review other's contributions. +Anyone may review a gem5 change and, if they feel it is ready, approve it. +All pull-requests can be found at . + +When reviewing a pull request we enforce the followings guidelines. +These have been designed to ensure clear and polite communication between all parties: + +* In all forms of communication, contributors and reviewers must be polite. +Comments seen as being rude or dismissive will not be tolerated. +* If choosing to not approve a PR, please state clearly why. +When asking for changes, the commits should be specific and actionable. +General criticisms which cannot be addressed or understood by the contributor are unhelpful. +If the contribution needs improvement, reviewers should state what their requested changes are. +If more information is needed for the reviewers to make a decision the reviewer should ask clear questions. +If the PR is generally not seen as a worthwhile contribution, a good justification should be given so the contributor may fairly rebuttal. +* By default, the original contributor is assumed to own a change. +I.e., they are assumed to be the sole party to submit patches to the pull request. +If someone other than the original contributor wishes to submit patches on the original contributors behalf they should first ask permission. +Pull requests which appear abandoned may be adopted by a new contributor as long as there is good enough reason to assume the original contributor is no longer working on the pull request. +* Maintainers have the final say on whether a change is merged. +Your review will be taken into account by the maintainer. +It is expected, in all but the most extreme cases, that the reviewer's concerns must be addressed and for the reviewer to approve the the contribution prior to the maintainer merging the pull request. + +We also recommend consulting Google's ["How to write code review comments"](https://google.github.io/eng-practices/review/reviewer/comments.html) for advice on giving feedback to contributors. + +## Releases gem5 releases occur 3 times per year. The procedure for releasing gem5 is as follows: @@ -435,7 +400,7 @@ gem5-dev mailing list will be notified that the staging branch will be merged into the stable branch after two weeks, thus marking the new release. 3. The staging branch will have the full suite of gem5 tests run on it to ensure all tests pass and the to-be-released code is in a decent state. -4. If a user submits a changeset to the staging branch, it will be considered +4. If a user submits a pull request to the staging branch, it will be considered and undergo the standard github review process. However, only alterations that cannot wait until the following release will be accepted for submission into the branch (i.e., submissions to the staging branch for "last minute" @@ -444,8 +409,8 @@ fix). The project maintainers will use their discretion in deciding whether a change may be submitted directly to the staging branch. All other submissions to gem5 will continue to be made to the develop branch. Patches submitted into the staging branch do not need to be re-added to the develop branch. -5. Once signed off by members of the PMC the staging branch shall be merged -into the stable and develop branch. The staging branch will then be deleted. +5. Once the staging branch has been deemed ready for release, the [release procedures](https://www.gem5.org/documentation/general_docs/development/release_procedures/) will be carried out. +This will end with the staging branch being merged into the stable branch. 6. The stable branch shall be tagged with the correct version number for that release. gem5 conforms to a "v{YY}.{MAJOR}.{MINOR}.{HOTFIX}" versioning system. E.g., the first major release of 2022 will be "v22.0.0.0", followed by @@ -455,8 +420,16 @@ the minor release numbers in case this policy changes in the future. 7. The gem5-dev and gem5-user mailing lists shall be notified of the new gem5 release. -Hotfixes --------- +### Exemptions + +Due to limitations with GitHub we may update the ".github" directory in the gem5 repo's `stable` branch between gem5 releases. +This is due to certain processes carried out by the GitHub Actions infrastructure which rely on configurations being present on a repository's primary branch. +As the files in ".github" only influence the functionality of our GitHub actions and other GitHub activities, updating these files does not change the functionality of the gem5 in way. +It is therefore safe to do this. +Despite this exemption to our normal procedure we aim to ensure that **the ".github" directory on the `stable` is never "ahead" of that in the `develop` branch**. +Therefore contributors who wish to update files in ".github" should submit their changes to `develop` and then request their changes to be applied to the `stable` branch. + +### Hotfixes There may be circumstances in which a change to gem5 is deemed critical and cannot wait for an official release (e.g., a high-priority bug fix). In these From 63d98018ea77b9a5121b0875a2aaa87b9dee7a81 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 21 Jul 2023 13:38:31 -0500 Subject: [PATCH 126/693] arch-x86: Move CPUID values to python CPUID values for X86 are currently hard-coded in the C++ source file. This makes it difficult to configure the bits if needed. Move these to python instead. This will provide a few benefits: 1. We can enable features for certain configurations, for example AVX can be enabled when the KVM CPU is used, but otherwise should not be enabled as gem5 does not have full AVX support. 2. We can more accurately communicate things like cache/TLB sizes based on the actual gem5 configuration. The CPUID values are can be used by some libraries, e.g., MPI, to query system topology. 3. Enabling some bits breaks things in certain configurations and this can be prevented by configuring in python. For example, enabling AVX seems to currently be breaking SMP, meaning gem5 can only boot one CPU in that configuration. Change-Id: Ib3866f39c86d61374b9451e60b119a3155575884 --- src/arch/x86/X86ISA.py | 56 +++++ src/arch/x86/cpuid.cc | 229 +++++++----------- src/arch/x86/cpuid.hh | 81 +++++-- src/arch/x86/isa.cc | 15 +- src/arch/x86/isa.hh | 3 + src/arch/x86/isa/decoder/two_byte_opcodes.isa | 5 +- src/arch/x86/isa/includes.isa | 1 + src/arch/x86/kvm/x86_cpu.cc | 10 +- 8 files changed, 231 insertions(+), 169 deletions(-) diff --git a/src/arch/x86/X86ISA.py b/src/arch/x86/X86ISA.py index bb72c415e9..aa5c29a98e 100644 --- a/src/arch/x86/X86ISA.py +++ b/src/arch/x86/X86ISA.py @@ -54,3 +54,59 @@ class X86ISA(BaseISA): vendor_string = Param.String( "HygonGenuine", "Vendor string for CPUID instruction" ) + name_string = Param.String( + "Fake gem5 x86_64 CPU", "Processor name for CPUID instruction" + ) + + # For the functions that return numerical values we use a vector of ints. + # The order of the values is: EAX, EBX, EDX, ECX. + # + # If the CPU function can take an index, the index value is used as an + # offset into the vector and four numerical values are added for each + # possible index value. For example, if the function accepts 3 index + # values, there are 12 total ints in the vector param. In addition, the + # last values for functions which take an index must be all zeros. All + # zeros indicates to the KVM cpu / OS that there are no more index values + # to iterate over. + # + # A good resource for these values can be found here: + # https://sandpile.org/x86/cpuid.htm + # 0000_0001h + FamilyModelStepping = VectorParam.UInt32( + [0x00020F51, 0x00000805, 0xEFDBFBFF, 0x00000209], + "type/family/model/stepping and feature flags", + ) + # 0000_0004h + CacheParams = VectorParam.UInt32( + [0x00000000, 0x00000000, 0x00000000, 0x00000000], + "cache configuration descriptors", + ) + # 0000_0007h + ExtendedFeatures = VectorParam.UInt32( + [0x00000000, 0x01800000, 0x00000000, 0x00000000], "feature flags" + ) + # 8000_0001h + FamilyModelSteppingBrandFeatures = VectorParam.UInt32( + [0x00020F51, 0x00000405, 0xEBD3FBFF, 0x00020001], + "family/model/stepping and features flags", + ) + # 8000_0005h + L1CacheAndTLB = VectorParam.UInt32( + [0xFF08FF08, 0xFF20FF20, 0x40020140, 0x40020140], + "L1 cache and L1 TLB configuration descriptors", + ) + # 8000_0006h + L2L3CacheAndL2TLB = VectorParam.UInt32( + [0x00000000, 0x42004200, 0x00000000, 0x04008140], + "L2/L3 cache and L2 TLB configuration descriptors", + ) + # 8000_0007h + APMInfo = VectorParam.UInt32( + [0x80000018, 0x68747541, 0x69746E65, 0x444D4163], + "processor feedback capabilities", + ) + # 8000_0008h + LongModeAddressSize = VectorParam.UInt32( + [0x00003030, 0x00000000, 0x00000000, 0x00000000], + "miscellaneous information", + ) diff --git a/src/arch/x86/cpuid.cc b/src/arch/x86/cpuid.cc index ac4709ce0e..2ce763e0af 100644 --- a/src/arch/x86/cpuid.cc +++ b/src/arch/x86/cpuid.cc @@ -31,162 +31,105 @@ #include "arch/x86/isa.hh" #include "base/bitfield.hh" #include "cpu/thread_context.hh" +#include "debug/X86.hh" namespace gem5 { -namespace X86ISA { - enum StandardCpuidFunction - { - VendorAndLargestStdFunc, - FamilyModelStepping, - CacheAndTLB, - SerialNumber, - CacheParams, - MonitorMwait, - ThermalPowerMgmt, - ExtendedFeatures, - NumStandardCpuidFuncs - }; +namespace X86ISA +{ - enum ExtendedCpuidFunctions - { - VendorAndLargestExtFunc, - FamilyModelSteppingBrandFeatures, - NameString1, - NameString2, - NameString3, - L1CacheAndTLB, - L2L3CacheAndL2TLB, - APMInfo, - LongModeAddressSize, +X86CPUID::X86CPUID(const std::string& vendor, const std::string& name) + : vendorString(vendor), nameString(name) +{ + fatal_if(vendorString.size() != 12, + "CPUID vendor string must be 12 characters\n"); +} - /* - * The following are defined by the spec but not yet implemented - */ -/* // Function 9 is reserved - SVMInfo = 10, - // Functions 11-24 are reserved - TLB1GBPageInfo = 25, - PerformanceInfo,*/ +void +X86CPUID::addStandardFunc(uint32_t func, std::vector values) +{ + capabilities[func] = values; +} - NumExtendedCpuidFuncs - }; +void +X86CPUID::addExtendedFunc(uint32_t func, std::vector values) +{ + // Extended functions begin with 8000_0000h, but the enum is based from + // zero, so we need to add that to the function value. + capabilities[func | 0x80000000] = values; +} - static const int nameStringSize = 48; - static const char nameString[nameStringSize] = "Fake M5 x86_64 CPU"; +bool +X86CPUID::doCpuid(ThreadContext * tc, uint32_t function, uint32_t index, + CpuidResult &result) +{ + constexpr uint32_t ext = 0x80000000; - uint64_t - stringToRegister(const char *str) - { - uint64_t reg = 0; - for (int pos = 3; pos >=0; pos--) { - reg <<= 8; - reg |= str[pos]; - } - return reg; - } + DPRINTF(X86, "Calling CPUID function %x with index %d\n", function, index); - bool - doCpuid(ThreadContext * tc, uint32_t function, - uint32_t index, CpuidResult &result) - { - uint16_t family = bits(function, 31, 16); - uint16_t funcNum = bits(function, 15, 0); - if (family == 0x8000) { - // The extended functions - switch (funcNum) { - case VendorAndLargestExtFunc: - { - ISA *isa = dynamic_cast(tc->getIsaPtr()); - auto vendor_string = isa->getVendorString(); - result = CpuidResult( - 0x80000000 + NumExtendedCpuidFuncs - 1, - stringToRegister(vendor_string.c_str()), - stringToRegister(vendor_string.c_str() + 4), - stringToRegister(vendor_string.c_str() + 8)); - } - break; - case FamilyModelSteppingBrandFeatures: - result = CpuidResult(0x00020f51, 0x00000405, - 0xebd3fbff, 0x00020001); - break; - case NameString1: - case NameString2: - case NameString3: - { - // Zero fill anything beyond the end of the string. This - // should go away once the string is a vetted parameter. - char cleanName[nameStringSize]; - memset(cleanName, '\0', nameStringSize); - strncpy(cleanName, nameString, nameStringSize); + // Handle the string-related CPUID functions specially + if (function == VendorAndLargestStdFunc) { + result = CpuidResult(NumStandardCpuidFuncs - 1, + stringToRegister(vendorString.c_str()), + stringToRegister(vendorString.c_str() + 4), + stringToRegister(vendorString.c_str() + 8)); - int offset = (funcNum - NameString1) * 16; - assert(nameStringSize >= offset + 16); - result = CpuidResult( - stringToRegister(cleanName + offset + 0), - stringToRegister(cleanName + offset + 4), - stringToRegister(cleanName + offset + 12), - stringToRegister(cleanName + offset + 8)); - } - break; - case L1CacheAndTLB: - result = CpuidResult(0xff08ff08, 0xff20ff20, - 0x40020140, 0x40020140); - break; - case L2L3CacheAndL2TLB: - result = CpuidResult(0x00000000, 0x42004200, - 0x00000000, 0x04008140); - break; - case APMInfo: - result = CpuidResult(0x80000018, 0x68747541, - 0x69746e65, 0x444d4163); - break; - case LongModeAddressSize: - result = CpuidResult(0x00003030, 0x00000000, - 0x00000000, 0x00000000); - break; -/* case SVMInfo: - case TLB1GBPageInfo: - case PerformanceInfo:*/ - default: - warn("x86 cpuid family 0x8000: unimplemented function %u", - funcNum); - return false; - } - } else if (family == 0x0000) { - // The standard functions - switch (funcNum) { - case VendorAndLargestStdFunc: - { - ISA *isa = dynamic_cast(tc->getIsaPtr()); - auto vendor_string = isa->getVendorString(); - result = CpuidResult( - NumStandardCpuidFuncs - 1, - stringToRegister(vendor_string.c_str()), - stringToRegister(vendor_string.c_str() + 4), - stringToRegister(vendor_string.c_str() + 8)); - } - break; - case FamilyModelStepping: - result = CpuidResult(0x00020f51, 0x00000805, - 0xefdbfbff, 0x00000209); - break; - case ExtendedFeatures: - result = CpuidResult(0x00000000, 0x01800000, - 0x00000000, 0x00000000); - break; - default: - warn("x86 cpuid family 0x0000: unimplemented function %u", - funcNum); - return false; - } - } else { - warn("x86 cpuid: unknown family %#x", family); - return false; - } + return true; + } else if (function == (ext | VendorAndLargestExtFunc)) { + result = CpuidResult(0x80000000 + NumExtendedCpuidFuncs - 1, + stringToRegister(vendorString.c_str()), + stringToRegister(vendorString.c_str() + 4), + stringToRegister(vendorString.c_str() + 8)); + + return true; + } else if ((function == (ext | NameString1)) || + (function == (ext | NameString2)) || + (function == (ext | NameString3))) { + // Zero fill anything beyond the end of the string. This + // should go away once the string is a vetted parameter. + char cleanName[nameStringSize]; + memset(cleanName, '\0', nameStringSize); + strncpy(cleanName, nameString.c_str(), nameStringSize-1); + + int funcNum = bits(function, 15, 0); + int offset = (funcNum - NameString1) * 16; + assert(nameStringSize >= offset + 16); + result = CpuidResult( + stringToRegister(cleanName + offset + 0), + stringToRegister(cleanName + offset + 4), + stringToRegister(cleanName + offset + 12), + stringToRegister(cleanName + offset + 8)); return true; } + + // Ignore anything not in the map of supported CPUID functions. + // This is checked after the string-related functions as those are not + // in the capabilities map. + if (!capabilities.count(function)) { + return false; + } + + auto &cap_vec = capabilities[function]; + result = CpuidResult(cap_vec[0], cap_vec[1], + cap_vec[2], cap_vec[3]); + DPRINTF(X86, "CPUID function %x returning (%x, %x, %x, %x)\n", + function, result.rax, result.rbx, result.rdx, result.rcx); + + return true; +} + +uint64_t +X86CPUID::stringToRegister(const char *str) +{ + uint64_t reg = 0; + for (int pos = 3; pos >=0; pos--) { + reg <<= 8; + reg |= str[pos]; + } + return reg; +} + } // namespace X86ISA } // namespace gem5 diff --git a/src/arch/x86/cpuid.hh b/src/arch/x86/cpuid.hh index 5c1a8ccb16..a48d99907d 100644 --- a/src/arch/x86/cpuid.hh +++ b/src/arch/x86/cpuid.hh @@ -29,7 +29,10 @@ #ifndef __ARCH_X86_CPUID_HH__ #define __ARCH_X86_CPUID_HH__ +#include + #include "base/types.hh" +#include "params/X86ISA.hh" namespace gem5 { @@ -38,28 +41,72 @@ class ThreadContext; namespace X86ISA { - struct CpuidResult - { - uint64_t rax; - uint64_t rbx; - uint64_t rcx; - uint64_t rdx; - // These are not in alphebetical order on purpose. The order reflects - // how the CPUID orders the registers when it returns results. - CpuidResult(uint64_t _rax, uint64_t _rbx, - uint64_t _rdx, uint64_t _rcx) : - rax(_rax), rbx(_rbx), rcx(_rcx), rdx(_rdx) - {} +enum StandardCpuidFunction +{ + VendorAndLargestStdFunc, + FamilyModelStepping, + CacheAndTLB, + SerialNumber, + CacheParams, + MonitorMwait, + ThermalPowerMgmt, + ExtendedFeatures, + NumStandardCpuidFuncs +}; - CpuidResult() - {} - }; +enum ExtendedCpuidFunctions +{ + VendorAndLargestExtFunc, + FamilyModelSteppingBrandFeatures, + NameString1, + NameString2, + NameString3, + L1CacheAndTLB, + L2L3CacheAndL2TLB, + APMInfo, + LongModeAddressSize, + NumExtendedCpuidFuncs +}; - uint64_t stringToRegister(const char *str); +constexpr int nameStringSize = 48; + +struct CpuidResult +{ + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + + // These are not in alphebetical order on purpose. The order reflects + // how the CPUID orders the registers when it returns results. + CpuidResult(uint64_t _rax, uint64_t _rbx, + uint64_t _rdx, uint64_t _rcx) : + rax(_rax), rbx(_rbx), rcx(_rcx), rdx(_rdx) + {} + + CpuidResult() + {} +}; + +class X86CPUID +{ + public: + X86CPUID(const std::string& vendor, const std::string& name); + + void addStandardFunc(uint32_t func, std::vector values); + void addExtendedFunc(uint32_t func, std::vector values); bool doCpuid(ThreadContext * tc, uint32_t function, - uint32_t index, CpuidResult &result); + uint32_t index, CpuidResult &result); + + private: + const std::string vendorString; + const std::string nameString; + std::unordered_map> capabilities; + + uint64_t stringToRegister(const char *str); +}; } // namespace X86ISA } // namespace gem5 diff --git a/src/arch/x86/isa.cc b/src/arch/x86/isa.cc index 31efae3a43..cf1ff9f593 100644 --- a/src/arch/x86/isa.cc +++ b/src/arch/x86/isa.cc @@ -151,10 +151,19 @@ RegClass matRegClass(MatRegClass, MatRegClassName, 1, debug::MatRegs); } // anonymous namespace -ISA::ISA(const X86ISAParams &p) : BaseISA(p), vendorString(p.vendor_string) +ISA::ISA(const X86ISAParams &p) + : BaseISA(p), cpuid(new X86CPUID(p.vendor_string, p.name_string)) { - fatal_if(vendorString.size() != 12, - "CPUID vendor string must be 12 characters\n"); + cpuid->addStandardFunc(FamilyModelStepping, p.FamilyModelStepping); + cpuid->addStandardFunc(CacheParams, p.CacheParams); + cpuid->addStandardFunc(ExtendedFeatures, p.ExtendedFeatures); + + cpuid->addExtendedFunc(FamilyModelSteppingBrandFeatures, + p.FamilyModelSteppingBrandFeatures); + cpuid->addExtendedFunc(L1CacheAndTLB, p.L1CacheAndTLB); + cpuid->addExtendedFunc(L2L3CacheAndL2TLB, p.L2L3CacheAndL2TLB); + cpuid->addExtendedFunc(APMInfo, p.APMInfo); + cpuid->addExtendedFunc(LongModeAddressSize, p.LongModeAddressSize); _regClasses.push_back(&flatIntRegClass); _regClasses.push_back(&flatFloatRegClass); diff --git a/src/arch/x86/isa.hh b/src/arch/x86/isa.hh index f7ae210f96..9c6dcf0921 100644 --- a/src/arch/x86/isa.hh +++ b/src/arch/x86/isa.hh @@ -33,6 +33,7 @@ #include #include "arch/generic/isa.hh" +#include "arch/x86/cpuid.hh" #include "arch/x86/pcstate.hh" #include "arch/x86/regs/ccr.hh" #include "arch/x86/regs/float.hh" @@ -93,6 +94,8 @@ class ISA : public BaseISA void setThreadContext(ThreadContext *_tc) override; std::string getVendorString() const; + + std::unique_ptr cpuid; }; } // namespace X86ISA diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 38937cb3e2..dac5706a06 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -690,8 +690,9 @@ } 0x2: CPUIDInst::CPUID({{ CpuidResult result; - bool success = doCpuid(xc->tcBase(), bits(Rax, 31, 0), - bits(Rcx, 31, 0), result); + ISA *isa = dynamic_cast(xc->tcBase()->getIsaPtr()); + bool success = isa->cpuid->doCpuid(xc->tcBase(), + bits(Rax, 31, 0), bits(Rcx, 31, 0), result); if (success) { Rax = result.rax; Rbx = result.rbx; diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 6fc5f448a0..9445f2032b 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -63,6 +63,7 @@ output header {{ #include "arch/x86/insts/microregop.hh" #include "arch/x86/insts/microspecop.hh" #include "arch/x86/insts/static_inst.hh" +#include "arch/x86/isa.hh" #include "arch/x86/regs/ccr.hh" #include "arch/x86/regs/int.hh" #include "arch/x86/regs/misc.hh" diff --git a/src/arch/x86/kvm/x86_cpu.cc b/src/arch/x86/kvm/x86_cpu.cc index 7faa9159ab..fdb557af88 100644 --- a/src/arch/x86/kvm/x86_cpu.cc +++ b/src/arch/x86/kvm/x86_cpu.cc @@ -37,6 +37,7 @@ #include "arch/x86/cpuid.hh" #include "arch/x86/faults.hh" #include "arch/x86/interrupts.hh" +#include "arch/x86/isa.hh" #include "arch/x86/regs/float.hh" #include "arch/x86/regs/int.hh" #include "arch/x86/regs/msr.hh" @@ -1443,26 +1444,27 @@ X86KvmCPU::updateCPUID() * currently not a problem since M5 doesn't expose any of them at * the moment. */ + X86ISA::ISA *isa = dynamic_cast(tc->getIsaPtr()); /* Basic features */ CpuidResult func0; - X86ISA::doCpuid(tc, 0x0, 0, func0); + isa->cpuid->doCpuid(tc, 0x0, 0, func0); for (uint32_t function = 0; function <= func0.rax; ++function) { CpuidResult cpuid; uint32_t idx(0); - X86ISA::doCpuid(tc, function, idx, cpuid); + isa->cpuid->doCpuid(tc, function, idx, cpuid); m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); } /* Extended features */ CpuidResult efunc0; - X86ISA::doCpuid(tc, 0x80000000, 0, efunc0); + isa->cpuid->doCpuid(tc, 0x80000000, 0, efunc0); for (uint32_t function = 0x80000000; function <= efunc0.rax; ++function) { CpuidResult cpuid; uint32_t idx(0); - X86ISA::doCpuid(tc, function, idx, cpuid); + isa->cpuid->doCpuid(tc, function, idx, cpuid); m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); } From 3946f7ba2c825afbd2c995201d5a9e4e2fe0f11c Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 21 Jul 2023 14:08:18 -0500 Subject: [PATCH 127/693] arch-x86: Support CPUID functions with indexes Various CPUID functions will return different values depending on the value of ECX when executing the CPUID instruction. Add support for this in the X86 KVM CPU. A subsequent patch will add a CPUID function which requires iterating through multiple ECX values. Change-Id: Ib44a52be52ea632d5e2cee3fb2ca390b60a7202a --- src/arch/x86/cpuid.cc | 22 ++++++++++-- src/arch/x86/cpuid.hh | 1 + src/arch/x86/kvm/x86_cpu.cc | 71 ++++++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/arch/x86/cpuid.cc b/src/arch/x86/cpuid.cc index 2ce763e0af..75e69735c1 100644 --- a/src/arch/x86/cpuid.cc +++ b/src/arch/x86/cpuid.cc @@ -111,9 +111,19 @@ X86CPUID::doCpuid(ThreadContext * tc, uint32_t function, uint32_t index, return false; } + int cap_offset = 0; + + // Ignore index values for functions that do not take index values. + if (hasSignificantIndex(function)) { + cap_offset = index * 4; + } + + // Ensure we have the offset and 4 dwords after it. + assert(capabilities[function].size() >= (cap_offset + 4)); + auto &cap_vec = capabilities[function]; - result = CpuidResult(cap_vec[0], cap_vec[1], - cap_vec[2], cap_vec[3]); + result = CpuidResult(cap_vec[cap_offset + 0], cap_vec[cap_offset + 1], + cap_vec[cap_offset + 2], cap_vec[cap_offset + 3]); DPRINTF(X86, "CPUID function %x returning (%x, %x, %x, %x)\n", function, result.rax, result.rbx, result.rdx, result.rcx); @@ -131,5 +141,13 @@ X86CPUID::stringToRegister(const char *str) return reg; } +// Return true if the CPUID function takes ECX index as an input AND +// those multiple index values are supported in gem5. +bool +X86CPUID::hasSignificantIndex(uint32_t function) +{ + return false; +} + } // namespace X86ISA } // namespace gem5 diff --git a/src/arch/x86/cpuid.hh b/src/arch/x86/cpuid.hh index a48d99907d..71e8d3c626 100644 --- a/src/arch/x86/cpuid.hh +++ b/src/arch/x86/cpuid.hh @@ -99,6 +99,7 @@ class X86CPUID bool doCpuid(ThreadContext * tc, uint32_t function, uint32_t index, CpuidResult &result); + bool hasSignificantIndex(uint32_t function); private: const std::string vendorString; diff --git a/src/arch/x86/kvm/x86_cpu.cc b/src/arch/x86/kvm/x86_cpu.cc index fdb557af88..e1c1b0dfc0 100644 --- a/src/arch/x86/kvm/x86_cpu.cc +++ b/src/arch/x86/kvm/x86_cpu.cc @@ -74,6 +74,13 @@ using namespace X86ISA; // data) is used to indicate that a segment has been accessed. #define SEG_TYPE_BIT_ACCESSED 1 +// Some linux distro s(e.g., RHEL7) define the KVM macros using "BIT" but do +// not include where BIT is defined, so define it here in that case. +#ifndef BIT +#define BIT(nr) (1UL << (nr)) +#endif + + struct GEM5_PACKED FXSave { uint16_t fcw; @@ -1420,12 +1427,12 @@ X86KvmCPU::ioctlRun() static struct kvm_cpuid_entry2 makeKvmCpuid(uint32_t function, uint32_t index, - CpuidResult &result) + CpuidResult &result, uint32_t flags = 0) { struct kvm_cpuid_entry2 e; e.function = function; e.index = index; - e.flags = 0; + e.flags = flags; e.eax = (uint32_t)result.rax; e.ebx = (uint32_t)result.rbx; e.ecx = (uint32_t)result.rcx; @@ -1438,12 +1445,6 @@ void X86KvmCPU::updateCPUID() { Kvm::CPUIDVector m5_supported; - - /* TODO: We currently don't support any of the functions that - * iterate through data structures in the CPU using an index. It's - * currently not a problem since M5 doesn't expose any of them at - * the moment. - */ X86ISA::ISA *isa = dynamic_cast(tc->getIsaPtr()); /* Basic features */ @@ -1453,8 +1454,31 @@ X86KvmCPU::updateCPUID() CpuidResult cpuid; uint32_t idx(0); - isa->cpuid->doCpuid(tc, function, idx, cpuid); - m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); + if (!isa->cpuid->hasSignificantIndex(function)) { + isa->cpuid->doCpuid(tc, function, idx, cpuid); + m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); + } else { + while (true) { + bool rv = isa->cpuid->doCpuid(tc, function, idx, cpuid); + assert(rv); + + if (idx && + !cpuid.rax && !cpuid.rbx && !cpuid.rdx && !cpuid.rcx) { + break; + } + + /* + * For functions in family 0, this flag tells Linux to compare + * the index as well as the function number rather than only + * the function number. Important: Do NOT set this flag if the + * function does not take an index. Doing so will break SMP. + */ + uint32_t flag = KVM_CPUID_FLAG_SIGNIFCANT_INDEX; + m5_supported.push_back( + makeKvmCpuid(function, idx, cpuid, flag)); + idx++; + } + } } /* Extended features */ @@ -1464,8 +1488,31 @@ X86KvmCPU::updateCPUID() CpuidResult cpuid; uint32_t idx(0); - isa->cpuid->doCpuid(tc, function, idx, cpuid); - m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); + if (!isa->cpuid->hasSignificantIndex(function)) { + isa->cpuid->doCpuid(tc, function, idx, cpuid); + m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); + } else { + while (true) { + bool rv = isa->cpuid->doCpuid(tc, function, idx, cpuid); + assert(rv); + + if (idx && + !cpuid.rax && !cpuid.rbx && !cpuid.rdx && !cpuid.rcx) { + break; + } + + /* + * For functions in family 0, this flag tells Linux to compare + * the index as well as the function number rather than only + * the function number. Important: Do NOT set this flag if the + * function does not take an index. Doing so will break SMP. + */ + uint32_t flag = KVM_CPUID_FLAG_SIGNIFCANT_INDEX; + m5_supported.push_back( + makeKvmCpuid(function, idx, cpuid, flag)); + idx++; + } + } } setCPUID(m5_supported); From 3584c3126cf5ecc7cc9df8011fb7ca19e2194243 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 21 Jul 2023 16:17:54 -0500 Subject: [PATCH 128/693] arch-x86: Expose CR4.osxsave bit Related to the recent changes with moving CPUID values to python, this value is needed to enable AVX and needs a way to be exposed to python as well in order to set the bit and the corresponding CPUID values at the same time. Change-Id: I3cadb0fe61ff4ebf6de903018a8d8a411bfdb4e0 --- src/arch/x86/X86FsWorkload.py | 1 + src/arch/x86/fs_workload.cc | 4 +++- src/arch/x86/fs_workload.hh | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/X86FsWorkload.py b/src/arch/x86/X86FsWorkload.py index 294241b51c..277a37988e 100644 --- a/src/arch/x86/X86FsWorkload.py +++ b/src/arch/x86/X86FsWorkload.py @@ -65,6 +65,7 @@ class X86FsWorkload(KernelWorkload): acpi_description_table_pointer = Param.X86ACPIRSDP( X86ACPIRSDP(), "ACPI root description pointer structure" ) + enable_osxsave = Param.Bool(False, "Enable OSXSAVE in CR4 register") class X86FsLinux(X86FsWorkload): diff --git a/src/arch/x86/fs_workload.cc b/src/arch/x86/fs_workload.cc index 1a412380a6..88d7deed68 100644 --- a/src/arch/x86/fs_workload.cc +++ b/src/arch/x86/fs_workload.cc @@ -58,7 +58,8 @@ FsWorkload::FsWorkload(const Params &p) : KernelWorkload(p), smbiosTable(p.smbios_table), mpFloatingPointer(p.intel_mp_pointer), mpConfigTable(p.intel_mp_table), - rsdp(p.acpi_description_table_pointer) + rsdp(p.acpi_description_table_pointer), + enable_osxsave(p.enable_osxsave) {} void @@ -295,6 +296,7 @@ FsWorkload::initState() CR4 cr4 = tc->readMiscRegNoEffect(misc_reg::Cr4); // Turn on pae. cr4.pae = 1; + cr4.osxsave = enable_osxsave; tc->setMiscReg(misc_reg::Cr4, cr4); // Point to the page tables. diff --git a/src/arch/x86/fs_workload.hh b/src/arch/x86/fs_workload.hh index 9d14f91bb5..81db414fb2 100644 --- a/src/arch/x86/fs_workload.hh +++ b/src/arch/x86/fs_workload.hh @@ -106,6 +106,9 @@ class FsWorkload : public KernelWorkload Addr &fpSize, Addr &tableSize, Addr table=0); void writeOutACPITables(Addr begin, Addr &size); + + private: + bool enable_osxsave; }; } // namespace X86ISA From 7c3c2b05f38f20ddd5be5e5f2d5828c36ba95528 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 27 Jul 2023 10:44:34 -0500 Subject: [PATCH 129/693] arch-x86: Add extended state CPUID function The extended state CPUID function is used to set the values of the XCR0 register as well as specify the size of storage for context switching storage for x87 and AVX+. This function is iterative and therefore requires (1) marking it as such in the hsaSignificantIndex function (2) setting multiple sets of 4-tuples for the default CPUID values where the last 4-tuple ends with all zeros. Change-Id: Ib6a43925afb1cae75f61d8acff52a3cc26ce17c8 --- src/arch/x86/X86ISA.py | 14 ++++++++++++++ src/arch/x86/cpuid.cc | 12 ++++++++++++ src/arch/x86/cpuid.hh | 1 + src/arch/x86/isa.cc | 1 + 4 files changed, 28 insertions(+) diff --git a/src/arch/x86/X86ISA.py b/src/arch/x86/X86ISA.py index aa5c29a98e..aa48d1aa6e 100644 --- a/src/arch/x86/X86ISA.py +++ b/src/arch/x86/X86ISA.py @@ -85,6 +85,20 @@ class X86ISA(BaseISA): ExtendedFeatures = VectorParam.UInt32( [0x00000000, 0x01800000, 0x00000000, 0x00000000], "feature flags" ) + # 0000_000Dh - This uses ECX index, so the last entry must be all zeros + ExtendedState = VectorParam.UInt32( + [ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + ], + "extended state enumeration", + ) # 8000_0001h FamilyModelSteppingBrandFeatures = VectorParam.UInt32( [0x00020F51, 0x00000405, 0xEBD3FBFF, 0x00020001], diff --git a/src/arch/x86/cpuid.cc b/src/arch/x86/cpuid.cc index 75e69735c1..2ce9ec9289 100644 --- a/src/arch/x86/cpuid.cc +++ b/src/arch/x86/cpuid.cc @@ -146,6 +146,18 @@ X86CPUID::stringToRegister(const char *str) bool X86CPUID::hasSignificantIndex(uint32_t function) { + uint16_t family = bits(function, 31, 16); + uint16_t funcNum = bits(function, 15, 0); + + if (family == 0x0000) { + switch (funcNum) { + case ExtendedState: + return true; + default: + return false; + } + } + return false; } diff --git a/src/arch/x86/cpuid.hh b/src/arch/x86/cpuid.hh index 71e8d3c626..1c932980d2 100644 --- a/src/arch/x86/cpuid.hh +++ b/src/arch/x86/cpuid.hh @@ -52,6 +52,7 @@ enum StandardCpuidFunction MonitorMwait, ThermalPowerMgmt, ExtendedFeatures, + ExtendedState = 0xD, NumStandardCpuidFuncs }; diff --git a/src/arch/x86/isa.cc b/src/arch/x86/isa.cc index cf1ff9f593..9e6082a268 100644 --- a/src/arch/x86/isa.cc +++ b/src/arch/x86/isa.cc @@ -157,6 +157,7 @@ ISA::ISA(const X86ISAParams &p) cpuid->addStandardFunc(FamilyModelStepping, p.FamilyModelStepping); cpuid->addStandardFunc(CacheParams, p.CacheParams); cpuid->addStandardFunc(ExtendedFeatures, p.ExtendedFeatures); + cpuid->addStandardFunc(ExtendedState, p.ExtendedState); cpuid->addExtendedFunc(FamilyModelSteppingBrandFeatures, p.FamilyModelSteppingBrandFeatures); From 9acfc5a751c4df408b2fa9f73aa4512392c48c02 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 21 Jul 2023 16:25:03 -0500 Subject: [PATCH 130/693] configs: Enable AVX2 for GPUFS+KVM AVX is a requirement for some ROCm libraries, such as rocBLAS, which are themselves requirements for libraries higher up the stack like PyTorch. This patch sets the necessary CPUID bits in the GPUFS config to enable AVX, AVX2, and various SSE features so that applications using these libraries do not cause an illegal instruction trap. Change-Id: Id22f543fb2a06b268271725a54075ee6a9a1f041 --- configs/example/gpufs/system/system.py | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index 19df310295..7ddc4f0752 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -231,6 +231,42 @@ def makeGpuFSSystem(args): clock=args.ruby_clock, voltage_domain=system.voltage_domain ) + # If we are using KVM cpu, enable AVX. AVX is used in some ROCm libraries + # such as rocBLAS which is used in higher level libraries like PyTorch. + use_avx = False + if ObjectList.is_kvm_cpu(TestCPUClass): + # AVX also requires CR4.osxsave to be 1. These must be set together + # of KVM will error out. + system.workload.enable_osxsave = 1 + use_avx = True + + # These values are taken from a real CPU and are further explained here: + # https://sandpile.org/x86/cpuid.htm#level_0000_000Dh + avx_extended_state = [ + 0x00000007, + 0x00000340, + 0x00000000, + 0x00000340, + 0x0000000F, + 0x00000340, + 0x00000000, + 0x00000000, + 0x00000100, + 0x00000240, + 0x00000000, + 0x00000040, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + ] + + # This modifies the default value for ECX only (4th in this array). + # See: https://sandpile.org/x86/cpuid.htm#level_0000_0001h + # Enables AVX, OSXSAVE, XSAVE, POPCNT, SSE4.2, SSE4.1, CMPXCHG16B, + # and FMA. + avx_cpu_features = [0x00020F51, 0x00000805, 0xEFDBFBFF, 0x1C983209] + for (i, cpu) in enumerate(system.cpu): # Break once we reach the shader "CPU" if i == args.num_cpus: @@ -247,6 +283,9 @@ def makeGpuFSSystem(args): for j in range(len(system.cpu[i].isa)): system.cpu[i].isa[j].vendor_string = "AuthenticAMD" + if use_avx: + system.cpu[i].isa[j].ExtendedState = avx_extended_state + system.cpu[i].isa[j].FamilyModelStepping = avx_cpu_features if args.host_parallel: # To get the KVM CPUs to run on different host CPUs, specify a From c722b0c73d2c1730ab32ba169d69e5cdba725170 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 28 Jul 2023 13:37:32 -0500 Subject: [PATCH 131/693] arch-vega: Fix vop2Helper scalar support A previous change added a vop2Helper to remove 100s of lines of common code from VOP2 instructions related to processing SDWA and DPP support. That change inadvertently changed the type of operand source 0 from const to non-const. The vector container operator[] does not allow reading a scalar value such as a constant, a dword literal, etc. The error shows up in the form of: assert(!scalar) in operand.hh. Since the SDWA and DPP cases need to modify the source vector and non-SDWA/DPP cases might require const, we make a non-const copy of the const source 0 vector and place it in a tempoary non-const vector. This non-const vector is passed to the lambda function implementation of the instruction. This prevents needing a const and non-const version of the lambda and avoids needing to propagate the template parameters through the various SDWA/DPP helper methods which seems like it will not work anyways as they need to modify the vector. As a result of this, as more VOP2 instructions are implemented using this helper,they will need to specify the const and non-const template parameters of the vector container needed for the instruction. Change-Id: Ia0b3c550d7de32b830040007a110f4821e3385aa --- src/arch/amdgpu/vega/insts/instructions.cc | 2 +- src/arch/amdgpu/vega/insts/op_encodings.hh | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index 0d3f2dc00b..ab9c1cecf2 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -6394,7 +6394,7 @@ namespace VegaISA } }; - vop2Helper(gpuDynInst, opImpl); + vop2Helper(gpuDynInst, opImpl); } // execute // --- Inst_VOP2__V_MUL_HI_U32_U24 class methods --- diff --git a/src/arch/amdgpu/vega/insts/op_encodings.hh b/src/arch/amdgpu/vega/insts/op_encodings.hh index f1954723af..0f5f502add 100644 --- a/src/arch/amdgpu/vega/insts/op_encodings.hh +++ b/src/arch/amdgpu/vega/insts/op_encodings.hh @@ -339,7 +339,7 @@ namespace VegaISA return src0_dpp; } - template + template void vop2Helper(GPUDynInstPtr gpuDynInst, void (*fOpImpl)(T&, T&, T&, Wavefront*)) { @@ -359,7 +359,19 @@ namespace VegaISA T src0_dpp = dppHelper(gpuDynInst, src1); fOpImpl(src0_dpp, src1, vdst, wf); } else { - fOpImpl(src0, src1, vdst, wf); + // src0 is unmodified. We need to use the const container + // type to allow reading scalar operands from src0. Only + // src0 can index scalar operands. We copy this to vdst + // temporarily to pass to the lambda so the instruction + // does not need to write two lambda functions (one for + // a const src0 and one of a mutable src0). + ConstT const_src0(gpuDynInst, instData.SRC0); + const_src0.readSrc(); + + for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) { + vdst[lane] = const_src0[lane]; + } + fOpImpl(vdst, src1, vdst, wf); } vdst.write(); From 48ac1ea38dce6d7068ba4c0f95a3046812ed787c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 28 Jul 2023 01:01:50 -0700 Subject: [PATCH 132/693] gpu-compute: "" -> "base/random.hh" in testers/gpu... In "src/cpu/testers/gpu_ruby_test" a random number generator was used. This was using the CPP "" library. This patch changes it to the gem5 random class (that declared in "base/random.hh"). In addition to this, undeterministic behavior has been removed. Via "protocol_tester.cc" the RNG is either seeded with a seed specified by the user, or goes with the gem5 default seed. This ensures reproducable runs. Prior to this patch the RNG was seeded with `time(NULL)`. This made finding faults difficult. Change-Id: Ia8e9f7b87e91323f828e0b7f6c3906c0c5793b2c --- src/cpu/testers/gpu_ruby_test/ProtocolTester.py | 2 +- src/cpu/testers/gpu_ruby_test/address_manager.cc | 12 ++++++++---- src/cpu/testers/gpu_ruby_test/episode.cc | 3 ++- src/cpu/testers/gpu_ruby_test/protocol_tester.cc | 10 +++++----- src/cpu/testers/gpu_ruby_test/tester_thread.cc | 4 +++- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/cpu/testers/gpu_ruby_test/ProtocolTester.py b/src/cpu/testers/gpu_ruby_test/ProtocolTester.py index 178376bee9..c314392520 100644 --- a/src/cpu/testers/gpu_ruby_test/ProtocolTester.py +++ b/src/cpu/testers/gpu_ruby_test/ProtocolTester.py @@ -73,7 +73,7 @@ class ProtocolTester(ClockedObject): random_seed = Param.Int( 0, "Random seed number. Default value (0) means \ - using runtime-specific value.", + using base/random.hh without seed.", ) log_file = Param.String("Log file's name") system = Param.System(Parent.any, "System we belong to") diff --git a/src/cpu/testers/gpu_ruby_test/address_manager.cc b/src/cpu/testers/gpu_ruby_test/address_manager.cc index 049ba86e51..a0c0670a8f 100644 --- a/src/cpu/testers/gpu_ruby_test/address_manager.cc +++ b/src/cpu/testers/gpu_ruby_test/address_manager.cc @@ -33,7 +33,6 @@ #include #include -#include #include "base/intmath.hh" #include "base/logging.hh" @@ -101,7 +100,8 @@ AddressManager::getAddress(Location loc) AddressManager::Location AddressManager::getAtomicLoc() { - Location ret_atomic_loc = random() % numAtomicLocs; + Location ret_atomic_loc = \ + random_mt.random() % numAtomicLocs; atomicStructs[ret_atomic_loc]->startLocSelection(); return ret_atomic_loc; } @@ -206,7 +206,9 @@ AddressManager::AtomicStruct::getLoadLoc() // we can pick any location btw // locArray [firstMark : arraySize-1] int range_size = arraySize - firstMark; - Location ret_loc = locArray[firstMark + random() % range_size]; + Location ret_loc = locArray[ + firstMark + random_mt.random() % range_size + ]; // update loadStoreMap LdStMap::iterator it = loadStoreMap.find(ret_loc); @@ -238,7 +240,9 @@ AddressManager::AtomicStruct::getStoreLoc() } else { // we can pick any location btw [firstMark : secondMark-1] int range_size = secondMark - firstMark; - Location ret_loc = locArray[firstMark + random() % range_size]; + Location ret_loc = locArray[ + firstMark + random_mt.random() % range_size + ]; // update loadStoreMap LdStMap::iterator it = loadStoreMap.find(ret_loc); diff --git a/src/cpu/testers/gpu_ruby_test/episode.cc b/src/cpu/testers/gpu_ruby_test/episode.cc index 6822049bbd..7e16b0ef07 100644 --- a/src/cpu/testers/gpu_ruby_test/episode.cc +++ b/src/cpu/testers/gpu_ruby_test/episode.cc @@ -34,6 +34,7 @@ #include #include +#include "base/random.hh" #include "cpu/testers/gpu_ruby_test/protocol_tester.hh" #include "cpu/testers/gpu_ruby_test/tester_thread.hh" @@ -100,7 +101,7 @@ Episode::initActions() int num_loads = numLoads; int num_stores = numStores; while ((num_loads + num_stores) > 0) { - switch (random() % 2) { + switch (random_mt.random() % 2) { case 0: // Load if (num_loads > 0) { actions.push_back(new Action(Action::Type::LOAD, diff --git a/src/cpu/testers/gpu_ruby_test/protocol_tester.cc b/src/cpu/testers/gpu_ruby_test/protocol_tester.cc index f2fd7f9600..fdf30304f1 100644 --- a/src/cpu/testers/gpu_ruby_test/protocol_tester.cc +++ b/src/cpu/testers/gpu_ruby_test/protocol_tester.cc @@ -34,8 +34,8 @@ #include #include #include -#include +#include "base/random.hh" #include "cpu/testers/gpu_ruby_test/cpu_thread.hh" #include "cpu/testers/gpu_ruby_test/dma_thread.hh" #include "cpu/testers/gpu_ruby_test/gpu_wavefront.hh" @@ -141,11 +141,11 @@ ProtocolTester::ProtocolTester(const Params &p) sentExitSignal = false; - // set random seed number + // set random seed number, if specified. + // Note: random_m5 will use a fixed key if random_seed is not set. + // This ensures a reproducable. if (p.random_seed != 0) { - srand(p.random_seed); - } else { - srand(time(NULL)); + random_mt.init(p.random_seed); } actionCount = 0; diff --git a/src/cpu/testers/gpu_ruby_test/tester_thread.cc b/src/cpu/testers/gpu_ruby_test/tester_thread.cc index 760f8c2d87..ce3a1bccc6 100644 --- a/src/cpu/testers/gpu_ruby_test/tester_thread.cc +++ b/src/cpu/testers/gpu_ruby_test/tester_thread.cc @@ -33,6 +33,7 @@ #include +#include "base/random.hh" #include "debug/ProtocolTest.hh" namespace gem5 @@ -144,7 +145,8 @@ TesterThread::attachTesterThreadToPorts(ProtocolTester *_tester, void TesterThread::issueNewEpisode() { - int num_reg_loads = random() % tester->getEpisodeLength(); + int num_reg_loads = \ + random_mt.random() % tester->getEpisodeLength(); int num_reg_stores = tester->getEpisodeLength() - num_reg_loads; // create a new episode From 08a3762a14d9905f3eda19d96a10e69ea7e45121 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 28 Jul 2023 10:02:04 -0700 Subject: [PATCH 133/693] gpu-compute: Add warn for `random_seed == 0` case Addresses: https://github.com/gem5/gem5/pull/140#pullrequestreview-1552383650 Change-Id: Ia09a2bc74f35d3d6cb066efaf9d113db6caf4557 --- src/cpu/testers/gpu_ruby_test/protocol_tester.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cpu/testers/gpu_ruby_test/protocol_tester.cc b/src/cpu/testers/gpu_ruby_test/protocol_tester.cc index fdf30304f1..6b3f9e19f1 100644 --- a/src/cpu/testers/gpu_ruby_test/protocol_tester.cc +++ b/src/cpu/testers/gpu_ruby_test/protocol_tester.cc @@ -146,6 +146,15 @@ ProtocolTester::ProtocolTester(const Params &p) // This ensures a reproducable. if (p.random_seed != 0) { random_mt.init(p.random_seed); + } else { + warn( + "If `random_seed == 0` (or `random_seed` is unset) " + "ProtocolTester does not seed the RNG. This will NOT result in " + "the RNG generating different results each run. In this case the " + "RNG is seeded by a default value. This differs from behavior in " + "previous versions of gem5. Setting `random_seed` to a non-zero " + "value is strongly recommended." + ); } actionCount = 0; From 3f2899a7a8a930c7a9f7cdc0f3ee45bb98851844 Mon Sep 17 00:00:00 2001 From: "Ranganath (Bujji) Selagamsetty" Date: Fri, 28 Jul 2023 17:26:06 -0500 Subject: [PATCH 134/693] mem: Minor typo fix in packet.hh Change-Id: I07c31b7a62d83fe3250b48141951aec3c2f280df --- src/mem/packet.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index ed7a94f4fb..ad05b72828 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -1156,7 +1156,7 @@ class Packet : public Printable, public Extensible public: /** * @{ - * @name Data accessor mehtods + * @name Data accessor methods */ /** From ede4d89a83984099c46e8b98031c232d845f5e94 Mon Sep 17 00:00:00 2001 From: "Ranganath (Bujji) Selagamsetty" Date: Wed, 26 Jul 2023 17:27:05 -0500 Subject: [PATCH 135/693] arch-vega, dev-amdgpu: Fix for memory leaks When using the new operator, delete should be called on any allocated memory after it's use is complete. Change-Id: Id5fcfb264b6ddc252c0a9dcafc2d3b020f7b5019 --- src/arch/amdgpu/vega/pagetable_walker.cc | 1 + src/dev/amdgpu/amdgpu_device.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/src/arch/amdgpu/vega/pagetable_walker.cc b/src/arch/amdgpu/vega/pagetable_walker.cc index 96ac0fe179..ea4d6b0de9 100644 --- a/src/arch/amdgpu/vega/pagetable_walker.cc +++ b/src/arch/amdgpu/vega/pagetable_walker.cc @@ -369,6 +369,7 @@ bool Walker::sendTiming(WalkerState* sending_walker, PacketPtr pkt) return true; } else { (void)pkt->popSenderState(); + delete walker_state; } return false; diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc index d1058f1606..44a1c9d394 100644 --- a/src/dev/amdgpu/amdgpu_device.cc +++ b/src/dev/amdgpu/amdgpu_device.cc @@ -291,6 +291,7 @@ AMDGPUDevice::readFrame(PacketPtr pkt, Addr offset) system->getDeviceMemory(readPkt)->access(readPkt); pkt->setUintX(readPkt->getUintX(ByteOrder::little), ByteOrder::little); + delete readPkt; } void From 3b35e73eb8e52261750aa8613ec9b4c77852759e Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 19 Jul 2023 15:26:02 -0500 Subject: [PATCH 136/693] dev-amdgpu: Implement SDMA constant fill This SDMA packet is much more common starting around ROCm 5.4. Previously this was mostly used to clear page tables after an application ended and was therefore left unimplemented. It is now used for basic operation like device memsets. This patch implements constant fill as it is now necessary. Change-Id: I9b2cf076ec17f5ed07c20bb820e7db0c082bbfbc --- src/dev/amdgpu/sdma_engine.cc | 71 ++++++++++++++++++++++++++++++++-- src/dev/amdgpu/sdma_engine.hh | 2 + src/dev/amdgpu/sdma_packets.hh | 19 ++++++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/dev/amdgpu/sdma_engine.cc b/src/dev/amdgpu/sdma_engine.cc index e99d694634..0202f583e6 100644 --- a/src/dev/amdgpu/sdma_engine.cc +++ b/src/dev/amdgpu/sdma_engine.cc @@ -510,9 +510,12 @@ SDMAEngine::decodeHeader(SDMAQueue *q, uint32_t header) dmaReadVirt(q->rptr(), sizeof(sdmaAtomic), cb, dmaBuffer); } break; case SDMA_OP_CONST_FILL: { - q->incRptr(sizeof(sdmaConstFill)); - warn("SDMA_OP_CONST_FILL not implemented"); - decodeNext(q); + DPRINTF(SDMAEngine, "SDMA Constant fill packet\n"); + dmaBuffer = new sdmaConstFill(); + cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { constFill(q, (sdmaConstFill *)dmaBuffer, header); }); + dmaReadVirt(q->rptr(), sizeof(sdmaConstFill), cb, dmaBuffer); } break; case SDMA_OP_PTEPDE: { DPRINTF(SDMAEngine, "SDMA PTEPDE packet\n"); @@ -1026,6 +1029,68 @@ SDMAEngine::atomicDone(SDMAQueue *q, sdmaAtomicHeader *header, sdmaAtomic *pkt, decodeNext(q); } +void +SDMAEngine::constFill(SDMAQueue *q, sdmaConstFill *pkt, uint32_t header) +{ + q->incRptr(sizeof(sdmaConstFill)); + + sdmaConstFillHeader fill_header; + fill_header.ordinal = header; + + DPRINTF(SDMAEngine, "ConstFill %lx srcData %x count %d size %d sw %d\n", + pkt->addr, pkt->srcData, pkt->count, fill_header.fillsize, + fill_header.sw); + + // Count is number of elements - 1. Size is log2 of byte size. + int fill_bytes = (pkt->count + 1) * (1 << fill_header.fillsize); + uint8_t *fill_data = new uint8_t[fill_bytes]; + + memset(fill_data, pkt->srcData, fill_bytes); + + Addr device_addr = getDeviceAddress(pkt->addr); + if (device_addr) { + DPRINTF(SDMAEngine, "ConstFill %d bytes of %x to device at %lx\n", + fill_bytes, pkt->srcData, pkt->addr); + + auto cb = new EventFunctionWrapper( + [ = ]{ constFillDone(q, pkt, fill_data); }, name()); + + // Copy the minimum page size at a time in case the physical addresses + // are not contiguous. + ChunkGenerator gen(pkt->addr, fill_bytes, AMDGPU_MMHUB_PAGE_SIZE); + for (; !gen.done(); gen.next()) { + Addr chunk_addr = getDeviceAddress(gen.addr()); + assert(chunk_addr); + + DPRINTF(SDMAEngine, "Copying chunk of %d bytes from %#lx (%#lx)\n", + gen.size(), gen.addr(), chunk_addr); + + gpuDevice->getMemMgr()->writeRequest(chunk_addr, fill_data, + gen.size(), 0, + gen.last() ? cb : nullptr); + fill_data += gen.size(); + } + } else { + DPRINTF(SDMAEngine, "ConstFill %d bytes of %x to host at %lx\n", + fill_bytes, pkt->srcData, pkt->addr); + + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { constFillDone(q, pkt, fill_data); }); + dmaWriteVirt(pkt->addr, fill_bytes, cb, (void *)fill_data); + } +} + +void +SDMAEngine::constFillDone(SDMAQueue *q, sdmaConstFill *pkt, uint8_t *fill_data) +{ + DPRINTF(SDMAEngine, "ConstFill to %lx done\n", pkt->addr); + + delete fill_data; + delete pkt; + decodeNext(q); +} + AddrRangeList SDMAEngine::getAddrRanges() const { diff --git a/src/dev/amdgpu/sdma_engine.hh b/src/dev/amdgpu/sdma_engine.hh index bcbd497e8a..5abe63fcc6 100644 --- a/src/dev/amdgpu/sdma_engine.hh +++ b/src/dev/amdgpu/sdma_engine.hh @@ -245,6 +245,8 @@ class SDMAEngine : public DmaVirtDevice uint64_t *dmaBuffer); void atomicDone(SDMAQueue *q, sdmaAtomicHeader *header, sdmaAtomic *pkt, uint64_t *dmaBuffer); + void constFill(SDMAQueue *q, sdmaConstFill *pkt, uint32_t header); + void constFillDone(SDMAQueue *q, sdmaConstFill *pkt, uint8_t *fill_data); /** * Methods for getting SDMA MMIO base address and size. These are set by diff --git a/src/dev/amdgpu/sdma_packets.hh b/src/dev/amdgpu/sdma_packets.hh index 52a47d3a2d..07d3f12600 100644 --- a/src/dev/amdgpu/sdma_packets.hh +++ b/src/dev/amdgpu/sdma_packets.hh @@ -37,7 +37,7 @@ namespace gem5 { /** - * SDMA packets + * SDMA packets - see src/core/inc/sdma_registers.h in ROCR-Runtime */ typedef struct GEM5_PACKED { @@ -80,6 +80,23 @@ typedef struct GEM5_PACKED } sdmaConstFill; static_assert(sizeof(sdmaConstFill) == 16); +typedef struct GEM5_PACKED +{ + union + { + struct + { + uint32_t op : 8; + uint32_t sub_op : 8; + uint32_t sw : 2; + uint32_t res0 : 12; + uint32_t fillsize : 2; + }; + uint32_t ordinal; + }; +} sdmaConstFillHeader; +static_assert(sizeof(sdmaConstFillHeader) == 4); + typedef struct GEM5_PACKED { uint32_t key0; From 3589a4c11fb72ee4cb6c1707ed08d9d5eec98d5c Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 19 Jul 2023 15:39:51 -0500 Subject: [PATCH 137/693] arch-vega: Implement translate further Starting with ROCm 5.4+, MI100 and MI200 make use of the translate further bit in the page table. This bit enables mixing 4kiB and 2MiB pages and is functionally equivalent to mixing page sizes using the PDE.P bit for which gem5 currently has support. With PDE.P bit set, we stop walking and the page size is equal to the level in the page table we stopped at. For example, stopping at level 2 would be a 1GiB page, stopping at level 3 would be a 2MiB page. This assumes most pages are 4kiB. When the F bit is used, it is assumed most pages are 2MiB and we will stop walking at the 3rd level of the page table unless the F bit is set. When the F bit is set, the 2nd level PDE contains a block fragment size representing the page size of the next PDE in the form of 2^(12+size). If the next page has the F bit set we continue walking to the 4th level. The block fragment size is hardcoded to 9 in the driver therefore we assert that the block fragment size must be 0 or 9. This enables MI200 with ROCm 5.4+ in gem5. This functionality was determine by examining the driver source code in Linux and there is no public documentation about this feature or why the change is made in or around ROCm 5.4. Change-Id: I603c0208cd9e821f7ad6eeb1d94ae15eaa146fb9 --- src/arch/amdgpu/vega/pagetable_walker.cc | 31 ++++++++++++++++++++---- src/arch/amdgpu/vega/pagetable_walker.hh | 4 ++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/arch/amdgpu/vega/pagetable_walker.cc b/src/arch/amdgpu/vega/pagetable_walker.cc index ea4d6b0de9..6a71b14838 100644 --- a/src/arch/amdgpu/vega/pagetable_walker.cc +++ b/src/arch/amdgpu/vega/pagetable_walker.cc @@ -239,9 +239,22 @@ Walker::WalkerState::walkStateMachine(PageTableEntry &pte, Addr &nextRead, Addr part2 = 0; PageDirectoryEntry pde = static_cast(pte); - // For a four level page table block fragment size should not be needed. - // For now issue a panic to prevent strange behavior if it is non-zero. - panic_if(pde.blockFragmentSize, "PDE blockFragmentSize must be 0"); + // Block fragment size can change the size of the pages pointed to while + // moving to the next PDE. A value of 0 implies native page size. A + // non-zero value implies the next leaf in the page table is a PTE unless + // the F bit is set. If we see a non-zero value, set it here and print + // for debugging. + if (pde.blockFragmentSize) { + DPRINTF(GPUPTWalker, + "blockFragmentSize: %d, pde: %#016lx, state: %d\n", + pde.blockFragmentSize, pde, state); + blockFragmentSize = pde.blockFragmentSize; + + // At this time, only a value of 9 is used in the driver: + // https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/ + // amd/amdgpu/gmc_v9_0.c#L1165 + assert(pde.blockFragmentSize == 9); + } switch(state) { case PDE2: @@ -287,7 +300,7 @@ Walker::WalkerState::walkStateMachine(PageTableEntry &pte, Addr &nextRead, nextState = PDE0; break; case PDE0: - if (pde.p) { + if (pde.p || (blockFragmentSize && !pte.f)) { DPRINTF(GPUPTWalker, "Treating PDE0 as PTE: %#016x frag: %d\n", (uint64_t)pte, pte.fragment); entry.pte = pte; @@ -299,7 +312,15 @@ Walker::WalkerState::walkStateMachine(PageTableEntry &pte, Addr &nextRead, } // Read the PteAddr part1 = ((((uint64_t)pte) >> 6) << 3); - part2 = offsetFunc(vaddr, 9, 0); + if (pte.f) { + // For F bit we want to use the blockFragmentSize in the previous + // PDE and the blockFragmentSize in this PTE for offset function. + part2 = offsetFunc(vaddr, + blockFragmentSize, + pde.blockFragmentSize); + } else { + part2 = offsetFunc(vaddr, 9, 0); + } nextRead = ((part1 + part2) << 3) & mask(48); DPRINTF(GPUPTWalker, "Got PDE0 entry %#016x. write:%s->%#016x va:%#016x\n", diff --git a/src/arch/amdgpu/vega/pagetable_walker.hh b/src/arch/amdgpu/vega/pagetable_walker.hh index 2ad0748c14..232be5de70 100644 --- a/src/arch/amdgpu/vega/pagetable_walker.hh +++ b/src/arch/amdgpu/vega/pagetable_walker.hh @@ -99,11 +99,13 @@ class Walker : public ClockedObject bool started; bool timing; PacketPtr tlbPkt; + int blockFragmentSize; public: WalkerState(Walker *_walker, PacketPtr pkt, bool is_functional = false) : walker(_walker), state(Ready), nextState(Ready), dataSize(8), - enableNX(true), retrying(false), started(false), tlbPkt(pkt) + enableNX(true), retrying(false), started(false), tlbPkt(pkt), + blockFragmentSize(0) { DPRINTF(GPUPTWalker, "Walker::WalkerState %p %p %d\n", this, walker, state); From f8490e4681e0b38f3cc8c12e195a915ef288e29b Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 19 Jul 2023 15:37:14 -0500 Subject: [PATCH 138/693] configs: Only require MMIO trace for Vega10 The MMIO trace contains register values for parts of the GPU that are not modeled in gem5, such as registers related to the graphics core. Since MI100 and MI200 do not have anything that is not modeled, the MMIO trace is not needed, therefore it does not need to be used or checked and the command line option goes away entirely for MI100/200. Change-Id: I23839db32b1b072bd44c8c977899a99347fc9687 --- configs/example/gpufs/runfs.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index 5346622155..0f090e2f89 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -179,10 +179,15 @@ def runGpuFSSystem(args): math.ceil(float(n_cu) / args.cu_per_scalar_cache) ) - # Verify MMIO trace is valid - mmio_md5 = hashlib.md5(open(args.gpu_mmio_trace, "rb").read()).hexdigest() - if mmio_md5 != "c4ff3326ae8a036e329b8b595c83bd6d": - m5.util.panic("MMIO file does not match gem5 resources") + # Verify MMIO trace is valid. This is only needed for Vega10 simulations. + # The md5sum refers to the md5sum of the Vega10 MMIO hardware trace in + # the gem5-resources repository. By checking it here, we avoid potential + # errors that would cause the driver not to load and simulations to fail. + if args.gpu_device == "Vega10": + mmio_file = open(args.gpu_mmio_trace, "rb") + mmio_md5 = hashlib.md5(mmio_file.read()).hexdigest() + if mmio_md5 != "c4ff3326ae8a036e329b8b595c83bd6d": + m5.util.panic("MMIO file does not match gem5 resources") system = makeGpuFSSystem(args) From d96df4025323e0173d32b5bba9086fea28c8444a Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 1 Aug 2023 16:22:44 -0700 Subject: [PATCH 139/693] stdlib: Added support for JSON via env variables. Change-Id: I5791e6d51b3b9f68eb212a46c4cd0add23668340 Co-authored-by: Kunal Pai --- src/python/gem5/resources/client.py | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py index ab8262bf92..c43dd76ac5 100644 --- a/src/python/gem5/resources/client.py +++ b/src/python/gem5/resources/client.py @@ -30,7 +30,7 @@ import os from typing import Optional, Dict, List from .client_api.client_wrapper import ClientWrapper from gem5.gem5_default_config import config -from m5.util import inform +from m5.util import inform, warn from _m5 import core @@ -53,6 +53,14 @@ clientwrapper = None def _get_clientwrapper(): global clientwrapper if clientwrapper is None: + if ( + "GEM5_RESOURCE_JSON" in os.environ + and "GEM5_RESOURCE_JSON_APPEND" in os.environ + ): + raise Exception( + "Both GEM5_RESOURCE_JSON and GEM5_RESOURCE_JSON_APPEND are set. Please set only one of them." + ) + # First check if the config file path is provided in the environment variable if "GEM5_CONFIG" in os.environ: config_file_path = Path(os.environ["GEM5_CONFIG"]) @@ -68,6 +76,29 @@ def _get_clientwrapper(): else: gem5_config = config inform("Using default config") + + # If the GEM5_RESOURCE_JSON_APPEND is set, append the resources to the gem5_config + if "GEM5_RESOURCE_JSON_APPEND" in os.environ: + json_source = { + "url": os.environ["GEM5_RESOURCE_JSON_APPEND"], + "isMongo": False, + } + gem5_config["sources"].update( + {"GEM5_RESOURCE_JSON_APPEND": json_source} + ) + inform( + f"Appending resources from {os.environ['GEM5_RESOURCE_JSON_APPEND']}" + ) + # If the GEM5_RESOURCE_JSON is set, use it as the only source + elif "GEM5_RESOURCE_JSON" in os.environ: + json_source = { + "url": os.environ["GEM5_RESOURCE_JSON"], + "isMongo": False, + } + gem5_config["sources"] = {"GEM5_RESOURCE_JSON": json_source} + warn( + f"No config sources are used, Using resources from {os.environ['GEM5_RESOURCE_JSON']}" + ) clientwrapper = ClientWrapper(gem5_config) return clientwrapper From 052c87005849d5406477607e352588b39fb96896 Mon Sep 17 00:00:00 2001 From: leoredivo <94771718+leoredivo@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:51:36 -0700 Subject: [PATCH 140/693] New function to kernel_disk_workload to allow new disk device location Added a parameter to kernel_disk_workload which allows users to change the disk device location. Maintained the previous way of setting a disk device as the default, however added a function to allow users to override this default --- .../gem5/components/boards/arm_board.py | 2 +- .../boards/experimental/lupv_board.py | 2 +- .../components/boards/kernel_disk_workload.py | 22 ++++++++++++++++++- .../gem5/components/boards/riscv_board.py | 2 +- .../gem5/components/boards/x86_board.py | 2 +- .../riscvmatched/riscvmatched_board.py | 2 +- 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index b439edf970..82b7a39107 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -354,7 +354,7 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): ) @overrides(KernelDiskWorkload) - def get_disk_device(self): + def _get_default_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index ad130b7273..cba50a1d56 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -539,7 +539,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): return ["console=ttyLIO0", "root={root_value}", "rw"] @overrides(KernelDiskWorkload) - def get_disk_device(self) -> str: + def set_default_disk_device(self) -> str: return "/dev/lda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 15e0cdf303..79d55ba8b4 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -39,6 +39,7 @@ import os from pathlib import Path import m5 +from m5 import warn class KernelDiskWorkload: @@ -84,11 +85,25 @@ class KernelDiskWorkload: """ raise NotImplementedError - @abstractmethod def get_disk_device(self) -> str: """ Get the disk device, e.g., "/dev/sda", where the disk image is placed. + :returns: The disk device. + """ + if self._disk_device is None: + warn("No disk device set, ie where the disk image is located. Defaulting to board disk device") + return _get_default_disk_device() + else: + return self._disk_device + + + + @abstractmethod + def _get_default_disk_device(self) -> str: + """ + Set a default disk device, in case user does not specify a disk device. + :returns: The disk device. """ raise NotImplementedError @@ -139,6 +154,7 @@ class KernelDiskWorkload: kernel: KernelResource, disk_image: DiskImageResource, bootloader: Optional[BootloaderResource] = None, + _disk_device: Optional[str] = None, readfile: Optional[str] = None, readfile_contents: Optional[str] = None, kernel_args: Optional[List[str]] = None, @@ -171,6 +187,9 @@ class KernelDiskWorkload: # Abstract board. This function will not work otherwise. assert isinstance(self, AbstractBoard) + # Set the disk device + self._disk_device = _disk_device + # If we are setting a workload of this type, we need to run as a # full-system simulation. self._set_fullsystem(True) @@ -192,6 +211,7 @@ class KernelDiskWorkload: if bootloader is not None: self._bootloader = [bootloader.get_local_path()] + # Set the readfile. if readfile: self.readfile = readfile diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 25f1fac562..d8020d1974 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -467,7 +467,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def get_disk_device(self): + def _get_default_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index 04fec617c1..1a3b9fa1c8 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -296,7 +296,7 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): ] @overrides(KernelDiskWorkload) - def get_disk_device(self): + def _get_default_disk_device(self): return "/dev/hda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index 9ca95839f8..3411ea61be 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -539,7 +539,7 @@ class RISCVMatchedBoard( fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def get_disk_device(self): + def _get_default_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) From 32b7ffc4546fd53bc50487d1899188844177bb1d Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 1 Aug 2023 17:22:35 -0700 Subject: [PATCH 141/693] stdlib: fixed warning message Change-Id: I04ef23529d7afc5d46fbba7558279ec08acd629a Co-authored-by: paikunal --- src/python/gem5/resources/client.py | 37 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py index c43dd76ac5..571a8254e0 100644 --- a/src/python/gem5/resources/client.py +++ b/src/python/gem5/resources/client.py @@ -60,9 +60,31 @@ def _get_clientwrapper(): raise Exception( "Both GEM5_RESOURCE_JSON and GEM5_RESOURCE_JSON_APPEND are set. Please set only one of them." ) - + gem5_config = {} + # If the GEM5_RESOURCE_JSON is set, use it as the only source + if "GEM5_RESOURCE_JSON" in os.environ: + json_source = { + "url": os.environ["GEM5_RESOURCE_JSON"], + "isMongo": False, + } + gem5_config["sources"] = {"GEM5_RESOURCE_JSON": json_source} + if "GEM5_CONFIG" in os.environ: + warn( + f"Both GEM5_CONFIG and GEM5_RESOURCE_JSON are set.\n" + f"GEM5_CONFIG will be ignored in favor of the GEM5_RESOURCE_JSON environment variable." + ) + elif (Path().cwd().resolve() / "gem5-config.json").exists(): + warn( + f"Both gem5-config.json and GEM5_RESOURCE_JSON are set.\n" + f"gem5-config.json will be ignored in favor of the GEM5_RESOURCE_JSON environment variable." + ) + else: + warn( + f"GEM5_RESOURCE_JSON is set.\n" + f"gem5-default-config will be ignored in favor of the GEM5_RESOURCE_JSON environment variable." + ) # First check if the config file path is provided in the environment variable - if "GEM5_CONFIG" in os.environ: + elif "GEM5_CONFIG" in os.environ: config_file_path = Path(os.environ["GEM5_CONFIG"]) gem5_config = getFileContent(config_file_path) inform("Using config file specified by $GEM5_CONFIG") @@ -89,16 +111,7 @@ def _get_clientwrapper(): inform( f"Appending resources from {os.environ['GEM5_RESOURCE_JSON_APPEND']}" ) - # If the GEM5_RESOURCE_JSON is set, use it as the only source - elif "GEM5_RESOURCE_JSON" in os.environ: - json_source = { - "url": os.environ["GEM5_RESOURCE_JSON"], - "isMongo": False, - } - gem5_config["sources"] = {"GEM5_RESOURCE_JSON": json_source} - warn( - f"No config sources are used, Using resources from {os.environ['GEM5_RESOURCE_JSON']}" - ) + clientwrapper = ClientWrapper(gem5_config) return clientwrapper From 73892c9b47984b1a1e4441ce4141aa0576147bf6 Mon Sep 17 00:00:00 2001 From: Xuan Hu Date: Tue, 21 Mar 2023 13:11:01 +0800 Subject: [PATCH 142/693] arch-riscv: Add risc-v vector regs and configs This commit add regs and configs for vector extension * Add 32 vector arch regs as spec defined and 8 internal regs for uop-based vector implementation. * Add default vector configs(VLEN = 256, ELEN = 64). These cannot be changed yet, since the vector implementation has only be tested with such configs. * Add disassamble register name v0~v31 and vtmp0~vtmp7. * Add CSR registers defined in RISCV Vector Spec v1.0. * Add vector bitfields. * Add vector operand_types and operands. Change-Id: I7bbab1ee9e0aa804d6f15ef7b77fac22d4f7212a Co-authored-by: Yang Liu Co-authored-by: Fan Yang <1209202421@qq.com> Co-authored-by: Jerin Joy arch-riscv: enable rvv flags only for RV64 Change-Id: I6586e322dfd562b598f63a18964d17326c14d4cf --- src/arch/riscv/faults.hh | 2 +- src/arch/riscv/isa.cc | 54 +++++++++++++++++-- src/arch/riscv/isa.hh | 2 + src/arch/riscv/isa/bitfields.isa | 24 +++++++++ src/arch/riscv/isa/includes.isa | 1 + src/arch/riscv/isa/operands.isa | 15 +++++- src/arch/riscv/regs/misc.hh | 31 +++++++++-- src/arch/riscv/regs/vector.hh | 90 ++++++++++++++++++++++++++++++++ src/arch/riscv/utility.hh | 10 +++- 9 files changed, 219 insertions(+), 10 deletions(-) create mode 100644 src/arch/riscv/regs/vector.hh diff --git a/src/arch/riscv/faults.hh b/src/arch/riscv/faults.hh index f687fd6f20..fa67e3b34c 100644 --- a/src/arch/riscv/faults.hh +++ b/src/arch/riscv/faults.hh @@ -173,7 +173,7 @@ class InstFault : public RiscvFault : RiscvFault(n, FaultType::OTHERS, INST_ILLEGAL), _inst(inst) {} - RegVal trap_value() const override { return bits(_inst, 31, 0); } + RegVal trap_value() const override { return _inst.instBits; } }; class UnknownInstFault : public InstFault diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 94a8239bac..2f9d52e1b2 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -43,6 +43,7 @@ #include "arch/riscv/regs/float.hh" #include "arch/riscv/regs/int.hh" #include "arch/riscv/regs/misc.hh" +#include "arch/riscv/regs/vector.hh" #include "base/bitfield.hh" #include "base/compiler.hh" #include "base/logging.hh" @@ -52,6 +53,7 @@ #include "debug/LLSC.hh" #include "debug/MatRegs.hh" #include "debug/RiscvMisc.hh" +#include "debug/VecRegs.hh" #include "mem/packet.hh" #include "mem/request.hh" #include "params/RiscvISA.hh" @@ -189,6 +191,14 @@ namespace RiscvISA [MISCREG_FFLAGS] = "FFLAGS", [MISCREG_FRM] = "FRM", + [MISCREG_VSTART] = "VSTART", + [MISCREG_VXSAT] = "VXSAT", + [MISCREG_VXRM] = "VXRM", + [MISCREG_VCSR] = "VCSR", + [MISCREG_VL] = "VL", + [MISCREG_VTYPE] = "VTYPE", + [MISCREG_VLENB] = "VLENB", + [MISCREG_NMIVEC] = "NMIVEC", [MISCREG_NMIE] = "NMIE", [MISCREG_NMIP] = "NMIP", @@ -234,11 +244,10 @@ namespace { /* Not applicable to RISCV */ -RegClass vecRegClass(VecRegClass, VecRegClassName, 1, debug::IntRegs); -RegClass vecElemClass(VecElemClass, VecElemClassName, 2, debug::IntRegs); -RegClass vecPredRegClass(VecPredRegClass, VecPredRegClassName, 1, +RegClass vecElemClass(VecElemClass, VecElemClassName, 0, debug::IntRegs); +RegClass vecPredRegClass(VecPredRegClass, VecPredRegClassName, 0, debug::IntRegs); -RegClass matRegClass(MatRegClass, MatRegClassName, 1, debug::MatRegs); +RegClass matRegClass(MatRegClass, MatRegClassName, 0, debug::MatRegs); RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs); } // anonymous namespace @@ -275,6 +284,13 @@ ISA::copyRegsFrom(ThreadContext *src) for (auto &id: floatRegClass) tc->setReg(id, src->getReg(id)); + // Third loop through the vector registers. + RiscvISA::VecRegContainer vc; + for (auto &id: vecRegClass) { + src->getReg(id, &vc); + tc->setReg(id, &vc); + } + // Lastly copy PC/NPC tc->pcState(src->pcState()); } @@ -299,6 +315,7 @@ void ISA::clear() // mark FS is initial status.fs = INITIAL; + // rv_type dependent init. switch (rv_type) { case RV32: @@ -307,6 +324,8 @@ void ISA::clear() case RV64: misa.rv64_mxl = 2; status.uxl = status.sxl = 2; + status.vs = VPUStatus::INITIAL; + misa.rvv = 1; break; default: panic("%s: Unknown rv_type: %d", name(), (int)rv_type); @@ -479,6 +498,17 @@ ISA::readMiscReg(RegIndex idx) return readMiscRegNoEffect(idx); } + case MISCREG_VLENB: + { + return VLENB; + } + break; + case MISCREG_VCSR: + { + return readMiscRegNoEffect(MISCREG_VXSAT) & + (readMiscRegNoEffect(MISCREG_VXRM) << 1); + } + break; default: // Try reading HPM counters // As a placeholder, all HPM counters are just cycle counters @@ -652,6 +682,22 @@ ISA::setMiscReg(RegIndex idx, RegVal val) setMiscRegNoEffect(idx, val); } break; + case MISCREG_VXSAT: + { + setMiscRegNoEffect(idx, val & 0x1); + } + break; + case MISCREG_VXRM: + { + setMiscRegNoEffect(idx, val & 0x3); + } + break; + case MISCREG_VCSR: + { + setMiscRegNoEffect(MISCREG_VXSAT, val & 0x1); + setMiscRegNoEffect(MISCREG_VXRM, (val & 0x6) >> 1); + } + break; default: setMiscRegNoEffect(idx, val); } diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 31001c04b4..d7b0a21a1f 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -67,6 +67,8 @@ enum FPUStatus DIRTY = 3, }; +using VPUStatus = FPUStatus; + class ISA : public BaseISA { protected: diff --git a/src/arch/riscv/isa/bitfields.isa b/src/arch/riscv/isa/bitfields.isa index 8589269949..280bcbab22 100644 --- a/src/arch/riscv/isa/bitfields.isa +++ b/src/arch/riscv/isa/bitfields.isa @@ -133,3 +133,27 @@ def bitfield BIT25 <25>; def bitfield RNUM <23:20>; def bitfield KFUNCT5 <29:25>; def bitfield BS <31:30>; + +// Vector instructions +def bitfield VFUNCT6 vfunct6; +def bitfield VFUNCT5 vfunct5; +def bitfield VFUNCT3 vfunct3; +def bitfield VFUNCT2 vfunct2; + +def bitfield VS3 vs3; +def bitfield VS2 vs2; +def bitfield VS1 vs1; +def bitfield VD vd; + +def bitfield NF nf; +def bitfield MEW mew; +def bitfield MOP mop; +def bitfield VM vm; +def bitfield LUMOP lumop; +def bitfield SUMOP sumop; +def bitfield WIDTH width; + +def bitfield BIT31 bit31; +def bitfield BIT30 bit30; +def bitfield SIMM5 uimm_vsetivli; +def bitfield SIMM3 simm3; diff --git a/src/arch/riscv/isa/includes.isa b/src/arch/riscv/isa/includes.isa index 8dddc2fb59..cb95f58f7e 100644 --- a/src/arch/riscv/isa/includes.isa +++ b/src/arch/riscv/isa/includes.isa @@ -95,6 +95,7 @@ output exec {{ #include "arch/riscv/reg_abi.hh" #include "arch/riscv/regs/float.hh" #include "arch/riscv/regs/misc.hh" +#include "arch/riscv/regs/vector.hh" #include "arch/riscv/utility.hh" #include "base/condcodes.hh" #include "cpu/base.hh" diff --git a/src/arch/riscv/isa/operands.isa b/src/arch/riscv/isa/operands.isa index 72d8f81bca..a81b28df57 100644 --- a/src/arch/riscv/isa/operands.isa +++ b/src/arch/riscv/isa/operands.isa @@ -38,7 +38,15 @@ def operand_types {{ 'sd' : 'int64_t', 'ud' : 'uint64_t', 'sf' : 'float', - 'df' : 'double' + 'df' : 'double', + + 'vi' : 'vi', + 'vu' : 'vu', + 'vwi' : 'vwi', + 'vwu' : 'vwu', + 'vext' : 'vext', + 'vextu' : 'vextu', + 'vc' : 'RiscvISA::VecRegContainer' }}; let {{ @@ -79,6 +87,11 @@ def operands {{ 'Fp2': FloatRegOp('df', 'FP2 + 8', 'IsFloating', 2), 'Fp2_bits': FloatRegOp('ud', 'FP2 + 8', 'IsFloating', 2), + 'Vd': VecRegOp('vc', 'VD', 'IsVector', 1), + 'Vs1': VecRegOp('vc', 'VS1', 'IsVector', 2), + 'Vs2': VecRegOp('vc', 'VS2', 'IsVector', 3), + 'Vs3': VecRegOp('vc', 'VS3', 'IsVector', 4), + #Memory Operand 'Mem': MemOp('ud', None, (None, 'IsLoad', 'IsStore'), 5), diff --git a/src/arch/riscv/regs/misc.hh b/src/arch/riscv/regs/misc.hh index 5ea3536141..64072c97e2 100644 --- a/src/arch/riscv/regs/misc.hh +++ b/src/arch/riscv/regs/misc.hh @@ -191,6 +191,14 @@ enum MiscRegIndex MISCREG_FFLAGS, MISCREG_FRM, + MISCREG_VSTART, + MISCREG_VXSAT, + MISCREG_VXRM, + MISCREG_VCSR, + MISCREG_VL, + MISCREG_VTYPE, + MISCREG_VLENB, + // These registers are not in the standard, hence does not exist in the // CSRData map. These are mainly used to provide a minimal implementation // for non-maskable-interrupt in our simple cpu. @@ -476,7 +484,15 @@ enum CSRIndex CSR_TDATA3 = 0x7A3, CSR_DCSR = 0x7B0, CSR_DPC = 0x7B1, - CSR_DSCRATCH = 0x7B2 + CSR_DSCRATCH = 0x7B2, + + CSR_VSTART = 0x008, + CSR_VXSAT = 0x009, + CSR_VXRM = 0x00A, + CSR_VCSR = 0x00F, + CSR_VL = 0xC20, + CSR_VTYPE = 0xC21, + CSR_VLENB = 0xC22 }; struct CSRMetadata @@ -718,7 +734,15 @@ const std::unordered_map CSRData = { {CSR_TDATA3, {"tdata3", MISCREG_TDATA3, rvTypeFlags(RV64, RV32)}}, {CSR_DCSR, {"dcsr", MISCREG_DCSR, rvTypeFlags(RV64, RV32)}}, {CSR_DPC, {"dpc", MISCREG_DPC, rvTypeFlags(RV64, RV32)}}, - {CSR_DSCRATCH, {"dscratch", MISCREG_DSCRATCH, rvTypeFlags(RV64, RV32)}} + {CSR_DSCRATCH, {"dscratch", MISCREG_DSCRATCH, rvTypeFlags(RV64, RV32)}}, + + {CSR_VSTART, {"vstart", MISCREG_VSTART, rvTypeFlags(RV64, RV32)}}, + {CSR_VXSAT, {"vxsat" , MISCREG_VXSAT, rvTypeFlags(RV64, RV32)}}, + {CSR_VXRM, {"vxrm" , MISCREG_VXRM, rvTypeFlags(RV64, RV32)}}, + {CSR_VCSR, {"vcsr" , MISCREG_VCSR, rvTypeFlags(RV64, RV32)}}, + {CSR_VL, {"vl" , MISCREG_VL, rvTypeFlags(RV64, RV32)}}, + {CSR_VTYPE, {"vtype" , MISCREG_VTYPE, rvTypeFlags(RV64, RV32)}}, + {CSR_VLENB, {"VLENB" , MISCREG_VLENB, rvTypeFlags(RV64, RV32)}} }; /** @@ -816,6 +840,7 @@ const off_t SBE_OFFSET[enums::Num_RiscvType] = { const off_t SXL_OFFSET = 34; const off_t UXL_OFFSET = 32; const off_t FS_OFFSET = 13; +const off_t VS_OFFSET = 9; const off_t FRM_OFFSET = 5; const RegVal ISA_MXL_MASKS[enums::Num_RiscvType] = { @@ -853,7 +878,7 @@ const RegVal STATUS_MPRV_MASK = 1ULL << 17; const RegVal STATUS_XS_MASK = 3ULL << 15; const RegVal STATUS_FS_MASK = 3ULL << FS_OFFSET; const RegVal STATUS_MPP_MASK = 3ULL << 11; -const RegVal STATUS_VS_MASK = 3ULL << 9; +const RegVal STATUS_VS_MASK = 3ULL << VS_OFFSET; const RegVal STATUS_SPP_MASK = 1ULL << 8; const RegVal STATUS_MPIE_MASK = 1ULL << 7; const RegVal STATUS_SPIE_MASK = 1ULL << 5; diff --git a/src/arch/riscv/regs/vector.hh b/src/arch/riscv/regs/vector.hh new file mode 100644 index 0000000000..d722c2d03a --- /dev/null +++ b/src/arch/riscv/regs/vector.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022 PLCT Lab + * 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. + */ + + +#ifndef __ARCH_RISCV_REGS_VECTOR_HH__ +#define __ARCH_RISCV_REGS_VECTOR_HH__ + +#include +#include +#include + +#include "arch/generic/vec_pred_reg.hh" +#include "arch/generic/vec_reg.hh" +#include "base/bitunion.hh" +#include "cpu/reg_class.hh" +#include "debug/VecRegs.hh" + +namespace gem5 +{ + +namespace RiscvISA +{ + +constexpr unsigned ELEN = 64; +constexpr unsigned VLEN = 256; +constexpr unsigned VLENB = VLEN / 8; + +using VecRegContainer = gem5::VecRegContainer; +using vreg_t = VecRegContainer; + +const int NumVecStandardRegs = 32; +const int NumVecInternalRegs = 8; // Used by vector uop +const int NumVecRegs = NumVecStandardRegs + NumVecInternalRegs; + +const std::vector VecRegNames = { + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + "vtmp0", "vtmp1", "vtmp2", "vtmp3", "vtmp4", "vtmp5", "vtmp6", "vtmp7" +}; + +// vector index +const int VecMemInternalReg0 = NumVecStandardRegs; + +static inline TypedRegClassOps vecRegClassOps; + +inline constexpr RegClass vecRegClass = + RegClass(VecRegClass, VecRegClassName, NumVecRegs, debug::VecRegs). + ops(vecRegClassOps). + regType(); + +BitUnion32(VTYPE) + Bitfield<31> vill; + Bitfield<7, 0> vtype8; + Bitfield<7> vma; + Bitfield<6> vta; + Bitfield<5, 3> vsew; + Bitfield<2, 0> vlmul; +EndBitUnion(VTYPE) + +} // namespace RiscvISA +} // namespace gem5 + +#endif // __ARCH_RISCV_REGS_VECTOR_HH__ diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh index 5fccc84c79..e0a8494ece 100644 --- a/src/arch/riscv/utility.hh +++ b/src/arch/riscv/utility.hh @@ -51,6 +51,7 @@ #include "arch/riscv/regs/float.hh" #include "arch/riscv/regs/int.hh" +#include "arch/riscv/regs/vector.hh" #include "base/types.hh" #include "cpu/reg_class.hh" #include "cpu/static_inst.hh" @@ -130,7 +131,14 @@ registerName(RegId reg) return str.str(); } return float_reg::RegNames[reg.index()]; - } else { + } else if (reg.is(VecRegClass)) { + if (reg.index() >= NumVecRegs) { + std::stringstream str; + str << "?? (v" << reg.index() << ')'; + return str.str(); + } + return VecRegNames[reg.index()]; + } else { /* It must be an InvalidRegClass, in RISC-V we should treat it as a * zero register for the disassembler to work correctly. */ From e14e066fde5516b7ab3921687248f9b74219bdf0 Mon Sep 17 00:00:00 2001 From: Xuan Hu Date: Tue, 21 Feb 2023 11:48:54 +0800 Subject: [PATCH 143/693] arch-riscv: Add risc-v vector ext v1.0 vset insts support Change-Id: I84363164ca327151101e8a1c3d8441a66338c909 Co-authored-by: Yang Liu Co-authored-by: Fan Yang <1209202421@qq.com> arch-riscv: Add a todo to fix vsetvl stall on decode Change-Id: Iafb129648fba89009345f0c0ad3710f773379bf6 --- src/arch/riscv/decoder.cc | 27 +++++ src/arch/riscv/decoder.hh | 12 +- src/arch/riscv/insts/SConscript | 1 + src/arch/riscv/insts/static_inst.hh | 1 + src/arch/riscv/insts/vector.cc | 126 +++++++++++++++++++++ src/arch/riscv/insts/vector.hh | 88 ++++++++++++++ src/arch/riscv/isa/decoder.isa | 33 ++++++ src/arch/riscv/isa/formats/formats.isa | 1 + src/arch/riscv/isa/formats/vector_conf.isa | 96 ++++++++++++++++ src/arch/riscv/isa/includes.isa | 2 + 10 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 src/arch/riscv/insts/vector.cc create mode 100644 src/arch/riscv/insts/vector.hh create mode 100644 src/arch/riscv/isa/formats/vector_conf.isa diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index 7faa310b1e..ce362ad522 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -42,6 +42,7 @@ void Decoder::reset() { aligned = true; mid = false; + vConfigDone = true; machInst = 0; emi = 0; } @@ -49,6 +50,15 @@ void Decoder::reset() void Decoder::moreBytes(const PCStateBase &pc, Addr fetchPC) { + // TODO: Current vsetvl instructions stall decode. Future fixes should + // enable speculation, and this code will be removed. + if (GEM5_UNLIKELY(!this->vConfigDone)) { + DPRINTF(Decode, "Waiting for vset*vl* to be executed\n"); + instDone = false; + outOfBytes = false; + return; + } + // The MSB of the upper and lower halves of a machine instruction. constexpr size_t max_bit = sizeof(machInst) * 8 - 1; constexpr size_t mid_bit = sizeof(machInst) * 4 - 1; @@ -78,6 +88,14 @@ Decoder::moreBytes(const PCStateBase &pc, Addr fetchPC) instDone = compressed(emi); } } + if (instDone) { + emi.vl = this->machVl; + emi.vtype8 = this->machVtype & 0xff; + emi.vill = this->machVtype.vill; + if (vconf(emi)) { + this->vConfigDone = false; // set true when vconfig inst execute + } + } } StaticInstPtr @@ -116,5 +134,14 @@ Decoder::decode(PCStateBase &_next_pc) return decode(emi, next_pc.instAddr()); } +void +Decoder::setVlAndVtype(uint32_t vl, VTYPE vtype) +{ + this->machVtype = vtype; + this->machVl = vl; + + this->vConfigDone = true; +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh index 15cbefe39c..d1d2f3cb0c 100644 --- a/src/arch/riscv/decoder.hh +++ b/src/arch/riscv/decoder.hh @@ -32,6 +32,7 @@ #include "arch/generic/decode_cache.hh" #include "arch/generic/decoder.hh" +#include "arch/riscv/insts/vector.hh" #include "arch/riscv/types.hh" #include "base/logging.hh" #include "base/types.hh" @@ -53,12 +54,16 @@ class Decoder : public InstDecoder decode_cache::InstMap instMap; bool aligned; bool mid; + bool vConfigDone; protected: //The extended machine instruction being generated ExtMachInst emi; uint32_t machInst; + VTYPE machVtype; + uint32_t machVl; + StaticInstPtr decodeInst(ExtMachInst mach_inst); /// Decode a machine instruction. @@ -74,13 +79,18 @@ class Decoder : public InstDecoder void reset() override; - inline bool compressed(ExtMachInst inst) { return (inst & 0x3) < 0x3; } + inline bool compressed(ExtMachInst inst) { return inst.quadRant < 0x3; } + inline bool vconf(ExtMachInst inst) { + return inst.opcode == 0b1010111u && inst.funct3 == 0b111u; + } //Use this to give data to the decoder. This should be used //when there is control flow. void moreBytes(const PCStateBase &pc, Addr fetchPC) override; StaticInstPtr decode(PCStateBase &nextPC) override; + + void setVlAndVtype(uint32_t vl, VTYPE vtype); }; } // namespace RiscvISA diff --git a/src/arch/riscv/insts/SConscript b/src/arch/riscv/insts/SConscript index 704152c040..2822cf86b4 100644 --- a/src/arch/riscv/insts/SConscript +++ b/src/arch/riscv/insts/SConscript @@ -33,3 +33,4 @@ Source('compressed.cc', tags='riscv isa') Source('mem.cc', tags='riscv isa') Source('standard.cc', tags='riscv isa') Source('static_inst.cc', tags='riscv isa') +Source('vector.cc', tags='riscv isa') diff --git a/src/arch/riscv/insts/static_inst.hh b/src/arch/riscv/insts/static_inst.hh index f835713505..74f9ddb452 100644 --- a/src/arch/riscv/insts/static_inst.hh +++ b/src/arch/riscv/insts/static_inst.hh @@ -33,6 +33,7 @@ #include #include "arch/riscv/pcstate.hh" +#include "arch/riscv/regs/misc.hh" #include "arch/riscv/types.hh" #include "cpu/exec_context.hh" #include "cpu/static_inst.hh" diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc new file mode 100644 index 0000000000..3965a45b26 --- /dev/null +++ b/src/arch/riscv/insts/vector.cc @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022 PLCT Lab + * 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. + */ + +#include "arch/riscv/insts/vector.hh" + +#include +#include + +#include "arch/riscv/insts/static_inst.hh" +#include "arch/riscv/utility.hh" +#include "cpu/static_inst.hh" + +namespace gem5 +{ + +namespace RiscvISA +{ + +/** + * This function translates the 3-bit value of vlmul bits to the corresponding + * lmul value as specified in RVV 1.0 spec p11-12 chapter 3.4.2. + * + * I.e., + * vlmul = -3 -> LMUL = 1/8 + * vlmul = -2 -> LMUL = 1/4 + * vlmul = -1 -> LMUL = 1/2 + * vlmul = 0 -> LMUL = 1 + * vlmul = 1 -> LMUL = 2 + * vlmul = 2 -> LMUL = 4 + * vlmul = 3 -> LMUL = 8 + * +**/ +float +getVflmul(uint32_t vlmul_encoding) { + int vlmul = sext<3>(vlmul_encoding & 7); + float vflmul = vlmul >= 0 ? 1 << vlmul : 1.0 / (1 << -vlmul); + return vflmul; +} + +uint32_t +getVlmax(VTYPE vtype, uint32_t vlen) { + uint32_t sew = getSew(vtype.vsew); + // vlmax is defined in RVV 1.0 spec p12 chapter 3.4.2. + uint32_t vlmax = (vlen/sew) * getVflmul(vtype.vlmul); + return vlmax; +} + +std::string +VConfOp::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", "; + if (bit31 && bit30 == 0) { + ss << registerName(srcRegIdx(0)) << ", " << registerName(srcRegIdx(1)); + } else if (bit31 && bit30) { + ss << uimm << ", " << generateZimmDisassembly(); + } else { + ss << registerName(srcRegIdx(0)) << ", " << generateZimmDisassembly(); + } + return ss.str(); +} + +std::string +VConfOp::generateZimmDisassembly() const +{ + std::stringstream s; + + // VSETIVLI uses ZIMM10 and VSETVLI uses ZIMM11 + uint64_t zimm = (bit31 && bit30) ? zimm10 : zimm11; + + bool frac_lmul = bits(zimm, 2); + int sew = 1 << (bits(zimm, 5, 3) + 3); + int lmul = bits(zimm, 1, 0); + auto vta = bits(zimm, 6) == 1 ? "ta" : "tu"; + auto vma = bits(zimm, 7) == 1 ? "ma" : "mu"; + s << "e" << sew; + if (frac_lmul) { + std::string lmul_str = ""; + switch(lmul){ + case 3: + lmul_str = "f2"; + break; + case 2: + lmul_str = "f4"; + break; + case 1: + lmul_str = "f8"; + break; + default: + panic("Unsupport fractional LMUL"); + } + s << ", m" << lmul_str; + } else { + s << ", m" << (1 << lmul); + } + s << ", " << vta << ", " << vma; + return s.str(); +} + +} // namespace RiscvISA +} // namespace gem5 diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh new file mode 100644 index 0000000000..cdeb48360c --- /dev/null +++ b/src/arch/riscv/insts/vector.hh @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 PLCT Lab + * 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. + */ + +#ifndef __ARCH_RISCV_INSTS_VECTOR_HH__ +#define __ARCH_RISCV_INSTS_VECTOR_HH__ + +#include + +#include "arch/riscv/insts/static_inst.hh" +#include "arch/riscv/regs/misc.hh" +#include "arch/riscv/regs/vector.hh" +#include "arch/riscv/utility.hh" +#include "cpu/exec_context.hh" +#include "cpu/static_inst.hh" + +namespace gem5 +{ + +namespace RiscvISA +{ + +float +getVflmul(uint32_t vlmul_encoding); + +inline uint32_t getSew(uint32_t vsew) { + assert(vsew <= 3); + return (8 << vsew); +} + +uint32_t +getVlmax(VTYPE vtype, uint32_t vlen); + +/** + * Base class for Vector Config operations + */ +class VConfOp : public RiscvStaticInst +{ + protected: + uint64_t bit30; + uint64_t bit31; + uint64_t zimm10; + uint64_t zimm11; + uint64_t uimm; + VConfOp(const char *mnem, ExtMachInst _extMachInst, OpClass __opClass) + : RiscvStaticInst(mnem, _extMachInst, __opClass), + bit30(_extMachInst.bit30), bit31(_extMachInst.bit31), + zimm10(_extMachInst.zimm_vsetivli), + zimm11(_extMachInst.zimm_vsetvli), + uimm(_extMachInst.uimm_vsetivli) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; + + std::string generateZimmDisassembly() const; +}; + + +} // namespace RiscvISA +} // namespace gem5 + + +#endif // __ARCH_RISCV_INSTS_VECTOR_HH__ diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index a339c11375..2e5b52a879 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -2012,6 +2012,39 @@ decode QUADRANT default Unknown::unknown() { } } + 0x15: decode FUNCT3 { + 0x7: decode BIT31 { + format VConfOp { + 0x0: vsetvli({{ + uint64_t rd_bits = RD; + uint64_t rs1_bits = RS1; + uint64_t requested_vl = Rs1_ud; + uint64_t requested_vtype = zimm11; + + Rd_ud = 0; + }}, VectorConfigOp, IsDirectControl, IsCondControl); + 0x1: decode BIT30 { + 0x0: vsetvl({{ + uint64_t rd_bits = RD; + uint64_t rs1_bits = RS1; + uint64_t requested_vl = Rs1_ud; + uint64_t requested_vtype = Rs2_ud; + + Rd_ud = 0; + }}, VectorConfigOp, IsDirectControl, IsCondControl); + 0x1: vsetivli({{ + uint64_t rd_bits = RD; + uint64_t rs1_bits = -1; + uint64_t requested_vl = uimm; + uint64_t requested_vtype = zimm10; + + Rd_ud = 0; + }}, VectorConfigOp, IsDirectControl, IsCondControl); + } + } + } + } + 0x18: decode FUNCT3 { format BOp { 0x0: beq({{ diff --git a/src/arch/riscv/isa/formats/formats.isa b/src/arch/riscv/isa/formats/formats.isa index 19749438a8..0f7c94da9a 100644 --- a/src/arch/riscv/isa/formats/formats.isa +++ b/src/arch/riscv/isa/formats/formats.isa @@ -37,6 +37,7 @@ ##include "fp.isa" ##include "amo.isa" ##include "bs.isa" +##include "vector_conf.isa" // Include formats for nonstandard extensions ##include "compressed.isa" diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa new file mode 100644 index 0000000000..556e230075 --- /dev/null +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -0,0 +1,96 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2022 PLCT Lab +// 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. + + +def format VConfOp(code, *flags) {{ + iop = InstObjParams(name, Name, 'VConfOp', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = VConfExecute.subst(iop) +}}; + +def template VConfExecute {{ + Fault + %(class_name)s::execute(ExecContext *xc, + trace::InstRecord *traceData) const + { + auto tc = xc->tcBase(); + + %(op_decl)s; + %(op_rd)s; + %(code)s; + + tc->setMiscReg(MISCREG_VSTART, 0); + + uint32_t vlen = xc->readMiscReg(MISCREG_VLENB) * 8; + uint32_t vlmax = getVlmax(xc->readMiscReg(MISCREG_VTYPE), vlen); + + VTYPE new_vtype = requested_vtype; + if (xc->readMiscReg(MISCREG_VTYPE) != new_vtype) { + vlmax = getVlmax(new_vtype, vlen); + + float vflmul = getVflmul(new_vtype.vlmul); + + uint32_t sew = getSew(new_vtype.vsew); + + uint32_t new_vill = + !(vflmul >= 0.125 && vflmul <= 8) || + sew > std::min(vflmul, 1.0f) * ELEN || + bits(requested_vtype, 30, 8) != 0; + if (new_vill) { + vlmax = 0; + new_vtype = 0; + new_vtype.vill = 1; + } + + xc->setMiscReg(MISCREG_VTYPE, new_vtype); + } + + uint32_t current_vl = xc->readMiscReg(MISCREG_VL); + uint32_t new_vl = 0; + if (vlmax == 0) { + new_vl = 0; + } else if (rd_bits == 0 && rs1_bits == 0) { + new_vl = current_vl > vlmax ? vlmax : current_vl; + } else if (rd_bits != 0 && rs1_bits == 0) { + new_vl = vlmax; + } else if (rs1_bits != 0) { + new_vl = requested_vl > vlmax ? vlmax : requested_vl; + } + + xc->setMiscReg(MISCREG_VL, new_vl); + + tc->getDecoderPtr()->as().setVlAndVtype(new_vl, new_vtype); + + Rd = new_vl; + + %(op_wb)s; + return NoFault; + } +}}; diff --git a/src/arch/riscv/isa/includes.isa b/src/arch/riscv/isa/includes.isa index cb95f58f7e..1d544f40ed 100644 --- a/src/arch/riscv/isa/includes.isa +++ b/src/arch/riscv/isa/includes.isa @@ -34,6 +34,7 @@ // output header {{ +#include #include #include #include @@ -45,6 +46,7 @@ output header {{ #include #include +#include "arch/riscv/decoder.hh" #include "arch/riscv/insts/amo.hh" #include "arch/riscv/insts/bs.hh" #include "arch/riscv/insts/compressed.hh" From 91b1d50f59b558a90eb529e8c8135d3a6d774464 Mon Sep 17 00:00:00 2001 From: Xuan Hu Date: Tue, 21 Feb 2023 12:58:30 +0800 Subject: [PATCH 144/693] arch-riscv: Add risc-v vector ext v1.0 mem insts support * TODOs: + Vector Segment Load/Store + Vector Fault-only-first Load Change-Id: I2815c76404e62babab7e9466e4ea33ea87e66e75 Co-authored-by: Yang Liu Co-authored-by: Fan Yang <1209202421@qq.com> Co-authored-by: Jerin Joy --- src/arch/riscv/insts/vector.cc | 173 +++ src/arch/riscv/insts/vector.hh | 341 +++++ src/arch/riscv/isa/decoder.isa | 268 ++++ src/arch/riscv/isa/formats/formats.isa | 1 + src/arch/riscv/isa/formats/vector_mem.isa | 205 +++ src/arch/riscv/isa/includes.isa | 8 + src/arch/riscv/isa/main.isa | 3 + src/arch/riscv/isa/templates/templates.isa | 2 + src/arch/riscv/isa/templates/vector_mem.isa | 1349 +++++++++++++++++++ src/arch/riscv/utility.hh | 55 + 10 files changed, 2405 insertions(+) create mode 100644 src/arch/riscv/isa/formats/vector_mem.isa create mode 100644 src/arch/riscv/isa/templates/templates.isa create mode 100644 src/arch/riscv/isa/templates/vector_mem.isa diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc index 3965a45b26..f2bde629e9 100644 --- a/src/arch/riscv/insts/vector.cc +++ b/src/arch/riscv/insts/vector.cc @@ -122,5 +122,178 @@ VConfOp::generateZimmDisassembly() const return s.str(); } +std::string VleMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')' << ", " + << registerName(srcRegIdx(1)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VlWholeMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; + return ss.str(); +} + +std::string VseMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " + << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VsWholeMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " + << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; + return ss.str(); +} + +std::string VleMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')'; + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VlWholeMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')'; + return ss.str(); +} + +std::string VseMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')'; + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VsWholeMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')'; + return ss.str(); +} + +std::string VlStrideMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')' << + ", " << registerName(srcRegIdx(1)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VlStrideMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')' << + ", "<< registerName(srcRegIdx(1)); + if (microIdx != 0 || machInst.vtype8.vma == 0 || machInst.vtype8.vta == 0) + ss << ", " << registerName(srcRegIdx(2)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VsStrideMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(2)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')' << + ", " << registerName(srcRegIdx(1)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VsStrideMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(2)) << ", " << + '(' << registerName(srcRegIdx(0)) << ')' << + ", "<< registerName(srcRegIdx(1)); + if (microIdx != 0 || machInst.vtype8.vma == 0 || machInst.vtype8.vta == 0) + ss << ", " << registerName(srcRegIdx(2)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VlIndexMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << '(' << registerName(srcRegIdx(0)) << ")," + << registerName(srcRegIdx(1)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VlIndexMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' + << registerName(destRegIdx(0)) << "[" << uint16_t(vdElemIdx) << "], " + << '(' << registerName(srcRegIdx(0)) << "), " + << registerName(srcRegIdx(1)) << "[" << uint16_t(vs2ElemIdx) << "]"; + if (microIdx != 0 || machInst.vtype8.vma == 0 || machInst.vtype8.vta == 0) + ss << ", " << registerName(srcRegIdx(2)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VsIndexMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(2)) << ", " + << '(' << registerName(srcRegIdx(0)) << ")," + << registerName(srcRegIdx(1)); + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + +std::string VsIndexMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' + << registerName(srcRegIdx(2)) << "[" << uint16_t(vs3ElemIdx) << "], " + << '(' << registerName(srcRegIdx(0)) << "), " + << registerName(srcRegIdx(1)) << "[" << uint16_t(vs2ElemIdx) << "]"; + if (!machInst.vm) ss << ", v0.t"; + return ss.str(); +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index cdeb48360c..f989d7ffbf 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -80,6 +80,347 @@ class VConfOp : public RiscvStaticInst std::string generateZimmDisassembly() const; }; +inline uint8_t checked_vtype(bool vill, uint8_t vtype) { + panic_if(vill, "vill has been set"); + const uint8_t vsew = bits(vtype, 5, 3); + panic_if(vsew >= 0b100, "vsew: %#x not supported", vsew); + const uint8_t vlmul = bits(vtype, 2, 0); + panic_if(vlmul == 0b100, "vlmul: %#x not supported", vlmul); + return vtype; +} + +class VectorMacroInst : public RiscvMacroInst +{ + protected: + uint32_t vl; + uint8_t vtype; + VectorMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : RiscvMacroInst(mnem, _machInst, __opClass), + vl(_machInst.vl), + vtype(checked_vtype(_machInst.vill, _machInst.vtype8)) + { + this->flags[IsVector] = true; + } +}; + +class VectorMicroInst : public RiscvMicroInst +{ +protected: + uint8_t microVl; + uint8_t microIdx; + uint8_t vtype; + VectorMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint8_t _microVl, uint8_t _microIdx) + : RiscvMicroInst(mnem, _machInst, __opClass), + microVl(_microVl), + microIdx(_microIdx), + vtype(_machInst.vtype8) + { + this->flags[IsVector] = true; + } +}; + +class VectorNopMicroInst : public RiscvMicroInst +{ +public: + VectorNopMicroInst(ExtMachInst _machInst) + : RiscvMicroInst("vnop", _machInst, No_OpClass) + {} + + Fault execute(ExecContext* xc, trace::InstRecord* traceData) + const override + { + return NoFault; + } + + std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) + const override + { + std::stringstream ss; + ss << mnemonic; + return ss.str(); + } +}; + +class VectorArithMicroInst : public VectorMicroInst +{ +protected: + VectorArithMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, + uint8_t _microIdx) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VectorArithMacroInst : public VectorMacroInst +{ + protected: + VectorArithMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMacroInst(mnem, _machInst, __opClass) + { + this->flags[IsVector] = true; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VectorMemMicroInst : public VectorMicroInst +{ + protected: + uint32_t offset; // Used to calculate EA. + Request::Flags memAccessFlags; + + VectorMemMicroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, uint8_t _microIdx, + uint32_t _offset) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + , offset(_offset) + , memAccessFlags(0) + {} +}; + +class VectorMemMacroInst : public VectorMacroInst +{ + protected: + VectorMemMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMacroInst(mnem, _machInst, __opClass) + {} +}; + +class VleMacroInst : public VectorMemMacroInst +{ + protected: + VleMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VseMacroInst : public VectorMemMacroInst +{ + protected: + VseMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VleMicroInst : public VectorMicroInst +{ + protected: + Request::Flags memAccessFlags; + + VleMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint8_t _microVl, uint8_t _microIdx) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + { + this->flags[IsLoad] = true; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VseMicroInst : public VectorMicroInst +{ + protected: + Request::Flags memAccessFlags; + + VseMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, + uint8_t _microVl, uint8_t _microIdx) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + { + this->flags[IsStore] = true; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VlWholeMacroInst : public VectorMemMacroInst +{ + protected: + VlWholeMacroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VlWholeMicroInst : public VectorMicroInst +{ + protected: + Request::Flags memAccessFlags; + + VlWholeMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, uint8_t _microIdx) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VsWholeMacroInst : public VectorMemMacroInst +{ + protected: + VsWholeMacroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VsWholeMicroInst : public VectorMicroInst +{ + protected: + Request::Flags memAccessFlags; + + VsWholeMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, uint8_t _microIdx) + : VectorMicroInst(mnem, _machInst, __opClass, _microIdx, _microIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VlStrideMacroInst : public VectorMemMacroInst +{ + protected: + VlStrideMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VlStrideMicroInst : public VectorMemMicroInst +{ + protected: + uint8_t regIdx; + VlStrideMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _regIdx, + uint8_t _microIdx, uint8_t _microVl) + : VectorMemMicroInst(mnem, _machInst, __opClass, _microVl, + _microIdx, 0) + , regIdx(_regIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VsStrideMacroInst : public VectorMemMacroInst +{ + protected: + VsStrideMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VsStrideMicroInst : public VectorMemMicroInst +{ + protected: + uint8_t regIdx; + VsStrideMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _regIdx, + uint8_t _microIdx, uint8_t _microVl) + : VectorMemMicroInst(mnem, _machInst, __opClass, _microVl, + _microIdx, 0) + , regIdx(_regIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VlIndexMacroInst : public VectorMemMacroInst +{ + protected: + VlIndexMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VlIndexMicroInst : public VectorMemMicroInst +{ + protected: + uint8_t vdRegIdx; + uint8_t vdElemIdx; + uint8_t vs2RegIdx; + uint8_t vs2ElemIdx; + VlIndexMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _vdRegIdx, uint8_t _vdElemIdx, + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + : VectorMemMicroInst(mnem, _machInst, __opClass, 1, + 0, 0) + , vdRegIdx(_vdRegIdx), vdElemIdx(_vdElemIdx) + , vs2RegIdx(_vs2RegIdx), vs2ElemIdx(_vs2ElemIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VsIndexMacroInst : public VectorMemMacroInst +{ + protected: + VsIndexMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMemMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VsIndexMicroInst : public VectorMemMicroInst +{ + protected: + uint8_t vs3RegIdx; + uint8_t vs3ElemIdx; + uint8_t vs2RegIdx; + uint8_t vs2ElemIdx; + VsIndexMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + : VectorMemMicroInst(mnem, _machInst, __opClass, 1, 0, 0) + , vs3RegIdx(_vs3RegIdx), vs3ElemIdx(_vs3ElemIdx) + , vs2RegIdx(_vs2RegIdx), vs2ElemIdx(_vs2ElemIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 2e5b52a879..0288f37ad8 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -500,6 +500,174 @@ decode QUADRANT default Unknown::unknown() { Fd_bits = fd.v; }}, inst_flags=FloatMemReadOp); } + + 0x0: decode MOP { + 0x0: decode LUMOP { + 0x00: VleOp::vle8_v({{ + if ((machInst.vm || elem_mask(v0, ei)) && + i < this->microVl) { + Vd_ub[i] = Mem_vc.as()[i]; + } else { + Vd_ub[i] = Vs2_ub[i]; + } + }}, inst_flags=VectorUnitStrideLoadOp); + 0x08: decode NF { + format VlWholeOp { + 0x0: vl1re8_v({{ + Vd_ub[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x1: vl2re8_v({{ + Vd_ub[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x3: vl4re8_v({{ + Vd_ub[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x7: vl8re8_v({{ + Vd_ub[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + } + } + 0x0b: VlmOp::vlm_v({{ + Vd_ub[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorUnitStrideMaskLoadOp); + } + 0x1: VlIndexOp::vluxei8_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_ub[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + 0x2: VlStrideOp::vlse8_v({{ + Vd_ub[microIdx] = Mem_vc.as()[0]; + }}, inst_flags=VectorStridedLoadOp); + 0x3: VlIndexOp::vloxei8_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_ub[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + } + 0x5: decode MOP { + 0x0: decode LUMOP { + 0x00: VleOp::vle16_v({{ + if ((machInst.vm || elem_mask(v0, ei)) && + i < this->microVl) { + Vd_uh[i] = Mem_vc.as()[i]; + } else { + Vd_uh[i] = Vs2_uh[i]; + } + }}, inst_flags=VectorUnitStrideLoadOp); + 0x08: decode NF { + format VlWholeOp { + 0x0: vl1re16_v({{ + Vd_uh[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x1: vl2re16_v({{ + Vd_uh[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x3: vl4re16_v({{ + Vd_uh[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x7: vl8re16_v({{ + Vd_uh[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + } + } + } + 0x1: VlIndexOp::vluxei16_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_uh[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + 0x2: VlStrideOp::vlse16_v({{ + Vd_uh[microIdx] = Mem_vc.as()[0]; + }}, inst_flags=VectorStridedLoadOp); + 0x3: VlIndexOp::vloxei16_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_uh[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + } + 0x6: decode MOP { + 0x0: decode LUMOP { + 0x00: VleOp::vle32_v({{ + if ((machInst.vm || elem_mask(v0, ei)) && + i < this->microVl) { + Vd_uw[i] = Mem_vc.as()[i]; + } else { + Vd_uw[i] = Vs2_uw[i]; + } + }}, inst_flags=VectorUnitStrideLoadOp); + 0x08: decode NF { + format VlWholeOp { + 0x0: vl1re32_v({{ + Vd_uw[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x1: vl2re32_v({{ + Vd_uw[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x3: vl4re32_v({{ + Vd_uw[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x7: vl8re32_v({{ + Vd_uw[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + } + } + } + 0x1: VlIndexOp::vluxei32_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_uw[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + 0x2: VlStrideOp::vlse32_v({{ + Vd_uw[microIdx] = Mem_vc.as()[0]; + }}, inst_flags=VectorStridedLoadOp); + 0x3: VlIndexOp::vloxei32_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_uw[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + } + 0x7: decode MOP { + 0x0: decode LUMOP { + 0x00: VleOp::vle64_v({{ + if ((machInst.vm || elem_mask(v0, ei)) && + i < this->microVl) { + Vd_ud[i] = Mem_vc.as()[i]; + } else { + Vd_ud[i] = Vs2_ud[i]; + } + }}, inst_flags=VectorUnitStrideLoadOp); + 0x08: decode NF { + format VlWholeOp { + 0x0: vl1re64_v({{ + Vd_ud[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x1: vl2re64_v({{ + Vd_ud[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x3: vl4re64_v({{ + Vd_ud[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + 0x7: vl8re64_v({{ + Vd_ud[i] = Mem_vc.as()[i]; + }}, inst_flags=VectorWholeRegisterLoadOp); + } + } + } + 0x1: VlIndexOp::vluxei64_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_ud[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + 0x2: VlStrideOp::vlse64_v({{ + Vd_ud[microIdx] = Mem_vc.as()[0]; + }}, inst_flags=VectorStridedLoadOp); + 0x3: VlIndexOp::vloxei64_v({{ + Vd_vu[vdElemIdx] = Mem_vc.as()[0]; + }}, {{ + EA = Rs1 + Vs2_ud[vs2ElemIdx]; + }}, inst_flags=VectorIndexedLoadOp); + } } 0x03: decode FUNCT3 { @@ -806,6 +974,106 @@ decode QUADRANT default Unknown::unknown() { Mem_ud = Fs2_bits; }}, inst_flags=FloatMemWriteOp); } + + 0x0: decode MOP { + 0x0: decode SUMOP { + 0x00: VseOp::vse8_v({{ + Mem_vc.as()[i] = Vs3_ub[i]; + }}, inst_flags=VectorUnitStrideStoreOp); + format VsWholeOp { + 0x8: decode NF { + 0x0: vs1r_v({{ + Mem_vc.as()[i] = Vs3_ub[i]; + }}, inst_flags=VectorWholeRegisterStoreOp); + 0x1: vs2r_v({{ + Mem_vc.as()[i] = Vs3_ub[i]; + }}, inst_flags=VectorWholeRegisterStoreOp); + 0x3: vs4r_v({{ + Mem_vc.as()[i] = Vs3_ub[i]; + }}, inst_flags=VectorWholeRegisterStoreOp); + 0x7: vs8r_v({{ + Mem_vc.as()[i] = Vs3_ub[i]; + }}, inst_flags=VectorWholeRegisterStoreOp); + } + } + 0x0b: VsmOp::vsm_v({{ + Mem_vc.as()[i] = Vs3_ub[i]; + }}, inst_flags=VectorUnitStrideMaskStoreOp); + } + 0x1: VsIndexOp::vsuxei8_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_ub[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + 0x2: VsStrideOp::vsse8_v({{ + Mem_vc.as()[0] = Vs3_ub[microIdx]; + }}, inst_flags=VectorStridedStoreOp); + 0x3: VsIndexOp::vsoxei8_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_ub[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + } + 0x5: decode MOP { + 0x0: decode SUMOP { + 0x00: VseOp::vse16_v({{ + Mem_vc.as()[i] = Vs3_uh[i]; + }}, inst_flags=VectorUnitStrideStoreOp); + } + 0x1: VsIndexOp::vsuxei16_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_uh[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + 0x2: VsStrideOp::vsse16_v({{ + Mem_vc.as()[0] = Vs3_uh[microIdx]; + }}, inst_flags=VectorStridedStoreOp); + 0x3: VsIndexOp::vsoxei16_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_uh[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + } + 0x6: decode MOP { + 0x0: decode SUMOP { + 0x00: VseOp::vse32_v({{ + Mem_vc.as()[i] = Vs3_uw[i]; + }}, inst_flags=VectorUnitStrideStoreOp); + } + 0x1: VsIndexOp::vsuxei32_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_uw[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + 0x2: VsStrideOp::vsse32_v({{ + Mem_vc.as()[0] = Vs3_uw[microIdx]; + }}, inst_flags=VectorStridedStoreOp); + 0x3: VsIndexOp::vsoxei32_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_uw[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + } + 0x7: decode MOP { + 0x0: decode SUMOP { + 0x00: VseOp::vse64_v({{ + Mem_vc.as()[i] = Vs3_ud[i]; + }}, inst_flags=VectorUnitStrideStoreOp); + } + 0x1: VsIndexOp::vsuxei64_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_ud[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + 0x2: VsStrideOp::vsse64_v({{ + Mem_vc.as()[0] = Vs3_ud[microIdx]; + }}, inst_flags=VectorStridedStoreOp); + 0x3: VsIndexOp::vsoxei64_v({{ + Mem_vc.as()[0] = Vs3_vu[vs3ElemIdx]; + }}, {{ + EA = Rs1 + Vs2_ud[vs2ElemIdx]; + }}, inst_flags=VectorIndexedStoreOp); + } } 0x0b: decode FUNCT3 { diff --git a/src/arch/riscv/isa/formats/formats.isa b/src/arch/riscv/isa/formats/formats.isa index 0f7c94da9a..4bdc3021d5 100644 --- a/src/arch/riscv/isa/formats/formats.isa +++ b/src/arch/riscv/isa/formats/formats.isa @@ -38,6 +38,7 @@ ##include "amo.isa" ##include "bs.isa" ##include "vector_conf.isa" +##include "vector_mem.isa" // Include formats for nonstandard extensions ##include "compressed.isa" diff --git a/src/arch/riscv/isa/formats/vector_mem.isa b/src/arch/riscv/isa/formats/vector_mem.isa new file mode 100644 index 0000000000..113250d5cf --- /dev/null +++ b/src/arch/riscv/isa/formats/vector_mem.isa @@ -0,0 +1,205 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2022 PLCT Lab +// 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. + + +let {{ + +def VMemBase(name, Name, ea_code, memacc_code, mem_flags, + inst_flags, base_class, postacc_code='', + declare_template_base=VMemMacroDeclare, + decode_template=BasicDecode, exec_template_base='', + # If it's a macroop, the corresponding microops will be + # generated. + is_macroop=True): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + iop = InstObjParams(name, Name, base_class, + {'ea_code': ea_code, + 'memacc_code': memacc_code, + 'postacc_code': postacc_code }, + inst_flags) + + constructTemplate = eval(exec_template_base + 'Constructor') + + header_output = declare_template_base.subst(iop) + decoder_output = '' + if declare_template_base is not VMemTemplateMacroDeclare: + decoder_output += constructTemplate.subst(iop) + else: + header_output += constructTemplate.subst(iop) + decode_block = decode_template.subst(iop) + exec_output = '' + if not is_macroop: + return (header_output, decoder_output, decode_block, exec_output) + + microiop = InstObjParams(name + '_micro', + Name + 'Micro', + exec_template_base + 'MicroInst', + {'ea_code': ea_code, + 'memacc_code': memacc_code, + 'postacc_code': postacc_code}, + inst_flags) + + if mem_flags: + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] + s = '\n\tmemAccessFlags = ' + '|'.join(mem_flags) + ';' + microiop.constructor += s + + microDeclTemplate = eval(exec_template_base + 'Micro' + 'Declare') + microExecTemplate = eval(exec_template_base + 'Micro' + 'Execute') + microInitTemplate = eval(exec_template_base + 'Micro' + 'InitiateAcc') + microCompTemplate = eval(exec_template_base + 'Micro' + 'CompleteAcc') + header_output = microDeclTemplate.subst(microiop) + header_output + micro_exec_output = (microExecTemplate.subst(microiop) + + microInitTemplate.subst(microiop) + + microCompTemplate.subst(microiop)) + if declare_template_base is not VMemTemplateMacroDeclare: + exec_output += micro_exec_output + else: + header_output += micro_exec_output + + return (header_output, decoder_output, decode_block, exec_output) + +}}; + +def format VleOp( + memacc_code, + ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VleMacroInst', exec_template_base='Vle') +}}; + +def format VseOp( + memacc_code, + ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VseMacroInst', exec_template_base='Vse') +}}; + +def format VlmOp( + memacc_code, + ea_code={{ EA = Rs1; }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VleMacroInst', exec_template_base='Vlm', is_macroop=False) +}}; + +def format VsmOp( + memacc_code, + ea_code={{ EA = Rs1; }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VseMacroInst', exec_template_base='Vsm', is_macroop=False) +}}; + +def format VlWholeOp( + memacc_code, + ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VlWholeMacroInst', exec_template_base='VlWhole') +}}; + +def format VsWholeOp( + memacc_code, + ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VsWholeMacroInst', exec_template_base='VsWhole') +}}; + +def format VlStrideOp( + memacc_code, + ea_code={{ EA = Rs1 + Rs2 * (regIdx * VLENB / elem_size + microIdx); }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VlStrideMacroInst', exec_template_base='VlStride') +}}; + +def format VsStrideOp( + memacc_code, + ea_code={{ EA = Rs1 + Rs2 * (regIdx * VLENB / elem_size + microIdx); }}, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VsStrideMacroInst', exec_template_base='VsStride') +}}; + +def format VlIndexOp( + memacc_code, + ea_code, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VlIndexMacroInst', exec_template_base='VlIndex', + declare_template_base=VMemTemplateMacroDeclare, + decode_template=VMemTemplateDecodeBlock + ) +}}; + +def format VsIndexOp( + memacc_code, + ea_code, + mem_flags=[], + inst_flags=[] +) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + 'VsIndexMacroInst', exec_template_base='VsIndex', + declare_template_base=VMemTemplateMacroDeclare, + decode_template=VMemTemplateDecodeBlock + ) +}}; diff --git a/src/arch/riscv/isa/includes.isa b/src/arch/riscv/isa/includes.isa index 1d544f40ed..76f2388faf 100644 --- a/src/arch/riscv/isa/includes.isa +++ b/src/arch/riscv/isa/includes.isa @@ -46,6 +46,7 @@ output header {{ #include #include +#include "arch/generic/memhelpers.hh" #include "arch/riscv/decoder.hh" #include "arch/riscv/insts/amo.hh" #include "arch/riscv/insts/bs.hh" @@ -55,6 +56,7 @@ output header {{ #include "arch/riscv/insts/standard.hh" #include "arch/riscv/insts/static_inst.hh" #include "arch/riscv/insts/unknown.hh" +#include "arch/riscv/insts/vector.hh" #include "arch/riscv/interrupts.hh" #include "cpu/static_inst.hh" #include "mem/packet.hh" @@ -68,9 +70,15 @@ output decoder {{ #include #include +/* riscv softfloat library */ +#include +#include +#include + #include "arch/riscv/decoder.hh" #include "arch/riscv/faults.hh" #include "arch/riscv/mmu.hh" +#include "arch/riscv/regs/float.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" diff --git a/src/arch/riscv/isa/main.isa b/src/arch/riscv/isa/main.isa index 24f366b00c..2923a965da 100644 --- a/src/arch/riscv/isa/main.isa +++ b/src/arch/riscv/isa/main.isa @@ -50,6 +50,9 @@ namespace RiscvISA; //Include the operand_types and operand definitions ##include "operands.isa" +//Include the definitions for the instruction templates +##include "templates/templates.isa" + //Include the definitions for the instruction formats ##include "formats/formats.isa" diff --git a/src/arch/riscv/isa/templates/templates.isa b/src/arch/riscv/isa/templates/templates.isa new file mode 100644 index 0000000000..b4de46d846 --- /dev/null +++ b/src/arch/riscv/isa/templates/templates.isa @@ -0,0 +1,2 @@ +// Include +##include "vector_mem.isa" diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa new file mode 100644 index 0000000000..d54243ad7d --- /dev/null +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -0,0 +1,1349 @@ +def template VMemMacroDeclare {{ + +class %(class_name)s : public %(base_class)s +{ +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VMemTemplateMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VleConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const uint32_t num_microops = ceil((float) this->vl / (micro_vlmax)); + int32_t remaining_vl = this->vl; + int32_t micro_vl = std::min(remaining_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + microop->setFlag(IsLoad); + this->microops.push_back(microop); + micro_vl = std::min(remaining_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VleMicroDeclare {{ + +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[3]; + RegId destRegIdxArr[1]; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, + _microIdx) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _microIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + } + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; + +}; + +}}; + +def template VleMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const +{ + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = width_EEW(machInst.width) / 8 * this->microVl; + const std::vector byte_enable(mem_size, true); + Fault fault = xc->readMem(EA, Mem.as(), mem_size, memAccessFlags, + byte_enable); + if (fault != NoFault) + return fault; + + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const size_t micro_elems = VLEN / width_EEW(machInst.width); + size_t ei; + for (size_t i = 0; i < micro_elems; i++) { + ei = i + micro_vlmax * microIdx; + %(memacc_code)s; + } + + %(op_wb)s; + return fault; +} + +}}; + +def template VleMicroInitiateAcc {{ + +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + Addr EA; + + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + uint32_t mem_size = width_EEW(this->machInst.width) / 8 * this->microVl; + const std::vector byte_enable(mem_size, true); + Fault fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, + byte_enable); + return fault; +} + +}}; + +def template VleMicroCompleteAcc {{ + +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, + trace::InstRecord *traceData) const +{ + %(op_decl)s; + %(op_rd)s; + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); + v0 = tmp_v0.as(); + } + + memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); + + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const size_t micro_elems = VLEN / width_EEW(machInst.width); + size_t ei; + for (size_t i = 0; i < micro_elems; i++) { + ei = i + micro_vlmax * microIdx; + %(memacc_code)s; + } + + %(op_wb)s; + return NoFault; +} + +}}; + +def template VseConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const uint32_t num_microops = ceil((float) this->vl / (micro_vlmax)); + int32_t remaining_vl = this->vl; + int32_t micro_vl = std::min(remaining_vl, micro_vlmax); + + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + microop->setFlag(IsStore); + this->microops.push_back(microop); + micro_vl = std::min(remaining_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFlag(IsFirstMicroop); + this->microops.back()->setFlag(IsLastMicroop); +} + +}}; + +def template VseMicroDeclare {{ + +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[3]; + RegId destRegIdxArr[0]; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _microVl, _microIdx) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _microIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsVector] = true; + this->flags[IsStore] = true; + } + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VseMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const +{ + Addr EA; + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); + v0 = tmp_v0.as(); + } + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const size_t eewb = width_EEW(machInst.width) / 8; + const size_t mem_size = eewb * microVl; + std::vector byte_enable(mem_size, false); + size_t ei; + for (size_t i = 0; i < microVl; i++) { + ei = i + micro_vlmax * microIdx; + if (machInst.vm || elem_mask(v0, ei)) { + %(memacc_code)s; + auto it = byte_enable.begin() + i * eewb; + std::fill(it, it + eewb, true); + } + } + + Fault fault; + fault = xc->writeMem(Mem.as(), mem_size, EA, memAccessFlags, + nullptr, byte_enable); + return fault; +} + +}}; + +def template VseMicroInitiateAcc {{ + +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + Addr EA; + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); + v0 = tmp_v0.as(); + } + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const size_t eewb = width_EEW(machInst.width) / 8; + const size_t mem_size = eewb * microVl; + std::vector byte_enable(mem_size, false); + size_t ei; + for (size_t i = 0; i < microVl; i++) { + ei = i + micro_vlmax * microIdx; + if (machInst.vm || elem_mask(v0, ei)) { + %(memacc_code)s; + auto it = byte_enable.begin() + i * eewb; + std::fill(it, it + eewb, true); + } + } + + Fault fault; + fault = xc->writeMem(Mem.as(), mem_size, EA, memAccessFlags, + nullptr, byte_enable); + return fault; +} + +}}; + +def template VseMicroCompleteAcc {{ + +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext* xc, + trace::InstRecord* traceData) const +{ + return NoFault; +} + +}}; + +def template VlmConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const uint32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + int32_t micro_vl = (std::min(this->vl, micro_vlmax) + 7) / 8; + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + } else { + microop = new Vle8_vMicro(_machInst, micro_vl, 0); + microop->setDelayedCommit(); + microop->setFlag(IsLoad); + } + this->microops.push_back(microop); + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VsmConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const uint32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + int32_t micro_vl = (std::min(this->vl, micro_vlmax) + 7) / 8; + + StaticInstPtr microop; + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + } else { + microop = new Vse8_vMicro(_machInst, micro_vl, 0); + microop->setDelayedCommit(); + microop->setFlag(IsStore); + } + this->microops.push_back(microop); + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VsWholeConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + size_t NFIELDS = machInst.nf + 1; + const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + + StaticInstPtr microop; + for (int i = 0; i < NFIELDS; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vlmax, i); + microop->setDelayedCommit(); + microop->setFlag(IsStore); + this->microops.push_back(microop); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VsWholeMicroDeclare {{ + +class %(class_name)s: public %(base_class)s +{ +private: + RegId destRegIdxArr[0]; + RegId srcRegIdxArr[2]; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _microVl, _microIdx) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _microIdx]); + this->flags[IsVector] = true; + this->flags[IsStore] = true; + } + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VsWholeMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const +{ + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + for (size_t i = 0; i < VLENB; i++) { + %(memacc_code)s; + } + + Fault fault = writeMemAtomicLE(xc, traceData, *(vreg_t::Container*)(&Mem), + EA, memAccessFlags, nullptr); + return fault; +} + +}}; + +def template VsWholeMicroInitiateAcc {{ + +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + for (size_t i = 0; i < VLENB; i++) { + %(memacc_code)s; + } + + Fault fault = writeMemTimingLE(xc, traceData, *(vreg_t::Container*)(&Mem), + EA, memAccessFlags, nullptr); + return fault; +} + +}}; + +def template VsWholeMicroCompleteAcc {{ + +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext* xc, + trace::InstRecord* traceData) const +{ + return NoFault; +} + +}}; + +def template VlWholeConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + size_t NFIELDS = machInst.nf + 1; + const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + + StaticInstPtr microop; + for (int i = 0; i < NFIELDS; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vlmax, i); + microop->setDelayedCommit(); + microop->setFlag(IsLoad); + this->microops.push_back(microop); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VlWholeMicroDeclare {{ + +class %(class_name)s: public %(base_class)s +{ +private: + RegId destRegIdxArr[1]; + RegId srcRegIdxArr[1]; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s_micro", _machInst, %(op_class)s, + _microVl, _microIdx) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + this->flags[IsVector] = true; + this->flags[IsLoad] = true; + } + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VlWholeMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const +{ + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + Fault fault = readMemAtomicLE(xc, traceData, EA, + *(vreg_t::Container*)(&Mem), memAccessFlags); + if (fault != NoFault) + return fault; + + size_t elem_per_reg = VLEN / width_EEW(machInst.width); + for (size_t i = 0; i < elem_per_reg; i++) { + %(memacc_code)s; + } + + %(op_wb)s; + return NoFault; +} + +}}; + +def template VlWholeMicroInitiateAcc {{ + +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + Addr EA; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + Fault fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); + return fault; +} + +}}; + +def template VlWholeMicroCompleteAcc {{ + +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext* xc, + trace::InstRecord* traceData) const +{ + %(op_decl)s; + %(op_rd)s; + + memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); + + size_t elem_per_reg = VLEN / width_EEW(machInst.width); + for (size_t i = 0; i < elem_per_reg; ++i) { + %(memacc_code)s; + } + + %(op_wb)s; + return NoFault; +} + +}}; + +def template VlStrideConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const int32_t num_elems_per_vreg = VLEN / width_EEW(_machInst.width); + int32_t remaining_vl = this->vl; + // Num of elems in one vreg + int32_t micro_vl = std::min(remaining_vl, num_elems_per_vreg); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; micro_vl > 0; ++i) { + for (int j = 0; j < micro_vl; ++j) { + microop = new %(class_name)sMicro(machInst, i, j, micro_vl); + microop->setFlag(IsDelayedCommit); + microop->setFlag(IsLoad); + this->microops.push_back(microop); + } + remaining_vl -= num_elems_per_vreg; + micro_vl = std::min(remaining_vl, num_elems_per_vreg); + } + + this->microops.front()->setFlag(IsFirstMicroop); + this->microops.back()->setFlag(IsLastMicroop); + this->flags[IsVector] = true; +} + +}}; + +def template VlStrideMicroDeclare {{ + +class %(class_name)s : public %(base_class)s +{ +private: + // rs1, rs2, vd, vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + uint8_t _microVl) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _regIdx, _microIdx, _microVl) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _regIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs2]); + // We treat agnostic as undistrubed + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _regIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsLoad] = true; + } + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VlStrideMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const +{ + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + constexpr uint8_t elem_size = sizeof(Vd[0]); + %(ea_code)s; // ea_code depends on elem_size + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = elem_size; + const std::vector byte_enable(mem_size, true); + + size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + if (machInst.vm || elem_mask(v0, ei)) { + fault = xc->readMem(EA, Mem.as(), mem_size, + memAccessFlags, byte_enable); + if (fault != NoFault) + return fault; + %(memacc_code)s; /* Vd[this->microIdx] = Mem[0]; */ + } + + %(op_wb)s; + return fault; +} + +}}; + +def template VlStrideMicroInitiateAcc {{ + +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + Fault fault = NoFault; + Addr EA; + + %(op_src_decl)s; + %(op_rd)s; + constexpr uint8_t elem_size = sizeof(Vd[0]); + %(ea_code)s; // ea_code depends on elem_size + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = elem_size; + size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + bool need_load = machInst.vm || elem_mask(v0, ei); + const std::vector byte_enable(mem_size, need_load); + fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, byte_enable); + return fault; +} + +}}; + +def template VlStrideMicroCompleteAcc {{ + +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, + trace::InstRecord *traceData) const +{ + %(op_decl)s; + %(op_rd)s; + + constexpr uint8_t elem_size = sizeof(Vd[0]); + + RiscvISA::vreg_t old_vd; + decltype(Vd) old_Vd = nullptr; + // We treat agnostic as undistrubed + xc->getRegOperand(this, 2, &old_vd); + old_Vd = old_vd.as >(); + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + if (microIdx == 0) { + // treat vma as vmu + // if (machInst.vtype8.vma == 0) + memcpy(Vd, old_Vd, microVl * elem_size); + // treat vta as vtu + // if (machInst.vtype8.vta == 0) + memcpy(Vd + microVl, old_Vd + microVl, VLENB - microVl * elem_size); + } else { + memcpy(Vd, old_Vd, VLENB); + } + + size_t ei = this->regIdx * VLENB / sizeof(Vd[0]) + this->microIdx; + if (machInst.vm || elem_mask(v0, ei)) { + memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); + %(memacc_code)s; /* Vd[this->microIdx] = Mem[0]; */ + } + + %(op_wb)s; + return NoFault; +} + +}}; + +def template VsStrideConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const int32_t num_elems_per_vreg = VLEN / width_EEW(_machInst.width); + int32_t remaining_vl = this->vl; + // Num of elems in one vreg + int32_t micro_vl = std::min(remaining_vl, num_elems_per_vreg); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; micro_vl > 0; ++i) { + for (int j = 0; j < micro_vl; ++j) { + microop = new %(class_name)sMicro(machInst, i, j, micro_vl); + microop->setFlag(IsDelayedCommit); + microop->setFlag(IsStore); + this->microops.push_back(microop); + } + remaining_vl -= num_elems_per_vreg; + micro_vl = std::min(remaining_vl, num_elems_per_vreg); + } + + this->microops.front()->setFlag(IsFirstMicroop); + this->microops.back()->setFlag(IsLastMicroop); + this->flags[IsVector] = true; +} + +}}; + +def template VsStrideMicroDeclare {{ + +class %(class_name)s : public %(base_class)s +{ +private: + // rs1, rs2, vs3, vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[0]; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + uint8_t _microVl) + : %(base_class)s("%(mnemonic)s""_micro", _machInst, %(op_class)s, + _regIdx, _microIdx, _microVl) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs2]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _regIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsStore] = true; + } + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VsStrideMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const +{ + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + constexpr uint8_t elem_size = sizeof(Vs3[0]); + %(ea_code)s; + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = elem_size; + const std::vector byte_enable(mem_size, true); + + size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + if (machInst.vm || elem_mask(v0, ei)) { + %(memacc_code)s; + fault = xc->writeMem(Mem.as(), mem_size, EA, + memAccessFlags, nullptr, byte_enable); + } + return fault; +} + +}}; + +def template VsStrideMicroInitiateAcc {{ + +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + Fault fault = NoFault; + Addr EA; + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); + v0 = tmp_v0.as(); + } + + %(op_decl)s; + %(op_rd)s; + constexpr uint8_t elem_size = sizeof(Vs3[0]); + %(ea_code)s; + + uint32_t mem_size = elem_size; + size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + bool need_store = machInst.vm || elem_mask(v0, ei); + if (need_store) { + const std::vector byte_enable(mem_size, need_store); + %(memacc_code)s; + fault = xc->writeMem(Mem.as(), mem_size, EA, + memAccessFlags, nullptr, byte_enable); + } + return fault; +} + +}}; + +def template VsStrideMicroCompleteAcc {{ + +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext* xc, + trace::InstRecord* traceData) const +{ + return NoFault; +} + +}}; + +def template VlIndexConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const uint32_t vd_eewb = sizeof(ElemType); + const uint32_t vs2_eewb = width_EEW(_machInst.width) / 8; + const uint8_t vs2_split_num = (vd_eewb + vs2_eewb - 1) / vs2_eewb; + const uint8_t vd_split_num = (vs2_eewb + vd_eewb - 1) / vd_eewb; + const int32_t micro_vlmax = VLENB / std::max(vd_eewb, vs2_eewb); + int32_t remaining_vl = this->vl; + int32_t micro_vl = std::min(remaining_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (uint8_t i = 0; micro_vl > 0; i++) { + for (uint8_t j = 0; j < micro_vl; ++j) { + uint8_t vdRegIdx = i / vd_split_num; + uint8_t vs2RegIdx = i / vs2_split_num; + uint8_t vdElemIdx = j + micro_vlmax * (i % vd_split_num); + uint8_t vs2ElemIdx = j + micro_vlmax * (i % vs2_split_num); + microop = new %(class_name)sMicro(machInst, + vdRegIdx, vdElemIdx, vs2RegIdx, vs2ElemIdx); + microop->setFlag(IsDelayedCommit); + microop->setFlag(IsLoad); + this->microops.push_back(microop); + } + remaining_vl -= micro_vlmax; + micro_vl = std::min(remaining_vl, micro_vlmax); + } + + this->microops.front()->setFlag(IsFirstMicroop); + this->microops.back()->setFlag(IsLastMicroop); + this->flags[IsVector] = true; +} + +}}; + +def template VlIndexMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // rs1, vs2, vd, vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _vdRegIdx, uint8_t _vdElemIdx, + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _vdRegIdx, _vdElemIdx, _vs2RegIdx, _vs2ElemIdx) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _vdRegIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _vs2RegIdx]); + // We treat agnostic as undistrubed + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _vdRegIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsLoad] = true; + } + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VlIndexMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext *xc, + trace::InstRecord *traceData)const +{ + using vu = std::make_unsigned_t; + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + constexpr uint8_t elem_size = sizeof(Vd[0]); + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = elem_size; + const std::vector byte_enable(mem_size, true); + + size_t ei = this->vdRegIdx * VLENB / elem_size + this->vdElemIdx; + if (machInst.vm || elem_mask(v0, ei)) { + fault = xc->readMem(EA, Mem.as(), mem_size, + memAccessFlags, byte_enable); + if (fault != NoFault) + return fault; + %(memacc_code)s; /* Vd[this->vdElemIdx] = Mem[0]; */ + } + + %(op_wb)s; + return fault; +} + +}}; + +def template VlIndexMicroInitiateAcc {{ + +template +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu = std::make_unsigned_t; + Fault fault = NoFault; + Addr EA; + + %(op_src_decl)s; + %(op_rd)s; + constexpr uint8_t elem_size = sizeof(Vd[0]); + %(ea_code)s; // ea_code depends on elem_size + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = elem_size; + size_t ei = this->vdRegIdx * VLENB / elem_size + this->vdElemIdx; + bool need_load = machInst.vm || elem_mask(v0, ei); + const std::vector byte_enable(mem_size, need_load); + fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, byte_enable); + return fault; +} + +}}; + +def template VlIndexMicroCompleteAcc {{ + +template +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, + trace::InstRecord *traceData) const +{ + using vu = std::make_unsigned_t; + %(op_decl)s; + %(op_rd)s; + + constexpr uint8_t elem_size = sizeof(Vd[0]); + + RiscvISA::vreg_t old_vd; + decltype(Vd) old_Vd = nullptr; + // We treat agnostic as undistrubed + xc->getRegOperand(this, 2, &old_vd); + old_Vd = old_vd.as >(); + + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + memcpy(Vd, old_Vd, VLENB); + + size_t ei = this->vdRegIdx * VLENB / elem_size + this->vdElemIdx; + if (machInst.vm || elem_mask(v0, ei)) { + memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); + %(memacc_code)s; /* Vd[this->microIdx] = Mem[0]; */ + } + + %(op_wb)s; + return NoFault; +} + +}}; + +def template VsIndexConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + + const uint32_t vs3_eewb = sizeof(ElemType); + const uint32_t vs2_eewb = width_EEW(_machInst.width) / 8; + const uint8_t vs2_split_num = (vs3_eewb + vs2_eewb - 1) / vs2_eewb; + const uint8_t vs3_split_num = (vs2_eewb + vs3_eewb - 1) / vs3_eewb; + const int32_t micro_vlmax = VLENB / std::max(vs3_eewb, vs2_eewb); + int32_t remaining_vl = this->vl; + int32_t micro_vl = std::min(remaining_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (uint8_t i = 0; micro_vl > 0; i++) { + for (uint8_t j = 0; j < micro_vl; ++j) { + uint8_t vs3RegIdx = i / vs3_split_num; + uint8_t vs2RegIdx = i / vs2_split_num; + uint8_t vs3ElemIdx = j + micro_vlmax * (i % vs3_split_num); + uint8_t vs2ElemIdx = j + micro_vlmax * (i % vs2_split_num); + microop = new %(class_name)sMicro(machInst, + vs3RegIdx, vs3ElemIdx, vs2RegIdx, vs2ElemIdx); + microop->setFlag(IsDelayedCommit); + microop->setFlag(IsStore); + this->microops.push_back(microop); + } + remaining_vl -= micro_vlmax; + micro_vl = std::min(remaining_vl, micro_vlmax); + } + + this->microops.front()->setFlag(IsFirstMicroop); + this->microops.back()->setFlag(IsLastMicroop); + this->flags[IsVector] = true; +} + +}}; + +def template VsIndexMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // rs1, vs2, vs3, vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[0]; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _vs3RegIdx, _vs3ElemIdx, _vs2RegIdx, _vs2ElemIdx) + { + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _vs2RegIdx]); + // We treat agnostic as undistrubed + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _vs3RegIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsStore] = true; + } + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc(PacketPtr, ExecContext *, + trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VsIndexMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext *xc, + trace::InstRecord *traceData)const +{ + using vu = std::make_unsigned_t; + Fault fault = NoFault; + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + constexpr uint8_t elem_size = sizeof(Vs3[0]); + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + uint32_t mem_size = elem_size; + const std::vector byte_enable(mem_size, true); + + size_t ei = this->vs3RegIdx * VLENB / elem_size + this->vs3ElemIdx; + if (machInst.vm || elem_mask(v0, ei)) { + %(memacc_code)s; /* Mem[0] = Vs3[this->vs3ElemIdx] */ + fault = xc->writeMem(Mem.as(), mem_size, EA, + memAccessFlags, nullptr, byte_enable); + } + return fault; +} + +}}; + +def template VsIndexMicroInitiateAcc {{ + +template +Fault +%(class_name)s::initiateAcc(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu = std::make_unsigned_t; + Fault fault = NoFault; + Addr EA; + + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + constexpr uint8_t elem_size = sizeof(Vs3[0]); + RiscvISA::vreg_t tmp_v0; + uint8_t *v0; + if (!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + + constexpr uint8_t mem_size = elem_size; + const std::vector byte_enable(mem_size, true); + + size_t ei = this->vs3RegIdx * VLENB / elem_size + this->vs3ElemIdx; + if (machInst.vm || elem_mask(v0, ei)) { + %(memacc_code)s; /* Mem[0] = Vs3[this->vs3ElemIdx] */ + fault = xc->writeMem(Mem.as(), mem_size, EA, + memAccessFlags, nullptr, byte_enable); + } + return fault; +} + +}}; + +def template VsIndexMicroCompleteAcc {{ + +template +Fault +%(class_name)s::completeAcc(PacketPtr pkt, ExecContext* xc, + trace::InstRecord* traceData) const +{ + return NoFault; +} + +}}; + +def template VMemTemplateDecodeBlock {{ + +switch(machInst.vtype8.vsew) { + case 0b000: { + return new %(class_name)s(machInst); + } + case 0b001: { + return new %(class_name)s(machInst); + } + case 0b010: { + return new %(class_name)s(machInst); + } + case 0b011: { + return new %(class_name)s(machInst); + } + default: GEM5_UNREACHABLE; +} + +}}; diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh index e0a8494ece..1db6d6df3b 100644 --- a/src/arch/riscv/utility.hh +++ b/src/arch/riscv/utility.hh @@ -241,6 +241,61 @@ remu(T rs1, T rs2) return (rs2 == 0) ? rs1 : rs1 % rs2; } +/* +* Encode LMUL to lmul as follows: +* LMUL vlmul lmul +* 1 000 0 +* 2 001 1 +* 4 010 2 +* 8 011 3 +* - 100 - +* 1/8 101 -3 +* 1/4 110 -2 +* 1/2 111 -1 +* +* then, we can calculate VLMAX = vlen >> (vsew + 3 - lmul) +* e.g. vlen = 256 bits, SEW = 16, LMUL = 1/8 +* => VLMAX = vlen >> (1 + 3 - (-3)) +* = 256 >> 7 +* = 2 +* Ref: https://github.com/qemu/qemu/blob/5e9d14f2/target/riscv/cpu.h +*/ +inline uint64_t +vtype_VLMAX(const uint64_t vtype, const bool per_reg = false) +{ + int64_t lmul = (int64_t)sext<3>(bits(vtype, 2, 0)); + lmul = per_reg ? std::min(0, lmul) : lmul; + int64_t vsew = bits(vtype, 5, 3); + return gem5::RiscvISA::VLEN >> (vsew + 3 - lmul); +} + +inline uint64_t +width_EEW(uint64_t width) +{ + switch (width) { + case 0b000: return 8; + case 0b101: return 16; + case 0b110: return 32; + case 0b111: return 64; + default: GEM5_UNREACHABLE; + } +} + +/* + * Spec Section 4.5 + * Ref: + * https://github.com/qemu/qemu/blob/c7d773ae/target/riscv/vector_helper.c +*/ +template +inline int +elem_mask(const T* vs, const int index) +{ + static_assert(std::is_integral_v); + int idx = index / (sizeof(T)*8); + int pos = index % (sizeof(T)*8); + return (vs[idx] >> pos) & 1; +} + } // namespace RiscvISA } // namespace gem5 From a9f9c4d6d3850308697632b585c5c4bfad9fe7b6 Mon Sep 17 00:00:00 2001 From: Xuan Hu Date: Mon, 27 Feb 2023 21:31:22 +0800 Subject: [PATCH 145/693] arch-riscv: Add risc-v vector ext v1.0 arith insts support TODOs: + vcompress.vm Change-Id: I86eceae66e90380416fd3be2c10ad616512b5eba Co-authored-by: Yang Liu Co-authored-by: Fan Yang <1209202421@qq.com> Co-authored-by: Jerin Joy arch-riscv: Add LICENCE to template files Change-Id: I825e72bffb84cce559d2e4c1fc2246c3b05a1243 --- src/arch/riscv/insts/vector.cc | 107 + src/arch/riscv/insts/vector.hh | 200 ++ src/arch/riscv/isa/decoder.isa | 2054 +++++++++++++++++ src/arch/riscv/isa/formats/formats.isa | 1 + src/arch/riscv/isa/formats/vector_arith.isa | 1319 +++++++++++ src/arch/riscv/isa/templates/templates.isa | 30 + src/arch/riscv/isa/templates/vector_arith.isa | 1989 ++++++++++++++++ src/arch/riscv/isa/templates/vector_mem.isa | 28 + src/arch/riscv/regs/float.hh | 14 + src/arch/riscv/utility.hh | 481 ++++ 10 files changed, 6223 insertions(+) create mode 100644 src/arch/riscv/isa/formats/vector_arith.isa create mode 100644 src/arch/riscv/isa/templates/vector_arith.isa diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc index f2bde629e9..a1ccf402c9 100644 --- a/src/arch/riscv/insts/vector.cc +++ b/src/arch/riscv/insts/vector.cc @@ -122,6 +122,93 @@ VConfOp::generateZimmDisassembly() const return s.str(); } +std::string +VectorNonSplitInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +std::string VectorArithMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", "; + if (machInst.funct3 == 0x3) { + // OPIVI + ss << registerName(srcRegIdx(0)) << ", " << machInst.vecimm; + } else { + ss << registerName(srcRegIdx(1)) << ", " << registerName(srcRegIdx(0)); + } + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +std::string VectorArithMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", "; + if (machInst.funct3 == 0x3) { + // OPIVI + ss << registerName(srcRegIdx(0)) << ", " << machInst.vecimm; + } else { + ss << registerName(srcRegIdx(1)) << ", " << registerName(srcRegIdx(0)); + } + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +std::string VectorVMUNARY0MicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +std::string VectorVMUNARY0MacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +std::string VectorSlideMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", "; + if (machInst.funct3 == 0x3) { + ss << registerName(srcRegIdx(0)) << ", " << machInst.vecimm; + } else { + ss << registerName(srcRegIdx(1)) << ", " << registerName(srcRegIdx(0)); + } + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +std::string VectorSlideMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", "; + if (machInst.funct3 == 0x3) { + ss << registerName(srcRegIdx(0)) << ", " << machInst.vecimm; + } else { + ss << registerName(srcRegIdx(1)) << ", " << registerName(srcRegIdx(0)); + } + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + std::string VleMicroInst::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const { @@ -295,5 +382,25 @@ std::string VsIndexMicroInst::generateDisassembly(Addr pc, return ss.str(); } +std::string +VMvWholeMacroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + registerName(srcRegIdx(1)); + return ss.str(); +} + +std::string +VMvWholeMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + registerName(srcRegIdx(1)); + return ss.str(); +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index f989d7ffbf..5d0874a994 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -89,6 +89,24 @@ inline uint8_t checked_vtype(bool vill, uint8_t vtype) { return vtype; } +class VectorNonSplitInst : public RiscvStaticInst +{ + protected: + uint32_t vl; + uint8_t vtype; + VectorNonSplitInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : RiscvStaticInst(mnem, _machInst, __opClass), + vl(_machInst.vl), + vtype(checked_vtype(_machInst.vill, _machInst.vtype8)) + { + this->flags[IsVector] = true; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + class VectorMacroInst : public RiscvMacroInst { protected: @@ -170,6 +188,63 @@ class VectorArithMacroInst : public VectorMacroInst Addr pc, const loader::SymbolTable *symtab) const override; }; +class VectorVMUNARY0MicroInst : public VectorMicroInst +{ +protected: + VectorVMUNARY0MicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, + uint8_t _microIdx) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VectorVMUNARY0MacroInst : public VectorMacroInst +{ + protected: + VectorVMUNARY0MacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMacroInst(mnem, _machInst, __opClass) + { + this->flags[IsVector] = true; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VectorSlideMacroInst : public VectorMacroInst +{ + protected: + VectorSlideMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorMacroInst(mnem, _machInst, __opClass) + { + this->flags[IsVector] = true; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VectorSlideMicroInst : public VectorMicroInst +{ + protected: + uint8_t vdIdx; + uint8_t vs2Idx; + VectorSlideMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, + uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + , vdIdx(_vdIdx), vs2Idx(_vs2Idx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + class VectorMemMicroInst : public VectorMicroInst { protected: @@ -421,6 +496,131 @@ class VsIndexMicroInst : public VectorMemMicroInst Addr pc, const loader::SymbolTable *symtab) const override; }; +class VMvWholeMacroInst : public VectorArithMacroInst +{ + protected: + VMvWholeMacroInst(const char* mnem, ExtMachInst _machInst, + OpClass __opClass) + : VectorArithMacroInst(mnem, _machInst, __opClass) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +class VMvWholeMicroInst : public VectorArithMicroInst +{ + protected: + VMvWholeMicroInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, uint8_t _microVl, + uint8_t _microIdx) + : VectorArithMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + {} + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; +}; + +template +class VMaskMergeMicroInst : public VectorArithMicroInst +{ + private: + RegId srcRegIdxArr[NumVecInternalRegs]; + RegId destRegIdxArr[1]; + + public: + VMaskMergeMicroInst(ExtMachInst extMachInst, uint8_t _dstReg, + uint8_t _numSrcs) + : VectorArithMicroInst("vmask_mv_micro", extMachInst, + VectorIntegerArithOp, 0, 0) + { + setRegIdxArrays( + reinterpret_cast( + &std::remove_pointer_t::srcRegIdxArr), + reinterpret_cast( + &std::remove_pointer_t::destRegIdxArr)); + + _numSrcRegs = 0; + _numDestRegs = 0; + + setDestRegIdx(_numDestRegs++, vecRegClass[_dstReg]); + _numTypedDestRegs[VecRegClass]++; + for (uint8_t i=0; i<_numSrcs; i++) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[VecMemInternalReg0 + i]); + } + } + + Fault execute(ExecContext* xc, trace::InstRecord* traceData) + const override { + vreg_t tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); + auto Vd = tmp_d0.as(); + constexpr uint8_t elems_per_vreg = VLENB / sizeof(ElemType); + size_t bit_cnt = elems_per_vreg; + vreg_t tmp_s; + xc->getRegOperand(this, 0, &tmp_s); + auto s = tmp_s.as(); + // cp the first result and tail + memcpy(Vd, s, VLENB); + for (uint8_t i = 1; i < this->_numSrcRegs; i++) { + xc->getRegOperand(this, i, &tmp_s); + s = tmp_s.as(); + if constexpr (elems_per_vreg < 8) { + constexpr uint8_t m = (1 << elems_per_vreg) - 1; + const uint8_t mask = m << (i * elems_per_vreg % 8); + // clr & ext bits + Vd[bit_cnt/8] ^= Vd[bit_cnt/8] & mask; + Vd[bit_cnt/8] |= s[bit_cnt/8] & mask; + bit_cnt += elems_per_vreg; + } else { + constexpr uint8_t byte_offset = elems_per_vreg / 8; + memcpy(Vd + i * byte_offset, s + i * byte_offset, byte_offset); + } + } + xc->setRegOperand(this, 0, &tmp_d0); + if (traceData) + traceData->setData(vecRegClass, &tmp_d0); + return NoFault; + } + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)); + for (uint8_t i = 0; i < this->_numSrcRegs; i++) { + ss << ", " << registerName(srcRegIdx(i)); + } + ss << ", offset:" << VLENB / sizeof(ElemType); + return ss.str(); + } +}; + +class VxsatMicroInst : public VectorArithMicroInst +{ + private: + bool* vxsat; + public: + VxsatMicroInst(bool* Vxsat, ExtMachInst extMachInst) + : VectorArithMicroInst("vxsat_micro", extMachInst, + VectorIntegerArithOp, 0, 0) + { + vxsat = Vxsat; + } + Fault execute(ExecContext* xc, trace::InstRecord* traceData) + const override + { + xc->setMiscReg(MISCREG_VXSAT,*vxsat); + auto vcsr = xc->readMiscReg(MISCREG_VCSR); + xc->setMiscReg(MISCREG_VCSR, ((vcsr&~1)|*vxsat)); + return NoFault; + } + std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) + const override + { + std::stringstream ss; + ss << mnemonic << ' ' << "VXSAT" << ", " << (*vxsat ? "0x1" : "0x0"); + return ss.str(); + } +}; } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 0288f37ad8..2b46752ffe 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -2281,6 +2281,2060 @@ decode QUADRANT default Unknown::unknown() { } 0x15: decode FUNCT3 { + // OPIVV + 0x0: decode VFUNCT6 { + format VectorIntFormat { + 0x0: vadd_vv({{ + Vd_vu[i] = Vs2_vu[i] + Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x2: vsub_vv({{ + Vd_vu[i] = Vs2_vu[i] - Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x4: vminu_vv({{ + Vd_vu[i] = Vs2_vu[i] < Vs1_vu[i] ? + Vs2_vu[i] : Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x5: vmin_vv({{ + Vd_vi[i] = Vs2_vi[i] < Vs1_vi[i] ? + Vs2_vi[i] : Vs1_vi[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x6: vmaxu_vv({{ + Vd_vu[i] = Vs2_vu[i] > Vs1_vu[i] ? + Vs2_vu[i] : Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x7: vmax_vv({{ + Vd_vi[i] = Vs2_vi[i] > Vs1_vi[i] ? + Vs2_vi[i] : Vs1_vi[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x9: vand_vv({{ + Vd_vu[i] = Vs2_vu[i] & Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0xa: vor_vv({{ + Vd_vu[i] = Vs2_vu[i] | Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0xb: vxor_vv({{ + Vd_vu[i] = Vs2_vu[i] ^ Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + } + 0x0c: VectorGatherFormat::vrgather_vv({{ + for (uint32_t i = 0; i < microVl; i++) { + uint32_t ei = i + vs1_idx * vs1_elems + vs1_bias; + if (this->vm || elem_mask(v0, ei)) { + const uint64_t idx = Vs1_vu[i] + - vs2_elems * vs2_idx; + auto res = (Vs1_vu[i] >= vlmax) ? 0 + : (idx < vs2_elems) ? Vs2_vu[idx] + : Vs3_vu[i]; + Vd_vu[i] = res; + } + } + }}, OPIVV, VectorMiscOp); + 0x0e: VectorGatherFormat::vrgatherei16_vv({{ + for (uint32_t i = 0; i < microVl; i++) { + uint32_t ei = i + vs1_idx * vs1_elems + vs1_bias; + if (this->vm || elem_mask(v0, ei)) { + const uint16_t idx = Vs1_uh[i + vs1_bias] + - vs2_elems * vs2_idx; + auto res = (Vs1_uh[i + vs1_bias] >= vlmax) ? 0 + : (idx < vs2_elems) ? Vs2_vu[idx] + : Vs3_vu[i + vd_bias]; + Vd_vu[i + vd_bias] = res; + } + } + }}, OPIVV, VectorMiscOp); + format VectorIntFormat { + 0x10: decode VM { + 0x0: vadc_vvm({{ + Vd_vi[i] = Vs2_vi[i] + Vs1_vi[i] + + elem_mask(v0, ei); + }}, OPIVV, VectorIntegerArithOp); + // the unmasked versions (vm=1) are reserved + } + 0x12: decode VM { + 0x0: vsbc_vvm({{ + Vd_vi[i] = Vs2_vi[i] - Vs1_vi[i] + - elem_mask(v0, ei); + }}, OPIVV, VectorIntegerArithOp); + // the unmasked versions (vm=1) are reserved + } + 0x17: decode VM { + 0x0: vmerge_vvm({{ + Vd_vu[i] = elem_mask(v0, ei) + ? Vs1_vu[i] + : Vs2_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + 0x1: decode VS2 { + 0x0: vmv_v_v({{ + Vd_vu[i] = Vs1_vu[i]; + }}, OPIVV, VectorIntegerArithOp); + } + } + } + format VectorIntVxsatFormat{ + 0x20: vsaddu_vv({{ + Vd_vu[i] = sat_addu(Vs2_vu[i], Vs1_vu[i], + vxsatptr); + }}, OPIVV, VectorIntegerArithOp); + 0x21: vsadd_vv({{ + Vd_vu[i] = sat_add(Vs2_vu[i], Vs1_vu[i], + vxsatptr); + }}, OPIVV, VectorIntegerArithOp); + 0x22: vssubu_vv({{ + Vd_vu[i] = sat_subu(Vs2_vu[i], Vs1_vu[i], + vxsatptr); + }}, OPIVV, VectorIntegerArithOp); + 0x23: vssub_vv({{ + Vd_vu[i] = sat_sub(Vs2_vu[i], Vs1_vu[i], + vxsatptr); + }}, OPIVV, VectorIntegerArithOp); + 0x27: vsmul_vv({{ + vi max = std::numeric_limits::max(); + vi min = std::numeric_limits::min(); + bool overflow = Vs1_vi[i] == Vs2_vi[i] && + Vs1_vi[i] == min; + __int128_t result = (__int128_t)Vs1_vi[i] * + (__int128_t)Vs2_vi[i]; + result = int_rounding<__int128_t>( + result, 0 /* TODO */, sew - 1); + result = result >> (sew - 1); + if (overflow) { + result = max; + *vxsatptr = true; + } + + Vd_vi[i] = (vi)result; + }}, OPIVV, VectorIntegerArithOp); + } + format VectorIntFormat { + 0x25: vsll_vv({{ + Vd_vu[i] = Vs2_vu[i] << (Vs1_vu[i] & (sew - 1)); + }}, OPIVV, VectorIntegerArithOp); + 0x28: vsrl_vv({{ + Vd_vu[i] = Vs2_vu[i] >> (Vs1_vu[i] & (sew - 1)); + }}, OPIVV, VectorIntegerArithOp); + 0x29: vsra_vv({{ + Vd_vi[i] = Vs2_vi[i] >> (Vs1_vu[i] & (sew - 1)); + }}, OPIVV, VectorIntegerArithOp); + 0x2a: vssrl_vv({{ + int sh = Vs1_vu[i] & (sew - 1); + __uint128_t val = Vs2_vu[i]; + + val = int_rounding<__uint128_t>(val, + xc->readMiscReg(MISCREG_VXRM), sh); + Vd_vu[i] = val >> sh; + }}, OPIVV, VectorIntegerArithOp); + 0x2b: vssra_vv({{ + int sh = Vs1_vi[i] & (sew - 1); + __int128_t val = Vs2_vi[i]; + + val = int_rounding<__int128_t>(val, + xc->readMiscReg(MISCREG_VXRM), sh); + Vd_vi[i] = val >> sh; + }}, OPIVV, VectorIntegerArithOp); + } + format VectorReduceIntWideningFormat { + 0x30: vwredsumu_vs({{ + Vd_vwu[0] = reduce_loop(std::plus(), + Vs1_vwu, Vs2_vu); + }}, OPIVV, VectorIntegerReduceOp); + 0x31: vwredsum_vs({{ + Vd_vwu[0] = reduce_loop(std::plus(), + Vs1_vwi, Vs2_vi); + }}, OPIVV, VectorIntegerReduceOp); + } + format VectorIntMaskFormat { + 0x11: decode VM { + 0x0: vmadc_vvm({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + carry_out(Vs2_vu[i], Vs1_vu[i], + elem_mask(v0, ei))); + }}, OPIVV, VectorIntegerArithOp); + 0x1: vmadc_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + carry_out(Vs2_vu[i], Vs1_vu[i])); + }}, OPIVV, VectorIntegerArithOp); + } + 0x13: decode VM { + 0x0: vmsbc_vvm({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + borrow_out(Vs2_vi[i], Vs1_vi[i], + elem_mask(v0, ei))); + }}, OPIVV, VectorIntegerArithOp); + 0x1: vmsbc_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + borrow_out(Vs2_vi[i], Vs1_vi[i])); + }}, OPIVV, VectorIntegerArithOp); + } + 0x18: vmseq_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] == Vs1_vu[i])); + }}, OPIVV, VectorIntegerArithOp); + 0x19: vmsne_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] != Vs1_vu[i])); + }}, OPIVV, VectorIntegerArithOp); + 0x1a: vmsltu_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] < Vs1_vu[i])); + }}, OPIVV, VectorIntegerArithOp); + 0x1b: vmslt_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] < Vs1_vi[i])); + }}, OPIVV, VectorIntegerArithOp); + 0x1c: vmsleu_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] <= Vs1_vu[i])); + }}, OPIVV, VectorIntegerArithOp); + 0x1d: vmsle_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] <= Vs1_vi[i])); + }}, OPIVV, VectorIntegerArithOp); + } + format VectorIntNarrowingFormat { + 0x2c: vnsrl_wv({{ + Vd_vu[i + offset] = (vu)(Vs2_vwu[i] >> + ((vwu)Vs1_vu[i + offset] & (sew * 2 - 1))); + }}, OPIVV, VectorIntegerArithOp); + 0x2d: vnsra_wv({{ + Vd_vi[i + offset] = (vi)(Vs2_vwi[i] >> + ((vwu)Vs1_vu[i + offset] & (sew * 2 - 1))); + }}, OPIVV, VectorIntegerArithOp); + 0x2e: vnclipu_wv({{ + vu max = std::numeric_limits::max(); + uint64_t sign_mask = + std::numeric_limits::max() << sew; + __uint128_t res = Vs2_vwu[i]; + unsigned shift = Vs1_vu[i + offset] & ((sew * 2) - 1); + + res = int_rounding<__uint128_t>( + res, 0 /* TODO */, shift) >> shift; + + if (res & sign_mask) { + res = max; + // TODO: vxsat + } + + Vd_vu[i + offset] = (vu)res; + }}, OPIVV, VectorIntegerArithOp); + 0x2f: vnclip_wv({{ + vi max = std::numeric_limits::max(); + vi min = std::numeric_limits::min(); + __int128_t res = Vs2_vwi[i]; + unsigned shift = Vs1_vi[i + offset] & ((sew * 2) - 1); + + res = int_rounding<__int128_t>( + res, 0 /* TODO */, shift) >> shift; + + if (res < min) { + res = min; + // TODO: vxsat + } else if (res > max) { + res = max; + // TODO: vxsat + } + + Vd_vi[i + offset] = (vi)res; + }}, OPIVV, VectorIntegerArithOp); + } + } + // OPFVV + 0x1: decode VFUNCT6 { + 0x00: VectorFloatFormat::vfadd_vv({{ + auto fd = fadd(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x01: VectorReduceFloatFormat::vfredusum_vs({{ + Vd_vu[0] = reduce_loop([](const vu& src1, const vu& src2) { + return fadd(ftype(src1), ftype(src2)); + }, Vs1_vu, Vs2_vu); + }}, OPFVV, VectorFloatReduceOp); + 0x02: VectorFloatFormat::vfsub_vv({{ + auto fd = fsub(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x03: VectorReduceFloatFormat::vfredosum_vs({{ + Vd_vu[0] = reduce_loop([](const vu& src1, const vu& src2) { + return fadd(ftype(src1), ftype(src2)); + }, Vs1_vu, Vs2_vu); + }}, OPFVV, VectorFloatReduceOp); + 0x04: VectorFloatFormat::vfmin_vv({{ + auto fd = fmin(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x05: VectorReduceFloatFormat::vfredmin_vs({{ + Vd_vu[0] = reduce_loop([](const vu& src1, const vu& src2) { + return fmin(ftype(src1), ftype(src2)); + }, Vs1_vu, Vs2_vu); + }}, OPFVV, VectorFloatReduceOp); + 0x06: VectorFloatFormat::vfmax_vv({{ + auto fd = fmax(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x07: VectorReduceFloatFormat::vfredmax_vs({{ + Vd_vu[0] = reduce_loop([](const vu& src1, const vu& src2) { + return fmax(ftype(src1), ftype(src2)); + }, Vs1_vu, Vs2_vu); + }}, OPFVV, VectorFloatReduceOp); + 0x08: VectorFloatFormat::vfsgnj_vv({{ + Vd_vu[i] = fsgnj(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]), + false, false).v; + }}, OPFVV, VectorFloatArithOp); + 0x09: VectorFloatFormat::vfsgnjn_vv({{ + Vd_vu[i] = fsgnj(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]), + true, false).v; + }}, OPFVV, VectorFloatArithOp); + 0x0a: VectorFloatFormat::vfsgnjx_vv({{ + Vd_vu[i] = fsgnj(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]), + false, true).v; + }}, OPFVV, VectorFloatArithOp); + // VWFUNARY0 + 0x10: decode VS1 { + 0x00: decode VM { + // The encodings corresponding to the masked versions + // (vm=0) of vfmv.f.s are reserved + 0x1: VectorNonSplitFormat::vfmv_f_s({{ + freg_t fd = freg(Vs2_vu[0]); + Fd_bits = fd.v; + }}, OPFVV, VectorMiscOp); + } + } + 0x12: decode VS1 { + format VectorFloatCvtFormat { + 0x00: vfcvt_xu_f_v({{ + Vd_vu[i] = f_to_ui(ftype(Vs2_vu[i]), + softfloat_roundingMode); + }}, OPFVV, VectorFloatConvertOp); + 0x01: vfcvt_x_f_v({{ + Vd_vu[i] = f_to_i(ftype(Vs2_vu[i]), + softfloat_roundingMode); + }}, OPFVV, VectorFloatConvertOp); + 0x02: vfcvt_f_xu_v({{ + auto fd = ui_to_f(Vs2_vu[i]); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x03: vfcvt_f_x_v({{ + auto fd = i_to_f(Vs2_vu[i]); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x06: vfcvt_rtz_xu_f_v({{ + Vd_vu[i] = f_to_ui(ftype(Vs2_vu[i]), + softfloat_round_minMag); + }}, OPFVV, VectorFloatConvertOp); + 0x07: vfcvt_rtz_x_f_v({{ + Vd_vu[i] = f_to_i(ftype(Vs2_vu[i]), + softfloat_round_minMag); + }}, OPFVV, VectorFloatConvertOp); + } + format VectorFloatWideningCvtFormat { + 0x08: vfwcvt_xu_f_v({{ + Vd_vwu[i] = f_to_wui( + ftype(Vs2_vu[i + offset]), + softfloat_roundingMode); + }}, OPFVV, VectorFloatConvertOp); + 0x09: vfwcvt_x_f_v({{ + Vd_vwu[i] = f_to_wi( + ftype(Vs2_vu[i + offset]), + softfloat_roundingMode); + }}, OPFVV, VectorFloatConvertOp); + 0x0a: vfwcvt_f_xu_v({{ + auto fd = ui_to_wf(Vs2_vu[i + offset]); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x0b: vfwcvt_f_x_v({{ + auto fd = i_to_wf(Vs2_vu[i + offset]); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x0c: vfwcvt_f_f_v({{ + auto fd = f_to_wf( + ftype(Vs2_vu[i + offset])); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x0e: vfwcvt_rtz_xu_f_v({{ + Vd_vwu[i] = f_to_wui( + ftype(Vs2_vu[i + offset]), + softfloat_round_minMag); + }}, OPFVV, VectorFloatConvertOp); + 0x0f: vfwcvt_rtz_x_f_v({{ + Vd_vwu[i] = f_to_wi( + ftype(Vs2_vu[i + offset]), + softfloat_round_minMag); + }}, OPFVV, VectorFloatConvertOp); + } + format VectorFloatNarrowingCvtFormat { + 0x10: vfncvt_xu_f_w({{ + Vd_vu[i + offset] = f_to_nui( + ftype(Vs2_vwu[i]), + softfloat_roundingMode); + }}, OPFVV, VectorFloatConvertOp); + 0x11: vfncvt_x_f_w({{ + Vd_vu[i + offset] = f_to_ni( + ftype(Vs2_vwu[i]), + softfloat_roundingMode); + }}, OPFVV, VectorFloatConvertOp); + 0x12: vfncvt_f_xu_w({{ + auto fd = ui_to_nf(Vs2_vwu[i]); + Vd_vu[i + offset] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x13: vfncvt_f_x_w({{ + auto fd = i_to_nf(Vs2_vwu[i]); + Vd_vu[i + offset] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x14: vfncvt_f_f_w({{ + auto fd = f_to_nf(ftype(Vs2_vwu[i])); + Vd_vu[i + offset] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x15: vfncvt_rod_f_f_w({{ + softfloat_roundingMode = softfloat_round_odd; + auto fd = f_to_nf(ftype(Vs2_vwu[i])); + Vd_vu[i + offset] = fd.v; + }}, OPFVV, VectorFloatConvertOp); + 0x16: vfncvt_rtz_xu_f_w({{ + Vd_vu[i + offset] = f_to_nui( + ftype(Vs2_vwu[i]), + softfloat_round_minMag); + }}, OPFVV, VectorFloatConvertOp); + 0x17: vfncvt_rtz_x_f_w({{ + Vd_vu[i + offset] = f_to_ni( + ftype(Vs2_vwu[i]), + softfloat_round_minMag); + }}, OPFVV, VectorFloatConvertOp); + } + } + 0x13: decode VS1 { + format VectorFloatCvtFormat { + 0x00: vfsqrt_v({{ + auto fd = fsqrt(ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x04: vfrsqrt7_v({{ + auto fd = frsqrte7(ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x05: vfrec7_v({{ + auto fd = frecip7(ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x10: vfclass_v({{ + auto fd = fclassify(ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + } + } + + format VectorFloatMaskFormat { + 0x18: vmfeq_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + feq(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]))); + }}, OPFVV, VectorFloatArithOp); + 0x19: vmfle_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + fle(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]))); + }}, OPFVV, VectorFloatArithOp); + 0x1b: vmflt_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + flt(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]))); + }}, OPFVV, VectorFloatArithOp); + 0x1c: vmfne_vv({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + !feq(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i]))); + }}, OPFVV, VectorFloatArithOp); + } + format VectorFloatFormat { + 0x20: vfdiv_vv({{ + auto fd = fdiv(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x24: vfmul_vv({{ + auto fd = fmul(ftype(Vs2_vu[i]), + ftype(Vs1_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x28: vfmadd_vv({{ + auto fd = fmadd(ftype(Vs3_vu[i]), + ftype(Vs1_vu[i]), + ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x29: vfnmadd_vv({{ + auto fd = fmadd(fneg(ftype(Vs3_vu[i])), + ftype(Vs1_vu[i]), + fneg(ftype(Vs2_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x2a: vfmsub_vv({{ + auto fd = fmadd(ftype(Vs3_vu[i]), + ftype(Vs1_vu[i]), + fneg(ftype(Vs2_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x2b: vfnmsub_vv({{ + auto fd = fmadd(fneg(ftype(Vs3_vu[i])), + ftype(Vs1_vu[i]), + ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x2c: vfmacc_vv({{ + auto fd = fmadd(ftype(Vs1_vu[i]), + ftype(Vs2_vu[i]), + ftype(Vs3_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x2d: vfnmacc_vv({{ + auto fd = fmadd(fneg(ftype(Vs1_vu[i])), + ftype(Vs2_vu[i]), + fneg(ftype(Vs3_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x2e: vfmsac_vv({{ + auto fd = fmadd(ftype(Vs1_vu[i]), + ftype(Vs2_vu[i]), + fneg(ftype(Vs3_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x2f: vfnmsac_vv({{ + auto fd = fmadd(fneg(ftype(Vs1_vu[i])), + ftype(Vs2_vu[i]), + ftype(Vs3_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x31: VectorReduceFloatWideningFormat::vfwredusum_vs({{ + Vd_vwu[0] = reduce_loop( + [](const vwu& src1, const vu& src2) { + return fadd( + ftype(src1), + f_to_wf(ftype(src2)) + ); + }, Vs1_vwu, Vs2_vu); + }}, OPFVV, VectorFloatReduceOp); + 0x33: VectorReduceFloatWideningFormat::vfwredosum_vs({{ + Vd_vwu[0] = reduce_loop( + [](const vwu& src1, const vu& src2) { + return fadd( + ftype(src1), + f_to_wf(ftype(src2)) + ); + }, Vs1_vwu, Vs2_vu); + }}, OPFVV, VectorFloatReduceOp); + } + format VectorFloatWideningFormat { + 0x30: vfwadd_vv({{ + auto fd = fadd( + fwiden(ftype(Vs2_vu[i + offset])), + fwiden(ftype(Vs1_vu[i + offset]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x32: vfwsub_vv({{ + auto fd = fsub( + fwiden(ftype(Vs2_vu[i + offset])), + fwiden(ftype(Vs1_vu[i + offset]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x34: vfwadd_wv({{ + auto fd = fadd( + ftype(Vs2_vwu[i]), + fwiden(ftype(Vs1_vu[i + offset]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x36: vfwsub_wv({{ + auto fd = fsub( + ftype(Vs2_vwu[i]), + fwiden(ftype(Vs1_vu[i + offset]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x38: vfwmul_vv({{ + auto fd = fmul( + fwiden(ftype(Vs2_vu[i + offset])), + fwiden(ftype(Vs1_vu[i + offset]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x3c: vfwmacc_vv({{ + auto fd = fmadd( + fwiden(ftype(Vs1_vu[i + offset])), + fwiden(ftype(Vs2_vu[i + offset])), + ftype(Vs3_vwu[i])); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x3d: vfwnmacc_vv({{ + auto fd = fmadd( + fwiden(fneg(ftype(Vs1_vu[i + offset]))), + fwiden(ftype(Vs2_vu[i + offset])), + fneg(ftype(Vs3_vwu[i]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x3e: vfwmsac_vv({{ + auto fd = fmadd( + fwiden(ftype(Vs1_vu[i + offset])), + fwiden(ftype(Vs2_vu[i + offset])), + fneg(ftype(Vs3_vwu[i]))); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + 0x3f: vfwnmsac_vv({{ + auto fd = fmadd( + fwiden(fneg(ftype(Vs1_vu[i + offset]))), + fwiden(ftype(Vs2_vu[i + offset])), + ftype(Vs3_vwu[i])); + Vd_vwu[i] = fd.v; + }}, OPFVV, VectorFloatArithOp); + } + } + // OPMVV + 0x2: decode VFUNCT6 { + format VectorReduceIntFormat { + 0x0: vredsum_vs({{ + Vd_vi[0] = + reduce_loop(std::plus(), Vs1_vi, Vs2_vi); + }}, OPMVV, VectorIntegerReduceOp); + 0x1: vredand_vs({{ + Vd_vi[0] = + reduce_loop(std::bit_and(), Vs1_vi, Vs2_vi); + }}, OPMVV, VectorIntegerReduceOp); + 0x2: vredor_vs({{ + Vd_vi[0] = + reduce_loop(std::bit_or(), Vs1_vi, Vs2_vi); + }}, OPMVV, VectorIntegerReduceOp); + 0x3: vredxor_vs({{ + Vd_vi[0] = + reduce_loop(std::bit_xor(), Vs1_vi, Vs2_vi); + }}, OPMVV, VectorIntegerReduceOp); + 0x4: vredminu_vs({{ + Vd_vu[0] = + reduce_loop([](const vu& src1, const vu& src2) { + return std::min(src1, src2); + }, Vs1_vu, Vs2_vu); + }}, OPMVV, VectorIntegerReduceOp); + 0x5: vredmin_vs({{ + Vd_vi[0] = + reduce_loop([](const vi& src1, const vi& src2) { + return std::min(src1, src2); + }, Vs1_vi, Vs2_vi); + }}, OPMVV, VectorIntegerReduceOp); + 0x6: vredmaxu_vs({{ + Vd_vu[0] = + reduce_loop([](const vu& src1, const vu& src2) { + return std::max(src1, src2); + }, Vs1_vu, Vs2_vu); + }}, OPMVV, VectorIntegerReduceOp); + 0x7: vredmax_vs({{ + Vd_vi[0] = + reduce_loop([](const vi& src1, const vi& src2) { + return std::max(src1, src2); + }, Vs1_vi, Vs2_vi); + }}, OPMVV, VectorIntegerReduceOp); + } + format VectorIntFormat { + 0x8: vaaddu_vv({{ + __uint128_t res = (__uint128_t)Vs2_vu[i] + Vs1_vu[i]; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vu[i] = res >> 1; + }}, OPMVV, VectorIntegerArithOp); + 0x9: vaadd_vv({{ + __uint128_t res = (__uint128_t)Vs2_vi[i] + Vs1_vi[i]; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vi[i] = res >> 1; + }}, OPMVV, VectorIntegerArithOp); + 0xa: vasubu_vv({{ + __uint128_t res = (__uint128_t)Vs2_vu[i] - Vs1_vu[i]; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vu[i] = res >> 1; + }}, OPMVV, VectorIntegerArithOp); + 0xb: vasub_vv({{ + __uint128_t res = (__uint128_t)Vs2_vi[i] - Vs1_vi[i]; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vi[i] = res >> 1; + }}, OPMVV, VectorIntegerArithOp); + } + // VWXUNARY0 + 0x10: decode VS1 { + 0x00: decode VM { + // The encodings corresponding to the masked versions + // (vm=0) of vmv.x.s are reserved. + 0x1: VectorNonSplitFormat::vmv_x_s({{ + Rd_ud = Vs2_vi[0]; + }}, OPMVV, VectorMiscOp); + } + 0x10: Vector1Vs1RdMaskFormat::vcpop_m({{ + uint64_t popcount = 0; + for (uint32_t i = 0; i < (uint32_t)machInst.vl; i++) { + bool vs2_lsb = elem_mask(Vs2_vu, i); + if(this->vm){ + popcount += vs2_lsb; + }else{ + bool do_mask = elem_mask(v0, i); + popcount += (vs2_lsb && do_mask); + } + } + Rd_vu = popcount; + }}, OPMVV, VectorMiscOp); + 0x11: Vector1Vs1RdMaskFormat::vfirst_m({{ + int64_t pos = -1; + for (uint32_t i = 0; i < (uint32_t)machInst.vl; i++) { + if(this->vm == 0){ + if(elem_mask(v0, i)==0){ + continue; + } + } + bool vs2_lsb = elem_mask(Vs2_vu, i); + if (vs2_lsb) { + pos = i; + break; + } + } + Rd_vu = pos; + }}, OPMVV, VectorMiscOp); + } + 0x12: decode VS1 { + format VectorIntExtFormat { + 0x02: vzext_vf8({{ + Vd_vu[i] = Vs2_vextu[i + offset]; + }}, OPMVV, VectorIntegerExtensionOp); + 0x03: vsext_vf8({{ + Vd_vi[i] = Vs2_vext[i + offset]; + }}, OPMVV, VectorIntegerExtensionOp); + 0x04: vzext_vf4({{ + Vd_vu[i] = Vs2_vextu[i + offset]; + }}, OPMVV, VectorIntegerExtensionOp); + 0x05: vsext_vf4({{ + Vd_vi[i] = Vs2_vext[i + offset]; + }}, OPMVV, VectorIntegerExtensionOp); + 0x06: vzext_vf2({{ + Vd_vu[i] = Vs2_vextu[i + offset]; + }}, OPMVV, VectorIntegerExtensionOp); + 0x07: vsext_vf2({{ + Vd_vi[i] = Vs2_vext[i + offset]; + }}, OPMVV, VectorIntegerExtensionOp); + } + } + 0x14: decode VS1 { + 0x01: Vector1Vs1VdMaskFormat::vmsbf_m({{ + bool has_one = false; + for (uint32_t i = 0; i < (uint32_t)machInst.vl; i++) { + bool vs2_lsb = elem_mask(Vs2_vu, i); + bool do_mask = elem_mask(v0, i); + if(this->vm||(this->vm == 0&&do_mask)){ + uint64_t res = 0; + if (!has_one && !vs2_lsb) { + res = 1; + } else if(!has_one && vs2_lsb) { + has_one = true; + } + Vd_ub[i/8] = ASSIGN_VD_BIT(i, res); + } + } + }}, OPMVV, VectorMiscOp); + 0x02: Vector1Vs1VdMaskFormat::vmsof_m({{ + bool has_one = false; + for (uint32_t i = 0; i < (uint32_t)machInst.vl; i++) { + bool vs2_lsb = elem_mask(Vs2_vu, i); + bool do_mask = elem_mask(v0, i); + if(this->vm||(this->vm == 0&&do_mask)){ + uint64_t res = 0; + if(!has_one && vs2_lsb) { + has_one = true; + res = 1; + } + Vd_ub[i/8] = ASSIGN_VD_BIT(i, res); + } + } + }}, OPMVV, VectorMiscOp); + 0x03: Vector1Vs1VdMaskFormat::vmsif_m({{ + bool has_one = false; + for (uint32_t i = 0; i < (uint32_t)machInst.vl; i++) { + bool vs2_lsb = elem_mask(Vs2_vu, i); + bool do_mask = elem_mask(v0, i); + if(this->vm||(this->vm == 0&&do_mask)){ + uint64_t res = 0; + if (!has_one && !vs2_lsb) { + res = 1; + } else if(!has_one && vs2_lsb) { + has_one = true; + res = 1; + } + Vd_ub[i/8] = ASSIGN_VD_BIT(i, res); + } + } + }}, OPMVV, VectorMiscOp); + 0x10: ViotaFormat::viota_m({{ + RiscvISAInst::VecRegContainer tmp_s2; + xc->getRegOperand(this, 2, + &tmp_s2); + auto Vs2bit = tmp_s2.as(); + for (uint32_t i = 0; i < this->microVl; i++) { + uint32_t ei = i + + vtype_VLMAX(vtype, true) * this->microIdx; + bool vs2_lsb = elem_mask(Vs2bit, ei); + bool do_mask = elem_mask(v0, ei); + bool has_one = false; + if (this->vm || (do_mask && !this->vm)) { + if (vs2_lsb) { + has_one = true; + } + } + bool use_ori = (!this->vm) && !do_mask; + if(use_ori == false){ + Vd_vu[i] = *cnt; + } + if (has_one) { + *cnt = *cnt+1; + } + } + }}, OPMVV, VectorMiscOp); + 0x11: VectorIntFormat::vid_v({{ + Vd_vu[i] = ei; + }}, OPMVV, VectorMiscOp); + } + format VectorMaskFormat { + 0x18: vmandn_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + elem_mask(Vs2_vu, i) & !elem_mask(Vs1_vu, i)); + }}, OPMVV, VectorMiscOp); + 0x19: vmand_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + elem_mask(Vs2_vu, i) & elem_mask(Vs1_vu, i)); + }}, OPMVV, VectorMiscOp); + 0x1a: vmor_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + elem_mask(Vs2_vu, i) | elem_mask(Vs1_vu, i)); + }}, OPMVV, VectorMiscOp); + 0x1b: vmxor_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + elem_mask(Vs2_vu, i) ^ elem_mask(Vs1_vu, i)); + }}, OPMVV, VectorMiscOp); + 0x1c: vmorn_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + elem_mask(Vs2_vu, i) | !elem_mask(Vs1_vu, i)); + }}, OPMVV, VectorMiscOp); + 0x1d: vmnand_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + !(elem_mask(Vs2_vu, i) & elem_mask(Vs1_vu, i))); + }}, OPMVV, VectorMiscOp); + 0x1e: vmnor_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + !(elem_mask(Vs2_vu, i) | elem_mask(Vs1_vu, i))); + }}, OPMVV, VectorMiscOp); + 0x1f: vmxnor_mm({{ + Vd_ub[i/8] = ASSIGN_VD_BIT(i, + !(elem_mask(Vs2_vu, i) ^ elem_mask(Vs1_vu, i))); + }}, OPMVV, VectorMiscOp); + } + format VectorIntFormat { + 0x20: vdivu_vv({{ + if (Vs1_vu[i] == 0) + Vd_vu[i] = (vu)-1; + else + Vd_vu[i] = Vs2_vu[i] / Vs1_vu[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x21: vdiv_vv({{ + if (Vs1_vi[i] == 0) + Vd_vi[i] = -1; + else if (Vs2_vi[i] == std::numeric_limits::min() + && Vs1_vi[i] == -1) + Vd_vi[i] = Vs2_vi[i]; + else + Vd_vi[i] = Vs2_vi[i] / Vs1_vi[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x22: vremu_vv({{ + if (Vs1_vu[i] == 0) { + Vd_vu[i] = Vs2_vu[i]; + } else { + Vd_vu[i] = Vs2_vu[i] % Vs1_vu[i]; + } + }}, OPMVV, VectorIntegerArithOp); + 0x23: vrem_vv({{ + if (Vs1_vi[i] == 0) { + Vd_vi[i] = Vs2_vi[i]; + } else if (Vs2_vi[i] == std::numeric_limits::min() + && Vs1_vi[i] == -1) { + Vd_vi[i] = 0; + } else { + Vd_vi[i] = Vs2_vi[i] % Vs1_vi[i]; + } + }}, OPMVV, VectorIntegerArithOp); + 0x24: vmulhu_vv({{ + if (sew < 64) { + Vd_vu[i] = ((uint64_t)Vs2_vu[i] * Vs1_vu[i]) + >> sew; + } else { + Vd_vu[i] = mulhu_64(Vs2_vu[i], Vs1_vu[i]); + } + }}, OPMVV, VectorIntegerArithOp); + 0x25: vmul_vv({{ + Vd_vi[i] = Vs2_vi[i] * Vs1_vi[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x26: vmulhsu_vv({{ + if (sew < 64) { + Vd_vi[i] = ((int64_t)Vs2_vi[i] * + (uint64_t)Vs1_vu[i]) + >> sew; + } else { + Vd_vi[i] = mulhsu_64(Vs2_vi[i], Vs1_vu[i]); + } + }}, OPMVV, VectorIntegerArithOp); + 0x27: vmulh_vv({{ + if (sew < 64) { + Vd_vi[i] = ((int64_t)Vs2_vi[i] * Vs1_vi[i]) + >> sew; + } else { + Vd_vi[i] = mulh_64(Vs2_vi[i], Vs1_vi[i]); + } + }}, OPMVV, VectorIntegerArithOp); + 0x29: vmadd_vv({{ + Vd_vi[i] = Vs3_vi[i] * Vs1_vi[i] + Vs2_vi[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x2b: vnmsub_vv({{ + Vd_vi[i] = -(Vs3_vi[i] * Vs1_vi[i]) + Vs2_vi[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x2d: vmacc_vv({{ + Vd_vi[i] = Vs2_vi[i] * Vs1_vi[i] + Vs3_vi[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x2f: vnmsac_vv({{ + Vd_vi[i] = -(Vs2_vi[i] * Vs1_vi[i]) + Vs3_vi[i]; + }}, OPMVV, VectorIntegerArithOp); + } + format VectorIntWideningFormat { + 0x30: vwaddu_vv({{ + Vd_vwu[i] = vwu(Vs2_vu[i + offset]) + + vwu(Vs1_vu[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x31: vwadd_vv({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) + + vwi(Vs1_vi[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x32: vwsubu_vv({{ + Vd_vwu[i] = vwu(Vs2_vu[i + offset]) + - vwu(Vs1_vu[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x33: vwsub_vv({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) + - vwi(Vs1_vi[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x34: vwaddu_wv({{ + Vd_vwu[i] = Vs2_vwu[i] + vwu(Vs1_vu[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x35: vwadd_wv({{ + Vd_vwi[i] = Vs2_vwi[i] + vwi(Vs1_vi[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x36: vwsubu_wv({{ + Vd_vwu[i] = Vs2_vwu[i] - vwu(Vs1_vu[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x37: vwsub_wv({{ + Vd_vwi[i] = Vs2_vwi[i] - vwi(Vs1_vi[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x38: vwmulu_vv({{ + Vd_vwu[i] = vwu(Vs2_vu[i + offset]) + * vwu(Vs1_vu[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x3a: vwmulsu_vv({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) + * vwu(Vs1_vu[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x3b: vwmul_vv({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) + * vwi(Vs1_vi[i + offset]); + }}, OPMVV, VectorIntegerArithOp); + 0x3c: vwmaccu_vv({{ + Vd_vwu[i] = vwu(Vs1_vu[i + offset]) + * vwu(Vs2_vu[i + offset]) + + Vs3_vwu[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x3d: vwmacc_vv({{ + Vd_vwi[i] = vwi(Vs1_vi[i + offset]) + * vwi(Vs2_vi[i + offset]) + + Vs3_vwi[i]; + }}, OPMVV, VectorIntegerArithOp); + 0x3f: vwmaccsu_vv({{ + Vd_vwi[i] = vwi(Vs1_vi[i + offset]) + * vwu(Vs2_vu[i + offset]) + + Vs3_vwi[i]; + }}, OPMVV, VectorIntegerArithOp); + } + } + // OPIVI + 0x3: decode VFUNCT6 { + format VectorIntFormat { + 0x00: vadd_vi({{ + Vd_vi[i] = Vs2_vi[i] + (vi)sext<5>(SIMM5); + }}, OPIVI, VectorIntegerArithOp); + 0x03: vrsub_vi({{ + Vd_vi[i] = (vi)sext<5>(SIMM5) - Vs2_vi[i]; + }}, OPIVI, VectorIntegerArithOp); + 0x09: vand_vi({{ + Vd_vi[i] = Vs2_vi[i] & (vi)sext<5>(SIMM5); + }}, OPIVI, VectorIntegerArithOp); + 0x0a: vor_vi({{ + Vd_vi[i] = Vs2_vi[i] | (vi)sext<5>(SIMM5); + }}, OPIVI, VectorIntegerArithOp); + 0x0b: vxor_vi({{ + Vd_vi[i] = Vs2_vi[i] ^ (vi)sext<5>(SIMM5); + }}, OPIVI, VectorIntegerArithOp); + } + 0x0c: VectorGatherFormat::vrgather_vi({{ + for (uint32_t i = 0; i < microVl; i++) { + uint32_t ei = i + vs1_idx * vs1_elems + vs1_bias; + if (this->vm || elem_mask(v0, ei)) { + const uint64_t idx = + (uint64_t)sext<5>(SIMM5) - vs2_elems * vs2_idx; + Vd_vu[i] = ((uint64_t)sext<5>(SIMM5) >= vlmax) ? 0 + : (idx < vs2_elems) ? Vs2_vu[idx] + : Vs3_vu[i]; + } + } + }}, OPIVI, VectorMiscOp); + 0x0e: VectorSlideUpFormat::vslideup_vi({{ + const int offset = (int)(uint64_t)(SIMM5); + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vdIdx - vs2Idx; + const int offsetInVreg = offset - vregOffset * microVlmax; + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int vs2Offset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int elemOffset = vdOffset + vdIdx * microVlmax; + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + if (this->vm || elem_mask(v0, i + elemOffset)) { + Vd_vu[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + } + } + }}, OPIVI, VectorMiscOp); + 0x0f: VectorSlideDownFormat::vslidedown_vi({{ + const int offset = (int)(uint64_t)(SIMM5); + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vs2Idx - vdIdx; + const int offsetInVreg = offset - vregOffset * microVlmax; + const int numVs2s = vtype_regs_per_group(vtype); + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const bool needZeroTail = numVs2s == vs2Idx + 1; + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int vs2Offset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int elemIdxBase = vdIdx * microVlmax; + vreg_t resVreg; + auto res = resVreg.as(); + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + res[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + if (needZeroTail) { + for (int i = upperBound + vdOffset; + i < microVlmax; i++) { + res[i] = 0; + } + } + for (int i = vdOffset; i < microVl ; i++) { + if (vm || elem_mask(v0, i + elemIdxBase)) { + Vd_vu[i] = res[i]; + } + } + } + }}, OPIVI, VectorMiscOp); + format VectorIntFormat { + 0x10: decode VM { + 0x0: vadc_vim({{ + Vd_vi[i] = Vs2_vi[i] + + (vi)sext<5>(SIMM5) + elem_mask(v0, ei); + }}, OPIVI, VectorIntegerArithOp); + // the unmasked versions (vm=1) are reserved + } + 0x17: decode VM { + 0x0: vmerge_vim({{ + Vd_vi[i] = elem_mask(v0, ei) + ? (vi)sext<5>(SIMM5) + : Vs2_vi[i]; + }}, OPIVI, VectorIntegerArithOp); + 0x1: vmv_v_i({{ + Vd_vi[i] = (vi)sext<5>(SIMM5); + }}, OPIVI, VectorIntegerArithOp); + } + } + format VectorIntVxsatFormat{ + 0x20: vsaddu_vi({{ + Vd_vu[i] = sat_addu(Vs2_vu[i], (vu)SIMM5, + vxsatptr); + }}, OPIVI, VectorIntegerArithOp); + 0x21: vsadd_vi({{ + Vd_vu[i] = sat_add(Vs2_vu[i], (vu)SIMM5, + vxsatptr); + }}, OPIVI, VectorIntegerArithOp); + } + format VectorIntFormat { + 0x25: vsll_vi({{ + Vd_vu[i] = Vs2_vu[i] << ((vu)SIMM5 & (sew - 1) & 0x1f); + }}, OPIVI, VectorIntegerArithOp); + 0x28: vsrl_vi({{ + Vd_vu[i] = Vs2_vu[i] >> ((vu)SIMM5 & (sew - 1) & 0x1f); + }}, OPIVI, VectorIntegerArithOp); + 0x2a: vssrl_vi({{ + int sh = SIMM5 & (vtype_SEW(vtype) - 1); + __uint128_t res = Vs2_vu[i]; + + res = int_rounding<__uint128_t>( + res, 0 /* TODO */, sh) >> sh; + + Vd_vu[i] = res; + }}, OPIVI, VectorIntegerArithOp); + 0x29: vsra_vi({{ + Vd_vi[i] = Vs2_vi[i] >> ((vu)SIMM5 & (sew - 1) & 0x1f); + }}, OPIVI, VectorIntegerArithOp); + 0x2b: vssra_vi({{ + int sh = SIMM5 & (sew - 1); + __int128_t val = Vs2_vi[i]; + + val = int_rounding<__int128_t>(val, + xc->readMiscReg(MISCREG_VXRM), sh); + Vd_vi[i] = val >> sh; + }}, OPIVI, VectorIntegerArithOp); + } + // According to Spec Section 16.6, + // vm must be 1 (unmasked) in vmvr.v instructions. + 0x27: decode VM { 0x1: decode SIMM3 { + format VMvWholeFormat { + 0x0: vmv1r_v({{ + Vd_ud[i] = Vs2_ud[i]; + }}, OPIVI, VectorMiscOp); + 0x1: vmv2r_v({{ + Vd_ud[i] = Vs2_ud[i]; + }}, OPIVI, VectorMiscOp); + 0x3: vmv4r_v({{ + Vd_ud[i] = Vs2_ud[i]; + }}, OPIVI, VectorMiscOp); + 0x7: vmv8r_v({{ + Vd_ud[i] = Vs2_ud[i]; + }}, OPIVI, VectorMiscOp); + } + }} + format VectorIntMaskFormat { + 0x11: decode VM { + 0x0: vmadc_vim({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + carry_out(Vs2_vi[i], (vi)sext<5>(SIMM5), + elem_mask(v0, ei))); + }}, OPIVI, VectorIntegerArithOp); + 0x1: vmadc_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + carry_out(Vs2_vi[i], (vi)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + } + 0x18: vmseq_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] == (vi)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + 0x19: vmsne_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] != (vi)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + 0x1c: vmsleu_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] <= (vu)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + 0x1d: vmsle_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] <= (vi)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + 0x1e: vmsgtu_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] > (vu)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + 0x1f: vmsgt_vi({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] > (vi)sext<5>(SIMM5))); + }}, OPIVI, VectorIntegerArithOp); + } + format VectorIntNarrowingFormat { + 0x2c: vnsrl_wi({{ + Vd_vu[i + offset] = (vu)(Vs2_vwu[i] >> + ((vwu)SIMM5 & (sew * 2 - 1))); + }}, OPIVI, VectorIntegerArithOp); + 0x2d: vnsra_wi({{ + Vd_vi[i + offset] = (vi)(Vs2_vwi[i] >> + ((vwu)SIMM5 & (sew * 2 - 1))); + }}, OPIVI, VectorIntegerArithOp); + 0x2e: vnclipu_wi({{ + vu max = std::numeric_limits::max(); + uint64_t sign_mask = + std::numeric_limits::max() << sew; + __uint128_t res = Vs2_vwu[i]; + unsigned shift = VS1 & ((sew * 2) - 1); + + res = int_rounding<__uint128_t>( + res, 0 /* TODO */, shift) >> shift; + + if (res & sign_mask) { + // TODO: vxsat + res = max; + } + + Vd_vu[i + offset] = (vu)res; + }}, OPIVI, VectorIntegerArithOp); + 0x2f: vnclip_wi({{ + vi max = std::numeric_limits::max(); + vi min = std::numeric_limits::min(); + __int128_t res = Vs2_vwi[i]; + unsigned shift = VS1 & ((sew * 2) - 1); + + res = int_rounding<__int128_t>( + res, 0 /* TODO */, shift) >> shift; + + if (res < min) { + res = min; + // TODO: vxsat + } else if (res > max) { + res = max; + // TODO: vxsat + } + + Vd_vi[i + offset] = (vi)res; + }}, OPIVI, VectorIntegerArithOp); + } + } + // OPIVX + 0x4: decode VFUNCT6 { + format VectorIntFormat { + 0x0: vadd_vx({{ + Vd_vu[i] = Vs2_vu[i] + Rs1_vu; + }}, OPIVX, VectorIntegerArithOp); + 0x2: vsub_vx({{ + Vd_vu[i] = Vs2_vu[i] - Rs1_vu; + }}, OPIVX, VectorIntegerArithOp); + 0x3: vrsub_vx({{ + Vd_vu[i] = Rs1_vu - Vs2_vu[i]; + }}, OPIVX, VectorIntegerArithOp); + 0x4: vminu_vx({{ + Vd_vu[i] = std::min(Vs2_vu[i], Rs1_vu); + }}, OPIVX, VectorIntegerArithOp); + 0x5: vmin_vx({{ + Vd_vi[i] = std::min(Vs2_vi[i], Rs1_vi); + }}, OPIVX, VectorIntegerArithOp); + 0x6: vmaxu_vx({{ + Vd_vu[i] = std::max(Vs2_vu[i], Rs1_vu); + }}, OPIVX, VectorIntegerArithOp); + 0x7: vmax_vx({{ + Vd_vi[i] = std::max(Vs2_vi[i], Rs1_vi); + }}, OPIVX, VectorIntegerArithOp); + 0x9: vand_vx({{ + Vd_vu[i] = Vs2_vu[i] & Rs1_vu; + }}, OPIVX, VectorIntegerArithOp); + 0xa: vor_vx({{ + Vd_vu[i] = Vs2_vu[i] | Rs1_vu; + }}, OPIVX, VectorIntegerArithOp); + 0xb: vxor_vx({{ + Vd_vu[i] = Vs2_vu[i] ^ Rs1_vu; + }}, OPIVX, VectorIntegerArithOp); + } + 0x0e: VectorSlideUpFormat::vslideup_vx({{ + const int offset = (int)Rs1_vu; + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vdIdx - vs2Idx; + const int offsetInVreg = offset - vregOffset * microVlmax; + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int vs2Offset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int elemOffset = vdOffset + vdIdx * microVlmax; + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + if (this->vm || elem_mask(v0, i + elemOffset)) { + Vd_vu[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + } + } + }}, OPIVX, VectorMiscOp); + 0x0f: VectorSlideDownFormat::vslidedown_vx({{ + const int offset = (int)Rs1_vu; + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vs2Idx - vdIdx; + const int offsetInVreg = offset - vregOffset * microVlmax; + const int numVs2s = vtype_regs_per_group(vtype); + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const bool needZeroTail = numVs2s == vs2Idx + 1; + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int vs2Offset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int elemIdxBase = vdIdx * microVlmax; + vreg_t resVreg; + auto res = resVreg.as(); + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + res[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + if (needZeroTail) { + for (int i = upperBound + vdOffset; + i < microVlmax; i++) { + res[i] = 0; + } + } + for (int i = vdOffset; i < microVl ; i++) { + if (vm || elem_mask(v0, i + elemIdxBase)) { + Vd_vu[i] = res[i]; + } + } + } + }}, OPIVX, VectorMiscOp); + 0x0c: VectorGatherFormat::vrgather_vx({{ + for (uint32_t i = 0; i < microVl; i++) { + uint32_t ei = i + vs1_idx * vs1_elems + vs1_bias; + if (this->vm || elem_mask(v0, ei)) { + const uint64_t idx = Rs1_vu - vs2_elems * vs2_idx; + Vd_vu[i] = (Rs1_vu >= vlmax) ? 0 + : (idx < vs2_elems) ? Vs2_vu[idx] + : Vs3_vu[i]; + } + } + }}, OPIVX, VectorMiscOp); + format VectorIntFormat { + 0x10: decode VM { + 0x0: vadc_vxm({{ + Vd_vi[i] = Vs2_vi[i] + Rs1_vi + elem_mask(v0, ei); + }}, OPIVX, VectorIntegerArithOp); + // the unmasked versions (vm=1) are reserved + } + 0x12: decode VM { + 0x0: vsbc_vxm({{ + Vd_vi[i] = Vs2_vi[i] - Rs1_vi - elem_mask(v0, ei); + }}, OPIVX, VectorIntegerArithOp); + // the unmasked versions (vm=1) are reserved + } + 0x17: decode VM { + 0x0: vmerge_vxm({{ + Vd_vu[i] = elem_mask(v0, ei) ? Rs1_vu : Vs2_vu[i]; + }}, OPIVX, VectorIntegerArithOp); + 0x1: decode VS2 { + 0x0: vmv_v_x({{ + Vd_vu[i] = Rs1_vu; + }}, OPIVX, VectorIntegerArithOp); + } + } + } + format VectorIntVxsatFormat{ + 0x20: vsaddu_vx({{ + Vd_vu[i] = sat_addu(Vs2_vu[i], Rs1_vu, + vxsatptr); + }}, OPIVX, VectorIntegerArithOp); + 0x21: vsadd_vx({{ + Vd_vu[i] = sat_add(Vs2_vu[i], Rs1_vu, + vxsatptr); + }}, OPIVX, VectorIntegerArithOp); + 0x22: vssubu_vx({{ + Vd_vu[i] = sat_subu(Vs2_vu[i], Rs1_vu, + vxsatptr); + }}, OPIVX, VectorIntegerArithOp); + 0x23: vssub_vx({{ + Vd_vu[i] = sat_sub(Vs2_vu[i], Rs1_vu, + vxsatptr); + }}, OPIVX, VectorIntegerArithOp); + 0x27: vsmul_vx({{ + vi max = std::numeric_limits::max(); + vi min = std::numeric_limits::min(); + bool overflow = Rs1_vi == Vs2_vi[i] && Rs1_vi == min; + __int128_t result = + (__int128_t)Rs1_vi * (__int128_t)Vs2_vi[i]; + result = int_rounding<__uint128_t>( + result, 0 /* TODO */, sew - 1); + result = result >> (sew - 1); + if (overflow) { + result = max; + *vxsatptr = true; + } + + Vd_vi[i] = (vi)result; + }}, OPIVX, VectorIntegerArithOp); + } + format VectorIntFormat { + 0x25: vsll_vx({{ + Vd_vu[i] = Vs2_vu[i] << (Rs1_vu & (sew - 1)); + }}, OPIVX, VectorIntegerArithOp); + 0x28: vsrl_vx({{ + Vd_vu[i] = Vs2_vu[i] >> (Rs1_vu & (sew - 1)); + }}, OPIVX, VectorIntegerArithOp); + 0x29: vsra_vx({{ + Vd_vi[i] = Vs2_vi[i] >> (Rs1_vu & (sew - 1)); + }}, OPIVX, VectorIntegerArithOp); + 0x2a: vssrl_vx({{ + int sh = Rs1_vu & (sew - 1); + __uint128_t val = Vs2_vu[i]; + + val = int_rounding<__uint128_t>(val, + xc->readMiscReg(MISCREG_VXRM), sh); + Vd_vu[i] = val >> sh; + }}, OPIVX, VectorIntegerArithOp); + 0x2b: vssra_vx({{ + int sh = Rs1_vu & (sew - 1); + __int128_t val = Vs2_vi[i]; + + val = int_rounding<__int128_t>(val, + xc->readMiscReg(MISCREG_VXRM), sh); + Vd_vi[i] = val >> sh; + }}, OPIVX, VectorIntegerArithOp); + } + format VectorIntNarrowingFormat { + 0x2c: vnsrl_wx({{ + Vd_vu[i + offset] = (vu)(Vs2_vwu[i] >> + ((vwu)Rs1_vu & (sew * 2 - 1))); + }}, OPIVX, VectorIntegerArithOp); + 0x2d: vnsra_wx({{ + Vd_vi[i + offset] = (vi)(Vs2_vwi[i] >> + ((vwu)Rs1_vu & (sew * 2 - 1))); + }}, OPIVX, VectorIntegerArithOp); + 0x2e: vnclipu_wx({{ + vu max = std::numeric_limits::max(); + uint64_t sign_mask = + std::numeric_limits::max() << sew; + __uint128_t res = Vs2_vwu[i]; + unsigned shift = Rs1_vu & ((sew * 2) - 1); + + res = int_rounding<__uint128_t>( + res, 0 /* TODO */, shift) >> shift; + + if (res & sign_mask) { + // TODO: vxsat + res = max; + } + + Vd_vu[i + offset] = (vu)res; + }}, OPIVX, VectorIntegerArithOp); + 0x2f: vnclip_wx({{ + vi max = std::numeric_limits::max(); + vi min = std::numeric_limits::min(); + __int128_t res = Vs2_vwi[i]; + unsigned shift = Rs1_vi & ((sew * 2) - 1); + + res = int_rounding<__int128_t>( + res, 0 /* TODO */, shift) >> shift; + + if (res < min) { + res = min; + // TODO: vxsat + } else if (res > max) { + res = max; + // TODO: vxsat + } + + Vd_vi[i + offset] = (vi)res; + }}, OPIVX, VectorIntegerArithOp); + } + + format VectorIntMaskFormat { + 0x11: decode VM { + 0x0: vmadc_vxm({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + carry_out(Vs2_vi[i], Rs1_vi, + elem_mask(v0, ei))); + }}, OPIVX, VectorIntegerArithOp); + 0x1: vmadc_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + carry_out(Vs2_vi[i], Rs1_vi)); + }}, OPIVX, VectorIntegerArithOp); + } + 0x13: decode VM { + 0x0: vmsbc_vxm({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + borrow_out(Vs2_vi[i], Rs1_vi, + elem_mask(v0, ei))); + }}, OPIVX, VectorIntegerArithOp); + 0x1: vmsbc_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + borrow_out(Vs2_vi[i], Rs1_vi)); + }}, OPIVX, VectorIntegerArithOp); + } + 0x18: vmseq_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] == Rs1_vu)); + }}, OPIVX, VectorIntegerArithOp); + 0x19: vmsne_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] != Rs1_vu)); + }}, OPIVX, VectorIntegerArithOp); + 0x1a: vmsltu_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] < Rs1_vu)); + }}, OPIVX, VectorIntegerArithOp); + 0x1b: vmslt_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] < Rs1_vi)); + }}, OPIVX, VectorIntegerArithOp); + 0x1c: vmsleu_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] <= Rs1_vu)); + }}, OPIVX, VectorIntegerArithOp); + 0x1d: vmsle_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] <= Rs1_vi)); + }}, OPIVX, VectorIntegerArithOp); + 0x1e: vmsgtu_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vu[i] > Rs1_vu)); + }}, OPIVX, VectorIntegerArithOp); + 0x1f: vmsgt_vx({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + (Vs2_vi[i] > Rs1_vi)); + }}, OPIVX, VectorIntegerArithOp); + } + } + // OPFVF + 0x5: decode VFUNCT6 { + format VectorFloatFormat{ + 0x00: vfadd_vf({{ + auto fd = fadd(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x02: vfsub_vf({{ + auto fd = fsub(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x04: vfmin_vf({{ + auto fd = fmin(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x06: vfmax_vf({{ + auto fd = fmax(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x08: vfsgnj_vf({{ + Vd_vu[i] = fsgnj(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)), + false, false).v; + }}, OPFVF, VectorFloatArithOp); + 0x09: vfsgnjn_vf({{ + Vd_vu[i] = fsgnj(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)), + true, false).v; + }}, OPFVF, VectorFloatArithOp); + 0x0a: vfsgnjx_vf({{ + Vd_vu[i] = fsgnj(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)), + false, true).v; + }}, OPFVF, VectorFloatArithOp); + } + 0x0e: VectorFloatSlideUpFormat::vfslide1up_vf({{ + const int offset = 1; + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vdIdx - vs2Idx; + const int offsetInVreg = offset - vregOffset * microVlmax; + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int vs2Offset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int elemOffset = vdOffset + vdIdx * microVlmax; + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + if (this->vm || elem_mask(v0, i + elemOffset)) { + Vd_vu[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + } + // TODO: dirty code + if (vdIdx == 0 && vs2Idx == 0 && + (this->vm || elem_mask(v0, 0))) { + tmp_d0.as()[0] = Rs1_vu; + } + } + }}, OPFVF, VectorMiscOp); + 0x0f: VectorFloatSlideDownFormat::vfslide1down_vf({{ + const int offset = 1; + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vs2Idx - vdIdx; + const int offsetInVreg = offset - vregOffset * microVlmax; + const int numVs2s = vtype_regs_per_group(vtype); + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const bool needZeroTail = numVs2s == vs2Idx + 1; + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int vs2Offset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int elemIdxBase = vdIdx * microVlmax; + vreg_t resVreg; + auto res = resVreg.as(); + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + res[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + if (needZeroTail) { + for (int i = upperBound + vdOffset; + i < microVlmax; i++) { + res[i] = 0; + } + } + for (int i = vdOffset; i < microVl ; i++) { + if (vm || elem_mask(v0, i + elemIdxBase)) { + Vd_vu[i] = (i + elemIdxBase != machInst.vl - 1) + ? res[i] + : Rs1_vu; + } + } + } + }}, OPFVF, VectorMiscOp); + // VRFUNARY0 + 0x10: decode VS2 { + 0x00: decode VM { + // The encodings corresponding to the masked versions + // (vm=0) of vfmv.s.f are reserved + 0x1: VectorNonSplitFormat::vfmv_s_f({{ + auto fd = ftype_freg(freg(Fs1_bits)); + Vd_vu[0] = fd.v; + }}, OPFVV, VectorMiscOp); + } + } + format VectorFloatFormat{ + 0x17: decode VM { + 0x0: vfmerge_vfm({{ + Vd_vu[i] = elem_mask(v0, ei) + ? ftype_freg(freg(Fs1_bits)).v + : Vs2_vu[i]; + }}, OPFVF, VectorFloatArithOp); + 0x1: vfmv_v_f({{ + auto fd = ftype_freg(freg(Fs1_bits)); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + } + } + format VectorFloatMaskFormat { + 0x18: vmfeq_vf({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + feq(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)))); + }}, OPFVF, VectorFloatArithOp); + 0x19: vmfle_vf({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + fle(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)))); + }}, OPFVF, VectorFloatArithOp); + 0x1b: vmflt_vf({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + flt(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)))); + }}, OPFVF, VectorFloatArithOp); + 0x1c: vmfne_vf({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + !feq(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits)))); + }}, OPFVF, VectorFloatArithOp); + 0x1d: vmfgt_vf({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + flt(ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i]))); + }}, OPFVF, VectorFloatArithOp); + 0x1f: vmfge_vf({{ + Vd_ub[(i + offset)/8] = ASSIGN_VD_BIT(i + offset, + fle(ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i]))); + }}, OPFVF, VectorFloatArithOp); + } + format VectorFloatFormat{ + 0x20: vfdiv_vf({{ + auto fd = fdiv(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x21: vfrdiv_vf({{ + auto fd = fdiv(ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x24: vfmul_vf({{ + auto fd = fmul(ftype(Vs2_vu[i]), + ftype_freg(freg(Fs1_bits))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x27: vfrsub_vf({{ + auto fd = fsub(ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x28: vfmadd_vf({{ + auto fd = fmadd(ftype(Vs3_vu[i]), + ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x29: vfnmadd_vf({{ + auto fd = fmadd(fneg(ftype(Vs3_vu[i])), + ftype_freg(freg(Fs1_bits)), + fneg(ftype(Vs2_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x2a: vfmsub_vf({{ + auto fd = fmadd(ftype(Vs3_vu[i]), + ftype_freg(freg(Fs1_bits)), + fneg(ftype(Vs2_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x2b: vfnmsub_vf({{ + auto fd = fmadd(fneg(ftype(Vs3_vu[i])), + ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x2c: vfmacc_vf({{ + auto fd = fmadd(ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i]), + ftype(Vs3_vu[i])); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x2d: vfnmacc_vf({{ + auto fd = fmadd( + fneg(ftype_freg(freg(Fs1_bits))), + ftype(Vs2_vu[i]), + fneg(ftype(Vs3_vu[i])) + ); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x2e: vfmsac_vf({{ + auto fd = fmadd(ftype_freg(freg(Fs1_bits)), + ftype(Vs2_vu[i]), + fneg(ftype(Vs3_vu[i]))); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x2f: vfnmsac_vf({{ + auto fd = fmadd( + fneg(ftype_freg(freg(Fs1_bits))), + ftype(Vs2_vu[i]), + ftype(Vs3_vu[i]) + ); + Vd_vu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + } + format VectorFloatWideningFormat { + 0x30: vfwadd_vf({{ + auto fd = fadd( + fwiden(ftype(Vs2_vu[i + offset])), + fwiden(ftype_freg(freg(Fs1_bits)))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x32: vfwsub_vf({{ + auto fd = fsub( + fwiden(ftype(Vs2_vu[i + offset])), + fwiden(ftype_freg(freg(Fs1_bits)))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x34: vfwadd_wf({{ + auto fd = fadd( + ftype(Vs2_vwu[i]), + fwiden(ftype_freg(freg(Fs1_bits)))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x36: vfwsub_wf({{ + auto fd = fsub( + ftype(Vs2_vwu[i]), + fwiden(ftype_freg(freg(Fs1_bits)))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x38: vfwmul_vf({{ + auto fd = fmul( + fwiden(ftype(Vs2_vu[i + offset])), + fwiden(ftype_freg(freg(Fs1_bits)))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x3c: vfwmacc_vf({{ + auto fd = fmadd( + fwiden(ftype_freg(freg(Fs1_bits))), + fwiden(ftype(Vs2_vu[i + offset])), + ftype(Vs3_vwu[i])); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x3d: vfwnmacc_vf({{ + auto fd = fmadd( + fwiden(fneg(ftype_freg(freg(Fs1_bits)))), + fwiden(ftype(Vs2_vu[i + offset])), + fneg(ftype(Vs3_vwu[i]))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x3e: vfwmsac_vf({{ + auto fd = fmadd( + fwiden(ftype_freg(freg(Fs1_bits))), + fwiden(ftype(Vs2_vu[i + offset])), + fneg(ftype(Vs3_vwu[i]))); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + 0x3f: vfwnmsac_vf({{ + auto fd = fmadd( + fwiden(fneg(ftype_freg(freg(Fs1_bits)))), + fwiden(ftype(Vs2_vu[i + offset])), + ftype(Vs3_vwu[i])); + Vd_vwu[i] = fd.v; + }}, OPFVF, VectorFloatArithOp); + } + } + // OPMVX + 0x6: decode VFUNCT6 { + format VectorIntFormat { + 0x08: vaaddu_vx({{ + __uint128_t res = (__uint128_t)Vs2_vu[i] + Rs1_vu; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vu[i] = res >> 1; + }}, OPMVX, VectorIntegerArithOp); + 0x09: vaadd_vx({{ + __uint128_t res = (__uint128_t)Vs2_vi[i] + Rs1_vi; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vi[i] = res >> 1; + }}, OPMVX, VectorIntegerArithOp); + } + 0x0e: VectorSlideUpFormat::vslide1up_vx({{ + const int offset = 1; + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vdIdx - vs2Idx; + const int offsetInVreg = offset - vregOffset * microVlmax; + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int vs2Offset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int elemOffset = vdOffset + vdIdx * microVlmax; + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + if (this->vm || elem_mask(v0, i + elemOffset)) { + Vd_vu[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + } + // TODO: dirty code + if (vdIdx == 0 && vs2Idx == 0 && + (this->vm || elem_mask(v0, 0))) { + tmp_d0.as()[0] = Rs1_vu; + } + } + }}, OPIVX, VectorMiscOp); + 0x0f: VectorSlideDownFormat::vslide1down_vx({{ + const int offset = 1; + const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int vregOffset = vs2Idx - vdIdx; + const int offsetInVreg = offset - vregOffset * microVlmax; + const int numVs2s = vtype_regs_per_group(vtype); + if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { + const bool needZeroTail = numVs2s == vs2Idx + 1; + const int upperBound = (offsetInVreg >= 0) + ? microVlmax - offsetInVreg + : microVlmax + offsetInVreg; + const int vdOffset = (offsetInVreg >= 0) + ? 0 + : -offsetInVreg; + const int vs2Offset = (offsetInVreg >= 0) + ? offsetInVreg + : 0; + const int elemIdxBase = vdIdx * microVlmax; + vreg_t resVreg; + auto res = resVreg.as(); + for (int i = 0; + i < upperBound && i + vdOffset < microVl; + i++) { + res[i + vdOffset] = Vs2_vu[i + vs2Offset]; + } + if (needZeroTail) { + for (int i = upperBound + vdOffset; + i < microVlmax; i++) { + res[i] = 0; + } + } + for (int i = vdOffset; i < microVl ; i++) { + if (vm || elem_mask(v0, i + elemIdxBase)) { + Vd_vu[i] = (i + elemIdxBase != machInst.vl - 1) + ? res[i] + : Rs1_vu; + } + } + } + }}, OPIVX, VectorMiscOp); + // VRXUNARY0 + 0x10: decode VS2 { + 0x00: decode VM { + // The encodings corresponding to the masked versions + // (vm=0) of vmv.s.x are reserved. + 0x1: VectorNonSplitFormat::vmv_s_x({{ + Vd_vu[0] = Rs1_vu; + }}, OPMVX, VectorMiscOp); + } + } + format VectorIntFormat { + 0x0a: vasubu_vx({{ + __uint128_t res = (__uint128_t)Vs2_vu[i] - Rs1_vu; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vu[i] = res >> 1; + }}, OPMVX, VectorIntegerArithOp); + 0x0b: vasub_vx({{ + __uint128_t res = (__uint128_t)Vs2_vi[i] - Rs1_vi; + res = int_rounding<__uint128_t>(res, 0 /* TODO */, 1); + Vd_vi[i] = res >> 1; + }}, OPMVX, VectorIntegerArithOp); + 0x20: vdivu_vx({{ + if (Rs1_vu == 0) + Vd_vu[i] = (vu)-1; + else + Vd_vu[i] = Vs2_vu[i] / Rs1_vu; + }}, OPMVX, VectorIntegerArithOp); + 0x21: vdiv_vx({{ + if (Rs1_vi == 0) + Vd_vi[i] = -1; + else if (Vs2_vi[i] == std::numeric_limits::min() + && Rs1_vi == -1) + Vd_vi[i] = Vs2_vi[i]; + else + Vd_vi[i] = Vs2_vi[i] / Rs1_vi; + }}, OPMVX, VectorIntegerArithOp); + 0x22: vremu_vx({{ + if (Rs1_vu == 0) + Vd_vu[i] = Vs2_vu[i]; + else + Vd_vu[i] = Vs2_vu[i] % Rs1_vu; + }}, OPMVX, VectorIntegerArithOp); + 0x23: vrem_vx({{ + if (Rs1_vi == 0) + Vd_vi[i] = Vs2_vi[i]; + else if (Vs2_vi[i] == std::numeric_limits::min() + && Rs1_vi == -1) + Vd_vi[i] = 0; + else + Vd_vi[i] = Vs2_vi[i] % Rs1_vi; + }}, OPMVX, VectorIntegerArithOp); + 0x24: vmulhu_vx({{ + if (sew < 64) + Vd_vu[i] = ((uint64_t)Vs2_vu[i] * Rs1_vu) + >> sew; + else + Vd_vu[i] = mulhu_64(Vs2_vu[i], Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x25: vmul_vx({{ + Vd_vi[i] = Vs2_vi[i] * Rs1_vi; + }}, OPMVX, VectorIntegerArithOp); + 0x26: vmulhsu_vx({{ + if (sew < 64) + Vd_vi[i] = ((int64_t)Vs2_vi[i] * + (uint64_t)Rs1_vu) + >> sew; + else + Vd_vi[i] = mulhsu_64(Vs2_vi[i], Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x27: vmulh_vx({{ + if (sew < 64) + Vd_vi[i] = ((int64_t)Vs2_vi[i] * Rs1_vi) + >> sew; + else + Vd_vi[i] = mulh_64(Vs2_vi[i], Rs1_vi); + }}, OPMVX, VectorIntegerArithOp); + 0x29: vmadd_vx({{ + Vd_vi[i] = Vs3_vi[i] * Rs1_vi + Vs2_vi[i]; + }}, OPMVX, VectorIntegerArithOp); + 0x2b: vnmsub_vx({{ + Vd_vi[i] = -(Vs3_vi[i] * Rs1_vi) + Vs2_vi[i]; + }}, OPMVX, VectorIntegerArithOp); + 0x2d: vmacc_vx({{ + Vd_vi[i] = Vs2_vi[i] * Rs1_vi + Vs3_vi[i]; + }}, OPMVX, VectorIntegerArithOp); + 0x2f: vnmsac_vx({{ + Vd_vi[i] = -(Vs2_vi[i] * Rs1_vi) + Vs3_vi[i]; + }}, OPMVX, VectorIntegerArithOp); + } + format VectorIntWideningFormat { + 0x30: vwaddu_vx({{ + Vd_vwu[i] = vwu(Vs2_vu[i + offset]) + vwu(Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x31: vwadd_vx({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) + vwi(Rs1_vi); + }}, OPMVX, VectorIntegerArithOp); + 0x32: vwsubu_vx({{ + Vd_vwu[i] = vwu(Vs2_vu[i + offset]) - vwu(Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x33: vwsub_vx({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) - vwi(Rs1_vi); + }}, OPMVX, VectorIntegerArithOp); + 0x34: vwaddu_wx({{ + Vd_vwu[i] = Vs2_vwu[i] + vwu(Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x35: vwadd_wx({{ + Vd_vwi[i] = Vs2_vwi[i] + vwi(Rs1_vi); + }}, OPMVX, VectorIntegerArithOp); + 0x36: vwsubu_wx({{ + Vd_vwu[i] = Vs2_vwu[i] - vwu(Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x37: vwsub_wx({{ + Vd_vwi[i] = Vs2_vwi[i] - vwi(Rs1_vi); + }}, OPMVX, VectorIntegerArithOp); + 0x38: vwmulu_vx({{ + Vd_vwu[i] = vwu(Vs2_vu[i + offset]) * vwu(Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x3a: vwmulsu_vx({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) * vwu(Rs1_vu); + }}, OPMVX, VectorIntegerArithOp); + 0x3b: vwmul_vx({{ + Vd_vwi[i] = vwi(Vs2_vi[i + offset]) * vwi(Rs1_vi); + }}, OPMVX, VectorIntegerArithOp); + 0x3c: vwmaccu_vx({{ + Vd_vwu[i] = vwu(Rs1_vu) * vwu(Vs2_vu[i + offset]) + + Vs3_vwu[i]; + }}, OPMVX, VectorIntegerArithOp); + 0x3d: vwmacc_vx({{ + Vd_vwi[i] = vwi(Rs1_vi) * vwi(Vs2_vi[i + offset]) + + Vs3_vwi[i]; + }}, OPMVX, VectorIntegerArithOp); + 0x3e: vwmaccus_vx({{ + Vd_vwi[i] = vwu(Rs1_vu) * vwi(Vs2_vi[i + offset]) + + Vs3_vwi[i]; + }}, OPMVX, VectorIntegerArithOp); + 0x3f: vwmaccsu_vx({{ + Vd_vwi[i] = vwi(Rs1_vi) * vwu(Vs2_vu[i + offset]) + + Vs3_vwi[i]; + }}, OPMVX, VectorIntegerArithOp); + } + } 0x7: decode BIT31 { format VConfOp { 0x0: vsetvli({{ diff --git a/src/arch/riscv/isa/formats/formats.isa b/src/arch/riscv/isa/formats/formats.isa index 4bdc3021d5..0102df17d7 100644 --- a/src/arch/riscv/isa/formats/formats.isa +++ b/src/arch/riscv/isa/formats/formats.isa @@ -38,6 +38,7 @@ ##include "amo.isa" ##include "bs.isa" ##include "vector_conf.isa" +##include "vector_arith.isa" ##include "vector_mem.isa" // Include formats for nonstandard extensions diff --git a/src/arch/riscv/isa/formats/vector_arith.isa b/src/arch/riscv/isa/formats/vector_arith.isa new file mode 100644 index 0000000000..c462e6c8d4 --- /dev/null +++ b/src/arch/riscv/isa/formats/vector_arith.isa @@ -0,0 +1,1319 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2022 PLCT Lab +// 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. + + +let {{ + def setDestWrapper(destRegId): + return "setDestRegIdx(_numDestRegs++, " + destRegId + ");\n" + \ + "_numTypedDestRegs[VecRegClass]++;\n" + def setSrcWrapper(srcRegId): + return "setSrcRegIdx(_numSrcRegs++, " + srcRegId + ");\n" + def setSrcVm(): + return "if (!this->vm)\n" + \ + " setSrcRegIdx(_numSrcRegs++, vecRegClass[0]);" + def vmDeclAndReadData(): + return ''' + [[maybe_unused]] RiscvISA::vreg_t tmp_v0; + [[maybe_unused]] uint8_t* v0; + if(!machInst.vm) { + xc->getRegOperand(this, _numSrcRegs-1, &tmp_v0); + v0 = tmp_v0.as(); + } + ''' + def copyOldVd(vd_idx): + return 'COPY_OLD_VD(%d);' % vd_idx + def loopWrapper(code, micro_inst = True): + if micro_inst: + upper_bound = "this->microVl" + else: + upper_bound = "(uint32_t)machInst.vl" + return ''' + for (uint32_t i = 0; i < %s; i++) { + %s + } + ''' % (upper_bound, code) + def maskCondWrapper(code): + return "if (this->vm || elem_mask(v0, ei)) {\n" + \ + code + "}\n" + def eiDeclarePrefix(code, widening = False): + if widening: + return ''' + uint32_t ei = i + micro_vlmax * this->microIdx; + ''' + code + else: + return ''' + uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + ''' + code + + def wideningOpRegisterConstraintChecks(code): + return ''' + const uint32_t num_microops = 1 << std::max(0, vtype_vlmul(machInst.vtype8) + 1); + if ((machInst.vd % alignToPowerOfTwo(num_microops)) != 0) { + std::string error = + csprintf("Unaligned Vd group in Widening op"); + return std::make_shared(error, machInst); + } + if ((machInst.vs2 <= machInst.vd) && (machInst.vd < (machInst.vs2 + num_microops - 1))) { + // A destination vector register group can overlap a source vector + // register group if The destination EEW is greater than the source + // EEW, the source EMUL is at least 1, and the overlap is in the + // highest- numbered part of the destination register group. + std::string error = + csprintf("Unsupported overlap in Vs2 and Vd for Widening op"); + return std::make_shared(error, machInst); + } + ''' + code + + def narrowingOpRegisterConstraintChecks(code): + return ''' + const uint32_t num_microops = 1 << std::max(0, vtype_vlmul(machInst.vtype8) + 1); + if ((machInst.vs2 % alignToPowerOfTwo(num_microops)) != 0) { + std::string error = + csprintf("Unaligned VS2 group in Narrowing op"); + return std::make_shared(error, machInst); + } + if ((machInst.vs2 < machInst.vd) && (machInst.vd <= (VS2 + num_microops - 1))) { + // A destination vector register group can overlap a source vector + // register group The destination EEW is smaller than the source EEW + // and the overlap is in the lowest-numbered part of the source + // register group + std::string error = + csprintf("Unsupported overlap in Vs2 and Vd for Narrowing op"); + return std::make_shared(error, machInst); + } + ''' + code + + def fflags_wrapper(code): + return ''' + RegVal FFLAGS = xc->readMiscReg(MISCREG_FFLAGS); + std::feclearexcept(FE_ALL_EXCEPT); + ''' + code + ''' + FFLAGS |= softfloat_exceptionFlags; + softfloat_exceptionFlags = 0; + xc->setMiscReg(MISCREG_FFLAGS, FFLAGS); + ''' +}}; + + +def format VectorIntFormat(code, category, *flags) {{ + macroop_class_name = 'VectorArithMacroInst' + microop_class_name = 'VectorArithMicroInst' + + if name == "vid_v" : + macroop_class_name = 'VectorVMUNARY0MacroInst' + microp_class_name = 'VectorVMUNARY0MicroInst' + + iop = InstObjParams(name, Name, macroop_class_name, {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + v0_required = inst_name not in ["vmv"] + mask_cond = v0_required and (inst_suffix not in ['vvm', 'vxm', 'vim']) + need_elem_idx = mask_cond or code.find("ei") != -1 + + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + + num_src_regs = 0 + + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + num_src_regs += 1 + + src1_reg_id = "" + if category in ["OPIVV", "OPMVV"]: + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx]" + num_src_regs += 1 + elif category in ["OPIVX", "OPMVX"]: + src1_reg_id = "intRegClass[_machInst.rs1]" + num_src_regs += 1 + elif category == "OPIVI": + pass + else: + error("not supported category for VectorIntFormat: %s" % category) + + old_vd_idx = num_src_regs + src3_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + if category != "OPIVI": + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + if v0_required: + set_src_reg_idx += setSrcVm() + + # code + if mask_cond: + code = maskCondWrapper(code) + if need_elem_idx: + code = eiDeclarePrefix(code) + code = loopWrapper(code) + + vm_decl_rd = "" + if v0_required: + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + microop_class_name, + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntMicroDeclare.subst(microiop) + \ + VectorIntMicroConstructor.subst(microiop) + \ + VectorIntMicroExecute.subst(microiop) + \ + VectorIntMacroDeclare.subst(iop) + \ + VectorIntMacroConstructor.subst(iop) + + decode_block = VectorIntDecodeBlock.subst(iop) +}}; + + +def format VectorIntExtFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + ext_div = int(inst_suffix[-1]) + + old_vd_idx = 1 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx / " + \ + str(ext_div) + "]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + set_src_reg_idx += setSrcVm() + + code = maskCondWrapper(code) + code = eiDeclarePrefix(code) + code = loopWrapper(code) + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'ext_div': ext_div}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntExtMicroDeclare.subst(microiop) + \ + VectorIntMicroConstructor.subst(microiop) + \ + VectorIntExtMicroExecute.subst(microiop) + \ + VectorIntExtMacroDeclare.subst(iop) + \ + VectorIntMacroConstructor.subst(iop) + + decode_block = VectorIntDecodeBlock.subst(iop) +}}; + +def format VectorIntWideningFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + v0_required = True + mask_cond = v0_required + need_elem_idx = mask_cond or code.find("ei") != -1 + old_vd_idx = 2 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src1_reg_id = "" + if category in ["OPIVV", "OPMVV"]: + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx / 2]" + elif category in ["OPIVX", "OPMVX"]: + src1_reg_id = "intRegClass[_machInst.rs1]" + else: + error("not supported category for VectorIntFormat: %s" % category) + src2_reg_id = "" + if inst_suffix in ["vv", "vx"]: + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx / 2]" + elif inst_suffix in ["wv", "wx"]: + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + if v0_required: + set_src_reg_idx += setSrcVm() + + # code + if mask_cond: + code = maskCondWrapper(code) + if need_elem_idx: + code = eiDeclarePrefix(code, widening=True) + code = loopWrapper(code) + + code = wideningOpRegisterConstraintChecks(code) + + vm_decl_rd = "" + if v0_required: + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntWideningMicroDeclare.subst(microiop) + \ + VectorIntWideningMicroConstructor.subst(microiop) + \ + VectorIntWideningMicroExecute.subst(microiop) + \ + VectorIntWideningMacroDeclare.subst(iop) + \ + VectorIntWideningMacroConstructor.subst(iop) + + decode_block = VectorIntWideningDecodeBlock.subst(iop) +}}; + +def format VectorIntNarrowingFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + mask_cond = True + need_elem_idx = True + + old_vd_idx = 2 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx / 2]" + if category in ["OPIVV"]: + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx / 2]" + elif category in ["OPIVX"]: + src1_reg_id = "intRegClass[_machInst.rs1]" + elif category == "OPIVI": + old_vd_idx = 1 + else: + error("not supported category for VectorIntFormat: %s" % category) + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vs3 + _microIdx / 2]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = "" + if category != "OPIVI": + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_src_reg_idx += setSrcVm() + # code + code = maskCondWrapper(code) + code = eiDeclarePrefix(code, widening=True) + code = loopWrapper(code) + code = narrowingOpRegisterConstraintChecks(code) + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx), + }, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntWideningMicroDeclare.subst(microiop) + \ + VectorIntWideningMicroConstructor.subst(microiop) + \ + VectorIntNarrowingMicroExecute.subst(microiop) + \ + VectorIntWideningMacroDeclare.subst(iop) + \ + VectorIntWideningMacroConstructor.subst(iop) + + decode_block = VectorIntWideningDecodeBlock.subst(iop) +}}; + +def format VectorIntMaskFormat(code, category, *flags) {{ + iop = InstObjParams(name, + Name, + 'VectorArithMacroInst', + {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + v0_required = not (inst_name in ["vmadc", "vmsbc"] \ + and inst_suffix in ["vv", "vx", "vi"]) + mask_cond = inst_name not in ['vmadc', 'vmsbc'] + need_elem_idx = mask_cond or code.find("ei") != -1 + + old_vd_idx = 2 + dest_reg_id = "vecRegClass[VecMemInternalReg0 + _microIdx]" + src1_reg_id = "" + if category == "OPIVV": + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx]" + elif category == "OPIVX": + src1_reg_id = "intRegClass[_machInst.rs1]" + elif category == "OPIVI": + old_vd_idx = 1 + else: + error("not supported category for VectorIntFormat: %s" % category) + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = "" + if category != "OPIVI": + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + if v0_required: + set_src_reg_idx += setSrcVm() + + #code + if mask_cond: + code = maskCondWrapper(code) + if need_elem_idx: + code = eiDeclarePrefix(code) + code = loopWrapper(code) + + vm_decl_rd = "" + if v0_required: + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntMaskMicroDeclare.subst(microiop) + \ + VectorIntMaskMicroConstructor.subst(microiop) + \ + VectorIntMaskMicroExecute.subst(microiop) + \ + VectorIntMaskMacroDeclare.subst(iop) + \ + VectorIntMaskMacroConstructor.subst(iop) + decode_block = VectorIntDecodeBlock.subst(iop) +}}; + +def format VectorGatherFormat(code, category, *flags) {{ + inst_name, inst_suffix = name.split("_", maxsplit=1) + if inst_name == "vrgatherei16": + idx_type = "uint16_t" + else: + idx_type = "elem_type" + iop = InstObjParams(name, Name, 'VectorArithMacroInst', + {'idx_type': idx_type, + 'code': code}, + flags) + old_vd_idx = 2 + dest_reg_id = "vecRegClass[_machInst.vd + vd_idx]" + src1_reg_id = "" + if category in ["OPIVV"]: + src1_reg_id = "vecRegClass[_machInst.vs1 + vs1_idx]" + elif category in ["OPIVX"]: + src1_reg_id = "intRegClass[_machInst.rs1]" + elif category == "OPIVI": + old_vd_idx = 1 + else: + error("not supported category for VectorIntFormat: %s" % category) + src2_reg_id = "vecRegClass[_machInst.vs2 + vs2_idx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + vd_idx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + if category != "OPIVI": + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + set_src_reg_idx += setSrcVm() + + # code + + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'idx_type': idx_type}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorGatherMicroDeclare.subst(microiop) + \ + VectorGatherMicroConstructor.subst(microiop) + \ + VectorGatherMicroExecute.subst(microiop) + \ + VectorGatherMacroDeclare.subst(iop) + \ + VectorGatherMacroConstructor.subst(iop) + + decode_block = VectorGatherDecodeBlock.subst(iop) + +}}; + +def format VectorFloatFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + v0_required = inst_name not in ["vfmv"] + mask_cond = v0_required and (inst_suffix not in ['vvm', 'vfm']) + need_elem_idx = mask_cond or code.find("ei") != -1 + + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src1_reg_id = "" + if category == "OPFVV": + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx]" + elif category == "OPFVF": + src1_reg_id = "floatRegClass[_machInst.rs1]" + else: + error("not supported category for VectorFloatFormat: %s" % category) + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + if v0_required: + set_src_reg_idx += setSrcVm() + # code + if mask_cond: + code = maskCondWrapper(code) + if need_elem_idx: + code = eiDeclarePrefix(code) + code = loopWrapper(code) + code = fflags_wrapper(code) + + vm_decl_rd = "" + if v0_required: + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorFloatMicroDeclare.subst(microiop) + \ + VectorFloatMicroConstructor.subst(microiop) + \ + VectorFloatMicroExecute.subst(microiop) + \ + VectorFloatMacroDeclare.subst(iop) + \ + VectorFloatMacroConstructor.subst(iop) + + decode_block = VectorFloatDecodeBlock.subst(iop) +}}; + +def format VectorFloatCvtFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + + old_vd_idx = 1 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + set_src_reg_idx += setSrcVm() + code = maskCondWrapper(code) + code = eiDeclarePrefix(code) + code = loopWrapper(code) + code = fflags_wrapper(code) + + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorFloatCvtMicroDeclare.subst(microiop) + \ + VectorFloatMicroConstructor.subst(microiop) + \ + VectorFloatMicroExecute.subst(microiop) + \ + VectorFloatCvtMacroDeclare.subst(iop) + \ + VectorFloatMacroConstructor.subst(iop) + + decode_block = VectorFloatDecodeBlock.subst(iop) +}}; + +def format VectorFloatWideningFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + v0_required = True + mask_cond = v0_required + need_elem_idx = mask_cond or code.find("ei") != -1 + + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src1_reg_id = "" + if category in ["OPFVV"]: + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx / 2]" + elif category in ["OPFVF"]: + src1_reg_id = "floatRegClass[_machInst.rs1]" + else: + error("not supported category for VectorFloatFormat: %s" % category) + src2_reg_id = "" + if inst_suffix in ["vv", "vf"]: + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx / 2]" + elif inst_suffix in ["wv", "wf"]: + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + if v0_required: + set_src_reg_idx += setSrcVm() + + # code + if mask_cond: + code = maskCondWrapper(code) + if need_elem_idx: + code = eiDeclarePrefix(code, widening=True) + code = loopWrapper(code) + code = fflags_wrapper(code) + + code = wideningOpRegisterConstraintChecks(code) + + vm_decl_rd = "" + if v0_required: + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntWideningMicroDeclare.subst(microiop) + \ + VectorIntWideningMicroConstructor.subst(microiop) + \ + VectorFloatWideningMicroExecute.subst(microiop) + \ + VectorIntWideningMacroDeclare.subst(iop) + \ + VectorIntWideningMacroConstructor.subst(iop) + + decode_block = VectorFloatWideningDecodeBlock.subst(iop) +}}; + +def format VectorFloatWideningCvtFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + + old_vd_idx = 1 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx / 2]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + set_src_reg_idx += setSrcVm() + code = maskCondWrapper(code) + code = eiDeclarePrefix(code) + code = loopWrapper(code) + code = fflags_wrapper(code) + + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorFloatCvtMicroDeclare.subst(microiop) + \ + VectorFloatMicroConstructor.subst(microiop) + \ + VectorFloatWideningMicroExecute.subst(microiop) + \ + VectorFloatCvtMacroDeclare.subst(iop) + \ + VectorIntWideningMacroConstructor.subst(iop) + + decode_block = VectorFloatWideningDecodeBlock.subst(iop) +}}; + +def format VectorFloatNarrowingCvtFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + + old_vd_idx = 1 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx / 2]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx / 2]" + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + set_src_reg_idx += setSrcVm() + code = maskCondWrapper(code) + code = eiDeclarePrefix(code) + code = loopWrapper(code) + code = fflags_wrapper(code) + code = narrowingOpRegisterConstraintChecks(code) + + vm_decl_rd = vmDeclAndReadData() + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorFloatCvtMicroDeclare.subst(microiop) + \ + VectorFloatMicroConstructor.subst(microiop) + \ + VectorFloatNarrowingMicroExecute.subst(microiop) + \ + VectorFloatCvtMacroDeclare.subst(iop) + \ + VectorIntWideningMacroConstructor.subst(iop) + + decode_block = VectorFloatWideningDecodeBlock.subst(iop) +}}; + +def format VectorFloatMaskFormat(code, category, *flags) {{ + iop = InstObjParams(name, + Name, + 'VectorArithMacroInst', + {'code': code}, + flags) + dest_reg_id = "vecRegClass[VecMemInternalReg0 + _microIdx]" + src1_reg_id = "" + if category == "OPFVV": + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx]" + elif category == "OPFVF": + src1_reg_id = "floatRegClass[_machInst.rs1]" + else: + error("not supported category for VectorFloatFormat: %s" % category) + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_src_reg_idx += setSrcVm() + vm_decl_rd = vmDeclAndReadData() + + code = maskCondWrapper(code) + code = eiDeclarePrefix(code) + code = loopWrapper(code) + code = fflags_wrapper(code) + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorFloatMaskMicroDeclare.subst(microiop) + \ + VectorFloatMaskMicroConstructor.subst(microiop) + \ + VectorFloatMaskMicroExecute.subst(microiop) + \ + VectorFloatMaskMacroDeclare.subst(iop) + \ + VectorFloatMaskMacroConstructor.subst(iop) + decode_block = VectorFloatDecodeBlock.subst(iop) +}}; + +def format VMvWholeFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VMvWholeMacroInst', {'code': code}, flags) + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VMvWholeMicroInst', + {'code': code}, + flags) + + header_output = \ + VMvWholeMacroDeclare.subst(iop) + \ + VMvWholeMicroDeclare.subst(microiop) + decoder_output = \ + VMvWholeMacroConstructor.subst(iop) + \ + VMvWholeMicroConstructor.subst(microiop) + exec_output = VMvWholeMicroExecute.subst(microiop) + decode_block = BasicDecode.subst(iop) +}}; + +def format ViotaFormat(code, category, *flags){{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + # The tail of vector mask inst should be treated as tail-agnostic. + # We treat it with tail-undisturbed policy, since + # the test suits only support undisturbed policy. + old_dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_dest_reg_idx = setDestWrapper(dest_reg_id) + vm_decl_rd = vmDeclAndReadData() + set_vm_idx = setSrcVm() + + microiop = InstObjParams(name+"_micro", + Name+"Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'set_vm_idx': set_vm_idx, + 'copy_old_vd': copyOldVd(1)}, + flags) + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + ViotaMicroDeclare.subst(microiop) + \ + ViotaMicroConstructor.subst(microiop) + \ + ViotaMicroExecute.subst(microiop)+\ + ViotaMacroDeclare.subst(iop) + \ + ViotaMacroConstructor.subst(iop) + + decode_block = VectorIntDecodeBlock.subst(iop) + +}}; + +def format Vector1Vs1VdMaskFormat(code, category, *flags){{ + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd]" + src2_reg_id = "vecRegClass[_machInst.vs2]" + # The tail of vector mask inst should be treated as tail-agnostic. + # We treat it with tail-undisturbed policy, since + # the test suits only support undisturbed policy. + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_dest_reg_idx = setDestWrapper(dest_reg_id) + vm_decl_rd = vmDeclAndReadData() + set_vm_idx = setSrcVm() + iop = InstObjParams(name, + Name, + 'VectorNonSplitInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'set_vm_idx': set_vm_idx, + 'copy_old_vd': copyOldVd(1)}, + flags) + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + Vector1Vs1RdMaskDeclare.subst(iop) + \ + Vector1Vs1VdMaskConstructor.subst(iop) + \ + Vector1Vs1VdMaskExecute.subst(iop) + + decode_block = VectorMaskDecodeBlock.subst(iop) +}}; + +def format Vector1Vs1RdMaskFormat(code, category, *flags){{ + inst_name, inst_suffix = name.split("_", maxsplit=1) + vm_decl_rd = vmDeclAndReadData() + set_vm_idx = setSrcVm() + iop = InstObjParams(name, + Name, + 'VectorNonSplitInst', + {'code': code, + 'vm_decl_rd': vm_decl_rd, + 'set_vm_idx': set_vm_idx}, + flags) + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + Vector1Vs1RdMaskDeclare.subst(iop) + \ + Vector1Vs1RdMaskConstructor.subst(iop) + \ + Vector1Vs1RdMaskExecute.subst(iop) + + decode_block = VectorMaskDecodeBlock.subst(iop) +}}; + +def format VectorNonSplitFormat(code, category, *flags) {{ + inst_name, inst_suffix = name.split("_", maxsplit=1) + vm_decl_rd = "" + + set_vm_idx = "" + + if inst_name == "vfmv" : + code = fflags_wrapper(code) + + iop = InstObjParams(name, + Name, + 'VectorNonSplitInst', + {'code': code, + 'vm_decl_rd': vm_decl_rd, + 'set_vm_idx': set_vm_idx}, + flags) + + + if inst_name == "vfmv" : + execute_block = VectorFloatNonSplitExecute.subst(iop) + decode_block = VectorFloatDecodeBlock.subst(iop) + elif inst_name == "vmv" : + execute_block = VectorIntNonSplitExecute.subst(iop) + decode_block = VectorIntDecodeBlock.subst(iop) + else : + error("Unsupported inst for VectorNonSplitFormat: %s" % inst_name) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorNonSplitDeclare.subst(iop) + \ + VectorNonSplitConstructor.subst(iop) + \ + execute_block + +}}; + +def format VectorMaskFormat(code, category, *flags) {{ + inst_name, inst_suffix = name.split("_", maxsplit=1) + old_vd_idx = 2 + if category not in ["OPMVV"]: + error("not supported category for VectorIntFormat: %s" % category) + dest_reg_id = "vecRegClass[_machInst.vd]" + src1_reg_id = "vecRegClass[_machInst.vs1]" + src2_reg_id = "vecRegClass[_machInst.vs2]" + + # The tail of vector mask inst should be treated as tail-agnostic. + # We treat it with tail-undisturbed policy, since + # the test suits only support undisturbed policy. + # TODO: remove it + old_dest_reg_id = "vecRegClass[_machInst.vd]" + + set_src_reg_idx = "" + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + code = loopWrapper(code, micro_inst = False) + + iop = InstObjParams(name, + Name, + 'VectorNonSplitInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorMaskDeclare.subst(iop) + \ + VectorMaskConstructor.subst(iop) + \ + VectorMaskExecute.subst(iop) + + decode_block = VectorMaskDecodeBlock.subst(iop) +}}; + +def format VectorReduceIntFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd]" + src1_reg_id = "vecRegClass[_machInst.vs1]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + # Treat tail undisturbed/agnostic as the same + # We always need old rd as src vreg + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_src_reg_idx += setSrcVm() + vm_decl_rd = vmDeclAndReadData() + type_def = ''' + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + ''' + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'type_def': type_def, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMicroConstructor.subst(microiop) + \ + VectorReduceIntMicroExecute.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + \ + VectorReduceMacroConstructor.subst(iop) + decode_block = VectorIntDecodeBlock.subst(iop) +}}; + +def format VectorReduceFloatFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd]" + src1_reg_id = "vecRegClass[_machInst.vs1]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + # Treat tail undisturbed/agnostic as the same + # We always need old rd as src vreg + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_src_reg_idx += setSrcVm() + vm_decl_rd = vmDeclAndReadData() + type_def = ''' + using et = ElemType; + using vu = decltype(et::v); + ''' + + code = fflags_wrapper(code) + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'type_def': type_def, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMicroConstructor.subst(microiop) + \ + VectorReduceFloatMicroExecute.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + \ + VectorReduceMacroConstructor.subst(iop) + decode_block = VectorFloatDecodeBlock.subst(iop) +}}; + +def format VectorReduceFloatWideningFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd]" + src1_reg_id = "vecRegClass[_machInst.vs1]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + # Treat tail undisturbed/agnostic as the same + # We always need old rd as src vreg + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_src_reg_idx += setSrcVm() + vm_decl_rd = vmDeclAndReadData() + type_def = ''' + using et = ElemType; + using vu [[maybe_unused]] = decltype(et::v); + using ewt = typename double_width::type; + using vwu = decltype(ewt::v); + ''' + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'type_def': type_def, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMicroConstructor.subst(microiop) + \ + VectorReduceFloatWideningMicroExecute.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + \ + VectorReduceMacroConstructor.subst(iop) + decode_block = VectorFloatWideningDecodeBlock.subst(iop) +}}; + +def format VectorIntVxsatFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + old_vd_idx = 2 + dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" + src1_reg_id = "" + if category in ["OPIVV"]: + src1_reg_id = "vecRegClass[_machInst.vs1 + _microIdx]" + elif category in ["OPIVX"]: + src1_reg_id = "intRegClass[_machInst.rs1]" + elif category == "OPIVI": + old_vd_idx = 1 + else: + error("not supported category for VectorIntVxsatFormat: %s" % category) + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + src3_reg_id = "vecRegClass[_machInst.vs3 + _microIdx]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + + set_src_reg_idx = "" + if category != "OPIVI": + set_src_reg_idx += setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + set_src_reg_idx += setSrcWrapper(src3_reg_id) + set_src_reg_idx += setSrcVm() + vm_decl_rd = vmDeclAndReadData() + + code = maskCondWrapper(code) + code = eiDeclarePrefix(code) + code = loopWrapper(code) + + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorIntVxsatMicroDeclare.subst(microiop) + \ + VectorIntVxsatMicroConstructor.subst(microiop) + \ + VectorIntMicroExecute.subst(microiop) + \ + VectorIntVxsatMacroDeclare.subst(iop) + \ + VectorIntVxsatMacroConstructor.subst(iop) + + decode_block = VectorIntDecodeBlock.subst(iop) +}}; + +def format VectorReduceIntWideningFormat(code, category, *flags) {{ + iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd]" + src1_reg_id = "vecRegClass[_machInst.vs1]" + src2_reg_id = "vecRegClass[_machInst.vs2 + _microIdx]" + old_dest_reg_id = "vecRegClass[_machInst.vd]" + set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_src_reg_idx = setSrcWrapper(src1_reg_id) + set_src_reg_idx += setSrcWrapper(src2_reg_id) + # Treat tail undisturbed/agnostic as the same + # We always need old rd as src vreg + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_src_reg_idx += setSrcVm() + vm_decl_rd = vmDeclAndReadData() + microiop = InstObjParams(name + "_micro", + Name + "Micro", + 'VectorArithMicroInst', + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(2)}, + flags) + + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMicroConstructor.subst(microiop) + \ + VectorReduceIntWideningMicroExecute.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + \ + VectorReduceMacroConstructor.subst(iop) + decode_block = VectorIntWideningDecodeBlock.subst(iop) +}}; + +let {{ + +def VectorSlideBase(name, Name, category, code, flags, macro_construtor, + decode_template, micro_execute_template): + macroop_class_name = 'VectorSlideMacroInst' + microop_class_name = 'VectorSlideMicroInst' + # Make sure flags are in lists (convert to lists if not). + flags = makeList(flags) + iop = InstObjParams(name, Name, macroop_class_name, {'code': code}, + flags) + inst_name, inst_suffix = name.split("_", maxsplit=1) + dest_reg_id = "vecRegClass[_machInst.vd + vdIdx]" + src2_reg_id = "vecRegClass[_machInst.vs2 + vs2Idx]" + src1_ireg_id = "intRegClass[_machInst.rs1]" + src1_freg_id = "floatRegClass[_machInst.rs1]" + + # The tail of vector mask inst should be treated as tail-agnostic. + # We treat it with tail-undisturbed policy, since + # the test suits only support undisturbed policy. + num_src_regs = 0 + + old_dest_reg_id = "vecRegClass[_machInst.vd + vdIdx]" + set_src_reg_idx = "" + if category in ["OPIVX", "OPMVX"]: + set_src_reg_idx += setSrcWrapper(src1_ireg_id) + num_src_regs += 1 + elif category in ["OPFVF"]: + set_src_reg_idx += setSrcWrapper(src1_freg_id) + num_src_regs += 1 + set_src_reg_idx += setSrcWrapper(src2_reg_id) + num_src_regs += 1 + old_vd_idx = num_src_regs + set_src_reg_idx += setSrcWrapper(old_dest_reg_id) + set_dest_reg_idx = setDestWrapper(dest_reg_id) + vm_decl_rd = vmDeclAndReadData() + set_src_reg_idx += setSrcVm() + microiop = InstObjParams(name + "_micro", + Name + "Micro", + microop_class_name, + {'code': code, + 'set_dest_reg_idx': set_dest_reg_idx, + 'set_src_reg_idx': set_src_reg_idx, + 'vm_decl_rd': vm_decl_rd, + 'copy_old_vd': copyOldVd(old_vd_idx)}, + flags) + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + # Because of the use of templates, we had to put all parts in header to + # keep the compiler happy. + header_output = \ + VectorSlideMicroDeclare.subst(microiop) + \ + VectorSlideMicroConstructor.subst(microiop) + \ + micro_execute_template.subst(microiop) + \ + VectorSlideMacroDeclare.subst(iop) + \ + macro_construtor.subst(iop) + + decode_block = decode_template.subst(iop) + return (header_output, decode_block) + +}}; + +def format VectorSlideUpFormat(code, category, *flags) {{ + (header_output, decode_block) = VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideUpMacroConstructor, + decode_template = VectorIntDecodeBlock, + micro_execute_template = VectorSlideMicroExecute) +}}; + +def format VectorSlideDownFormat(code, category, *flags) {{ + (header_output, decode_block) = VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideDownMacroConstructor, + decode_template = VectorIntDecodeBlock, + micro_execute_template = VectorSlideMicroExecute) +}}; + +def format VectorFloatSlideUpFormat(code, category, *flags) {{ + (header_output, decode_block) = VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideUpMacroConstructor, + decode_template = VectorFloatDecodeBlock, + micro_execute_template = VectorFloatSlideMicroExecute) +}}; + +def format VectorFloatSlideDownFormat(code, category, *flags) {{ + (header_output, decode_block) = VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideDownMacroConstructor, + decode_template = VectorFloatDecodeBlock, + micro_execute_template = VectorFloatSlideMicroExecute) +}}; diff --git a/src/arch/riscv/isa/templates/templates.isa b/src/arch/riscv/isa/templates/templates.isa index b4de46d846..ed3f5287c0 100644 --- a/src/arch/riscv/isa/templates/templates.isa +++ b/src/arch/riscv/isa/templates/templates.isa @@ -1,2 +1,32 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2022 PLCT Lab +// 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. + + // Include ##include "vector_mem.isa" +##include "vector_arith.isa" diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa new file mode 100644 index 0000000000..d15ab70f20 --- /dev/null +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -0,0 +1,1989 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2022 PLCT Lab +// 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. + +output header {{ + +#define ASSIGN_VD_BIT(idx, bit) \ + ((Vd[(idx)/8] & ~(1 << (idx)%8)) | ((bit) << (idx)%8)) + +#define COPY_OLD_VD(idx) \ + [[maybe_unused]] RiscvISA::vreg_t old_vd; \ + [[maybe_unused]] decltype(Vd) old_Vd = nullptr; \ + xc->getRegOperand(this, (idx), &old_vd); \ + old_Vd = old_vd.as >(); \ + memcpy(Vd, old_Vd, VLENB); + +#define VRM_REQUIRED \ + uint_fast8_t frm = xc->readMiscReg(MISCREG_FRM); \ + if (frm > 4) \ + return std::make_shared("RM fault", machInst); \ + softfloat_roundingMode = frm; + +template +bool inline +carry_out(Type a, Type b, bool carry_in = false) { + using TypeU = std::make_unsigned_t; + TypeU s = *reinterpret_cast(&a) + + *reinterpret_cast(&b) + carry_in; + return carry_in + ? (s <= *reinterpret_cast(&a)) + : (s < *reinterpret_cast(&a)); +} + +template +bool inline +borrow_out(Type a, Type b, bool borrow_in = false) { + using TypeU = std::make_unsigned_t; + return borrow_in + ? (*reinterpret_cast(&a) <= *reinterpret_cast(&b)) + : (*reinterpret_cast(&a) < *reinterpret_cast(&b)); +} + +}}; + +def template VectorIntMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} +}}; + +def template VectorIntMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs1, vs2, vs3(old_vd), vm for *.vv, *.vx + // vs2, (old_vd), vm for *.vi + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorIntMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + + return NoFault; +} + +}}; + +def template VectorIntExtMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + std::string generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const override + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); + } +}; + +}}; + +def template VectorIntExtMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[3]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + std::string generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const override + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); + } +}; + +}}; + +def template VectorIntExtMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + auto SEW = vtype_SEW(vtype); + auto offset = (VLEN / SEW) * (microIdx % %(ext_div)d); + switch (SEW / %(ext_div)d) { + case 8: { + using vext [[maybe_unused]] = int8_t; + using vextu [[maybe_unused]] = uint8_t; + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + break; + } + case 16: { + using vext [[maybe_unused]] = int16_t; + using vextu [[maybe_unused]] = uint16_t; + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + break; + } + case 32: { + using vext [[maybe_unused]] = int32_t; + using vextu [[maybe_unused]] = uint32_t; + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + break; + } + default: break; + } + + return NoFault; +} + +}}; + +def template VectorIntDecodeBlock {{ + +switch(machInst.vtype8.vsew) { +case 0b000: return new %(class_name)s(machInst); +case 0b001: return new %(class_name)s(machInst); +case 0b010: return new %(class_name)s(machInst); +case 0b011: return new %(class_name)s(machInst); +default: GEM5_UNREACHABLE; +} + +}}; + +def template VectorIntWideningMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntWideningMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const int64_t vlmul = vtype_vlmul(_machInst.vtype8); + // Todo: move to Decode template + panic_if(vlmul == 3, "LMUL=8 is illegal for widening inst"); + // when LMUL setted as m1, need to split to 2 micro insts + const uint32_t num_microops = 1 << std::max(0, vlmul + 1); + + int32_t tmp_vl = this->vl; + const int32_t t_micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorIntWideningMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs1, vs2, vs3(old_vd), vm for *.vv, *.vx + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntWideningMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorIntWideningMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + using vwu [[maybe_unused]] = typename double_width::type; + using vwi [[maybe_unused]] = typename double_width::type; + [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + const int64_t vlmul = vtype_vlmul(machInst.vtype8); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; + [[maybe_unused]] const size_t offset = + (this->microIdx % 2 == 0) ? 0 : micro_vlmax; + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorIntNarrowingMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + using vwu [[maybe_unused]] = typename double_width::type; + using vwi [[maybe_unused]] = typename double_width::type; + [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + const int64_t vlmul = vtype_vlmul(machInst.vtype8); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; + [[maybe_unused]] const size_t offset = + (this->microIdx % 2 == 0) ? 0 : micro_vlmax; + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorIntWideningDecodeBlock {{ + +switch(machInst.vtype8.vsew) { +case 0b000: return new %(class_name)s(machInst); +case 0b001: return new %(class_name)s(machInst); +case 0b010: return new %(class_name)s(machInst); +default: GEM5_UNREACHABLE; +} + +}}; + +def template VectorFloatMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorFloatMacroConstructor {{ +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} +}}; + +def template VectorFloatMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs1, vs2, vs3(old_vd), vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorFloatMicroConstructor {{ +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorFloatMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using et = ElemType; + using vu = decltype(et::v); + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + VRM_REQUIRED; + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + + return NoFault; +} + +}}; + +def template VectorFloatDecodeBlock {{ + +switch(machInst.vtype8.vsew) { +case 0b010: return new %(class_name)s(machInst); +case 0b011: return new %(class_name)s(machInst); +default: GEM5_UNREACHABLE; +} + +}}; + +def template VectorFloatCvtMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + std::string generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const override + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); + } +}; + +}}; + +def template VectorFloatCvtMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[3]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + std::string generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const override + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); + } +}; + +}}; + + +def template VectorFloatWideningMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using et = ElemType; + using vu [[maybe_unused]] = decltype(et::v); + using ewt = typename double_width::type; + using vwu = decltype(ewt::v); + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + VRM_REQUIRED; + + const int64_t vlmul = vtype_vlmul(machInst.vtype8); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; + [[maybe_unused]] const size_t offset = + (this->microIdx % 2 == 0) ? 0 : micro_vlmax; + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorFloatNarrowingMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using et = ElemType; + using vu [[maybe_unused]] = decltype(et::v); + using ewt = typename double_width::type; + using vwu = decltype(ewt::v); + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + VRM_REQUIRED; + + const int64_t vlmul = vtype_vlmul(machInst.vtype8); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; + [[maybe_unused]] const size_t offset = + (this->microIdx % 2 == 0) ? 0 : micro_vlmax; + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorFloatWideningDecodeBlock {{ + +switch(machInst.vtype8.vsew) { +case 0b010: return new %(class_name)s(machInst); +default: GEM5_UNREACHABLE; +} + +}}; + +def template ViotaMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + int cnt = 0; + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + + +def template ViotaMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + + StaticInstPtr microop; + + // Allow one empty micro op to hold IsLastMicroop flag + for (int i = 0; i < num_microops && micro_vl >= 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i, + &cnt); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template ViotaMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; + int* cnt; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx, int* cnt); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template ViotaMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx, int* cnt) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + this->cnt = cnt; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2]); +} + +}}; + +def template ViotaMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + + +def template Vector1Vs1VdMaskConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; + %(set_vm_idx)s; +} + +}}; + +def template Vector1Vs1VdMaskExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu = uint8_t; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + return NoFault; +}; + +}}; + +def template Vector1Vs1RdMaskDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + RegId srcRegIdxArr[2]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template Vector1Vs1RdMaskConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + %(constructor)s; + %(set_vm_idx)s; +} + +}}; + +def template Vector1Vs1RdMaskExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + %(op_rd)s; + uint64_t Rd = 0; + %(vm_decl_rd)s; + %(code)s; + %(op_wb)s; + return NoFault; +}; + +}}; + +def template VectorIntMaskMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntMaskMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, + this->microops.size()); + this->microops.push_back(microop); + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorIntMaskMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs1(rs1), vs2, old_vd, v0 for *.vv[m] or *.vx[m] + // vs2, old_vd, v0 for *.vi[m] + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntMaskMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) +: %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorIntMaskMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + + constexpr uint16_t bit_offset = VLENB / sizeof(ElemType); + const uint16_t offset = bit_offset * microIdx; + + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorFloatMaskMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorFloatMaskMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, + this->microops.size()); + this->microops.push_back(microop); + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorFloatMaskMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs1(rs1), vs2, old_vd, v0 for *.vv or *.vf + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorFloatMaskMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) +: %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorFloatMaskMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using et = ElemType; + using vu = decltype(et::v); + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + + constexpr uint16_t bit_offset = VLENB / sizeof(ElemType); + const uint16_t offset = bit_offset * microIdx; + + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VMvWholeMacroDeclare {{ + +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VMvWholeMacroConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = _machInst.simm3 + 1; + StaticInstPtr microop; + + for (int i = 0; i < num_microops; ++i) { + microop = new %(class_name)sMicro(_machInst, 0, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VMvWholeMicroDeclare {{ + +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[1]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VMvWholeMicroConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _microIdx]); +} + +}}; + +def template VMvWholeMicroExecute {{ + +Fault +%(class_name)s::execute(ExecContext* xc, trace::InstRecord* traceData) const +{ + // TODO: Check register alignment. + // TODO: If vd is equal to vs2 the instruction is an architectural NOP. + %(op_decl)s; + %(op_rd)s; + for (size_t i = 0; i < (VLEN / 64); i++) { + %(code)s; + } + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorMaskDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + RegId srcRegIdxArr[3]; + RegId destRegIdxArr[1]; +public: + %(class_name)s(ExtMachInst _machInst); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorMaskConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorMaskExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu = uint8_t; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + // TODO: remove it + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + + return NoFault; +}; + +}}; + +def template VectorMaskDecodeBlock {{ + +return new %(class_name)s(machInst); + +}}; + +def template VectorNonSplitDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + RegId srcRegIdxArr[2]; + RegId destRegIdxArr[1]; +public: + %(class_name)s(ExtMachInst _machInst); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorNonSplitConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + %(set_vm_idx)s; +} + +}}; + +def template VectorIntNonSplitExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorFloatNonSplitExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using et = ElemType; + using vu = decltype(et::v); + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorReduceMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorReduceMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorReduceMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs2, vs1, vd, vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorReduceMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) +: %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorReduceIntMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + %(type_def)s; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + + auto reduce_loop = + [&, this](const auto& f, const auto* _, const auto* vs2) { + ElemType microop_result = this->microIdx != 0 ? old_Vd[0] : Vs1[0]; + for (uint32_t i = 0; i < this->microVl; i++) { + uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + if (this->vm || elem_mask(v0, ei)) { + microop_result = f(microop_result, Vs2[i]); + } + } + return microop_result; + }; + + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorReduceFloatMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + %(type_def)s; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + + Vd[0] = this->microIdx != 0 ? old_Vd[0] : Vs1[0]; + + auto reduce_loop = + [&, this](const auto& f, const auto* _, const auto* vs2) { + vu tmp_val = Vd[0]; + for (uint32_t i = 0; i < this->microVl; i++) { + uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + if (this->vm || elem_mask(v0, ei)) { + tmp_val = f(tmp_val, Vs2[i]).v; + } + } + return tmp_val; + }; + + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorReduceFloatWideningMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + %(type_def)s; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + + Vd[0] = this->microIdx != 0 ? old_Vd[0] : Vs1[0]; + + auto reduce_loop = + [&, this](const auto& f, const auto* _, const auto* vs2) { + vwu tmp_val = Vd[0]; + for (uint32_t i = 0; i < this->microVl; i++) { + uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + if (this->vm || elem_mask(v0, ei)) { + tmp_val = f(tmp_val, Vs2[i]).v; + } + } + return tmp_val; + }; + + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorGatherMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s{ +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorGatherMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + constexpr uint32_t vd_eewb = sizeof(ElemType); + constexpr uint32_t vs2_eewb = sizeof(ElemType); + constexpr uint32_t vs1_eewb = sizeof(IndexType); + constexpr bool vs1_split = vd_eewb > vs1_eewb; + const int8_t lmul = vtype_vlmul(vtype); + const int8_t vs1_emul = lmul + + (vs1_split ? -(vs2_eewb / vs1_eewb) : vs1_eewb / vs2_eewb); + const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; + const uint8_t vs1_vregs = vs1_emul < 0 ? 1 : 1 << vs1_emul; + const uint8_t vd_vregs = vs2_vregs; + const int32_t micro_vlmax = VLENB / std::max(vd_eewb, vs1_eewb); + int32_t remaining_vl = this->vl; + int32_t micro_vl = std::min(remaining_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (uint8_t i = 0; i < std::max(vs1_vregs, vd_vregs) && micro_vl > 0; + i++) { + for (uint8_t j = 0; j < vs2_vregs; j++) { + microop = new %(class_name)sMicro( + _machInst, micro_vl, i * vs2_vregs + j); + microop->setDelayedCommit(); + this->microops.push_back(microop); + } + micro_vl = std::min(remaining_vl -= micro_vlmax, micro_vlmax); + } + + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorGatherMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs2, vs1, vd, vm + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorGatherMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx) +: %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + [[maybe_unused]] constexpr uint32_t vd_eewb = sizeof(ElemType); + [[maybe_unused]] constexpr uint32_t vs2_eewb = sizeof(ElemType); + [[maybe_unused]] constexpr uint32_t vs1_eewb = sizeof(IndexType); + constexpr uint8_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; + constexpr uint8_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; + const int8_t lmul = vtype_vlmul(vtype); + const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; + [[maybe_unused]] const uint8_t vs2_idx = _microIdx % vs2_vregs; + [[maybe_unused]] const uint8_t vs1_idx = + _microIdx / vs2_vregs / vs1_split_num; + [[maybe_unused]] const uint8_t vd_idx = + _microIdx / vs2_vregs / vd_split_num; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorGatherMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + const uint32_t vlmax = vtype_VLMAX(vtype); + constexpr uint8_t vd_eewb = sizeof(ElemType); + constexpr uint8_t vs1_eewb = sizeof(IndexType); + constexpr uint8_t vs2_eewb = sizeof(ElemType); + constexpr uint8_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; + constexpr uint8_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; + [[maybe_unused]] constexpr uint16_t vd_elems = VLENB / vd_eewb; + [[maybe_unused]] constexpr uint16_t vs1_elems = VLENB / vs1_eewb; + [[maybe_unused]] constexpr uint16_t vs2_elems = VLENB / vs2_eewb; + [[maybe_unused]] const int8_t lmul = vtype_vlmul(vtype); + [[maybe_unused]] const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; + [[maybe_unused]] const uint8_t vs2_idx = microIdx % vs2_vregs; + [[maybe_unused]] const uint8_t vs1_idx = + microIdx / vs2_vregs / vs1_split_num; + [[maybe_unused]] const uint8_t vd_idx = + microIdx / vs2_vregs / vd_split_num; + [[maybe_unused]] const uint16_t vs1_bias = + vs1_elems * (vd_idx % vs1_split_num) / vs1_split_num; + [[maybe_unused]] const uint16_t vd_bias = + vd_elems * (vs1_idx % vd_split_num) / vd_split_num; + + %(code)s; + %(op_wb)s; + + return NoFault; +} + +}}; + +def template VectorGatherDecodeBlock {{ + +switch(machInst.vtype8.vsew) { + case 0b000: { + using elem_type [[maybe_unused]] = uint8_t; + return new %(class_name)s(machInst); + } + case 0b001: { + using elem_type [[maybe_unused]] = uint16_t; + return new %(class_name)s(machInst); + } + case 0b010: { + using elem_type [[maybe_unused]] = uint32_t; + return new %(class_name)s(machInst); + } + case 0b011: { + using elem_type [[maybe_unused]] = uint64_t; + return new %(class_name)s(machInst); + } + default: GEM5_UNREACHABLE; +} + +}}; + +def template VectorIntVxsatMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s{ +private: + %(reg_idx_arr_decl)s; + bool vxsat = false; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntVxsatMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + microop = new %(class_name)sMicro(_machInst, + micro_vl, i, &vxsat); + microop->setDelayedCommit(); + this->microops.push_back(microop); + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + + microop = new VxsatMicroInst(&vxsat, _machInst); + microop->setFlag(StaticInst::IsSerializeAfter); + microop->setFlag(StaticInst::IsNonSpeculative); + this->microops.push_back(microop); + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} +}}; + +def template VectorIntVxsatMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; + bool* vxsatptr; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx, bool* vxsatptr); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorIntVxsatMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx, bool* vxsatptr) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx) +{ + this->vm = _machInst.vm; + this->vxsatptr = vxsatptr; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorReduceIntWideningMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + using vwu [[maybe_unused]] = typename double_width::type; + using vwi [[maybe_unused]] = typename double_width::type; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + + Vd[0] = this->microIdx != 0 ? old_Vd[0] : Vs1[0]; + + auto reduce_loop = + [&, this](const auto& f, const auto* _, const auto* vs2) { + vwu tmp_val = Vd[0]; + for (uint32_t i = 0; i < this->microVl; i++) { + uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + if (this->vm || elem_mask(v0, ei)) { + tmp_val = f(tmp_val, Vs2[i]); + } + } + return tmp_val; + }; + + %(code)s; + %(op_wb)s; + return NoFault; +} + +}}; + +def template VectorSlideMacroDeclare {{ + +template +class %(class_name)s : public %(base_class)s { +private: + %(reg_idx_arr_decl)s; +public: + %(class_name)s(ExtMachInst _machInst); + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorSlideUpMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + // Todo static filter out useless uop + int micro_idx = 0; + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + for (int j = 0; j <= i; ++j) { + microop = new %(class_name)sMicro( + _machInst, micro_vl, micro_idx++, i, j); + microop->setDelayedCommit(); + this->microops.push_back(microop); + } + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorSlideDownMacroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +{ + %(set_reg_idx_arr)s; + %(constructor)s; + const uint32_t num_microops = vtype_regs_per_group(vtype); + int32_t tmp_vl = this->vl; + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + int32_t micro_vl = std::min(tmp_vl, micro_vlmax); + StaticInstPtr microop; + + if (micro_vl == 0) { + microop = new VectorNopMicroInst(_machInst); + this->microops.push_back(microop); + } + // Todo static filter out useless uop + int micro_idx = 0; + for (int i = 0; i < num_microops && micro_vl > 0; ++i) { + for (int j = i; j < num_microops; ++j) { + microop = new %(class_name)sMicro( + _machInst, micro_vl, micro_idx++, i, j); + microop->setDelayedCommit(); + this->microops.push_back(microop); + } + micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); + } + this->microops.front()->setFirstMicroop(); + this->microops.back()->setLastMicroop(); +} + +}}; + +def template VectorSlideMicroDeclare {{ + +template +class %(class_name)s : public %(base_class)s +{ +private: + // vs2, vs1, vs3(old_vd), vm for *.vv, *.vx + // vs2, (old_vd), vm for *.vi + RegId srcRegIdxArr[4]; + RegId destRegIdxArr[1]; + bool vm; +public: + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx); + Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; + using %(base_class)s::generateDisassembly; +}; + +}}; + +def template VectorSlideMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, + _microIdx, _vdIdx, _vs2Idx) +{ + this->vm = _machInst.vm; + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + %(set_dest_reg_idx)s; + %(set_src_reg_idx)s; +} + +}}; + +def template VectorSlideMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using vu [[maybe_unused]] = std::make_unsigned_t; + using vi [[maybe_unused]] = std::make_signed_t; + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + + return NoFault; +}; + +}}; + +def template VectorFloatSlideMicroExecute {{ + +template +Fault +%(class_name)s::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + using et = ElemType; + using vu = decltype(et::v); + + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); + + %(op_decl)s; + %(op_rd)s; + %(vm_decl_rd)s; + %(copy_old_vd)s; + %(code)s; + %(op_wb)s; + + return NoFault; +}; + +}}; diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index d54243ad7d..f8be1e555b 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -1,3 +1,31 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2022 PLCT Lab +// 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. + def template VMemMacroDeclare {{ class %(class_name)s : public %(base_class)s diff --git a/src/arch/riscv/regs/float.hh b/src/arch/riscv/regs/float.hh index 4809372070..cca9e1be2f 100644 --- a/src/arch/riscv/regs/float.hh +++ b/src/arch/riscv/regs/float.hh @@ -211,6 +211,20 @@ const std::vector RegNames = { } // namespace float_reg +inline float32_t +fsgnj32(float32_t a, float32_t b, bool n, bool x) { + if (n) b.v = ~b.v; + else if (x) b.v = a.v ^ b.v; + return f32(insertBits(b.v, 30, 0, a.v)); +} + +inline float64_t +fsgnj64(float64_t a, float64_t b, bool n, bool x) { + if (n) b.v = ~b.v; + else if (x) b.v = a.v ^ b.v; + return f64(insertBits(b.v, 62, 0, a.v)); +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh index 1db6d6df3b..40054aec0f 100644 --- a/src/arch/riscv/utility.hh +++ b/src/arch/riscv/utility.hh @@ -241,6 +241,13 @@ remu(T rs1, T rs2) return (rs2 == 0) ? rs1 : rs1 % rs2; } +// Vector extension functions +inline uint64_t +vtype_SEW(const uint64_t vtype) +{ + return 8 << bits(vtype, 5, 3); +} + /* * Encode LMUL to lmul as follows: * LMUL vlmul lmul @@ -269,6 +276,25 @@ vtype_VLMAX(const uint64_t vtype, const bool per_reg = false) return gem5::RiscvISA::VLEN >> (vsew + 3 - lmul); } +inline int64_t +vtype_vlmul(const uint64_t vtype) +{ + return (int64_t)sext<3>(bits(vtype, 2, 0)); +} + +inline uint64_t +vtype_regs_per_group(const uint64_t vtype) +{ + int64_t lmul = (int64_t)sext<3>(bits(vtype, 2, 0)); + return 1 << std::max(0, lmul); +} + +inline void +vtype_set_vill(uint64_t& vtype) +{ + vtype = (uint64_t)0 ^ (1UL << (sizeof(RegVal) * 8 - 1)); +} + inline uint64_t width_EEW(uint64_t width) { @@ -296,6 +322,461 @@ elem_mask(const T* vs, const int index) return (vs[idx] >> pos) & 1; } +template struct double_width; +template<> struct double_width { using type = uint16_t;}; +template<> struct double_width { using type = uint32_t;}; +template<> struct double_width { using type = uint64_t;}; +template<> struct double_width { using type = int16_t; }; +template<> struct double_width { using type = int32_t; }; +template<> struct double_width { using type = int64_t; }; +template<> struct double_width { using type = float64_t;}; + +template struct double_widthf; +template<> struct double_widthf { using type = float64_t;}; +template<> struct double_widthf { using type = float64_t;}; + +template auto +ftype(IntType a) -> FloatType +{ + if constexpr(std::is_same_v) + return f32(a); + else if constexpr(std::is_same_v) + return f64(a); + GEM5_UNREACHABLE; +} + +// TODO: Consolidate ftype_freg(freg_t a) and ftype(IntType a) into a +// single function +template auto +ftype_freg(freg_t a) -> FloatType +{ + if constexpr(std::is_same_v) + return f32(a); + else if constexpr(std::is_same_v) + return f64(a); + GEM5_UNREACHABLE; +} + +template FloatType +fadd(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_add(a, b); + else if constexpr(std::is_same_v) + return f64_add(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fsub(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_sub(a, b); + else if constexpr(std::is_same_v) + return f64_sub(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fmin(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_min(a, b); + else if constexpr(std::is_same_v) + return f64_min(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fmax(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_max(a, b); + else if constexpr(std::is_same_v) + return f64_max(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fdiv(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_div(a, b); + else if constexpr(std::is_same_v) + return f64_div(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fmul(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_mul(a, b); + else if constexpr(std::is_same_v) + return f64_mul(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fsqrt(FloatType a) +{ + if constexpr(std::is_same_v) + return f32_sqrt(a); + else if constexpr(std::is_same_v) + return f64_sqrt(a); + GEM5_UNREACHABLE; +} + +template FloatType +frsqrte7(FloatType a) +{ + if constexpr(std::is_same_v) + return f32_rsqrte7(a); + else if constexpr(std::is_same_v) + return f64_rsqrte7(a); + GEM5_UNREACHABLE; +} + +template FloatType +frecip7(FloatType a) +{ + if constexpr(std::is_same_v) + return f32_recip7(a); + else if constexpr(std::is_same_v) + return f64_recip7(a); + GEM5_UNREACHABLE; +} + +template FloatType +fclassify(FloatType a) +{ + if constexpr(std::is_same_v) + return f32(f32_classify(a)); + else if constexpr(std::is_same_v) + return f64(f64_classify(a)); + GEM5_UNREACHABLE; +} + +template FloatType +fsgnj(FloatType a, FloatType b, bool n, bool x) +{ + if constexpr(std::is_same_v) + return fsgnj32(a, b, n, x); + else if constexpr(std::is_same_v) + return fsgnj64(a, b, n, x); + GEM5_UNREACHABLE; +} + +template bool +fle(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_le(a, b); + else if constexpr(std::is_same_v) + return f64_le(a, b); + GEM5_UNREACHABLE; +} + +template bool +feq(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_eq(a, b); + else if constexpr(std::is_same_v) + return f64_eq(a, b); + GEM5_UNREACHABLE; +} + +template bool +flt(FloatType a, FloatType b) +{ + if constexpr(std::is_same_v) + return f32_lt(a, b); + else if constexpr(std::is_same_v) + return f64_lt(a, b); + GEM5_UNREACHABLE; +} + +template FloatType +fmadd(FloatType a, FloatType b, FloatType c) +{ + if constexpr(std::is_same_v) + return f32_mulAdd(a, b, c); + else if constexpr(std::is_same_v) + return f64_mulAdd(a, b, c); + GEM5_UNREACHABLE; +} + +template FloatType +fneg(FloatType a) +{ + if constexpr(std::is_same_v) + return f32(a.v ^ uint32_t(mask(31, 31))); + else if constexpr(std::is_same_v) + return f64(a.v ^ mask(63, 63)); + GEM5_UNREACHABLE; +} + +template::type> WFT +fwiden(FT a) +{ + if constexpr(std::is_same_v) + return f32_to_f64(a); + GEM5_UNREACHABLE; +} + +template IntType +f_to_ui(FloatType a, uint_fast8_t mode) +{ + if constexpr(std::is_same_v) + return f32_to_ui32(a, mode, true); + else if constexpr(std::is_same_v) + return f64_to_ui64(a, mode, true); + GEM5_UNREACHABLE; +} + +template< + typename FloatType, + typename IntType = decltype(double_width::type::v) +> IntType +f_to_wui(FloatType a, uint_fast8_t mode) +{ + if constexpr(std::is_same_v) + return f32_to_ui64(a, mode, true); + GEM5_UNREACHABLE; +} + +template< + typename IntType, + typename FloatType = typename double_widthf::type +> IntType +f_to_nui(FloatType a, uint_fast8_t mode) +{ + if constexpr(std::is_same_v) + return f64_to_ui32(a, mode, true); + GEM5_UNREACHABLE; +} + +template IntType +f_to_i(FloatType a, uint_fast8_t mode) +{ + if constexpr(std::is_same_v) + return (uint32_t)f32_to_i32(a, mode, true); + else if constexpr(std::is_same_v) + return (uint64_t)f64_to_i64(a, mode, true); + GEM5_UNREACHABLE; +} + +template< + typename FloatType, + typename IntType = decltype(double_width::type::v) +> IntType +f_to_wi(FloatType a, uint_fast8_t mode) +{ + if constexpr(std::is_same_v) + return (uint64_t)f32_to_i64(a, mode, true); + GEM5_UNREACHABLE; +} + +template< + typename IntType, + typename FloatType = typename double_widthf::type +> IntType +f_to_ni(FloatType a, uint_fast8_t mode) +{ + if constexpr(std::is_same_v) + return (uint32_t)f64_to_i32(a, mode, true); + GEM5_UNREACHABLE; +} + +template +FloatType +ui_to_f(IntType a) +{ + if constexpr(std::is_same_v) + return ui32_to_f32(a); + else if constexpr(std::is_same_v) + return ui64_to_f64(a); + GEM5_UNREACHABLE; +} + +template< + typename IntType, + typename FloatType = typename double_widthf::type +> FloatType +ui_to_wf(IntType a) +{ + if constexpr(std::is_same_v) + return ui32_to_f64(a); + GEM5_UNREACHABLE; +} + +template< + typename FloatType, + typename IntType = decltype(double_width::type::v) +> FloatType +ui_to_nf(IntType a) +{ + if constexpr(std::is_same_v) + return ui64_to_f32(a); + GEM5_UNREACHABLE; +} + +template +FloatType +i_to_f(IntType a) +{ + if constexpr(std::is_same_v) + return i32_to_f32((int32_t)a); + else if constexpr(std::is_same_v) + return i64_to_f64((int64_t)a); + GEM5_UNREACHABLE; +} + +template< + typename IntType, + typename FloatType = typename double_widthf::type +> FloatType +i_to_wf(IntType a) +{ + if constexpr(std::is_same_v) + return i32_to_f64((int32_t)a); + GEM5_UNREACHABLE; +} + +template< + typename FloatType, + typename IntType = std::make_signed_t< + decltype(double_width::type::v) + > +> FloatType +i_to_nf(IntType a) +{ + if constexpr(std::is_same_v) + return i64_to_f32(a); + GEM5_UNREACHABLE; +} + +template< + typename FloatType, + typename FloatWType = typename double_width::type +> FloatWType +f_to_wf(FloatType a) +{ + if constexpr(std::is_same_v) + return f32_to_f64(a); + GEM5_UNREACHABLE; +} + +template< + typename FloatNType, + typename FloatType = typename double_width::type +> FloatNType +f_to_nf(FloatType a) +{ + if constexpr(std::is_same_v) + return f64_to_f32(a); + GEM5_UNREACHABLE; +} + +//ref: https://locklessinc.com/articles/sat_arithmetic/ +template T +sat_add(T x, T y, bool* sat) +{ + using UT = std::make_unsigned_t; + UT ux = x; + UT uy = y; + UT res = ux + uy; + + int sh = sizeof(T) * 8 - 1; + + ux = (ux >> sh) + (((UT)0x1 << sh) - 1); + + if ((T) ((ux ^ uy) | ~(uy ^ res)) >= 0) { + res = ux; + *sat = true; + } + return res; +} + +template T +sat_sub(T x, T y, bool* sat) +{ + using UT = std::make_unsigned_t; + UT ux = x; + UT uy = y; + UT res = ux - uy; + + int sh = sizeof(T) * 8 - 1; + + ux = (ux >> sh) + (((UT)0x1 << sh) - 1); + + if ((T) ((ux ^ uy) & (ux ^ res)) < 0) { + res = ux; + *sat = true; + } + return res; +} + +template T +sat_addu(T x, T y, bool* sat) +{ + T res = x + y; + + bool t = res < x; + if (false == *sat){ + *sat = t; + } + res |= -(res < x); + + return res; +} + +template T +sat_subu(T x, T y, bool* sat) +{ + T res = x - y; + + bool t = !(res <= x); + if (false == *sat){ + *sat = t; + } + + res &= -(res <= x); + + return res; +} + +/** + * Ref: + * https://github.com/riscv-software-src/riscv-isa-sim + */ +template T +int_rounding(T result, uint8_t xrm, unsigned gb) { + const uint64_t lsb = 1UL << gb; + const uint64_t lsb_half = lsb >> 1; + switch (xrm) { + case 0 /* RNU */: + result += lsb_half; + break; + case 1 /* RNE */: + if ((result & lsb_half) && + ((result & (lsb_half - 1)) || (result & lsb))) + result += lsb; + break; + case 2 /* RDN */: + break; + case 3 /* ROD */: + if (result & (lsb - 1)) + result |= lsb; + break; + default: + panic("Invalid xrm value %d", (int)xrm); + } + + return result; +} + } // namespace RiscvISA } // namespace gem5 From ae651f4de1a981a780bd450b031e6258ad022123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= Date: Fri, 21 Jul 2023 18:36:48 +0200 Subject: [PATCH 146/693] configs: update riscv restore checkpoint test Change-Id: I019fc6394a03196711ab52533ad8062b22c89daf --- .../gem5_library/checkpoints/riscv-hello-restore-checkpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py b/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py index 9f9bf839a6..eed76e2448 100644 --- a/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py @@ -90,7 +90,7 @@ board = SimpleBoard( board.set_se_binary_workload( # the workload should be the same as the save-checkpoint script obtain_resource("riscv-hello"), - checkpoint=obtain_resource("riscv-hello-example-checkpoint-v23"), + checkpoint=obtain_resource("riscv-hello-example-checkpoint"), ) simulator = Simulator( From af1b2ec2d5768a08bd42f11466be991302149482 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Fri, 28 Jul 2023 09:44:28 -0700 Subject: [PATCH 147/693] arch-riscv: Add fatal if RVV used with o3 or minor Since the O3 and Minor CPU models do not support RVV right now as the implementation stalls the decode until vsetvl instructions are exectued, this change calls `fatal` if RVV is not explicitly enabled. It is possible to override this if you explicitly enable RVV in the config file. Change-Id: Ia801911141bb2fb2bedcff3e139bf41ba8936085 Signed-off-by: Jason Lowe-Power --- src/arch/riscv/RiscvCPU.py | 15 +++++++++++++-- src/arch/riscv/RiscvDecoder.py | 1 + src/arch/riscv/RiscvISA.py | 2 ++ src/arch/riscv/decoder.cc | 12 ++++++++++++ src/arch/riscv/decoder.hh | 6 ++---- src/arch/riscv/isa.cc | 9 ++++++--- src/arch/riscv/isa.hh | 3 +++ 7 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/arch/riscv/RiscvCPU.py b/src/arch/riscv/RiscvCPU.py index 1c77045c67..449bf5e7af 100644 --- a/src/arch/riscv/RiscvCPU.py +++ b/src/arch/riscv/RiscvCPU.py @@ -41,6 +41,17 @@ class RiscvCPU: ArchISA = RiscvISA +class RiscvISANoRVV(RiscvISA): + enable_rvv = False + + +class RiscvCPUNoRVV: + ArchDecoder = RiscvDecoder + ArchMMU = RiscvMMU + ArchInterrupts = RiscvInterrupts + ArchISA = RiscvISANoRVV + + class RiscvAtomicSimpleCPU(BaseAtomicSimpleCPU, RiscvCPU): mmu = RiscvMMU() @@ -53,9 +64,9 @@ class RiscvTimingSimpleCPU(BaseTimingSimpleCPU, RiscvCPU): mmu = RiscvMMU() -class RiscvO3CPU(BaseO3CPU, RiscvCPU): +class RiscvO3CPU(BaseO3CPU, RiscvCPUNoRVV): mmu = RiscvMMU() -class RiscvMinorCPU(BaseMinorCPU, RiscvCPU): +class RiscvMinorCPU(BaseMinorCPU, RiscvCPUNoRVV): mmu = RiscvMMU() diff --git a/src/arch/riscv/RiscvDecoder.py b/src/arch/riscv/RiscvDecoder.py index 30c1077662..4100a3c5b3 100644 --- a/src/arch/riscv/RiscvDecoder.py +++ b/src/arch/riscv/RiscvDecoder.py @@ -24,6 +24,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.InstDecoder import InstDecoder +from m5.params import * class RiscvDecoder(InstDecoder): diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index bb9a05babe..f66171a95a 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -56,3 +56,5 @@ class RiscvISA(BaseISA): True, "whether to check memory access alignment" ) riscv_type = Param.RiscvType("RV64", "RV32 or RV64") + + enable_rvv = Param.Bool(True, "Enable vector extension") diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index ce362ad522..702d84fd91 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -28,6 +28,7 @@ */ #include "arch/riscv/decoder.hh" +#include "arch/riscv/isa.hh" #include "arch/riscv/types.hh" #include "base/bitfield.hh" #include "debug/Decode.hh" @@ -38,6 +39,13 @@ namespace gem5 namespace RiscvISA { +Decoder::Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst) +{ + ISA *isa = dynamic_cast(p.isa); + enableRvv = isa->getEnableRvv(); + reset(); +} + void Decoder::reset() { aligned = true; @@ -53,6 +61,10 @@ Decoder::moreBytes(const PCStateBase &pc, Addr fetchPC) // TODO: Current vsetvl instructions stall decode. Future fixes should // enable speculation, and this code will be removed. if (GEM5_UNLIKELY(!this->vConfigDone)) { + fatal_if(!enableRvv, + "Vector extension is not enabled for this CPU type\n" + "You can manually enable vector extensions by setting rvv_enabled " + "to true for each ISA object after `createThreads()`\n"); DPRINTF(Decode, "Waiting for vset*vl* to be executed\n"); instDone = false; outOfBytes = false; diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh index d1d2f3cb0c..1f510e8280 100644 --- a/src/arch/riscv/decoder.hh +++ b/src/arch/riscv/decoder.hh @@ -61,6 +61,7 @@ class Decoder : public InstDecoder ExtMachInst emi; uint32_t machInst; + bool enableRvv = false; VTYPE machVtype; uint32_t machVl; @@ -72,10 +73,7 @@ class Decoder : public InstDecoder StaticInstPtr decode(ExtMachInst mach_inst, Addr addr); public: - Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst) - { - reset(); - } + Decoder(const RiscvDecoderParams &p); void reset() override; diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 2f9d52e1b2..84205eb57a 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -253,7 +253,8 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs); } // anonymous namespace ISA::ISA(const Params &p) : - BaseISA(p), rv_type(p.riscv_type), checkAlignment(p.check_alignment) + BaseISA(p), rv_type(p.riscv_type), checkAlignment(p.check_alignment), + enableRvv(p.enable_rvv) { _regClasses.push_back(&intRegClass); _regClasses.push_back(&floatRegClass); @@ -324,8 +325,10 @@ void ISA::clear() case RV64: misa.rv64_mxl = 2; status.uxl = status.sxl = 2; - status.vs = VPUStatus::INITIAL; - misa.rvv = 1; + if (getEnableRvv()) { + status.vs = VPUStatus::INITIAL; + misa.rvv = 1; + } break; default: panic("%s: Unknown rv_type: %d", name(), (int)rv_type); diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index d7b0a21a1f..1be45ac7fa 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -75,6 +75,7 @@ class ISA : public BaseISA RiscvType rv_type; std::vector miscRegFile; bool checkAlignment; + bool enableRvv; bool hpmCounterEnabled(int counter) const; @@ -138,6 +139,8 @@ class ISA : public BaseISA RiscvType rvType() const { return rv_type; } + bool getEnableRvv() const { return enableRvv; } + void clearLoadReservation(ContextID cid) { From 98d68a7307e2f93e547acf2ff67c957a198bd0ac Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Fri, 28 Jul 2023 09:46:21 -0700 Subject: [PATCH 148/693] arch-riscv: Improve style Minor style fixes in vector code Change-Id: If0de45a2dbfb5d5aaa65ed3b5d91d9bee9bcc960 Signed-off-by: Jason Lowe-Power --- src/arch/riscv/insts/vector.cc | 20 +++++++++++--------- src/arch/riscv/insts/vector.hh | 33 +++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc index a1ccf402c9..6ecec44dc5 100644 --- a/src/arch/riscv/insts/vector.cc +++ b/src/arch/riscv/insts/vector.cc @@ -56,18 +56,20 @@ namespace RiscvISA * **/ float -getVflmul(uint32_t vlmul_encoding) { - int vlmul = sext<3>(vlmul_encoding & 7); - float vflmul = vlmul >= 0 ? 1 << vlmul : 1.0 / (1 << -vlmul); - return vflmul; +getVflmul(uint32_t vlmul_encoding) +{ + int vlmul = sext<3>(vlmul_encoding & 7); + float vflmul = vlmul >= 0 ? 1 << vlmul : 1.0 / (1 << -vlmul); + return vflmul; } uint32_t -getVlmax(VTYPE vtype, uint32_t vlen) { - uint32_t sew = getSew(vtype.vsew); - // vlmax is defined in RVV 1.0 spec p12 chapter 3.4.2. - uint32_t vlmax = (vlen/sew) * getVflmul(vtype.vlmul); - return vlmax; +getVlmax(VTYPE vtype, uint32_t vlen) +{ + uint32_t sew = getSew(vtype.vsew); + // vlmax is defined in RVV 1.0 spec p12 chapter 3.4.2. + uint32_t vlmax = (vlen/sew) * getVflmul(vtype.vlmul); + return vlmax; } std::string diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index 5d0874a994..cae0dcac0a 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -47,7 +47,9 @@ namespace RiscvISA float getVflmul(uint32_t vlmul_encoding); -inline uint32_t getSew(uint32_t vsew) { +inline uint32_t +getSew(uint32_t vsew) +{ assert(vsew <= 3); return (8 << vsew); } @@ -124,7 +126,7 @@ class VectorMacroInst : public RiscvMacroInst class VectorMicroInst : public RiscvMicroInst { -protected: + protected: uint8_t microVl; uint8_t microIdx; uint8_t vtype; @@ -420,7 +422,7 @@ class VsStrideMacroInst : public VectorMemMacroInst class VsStrideMicroInst : public VectorMemMicroInst { protected: - uint8_t regIdx; + uint8_t regIdx; VsStrideMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint8_t _regIdx, uint8_t _microIdx, uint8_t _microVl) @@ -487,9 +489,9 @@ class VsIndexMicroInst : public VectorMemMicroInst VsIndexMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) - : VectorMemMicroInst(mnem, _machInst, __opClass, 1, 0, 0) - , vs3RegIdx(_vs3RegIdx), vs3ElemIdx(_vs3ElemIdx) - , vs2RegIdx(_vs2RegIdx), vs2ElemIdx(_vs2ElemIdx) + : VectorMemMicroInst(mnem, _machInst, __opClass, 1, 0, 0), + vs3RegIdx(_vs3RegIdx), vs3ElemIdx(_vs3ElemIdx), + vs2RegIdx(_vs2RegIdx), vs2ElemIdx(_vs2ElemIdx) {} std::string generateDisassembly( @@ -532,7 +534,7 @@ class VMaskMergeMicroInst : public VectorArithMicroInst VMaskMergeMicroInst(ExtMachInst extMachInst, uint8_t _dstReg, uint8_t _numSrcs) : VectorArithMicroInst("vmask_mv_micro", extMachInst, - VectorIntegerArithOp, 0, 0) + VectorIntegerArithOp, 0, 0) { setRegIdxArrays( reinterpret_cast( @@ -550,8 +552,9 @@ class VMaskMergeMicroInst : public VectorArithMicroInst } } - Fault execute(ExecContext* xc, trace::InstRecord* traceData) - const override { + Fault + execute(ExecContext* xc, trace::InstRecord* traceData) const override + { vreg_t tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); auto Vd = tmp_d0.as(); constexpr uint8_t elems_per_vreg = VLENB / sizeof(ElemType); @@ -582,8 +585,10 @@ class VMaskMergeMicroInst : public VectorArithMicroInst return NoFault; } - std::string generateDisassembly( - Addr pc, const loader::SymbolTable *symtab) const override { + std::string + generateDisassembly(Addr pc, const loader::SymbolTable *symtab) + const override + { std::stringstream ss; ss << mnemonic << ' ' << registerName(destRegIdx(0)); for (uint8_t i = 0; i < this->_numSrcRegs; i++) { @@ -605,8 +610,8 @@ class VxsatMicroInst : public VectorArithMicroInst { vxsat = Vxsat; } - Fault execute(ExecContext* xc, trace::InstRecord* traceData) - const override + Fault + execute(ExecContext* xc, trace::InstRecord* traceData) const override { xc->setMiscReg(MISCREG_VXSAT,*vxsat); auto vcsr = xc->readMiscReg(MISCREG_VCSR); @@ -614,7 +619,7 @@ class VxsatMicroInst : public VectorArithMicroInst return NoFault; } std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) - const override + const override { std::stringstream ss; ss << mnemonic << ' ' << "VXSAT" << ", " << (*vxsat ? "0x1" : "0x0"); From 884d62b33af866664960e399ddc09b654753b794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= Date: Wed, 2 Aug 2023 14:05:21 +0200 Subject: [PATCH 149/693] arch-riscv: Make vset*vl* instructions serialize Current implementation of vset*vl* instructions serialize pipeline and are non-speculative. Change-Id: Ibf93b60133fb3340690b126db12827e36e2c202d --- src/arch/riscv/isa/decoder.isa | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 2b46752ffe..d34adfaa02 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -4344,7 +4344,7 @@ decode QUADRANT default Unknown::unknown() { uint64_t requested_vtype = zimm11; Rd_ud = 0; - }}, VectorConfigOp, IsDirectControl, IsCondControl); + }}, VectorConfigOp, IsSerializeAfter, IsNonSpeculative); 0x1: decode BIT30 { 0x0: vsetvl({{ uint64_t rd_bits = RD; @@ -4353,7 +4353,8 @@ decode QUADRANT default Unknown::unknown() { uint64_t requested_vtype = Rs2_ud; Rd_ud = 0; - }}, VectorConfigOp, IsDirectControl, IsCondControl); + }}, VectorConfigOp, IsSerializeAfter, + IsNonSpeculative); 0x1: vsetivli({{ uint64_t rd_bits = RD; uint64_t rs1_bits = -1; @@ -4361,7 +4362,8 @@ decode QUADRANT default Unknown::unknown() { uint64_t requested_vtype = zimm10; Rd_ud = 0; - }}, VectorConfigOp, IsDirectControl, IsCondControl); + }}, VectorConfigOp, IsSerializeAfter, + IsNonSpeculative); } } } From 51d492487ee6dfed9006c1c27049381b807cdb71 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 2 Aug 2023 12:25:46 -0700 Subject: [PATCH 150/693] stdlib: stlye fix rv_type to _rvType in isa.hh and isa.cc Change-Id: I68e2b1be9150e6528693e68fb73470d158838885 --- src/arch/riscv/isa.cc | 18 +++++++++--------- src/arch/riscv/isa.hh | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 94a8239bac..266c9568b2 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -244,7 +244,7 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs); } // anonymous namespace ISA::ISA(const Params &p) : - BaseISA(p), rv_type(p.riscv_type), checkAlignment(p.check_alignment) + BaseISA(p), _rvType(p.riscv_type), checkAlignment(p.check_alignment) { _regClasses.push_back(&intRegClass); _regClasses.push_back(&floatRegClass); @@ -299,8 +299,8 @@ void ISA::clear() // mark FS is initial status.fs = INITIAL; - // rv_type dependent init. - switch (rv_type) { + // _rvType dependent init. + switch (_rvType) { case RV32: misa.rv32_mxl = 1; break; @@ -309,7 +309,7 @@ void ISA::clear() status.uxl = status.sxl = 2; break; default: - panic("%s: Unknown rv_type: %d", name(), (int)rv_type); + panic("%s: Unknown _rvType: %d", name(), (int)_rvType); } miscRegFile[MISCREG_ISA] = misa; @@ -465,7 +465,7 @@ ISA::readMiscReg(RegIndex idx) (status.xs == 3) || (status.fs == 3) || (status.vs == 3); // For RV32, the SD bit is at index 31 // For RV64, the SD bit is at index 63. - switch (rv_type) { + switch (_rvType) { case RV32: status.rv32_sd = sd_bit; break; @@ -473,7 +473,7 @@ ISA::readMiscReg(RegIndex idx) status.rv64_sd = sd_bit; break; default: - panic("%s: Unknown rv_type: %d", name(), (int)rv_type); + panic("%s: Unknown _rvType: %d", name(), (int)_rvType); } setMiscRegNoEffect(idx, status); @@ -541,7 +541,7 @@ ISA::setMiscReg(RegIndex idx, RegVal val) assert(readMiscRegNoEffect(MISCREG_PRV) == PRV_M); int regSize = 0; - switch (rv_type) { + switch (_rvType) { case RV32: regSize = 4; break; @@ -549,7 +549,7 @@ ISA::setMiscReg(RegIndex idx, RegVal val) regSize = 8; break; default: - panic("%s: Unknown rv_type: %d", name(), (int)rv_type); + panic("%s: Unknown _rvType: %d", name(), (int)_rvType); } // Specs do not seem to mention what should be @@ -643,7 +643,7 @@ ISA::setMiscReg(RegIndex idx, RegVal val) break; case MISCREG_STATUS: { - if (rv_type != RV32) { + if (_rvType != RV32) { // SXL and UXL are hard-wired to 64 bit auto cur = readMiscRegNoEffect(idx); val &= ~(STATUS_SXL_MASK | STATUS_UXL_MASK); diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 31001c04b4..a2cda6b10a 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -70,7 +70,7 @@ enum FPUStatus class ISA : public BaseISA { protected: - RiscvType rv_type; + RiscvType _rvType; std::vector miscRegFile; bool checkAlignment; @@ -89,7 +89,7 @@ class ISA : public BaseISA PCStateBase* newPCState(Addr new_inst_addr=0) const override { - return new PCState(new_inst_addr, rv_type); + return new PCState(new_inst_addr, _rvType); } public: @@ -110,7 +110,7 @@ class ISA : public BaseISA virtual const std::unordered_map& getCSRMaskMap() const { - return CSRMasks[rv_type]; + return CSRMasks[_rvType]; } bool alignmentCheckEnabled() const { return checkAlignment; } @@ -134,7 +134,7 @@ class ISA : public BaseISA void resetThread() override; - RiscvType rvType() const { return rv_type; } + RiscvType rvType() const { return _rvType; } void clearLoadReservation(ContextID cid) From 57fff0221b5b73375a08a153547dba6d00db2717 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 5 May 2023 11:30:03 -0700 Subject: [PATCH 151/693] tests: Unify testing directory names This updates the testing directory so everything uses underscores and is more uniform. Change-Id: I7ea45c9e0fc1892605387cd2453ce8656ddccd49 --- tests/gem5/{arm-boot-tests => arm_boot_tests}/test_linux_boot.py | 0 tests/gem5/{dram-lowp => dram_lowp}/ref/simout | 0 tests/gem5/{dram-lowp => dram_lowp}/test_dram_lowp.py | 0 .../{gem5-resources => gem5_resources}/test_download_resources.py | 0 .../gem5/{kvm-fork-tests => kvm_fork_tests}/test_kvm_fork_run.py | 0 .../{kvm-switch-tests => kvm_switch_tests}/test_kvm_cpu_switch.py | 0 .../gem5/{parsec-benchmarks => parsec_benchmarks}/test_parsec.py | 0 tests/gem5/{replacement-policies => replacement_policies}/README | 0 .../cache_hierarchies.py | 0 .../ref/fifo_test1_ld | 0 .../ref/fifo_test1_st | 0 .../ref/fifo_test2_ld | 0 .../ref/fifo_test2_st | 0 .../ref/lfu_test1_ld | 0 .../ref/lfu_test1_st | 0 .../ref/lfu_test2_ld | 0 .../ref/lfu_test2_st | 0 .../ref/lfu_test3_ld | 0 .../ref/lfu_test3_st | 0 .../ref/lip_test1_ld | 0 .../ref/lip_test1_st | 0 .../ref/lru_test1_ld | 0 .../ref/lru_test1_st | 0 .../ref/lru_test2_ld | 0 .../ref/lru_test2_st | 0 .../ref/lru_test3_ld | 0 .../ref/lru_test3_st | 0 .../ref/lru_test4_ld | 0 .../ref/lru_test4_st | 0 .../ref/mru_test1_ld | 0 .../ref/mru_test1_st | 0 .../ref/mru_test2_ld | 0 .../ref/mru_test2_st | 0 .../ref/nru_test1_ld | 0 .../ref/nru_test1_st | 0 .../ref/rrip_test1_ld | 0 .../ref/rrip_test1_st | 0 .../ref/rrip_test2_ld | 0 .../ref/rrip_test2_st | 0 .../ref/second_chance_test1_ld | 0 .../ref/second_chance_test1_st | 0 .../ref/second_chance_test2_ld | 0 .../ref/second_chance_test2_st | 0 .../ref/second_chance_test3_ld | 0 .../ref/second_chance_test3_st | 0 .../ref/tree_plru_test1_ld | 0 .../ref/tree_plru_test1_st | 0 .../ref/tree_plru_test2_ld | 0 .../ref/tree_plru_test2_st | 0 .../ref/tree_plru_test3_ld | 0 .../ref/tree_plru_test3_st | 0 .../run_replacement_policy.py | 0 .../test_replacement_policies.py | 0 .../traces/fifo_test1_ld.py | 0 .../traces/fifo_test1_st.py | 0 .../traces/fifo_test2_ld.py | 0 .../traces/fifo_test2_st.py | 0 .../traces/lfu_test1_ld.py | 0 .../traces/lfu_test1_st.py | 0 .../traces/lfu_test2_ld.py | 0 .../traces/lfu_test2_st.py | 0 .../traces/lfu_test3_ld.py | 0 .../traces/lfu_test3_st.py | 0 .../traces/lip_test1_ld.py | 0 .../traces/lip_test1_st.py | 0 .../traces/lru_test1_ld.py | 0 .../traces/lru_test1_st.py | 0 .../traces/lru_test2_ld.py | 0 .../traces/lru_test2_st.py | 0 .../traces/lru_test3_ld.py | 0 .../traces/lru_test3_st.py | 0 .../traces/lru_test4_ld.py | 0 .../traces/lru_test4_st.py | 0 .../traces/mru_test1_ld.py | 0 .../traces/mru_test1_st.py | 0 .../traces/mru_test2_ld.py | 0 .../traces/mru_test2_st.py | 0 .../traces/nru_test1_ld.py | 0 .../traces/nru_test1_st.py | 0 .../traces/rrip_test1_ld.py | 0 .../traces/rrip_test1_st.py | 0 .../traces/rrip_test2_ld.py | 0 .../traces/rrip_test2_st.py | 0 .../traces/second_chance_test1_ld.py | 0 .../traces/second_chance_test1_st.py | 0 .../traces/second_chance_test2_ld.py | 0 .../traces/second_chance_test2_st.py | 0 .../traces/second_chance_test3_ld.py | 0 .../traces/second_chance_test3_st.py | 0 .../traces/tree_plru_test1_ld.py | 0 .../traces/tree_plru_test1_st.py | 0 .../traces/tree_plru_test2_ld.py | 0 .../traces/tree_plru_test2_st.py | 0 .../traces/tree_plru_test3_ld.py | 0 .../traces/tree_plru_test3_st.py | 0 .../{riscv-boot-tests => riscv_boot_tests}/test_linux_boot.py | 0 tests/gem5/{x86-boot-tests => x86_boot_tests}/test_linux_boot.py | 0 97 files changed, 0 insertions(+), 0 deletions(-) rename tests/gem5/{arm-boot-tests => arm_boot_tests}/test_linux_boot.py (100%) rename tests/gem5/{dram-lowp => dram_lowp}/ref/simout (100%) rename tests/gem5/{dram-lowp => dram_lowp}/test_dram_lowp.py (100%) rename tests/gem5/{gem5-resources => gem5_resources}/test_download_resources.py (100%) rename tests/gem5/{kvm-fork-tests => kvm_fork_tests}/test_kvm_fork_run.py (100%) rename tests/gem5/{kvm-switch-tests => kvm_switch_tests}/test_kvm_cpu_switch.py (100%) rename tests/gem5/{parsec-benchmarks => parsec_benchmarks}/test_parsec.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/README (100%) rename tests/gem5/{replacement-policies => replacement_policies}/cache_hierarchies.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/fifo_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/fifo_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/fifo_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/fifo_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lfu_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lfu_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lfu_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lfu_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lfu_test3_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lfu_test3_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lip_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lip_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test3_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test3_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test4_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/lru_test4_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/mru_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/mru_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/mru_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/mru_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/nru_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/nru_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/rrip_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/rrip_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/rrip_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/rrip_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/second_chance_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/second_chance_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/second_chance_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/second_chance_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/second_chance_test3_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/second_chance_test3_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/tree_plru_test1_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/tree_plru_test1_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/tree_plru_test2_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/tree_plru_test2_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/tree_plru_test3_ld (100%) rename tests/gem5/{replacement-policies => replacement_policies}/ref/tree_plru_test3_st (100%) rename tests/gem5/{replacement-policies => replacement_policies}/run_replacement_policy.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/test_replacement_policies.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/fifo_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/fifo_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/fifo_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/fifo_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lfu_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lfu_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lfu_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lfu_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lfu_test3_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lfu_test3_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lip_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lip_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test3_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test3_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test4_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/lru_test4_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/mru_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/mru_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/mru_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/mru_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/nru_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/nru_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/rrip_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/rrip_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/rrip_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/rrip_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/second_chance_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/second_chance_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/second_chance_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/second_chance_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/second_chance_test3_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/second_chance_test3_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/tree_plru_test1_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/tree_plru_test1_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/tree_plru_test2_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/tree_plru_test2_st.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/tree_plru_test3_ld.py (100%) rename tests/gem5/{replacement-policies => replacement_policies}/traces/tree_plru_test3_st.py (100%) rename tests/gem5/{riscv-boot-tests => riscv_boot_tests}/test_linux_boot.py (100%) rename tests/gem5/{x86-boot-tests => x86_boot_tests}/test_linux_boot.py (100%) diff --git a/tests/gem5/arm-boot-tests/test_linux_boot.py b/tests/gem5/arm_boot_tests/test_linux_boot.py similarity index 100% rename from tests/gem5/arm-boot-tests/test_linux_boot.py rename to tests/gem5/arm_boot_tests/test_linux_boot.py diff --git a/tests/gem5/dram-lowp/ref/simout b/tests/gem5/dram_lowp/ref/simout similarity index 100% rename from tests/gem5/dram-lowp/ref/simout rename to tests/gem5/dram_lowp/ref/simout diff --git a/tests/gem5/dram-lowp/test_dram_lowp.py b/tests/gem5/dram_lowp/test_dram_lowp.py similarity index 100% rename from tests/gem5/dram-lowp/test_dram_lowp.py rename to tests/gem5/dram_lowp/test_dram_lowp.py diff --git a/tests/gem5/gem5-resources/test_download_resources.py b/tests/gem5/gem5_resources/test_download_resources.py similarity index 100% rename from tests/gem5/gem5-resources/test_download_resources.py rename to tests/gem5/gem5_resources/test_download_resources.py diff --git a/tests/gem5/kvm-fork-tests/test_kvm_fork_run.py b/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py similarity index 100% rename from tests/gem5/kvm-fork-tests/test_kvm_fork_run.py rename to tests/gem5/kvm_fork_tests/test_kvm_fork_run.py diff --git a/tests/gem5/kvm-switch-tests/test_kvm_cpu_switch.py b/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py similarity index 100% rename from tests/gem5/kvm-switch-tests/test_kvm_cpu_switch.py rename to tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py diff --git a/tests/gem5/parsec-benchmarks/test_parsec.py b/tests/gem5/parsec_benchmarks/test_parsec.py similarity index 100% rename from tests/gem5/parsec-benchmarks/test_parsec.py rename to tests/gem5/parsec_benchmarks/test_parsec.py diff --git a/tests/gem5/replacement-policies/README b/tests/gem5/replacement_policies/README similarity index 100% rename from tests/gem5/replacement-policies/README rename to tests/gem5/replacement_policies/README diff --git a/tests/gem5/replacement-policies/cache_hierarchies.py b/tests/gem5/replacement_policies/cache_hierarchies.py similarity index 100% rename from tests/gem5/replacement-policies/cache_hierarchies.py rename to tests/gem5/replacement_policies/cache_hierarchies.py diff --git a/tests/gem5/replacement-policies/ref/fifo_test1_ld b/tests/gem5/replacement_policies/ref/fifo_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/fifo_test1_ld rename to tests/gem5/replacement_policies/ref/fifo_test1_ld diff --git a/tests/gem5/replacement-policies/ref/fifo_test1_st b/tests/gem5/replacement_policies/ref/fifo_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/fifo_test1_st rename to tests/gem5/replacement_policies/ref/fifo_test1_st diff --git a/tests/gem5/replacement-policies/ref/fifo_test2_ld b/tests/gem5/replacement_policies/ref/fifo_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/fifo_test2_ld rename to tests/gem5/replacement_policies/ref/fifo_test2_ld diff --git a/tests/gem5/replacement-policies/ref/fifo_test2_st b/tests/gem5/replacement_policies/ref/fifo_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/fifo_test2_st rename to tests/gem5/replacement_policies/ref/fifo_test2_st diff --git a/tests/gem5/replacement-policies/ref/lfu_test1_ld b/tests/gem5/replacement_policies/ref/lfu_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lfu_test1_ld rename to tests/gem5/replacement_policies/ref/lfu_test1_ld diff --git a/tests/gem5/replacement-policies/ref/lfu_test1_st b/tests/gem5/replacement_policies/ref/lfu_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lfu_test1_st rename to tests/gem5/replacement_policies/ref/lfu_test1_st diff --git a/tests/gem5/replacement-policies/ref/lfu_test2_ld b/tests/gem5/replacement_policies/ref/lfu_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lfu_test2_ld rename to tests/gem5/replacement_policies/ref/lfu_test2_ld diff --git a/tests/gem5/replacement-policies/ref/lfu_test2_st b/tests/gem5/replacement_policies/ref/lfu_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lfu_test2_st rename to tests/gem5/replacement_policies/ref/lfu_test2_st diff --git a/tests/gem5/replacement-policies/ref/lfu_test3_ld b/tests/gem5/replacement_policies/ref/lfu_test3_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lfu_test3_ld rename to tests/gem5/replacement_policies/ref/lfu_test3_ld diff --git a/tests/gem5/replacement-policies/ref/lfu_test3_st b/tests/gem5/replacement_policies/ref/lfu_test3_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lfu_test3_st rename to tests/gem5/replacement_policies/ref/lfu_test3_st diff --git a/tests/gem5/replacement-policies/ref/lip_test1_ld b/tests/gem5/replacement_policies/ref/lip_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lip_test1_ld rename to tests/gem5/replacement_policies/ref/lip_test1_ld diff --git a/tests/gem5/replacement-policies/ref/lip_test1_st b/tests/gem5/replacement_policies/ref/lip_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lip_test1_st rename to tests/gem5/replacement_policies/ref/lip_test1_st diff --git a/tests/gem5/replacement-policies/ref/lru_test1_ld b/tests/gem5/replacement_policies/ref/lru_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test1_ld rename to tests/gem5/replacement_policies/ref/lru_test1_ld diff --git a/tests/gem5/replacement-policies/ref/lru_test1_st b/tests/gem5/replacement_policies/ref/lru_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test1_st rename to tests/gem5/replacement_policies/ref/lru_test1_st diff --git a/tests/gem5/replacement-policies/ref/lru_test2_ld b/tests/gem5/replacement_policies/ref/lru_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test2_ld rename to tests/gem5/replacement_policies/ref/lru_test2_ld diff --git a/tests/gem5/replacement-policies/ref/lru_test2_st b/tests/gem5/replacement_policies/ref/lru_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test2_st rename to tests/gem5/replacement_policies/ref/lru_test2_st diff --git a/tests/gem5/replacement-policies/ref/lru_test3_ld b/tests/gem5/replacement_policies/ref/lru_test3_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test3_ld rename to tests/gem5/replacement_policies/ref/lru_test3_ld diff --git a/tests/gem5/replacement-policies/ref/lru_test3_st b/tests/gem5/replacement_policies/ref/lru_test3_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test3_st rename to tests/gem5/replacement_policies/ref/lru_test3_st diff --git a/tests/gem5/replacement-policies/ref/lru_test4_ld b/tests/gem5/replacement_policies/ref/lru_test4_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test4_ld rename to tests/gem5/replacement_policies/ref/lru_test4_ld diff --git a/tests/gem5/replacement-policies/ref/lru_test4_st b/tests/gem5/replacement_policies/ref/lru_test4_st similarity index 100% rename from tests/gem5/replacement-policies/ref/lru_test4_st rename to tests/gem5/replacement_policies/ref/lru_test4_st diff --git a/tests/gem5/replacement-policies/ref/mru_test1_ld b/tests/gem5/replacement_policies/ref/mru_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/mru_test1_ld rename to tests/gem5/replacement_policies/ref/mru_test1_ld diff --git a/tests/gem5/replacement-policies/ref/mru_test1_st b/tests/gem5/replacement_policies/ref/mru_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/mru_test1_st rename to tests/gem5/replacement_policies/ref/mru_test1_st diff --git a/tests/gem5/replacement-policies/ref/mru_test2_ld b/tests/gem5/replacement_policies/ref/mru_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/mru_test2_ld rename to tests/gem5/replacement_policies/ref/mru_test2_ld diff --git a/tests/gem5/replacement-policies/ref/mru_test2_st b/tests/gem5/replacement_policies/ref/mru_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/mru_test2_st rename to tests/gem5/replacement_policies/ref/mru_test2_st diff --git a/tests/gem5/replacement-policies/ref/nru_test1_ld b/tests/gem5/replacement_policies/ref/nru_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/nru_test1_ld rename to tests/gem5/replacement_policies/ref/nru_test1_ld diff --git a/tests/gem5/replacement-policies/ref/nru_test1_st b/tests/gem5/replacement_policies/ref/nru_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/nru_test1_st rename to tests/gem5/replacement_policies/ref/nru_test1_st diff --git a/tests/gem5/replacement-policies/ref/rrip_test1_ld b/tests/gem5/replacement_policies/ref/rrip_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/rrip_test1_ld rename to tests/gem5/replacement_policies/ref/rrip_test1_ld diff --git a/tests/gem5/replacement-policies/ref/rrip_test1_st b/tests/gem5/replacement_policies/ref/rrip_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/rrip_test1_st rename to tests/gem5/replacement_policies/ref/rrip_test1_st diff --git a/tests/gem5/replacement-policies/ref/rrip_test2_ld b/tests/gem5/replacement_policies/ref/rrip_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/rrip_test2_ld rename to tests/gem5/replacement_policies/ref/rrip_test2_ld diff --git a/tests/gem5/replacement-policies/ref/rrip_test2_st b/tests/gem5/replacement_policies/ref/rrip_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/rrip_test2_st rename to tests/gem5/replacement_policies/ref/rrip_test2_st diff --git a/tests/gem5/replacement-policies/ref/second_chance_test1_ld b/tests/gem5/replacement_policies/ref/second_chance_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/second_chance_test1_ld rename to tests/gem5/replacement_policies/ref/second_chance_test1_ld diff --git a/tests/gem5/replacement-policies/ref/second_chance_test1_st b/tests/gem5/replacement_policies/ref/second_chance_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/second_chance_test1_st rename to tests/gem5/replacement_policies/ref/second_chance_test1_st diff --git a/tests/gem5/replacement-policies/ref/second_chance_test2_ld b/tests/gem5/replacement_policies/ref/second_chance_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/second_chance_test2_ld rename to tests/gem5/replacement_policies/ref/second_chance_test2_ld diff --git a/tests/gem5/replacement-policies/ref/second_chance_test2_st b/tests/gem5/replacement_policies/ref/second_chance_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/second_chance_test2_st rename to tests/gem5/replacement_policies/ref/second_chance_test2_st diff --git a/tests/gem5/replacement-policies/ref/second_chance_test3_ld b/tests/gem5/replacement_policies/ref/second_chance_test3_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/second_chance_test3_ld rename to tests/gem5/replacement_policies/ref/second_chance_test3_ld diff --git a/tests/gem5/replacement-policies/ref/second_chance_test3_st b/tests/gem5/replacement_policies/ref/second_chance_test3_st similarity index 100% rename from tests/gem5/replacement-policies/ref/second_chance_test3_st rename to tests/gem5/replacement_policies/ref/second_chance_test3_st diff --git a/tests/gem5/replacement-policies/ref/tree_plru_test1_ld b/tests/gem5/replacement_policies/ref/tree_plru_test1_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/tree_plru_test1_ld rename to tests/gem5/replacement_policies/ref/tree_plru_test1_ld diff --git a/tests/gem5/replacement-policies/ref/tree_plru_test1_st b/tests/gem5/replacement_policies/ref/tree_plru_test1_st similarity index 100% rename from tests/gem5/replacement-policies/ref/tree_plru_test1_st rename to tests/gem5/replacement_policies/ref/tree_plru_test1_st diff --git a/tests/gem5/replacement-policies/ref/tree_plru_test2_ld b/tests/gem5/replacement_policies/ref/tree_plru_test2_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/tree_plru_test2_ld rename to tests/gem5/replacement_policies/ref/tree_plru_test2_ld diff --git a/tests/gem5/replacement-policies/ref/tree_plru_test2_st b/tests/gem5/replacement_policies/ref/tree_plru_test2_st similarity index 100% rename from tests/gem5/replacement-policies/ref/tree_plru_test2_st rename to tests/gem5/replacement_policies/ref/tree_plru_test2_st diff --git a/tests/gem5/replacement-policies/ref/tree_plru_test3_ld b/tests/gem5/replacement_policies/ref/tree_plru_test3_ld similarity index 100% rename from tests/gem5/replacement-policies/ref/tree_plru_test3_ld rename to tests/gem5/replacement_policies/ref/tree_plru_test3_ld diff --git a/tests/gem5/replacement-policies/ref/tree_plru_test3_st b/tests/gem5/replacement_policies/ref/tree_plru_test3_st similarity index 100% rename from tests/gem5/replacement-policies/ref/tree_plru_test3_st rename to tests/gem5/replacement_policies/ref/tree_plru_test3_st diff --git a/tests/gem5/replacement-policies/run_replacement_policy.py b/tests/gem5/replacement_policies/run_replacement_policy.py similarity index 100% rename from tests/gem5/replacement-policies/run_replacement_policy.py rename to tests/gem5/replacement_policies/run_replacement_policy.py diff --git a/tests/gem5/replacement-policies/test_replacement_policies.py b/tests/gem5/replacement_policies/test_replacement_policies.py similarity index 100% rename from tests/gem5/replacement-policies/test_replacement_policies.py rename to tests/gem5/replacement_policies/test_replacement_policies.py diff --git a/tests/gem5/replacement-policies/traces/fifo_test1_ld.py b/tests/gem5/replacement_policies/traces/fifo_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/fifo_test1_ld.py rename to tests/gem5/replacement_policies/traces/fifo_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/fifo_test1_st.py b/tests/gem5/replacement_policies/traces/fifo_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/fifo_test1_st.py rename to tests/gem5/replacement_policies/traces/fifo_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/fifo_test2_ld.py b/tests/gem5/replacement_policies/traces/fifo_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/fifo_test2_ld.py rename to tests/gem5/replacement_policies/traces/fifo_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/fifo_test2_st.py b/tests/gem5/replacement_policies/traces/fifo_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/fifo_test2_st.py rename to tests/gem5/replacement_policies/traces/fifo_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/lfu_test1_ld.py b/tests/gem5/replacement_policies/traces/lfu_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lfu_test1_ld.py rename to tests/gem5/replacement_policies/traces/lfu_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/lfu_test1_st.py b/tests/gem5/replacement_policies/traces/lfu_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lfu_test1_st.py rename to tests/gem5/replacement_policies/traces/lfu_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/lfu_test2_ld.py b/tests/gem5/replacement_policies/traces/lfu_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lfu_test2_ld.py rename to tests/gem5/replacement_policies/traces/lfu_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/lfu_test2_st.py b/tests/gem5/replacement_policies/traces/lfu_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lfu_test2_st.py rename to tests/gem5/replacement_policies/traces/lfu_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/lfu_test3_ld.py b/tests/gem5/replacement_policies/traces/lfu_test3_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lfu_test3_ld.py rename to tests/gem5/replacement_policies/traces/lfu_test3_ld.py diff --git a/tests/gem5/replacement-policies/traces/lfu_test3_st.py b/tests/gem5/replacement_policies/traces/lfu_test3_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lfu_test3_st.py rename to tests/gem5/replacement_policies/traces/lfu_test3_st.py diff --git a/tests/gem5/replacement-policies/traces/lip_test1_ld.py b/tests/gem5/replacement_policies/traces/lip_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lip_test1_ld.py rename to tests/gem5/replacement_policies/traces/lip_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/lip_test1_st.py b/tests/gem5/replacement_policies/traces/lip_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lip_test1_st.py rename to tests/gem5/replacement_policies/traces/lip_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/lru_test1_ld.py b/tests/gem5/replacement_policies/traces/lru_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test1_ld.py rename to tests/gem5/replacement_policies/traces/lru_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/lru_test1_st.py b/tests/gem5/replacement_policies/traces/lru_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test1_st.py rename to tests/gem5/replacement_policies/traces/lru_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/lru_test2_ld.py b/tests/gem5/replacement_policies/traces/lru_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test2_ld.py rename to tests/gem5/replacement_policies/traces/lru_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/lru_test2_st.py b/tests/gem5/replacement_policies/traces/lru_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test2_st.py rename to tests/gem5/replacement_policies/traces/lru_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/lru_test3_ld.py b/tests/gem5/replacement_policies/traces/lru_test3_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test3_ld.py rename to tests/gem5/replacement_policies/traces/lru_test3_ld.py diff --git a/tests/gem5/replacement-policies/traces/lru_test3_st.py b/tests/gem5/replacement_policies/traces/lru_test3_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test3_st.py rename to tests/gem5/replacement_policies/traces/lru_test3_st.py diff --git a/tests/gem5/replacement-policies/traces/lru_test4_ld.py b/tests/gem5/replacement_policies/traces/lru_test4_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test4_ld.py rename to tests/gem5/replacement_policies/traces/lru_test4_ld.py diff --git a/tests/gem5/replacement-policies/traces/lru_test4_st.py b/tests/gem5/replacement_policies/traces/lru_test4_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/lru_test4_st.py rename to tests/gem5/replacement_policies/traces/lru_test4_st.py diff --git a/tests/gem5/replacement-policies/traces/mru_test1_ld.py b/tests/gem5/replacement_policies/traces/mru_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/mru_test1_ld.py rename to tests/gem5/replacement_policies/traces/mru_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/mru_test1_st.py b/tests/gem5/replacement_policies/traces/mru_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/mru_test1_st.py rename to tests/gem5/replacement_policies/traces/mru_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/mru_test2_ld.py b/tests/gem5/replacement_policies/traces/mru_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/mru_test2_ld.py rename to tests/gem5/replacement_policies/traces/mru_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/mru_test2_st.py b/tests/gem5/replacement_policies/traces/mru_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/mru_test2_st.py rename to tests/gem5/replacement_policies/traces/mru_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/nru_test1_ld.py b/tests/gem5/replacement_policies/traces/nru_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/nru_test1_ld.py rename to tests/gem5/replacement_policies/traces/nru_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/nru_test1_st.py b/tests/gem5/replacement_policies/traces/nru_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/nru_test1_st.py rename to tests/gem5/replacement_policies/traces/nru_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/rrip_test1_ld.py b/tests/gem5/replacement_policies/traces/rrip_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/rrip_test1_ld.py rename to tests/gem5/replacement_policies/traces/rrip_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/rrip_test1_st.py b/tests/gem5/replacement_policies/traces/rrip_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/rrip_test1_st.py rename to tests/gem5/replacement_policies/traces/rrip_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/rrip_test2_ld.py b/tests/gem5/replacement_policies/traces/rrip_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/rrip_test2_ld.py rename to tests/gem5/replacement_policies/traces/rrip_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/rrip_test2_st.py b/tests/gem5/replacement_policies/traces/rrip_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/rrip_test2_st.py rename to tests/gem5/replacement_policies/traces/rrip_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/second_chance_test1_ld.py b/tests/gem5/replacement_policies/traces/second_chance_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/second_chance_test1_ld.py rename to tests/gem5/replacement_policies/traces/second_chance_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/second_chance_test1_st.py b/tests/gem5/replacement_policies/traces/second_chance_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/second_chance_test1_st.py rename to tests/gem5/replacement_policies/traces/second_chance_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/second_chance_test2_ld.py b/tests/gem5/replacement_policies/traces/second_chance_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/second_chance_test2_ld.py rename to tests/gem5/replacement_policies/traces/second_chance_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/second_chance_test2_st.py b/tests/gem5/replacement_policies/traces/second_chance_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/second_chance_test2_st.py rename to tests/gem5/replacement_policies/traces/second_chance_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/second_chance_test3_ld.py b/tests/gem5/replacement_policies/traces/second_chance_test3_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/second_chance_test3_ld.py rename to tests/gem5/replacement_policies/traces/second_chance_test3_ld.py diff --git a/tests/gem5/replacement-policies/traces/second_chance_test3_st.py b/tests/gem5/replacement_policies/traces/second_chance_test3_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/second_chance_test3_st.py rename to tests/gem5/replacement_policies/traces/second_chance_test3_st.py diff --git a/tests/gem5/replacement-policies/traces/tree_plru_test1_ld.py b/tests/gem5/replacement_policies/traces/tree_plru_test1_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/tree_plru_test1_ld.py rename to tests/gem5/replacement_policies/traces/tree_plru_test1_ld.py diff --git a/tests/gem5/replacement-policies/traces/tree_plru_test1_st.py b/tests/gem5/replacement_policies/traces/tree_plru_test1_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/tree_plru_test1_st.py rename to tests/gem5/replacement_policies/traces/tree_plru_test1_st.py diff --git a/tests/gem5/replacement-policies/traces/tree_plru_test2_ld.py b/tests/gem5/replacement_policies/traces/tree_plru_test2_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/tree_plru_test2_ld.py rename to tests/gem5/replacement_policies/traces/tree_plru_test2_ld.py diff --git a/tests/gem5/replacement-policies/traces/tree_plru_test2_st.py b/tests/gem5/replacement_policies/traces/tree_plru_test2_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/tree_plru_test2_st.py rename to tests/gem5/replacement_policies/traces/tree_plru_test2_st.py diff --git a/tests/gem5/replacement-policies/traces/tree_plru_test3_ld.py b/tests/gem5/replacement_policies/traces/tree_plru_test3_ld.py similarity index 100% rename from tests/gem5/replacement-policies/traces/tree_plru_test3_ld.py rename to tests/gem5/replacement_policies/traces/tree_plru_test3_ld.py diff --git a/tests/gem5/replacement-policies/traces/tree_plru_test3_st.py b/tests/gem5/replacement_policies/traces/tree_plru_test3_st.py similarity index 100% rename from tests/gem5/replacement-policies/traces/tree_plru_test3_st.py rename to tests/gem5/replacement_policies/traces/tree_plru_test3_st.py diff --git a/tests/gem5/riscv-boot-tests/test_linux_boot.py b/tests/gem5/riscv_boot_tests/test_linux_boot.py similarity index 100% rename from tests/gem5/riscv-boot-tests/test_linux_boot.py rename to tests/gem5/riscv_boot_tests/test_linux_boot.py diff --git a/tests/gem5/x86-boot-tests/test_linux_boot.py b/tests/gem5/x86_boot_tests/test_linux_boot.py similarity index 100% rename from tests/gem5/x86-boot-tests/test_linux_boot.py rename to tests/gem5/x86_boot_tests/test_linux_boot.py From 7ff67459b6c0437be2b2b72d452fb7544328a4b6 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 5 May 2023 10:09:50 -0700 Subject: [PATCH 152/693] tests: Add READMEs to the testing directory This change adds READMEs to each directory within tests/gem5, with a short description of the test, as well as how to run it. Change-Id: I574ebcdc837848b52f21e8c0f8856ff09463284b --- tests/gem5/arm_boot_tests/README.md | 9 +++++++++ tests/gem5/asmtest/README.md | 9 +++++++++ tests/gem5/cpu_tests/README.md | 8 ++++++++ tests/gem5/dram_lowp/README.md | 8 ++++++++ tests/gem5/fs/linux/arm/README.md | 8 ++++++++ tests/gem5/gem5_library_example_tests/README.md | 8 ++++++++ tests/gem5/gem5_resources/README.md | 8 ++++++++ tests/gem5/gpu/README.md | 8 ++++++++ tests/gem5/insttest_se/README.md | 8 ++++++++ tests/gem5/kvm_fork_tests/README.md | 8 ++++++++ tests/gem5/kvm_switch_tests/README.md | 8 ++++++++ tests/gem5/learning_gem5/README.md | 9 +++++++++ tests/gem5/m5_util/README.md | 8 ++++++++ tests/gem5/m5threads_test_atomic/README.md | 8 ++++++++ tests/gem5/memory/README.md | 9 +++++++++ tests/gem5/multi_isa/README.md | 9 +++++++++ tests/gem5/parsec_benchmarks/README.md | 9 +++++++++ tests/gem5/riscv_boot_tests/README.md | 9 +++++++++ tests/gem5/se_mode/hello_se/README.md | 8 ++++++++ tests/gem5/stats/README.md | 8 ++++++++ tests/gem5/stdlib/README.md | 8 ++++++++ tests/gem5/to_tick/README.md | 8 ++++++++ tests/gem5/traffic_gen/README.md | 9 +++++++++ tests/gem5/x86_boot_tests/README.md | 9 +++++++++ 24 files changed, 201 insertions(+) create mode 100644 tests/gem5/arm_boot_tests/README.md create mode 100644 tests/gem5/asmtest/README.md create mode 100644 tests/gem5/cpu_tests/README.md create mode 100644 tests/gem5/dram_lowp/README.md create mode 100644 tests/gem5/fs/linux/arm/README.md create mode 100644 tests/gem5/gem5_library_example_tests/README.md create mode 100644 tests/gem5/gem5_resources/README.md create mode 100644 tests/gem5/gpu/README.md create mode 100644 tests/gem5/insttest_se/README.md create mode 100644 tests/gem5/kvm_fork_tests/README.md create mode 100644 tests/gem5/kvm_switch_tests/README.md create mode 100644 tests/gem5/learning_gem5/README.md create mode 100644 tests/gem5/m5_util/README.md create mode 100644 tests/gem5/m5threads_test_atomic/README.md create mode 100644 tests/gem5/memory/README.md create mode 100644 tests/gem5/multi_isa/README.md create mode 100644 tests/gem5/parsec_benchmarks/README.md create mode 100644 tests/gem5/riscv_boot_tests/README.md create mode 100644 tests/gem5/se_mode/hello_se/README.md create mode 100644 tests/gem5/stats/README.md create mode 100644 tests/gem5/stdlib/README.md create mode 100644 tests/gem5/to_tick/README.md create mode 100644 tests/gem5/traffic_gen/README.md create mode 100644 tests/gem5/x86_boot_tests/README.md diff --git a/tests/gem5/arm_boot_tests/README.md b/tests/gem5/arm_boot_tests/README.md new file mode 100644 index 0000000000..68d5de97f1 --- /dev/null +++ b/tests/gem5/arm_boot_tests/README.md @@ -0,0 +1,9 @@ +# Arm Boot Tests + +These tests run a series of Linux boots on the ARMBoard. +It varies the CPU type, number of CPUs, and memory used for each run. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/arm_boot_tests --length=[length] +``` diff --git a/tests/gem5/asmtest/README.md b/tests/gem5/asmtest/README.md new file mode 100644 index 0000000000..fcbe8ea65c --- /dev/null +++ b/tests/gem5/asmtest/README.md @@ -0,0 +1,9 @@ +# ASM Test + +These tests run a set of RISCV binaries on a bare bones syscall execution. +In addition, these test run these binaries against different CPU types. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/asmtest --length=[length] +``` diff --git a/tests/gem5/cpu_tests/README.md b/tests/gem5/cpu_tests/README.md new file mode 100644 index 0000000000..574d12ce0a --- /dev/null +++ b/tests/gem5/cpu_tests/README.md @@ -0,0 +1,8 @@ +# CPU Tests + +These tests run the Bubblesort and FloatMM workloads against the different CPU models. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/cpu_tests --length=[length] +``` diff --git a/tests/gem5/dram_lowp/README.md b/tests/gem5/dram_lowp/README.md new file mode 100644 index 0000000000..bff3f033fd --- /dev/null +++ b/tests/gem5/dram_lowp/README.md @@ -0,0 +1,8 @@ +# DRAM LowP + +These tests run the `configs/dram` scripts that trigger low power state transitions in the DRAM controller. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/dram_lowp --length=[length] +``` diff --git a/tests/gem5/fs/linux/arm/README.md b/tests/gem5/fs/linux/arm/README.md new file mode 100644 index 0000000000..ba4bf07b36 --- /dev/null +++ b/tests/gem5/fs/linux/arm/README.md @@ -0,0 +1,8 @@ +# FS + +This is a set of full system ARM tests. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/fs/linux/arm --length=[length] +``` diff --git a/tests/gem5/gem5_library_example_tests/README.md b/tests/gem5/gem5_library_example_tests/README.md new file mode 100644 index 0000000000..3abba289f7 --- /dev/null +++ b/tests/gem5/gem5_library_example_tests/README.md @@ -0,0 +1,8 @@ +# gem5 Library Example Tests + +This set of tests checks the examples in `configs/example/gem5_library`, and makes sure they run to completion. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/gem5-resources --length=very-long +``` diff --git a/tests/gem5/gem5_resources/README.md b/tests/gem5/gem5_resources/README.md new file mode 100644 index 0000000000..8243c01b9f --- /dev/null +++ b/tests/gem5/gem5_resources/README.md @@ -0,0 +1,8 @@ +# gem5 Resources + +This test makes sure that resources you download within gem5 work properly, and the downloaded resource matches the input given. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/gem5_resources --length=very-long +``` diff --git a/tests/gem5/gpu/README.md b/tests/gem5/gpu/README.md new file mode 100644 index 0000000000..9722e30161 --- /dev/null +++ b/tests/gem5/gpu/README.md @@ -0,0 +1,8 @@ +# GPU + +These tests do random checks to the Ruby GPU protocol within gem5. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/gem5-resources --length=very-long +``` diff --git a/tests/gem5/insttest_se/README.md b/tests/gem5/insttest_se/README.md new file mode 100644 index 0000000000..3895316674 --- /dev/null +++ b/tests/gem5/insttest_se/README.md @@ -0,0 +1,8 @@ +# Inst Test SE + +These test the insttest binary running on the SPARC ISA, checking against different CPU models. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/insttest_se --length=[length] +``` diff --git a/tests/gem5/kvm_fork_tests/README.md b/tests/gem5/kvm_fork_tests/README.md new file mode 100644 index 0000000000..5d2d8e8ff8 --- /dev/null +++ b/tests/gem5/kvm_fork_tests/README.md @@ -0,0 +1,8 @@ +# KVM Fork Tests + +These tests check that gem5 can fork with the KVM cpu, then switch to a different CPU. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/kvm_fork_tests --length=[length] +``` diff --git a/tests/gem5/kvm_switch_tests/README.md b/tests/gem5/kvm_switch_tests/README.md new file mode 100644 index 0000000000..9a46aa6c8b --- /dev/null +++ b/tests/gem5/kvm_switch_tests/README.md @@ -0,0 +1,8 @@ +# KVM Switch Tests + +These tests ensure that gem5 can switch processors during simulation. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/kvm_switch_tests --length=[length] +``` diff --git a/tests/gem5/learning_gem5/README.md b/tests/gem5/learning_gem5/README.md new file mode 100644 index 0000000000..eda68d9d4c --- /dev/null +++ b/tests/gem5/learning_gem5/README.md @@ -0,0 +1,9 @@ +# Learning gem5 + +This set of tests ensures that the example scripts for the gem5 tutorial run properly. + +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/learning_gem5 --length=[length] +``` diff --git a/tests/gem5/m5_util/README.md b/tests/gem5/m5_util/README.md new file mode 100644 index 0000000000..133345a904 --- /dev/null +++ b/tests/gem5/m5_util/README.md @@ -0,0 +1,8 @@ +# m5 Util + +These test the util m5 exit assembly instruction. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/m5_util --length=[length] +``` diff --git a/tests/gem5/m5threads_test_atomic/README.md b/tests/gem5/m5threads_test_atomic/README.md new file mode 100644 index 0000000000..5e52b91958 --- /dev/null +++ b/tests/gem5/m5threads_test_atomic/README.md @@ -0,0 +1,8 @@ +# m5 Threads Test Atomic + +These are m5threads atomic tests that run against different CPU types. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/m5threads_test_atomic --length=[length] +``` diff --git a/tests/gem5/memory/README.md b/tests/gem5/memory/README.md new file mode 100644 index 0000000000..892593394d --- /dev/null +++ b/tests/gem5/memory/README.md @@ -0,0 +1,9 @@ +# Memory + +These run a set of tests on memory within gem5. + +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/memory --length=[length] +``` diff --git a/tests/gem5/multi_isa/README.md b/tests/gem5/multi_isa/README.md new file mode 100644 index 0000000000..94d8c1a3e1 --- /dev/null +++ b/tests/gem5/multi_isa/README.md @@ -0,0 +1,9 @@ +# Multi ISA + +These tests check that all our ISAs are both currrently supported within gem5, as well as checking that get_runtime_isa() works as expected. + +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/multi_isa --length=[length] +``` diff --git a/tests/gem5/parsec_benchmarks/README.md b/tests/gem5/parsec_benchmarks/README.md new file mode 100644 index 0000000000..90dfd5a8e8 --- /dev/null +++ b/tests/gem5/parsec_benchmarks/README.md @@ -0,0 +1,9 @@ +# Parsec Benchmarks + +These tests run through a subset of the parsec benchmarks within gem5. + +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/parsec_benchmarks --length=[length] +``` diff --git a/tests/gem5/riscv_boot_tests/README.md b/tests/gem5/riscv_boot_tests/README.md new file mode 100644 index 0000000000..002cc4d09d --- /dev/null +++ b/tests/gem5/riscv_boot_tests/README.md @@ -0,0 +1,9 @@ +# RISCV Boot Tests + +These tests run a series of Linux boots on the RISCVBoard. +It varies the CPU type, number of CPUs, and memory used for each run. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/riscv_boot_tests --length=[length] +``` diff --git a/tests/gem5/se_mode/hello_se/README.md b/tests/gem5/se_mode/hello_se/README.md new file mode 100644 index 0000000000..b3109692b0 --- /dev/null +++ b/tests/gem5/se_mode/hello_se/README.md @@ -0,0 +1,8 @@ +# SE Mode + +These tests use the SimpleBoard to test simple binaries in SE mode, both with single and multi cores. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/se_mode/hello_se --length=[length] +``` diff --git a/tests/gem5/stats/README.md b/tests/gem5/stats/README.md new file mode 100644 index 0000000000..c55600bed1 --- /dev/null +++ b/tests/gem5/stats/README.md @@ -0,0 +1,8 @@ +# Stats + +This test runs an SE simulation with the hdf5 stats and checks that the simulation succeeds and the stats file exists. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/stats --length=[length] +``` diff --git a/tests/gem5/stdlib/README.md b/tests/gem5/stdlib/README.md new file mode 100644 index 0000000000..0b0649f6b6 --- /dev/null +++ b/tests/gem5/stdlib/README.md @@ -0,0 +1,8 @@ +# Standard Library + +These tests check that the BaseCPUProcessor and the gem5.utils.requires function work as intended. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/stdlib --length=[length] +``` diff --git a/tests/gem5/to_tick/README.md b/tests/gem5/to_tick/README.md new file mode 100644 index 0000000000..e675905120 --- /dev/null +++ b/tests/gem5/to_tick/README.md @@ -0,0 +1,8 @@ +# To Tick + +These tests check that setting the max tick in various ways behaves as expected, as well as that event scheduling at a certain tick works. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/to_tick --length=[length] +``` diff --git a/tests/gem5/traffic_gen/README.md b/tests/gem5/traffic_gen/README.md new file mode 100644 index 0000000000..dadb71b641 --- /dev/null +++ b/tests/gem5/traffic_gen/README.md @@ -0,0 +1,9 @@ +# Traffic Generator + +This tests the gem5 memory components with a simple traffic generator. +It also checks the correctness of the statistics outputted by gem5. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/traffic_gen --length=[length] +``` diff --git a/tests/gem5/x86_boot_tests/README.md b/tests/gem5/x86_boot_tests/README.md new file mode 100644 index 0000000000..92357b6bb2 --- /dev/null +++ b/tests/gem5/x86_boot_tests/README.md @@ -0,0 +1,9 @@ +# X86 Boot Tests + +These tests run a series of Linux boots on the X86Board. +It varies the CPU type, number of CPUs, and memory used for each run. +To run these tests by themselves, you can run the following command in the tests directory: + +```bash +./main.py run gem5/x86_boot_tests --length=[length] +``` From 3bf92d0e0be31c6b1242a57ca37c35fd0e496e5b Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 5 May 2023 10:13:14 -0700 Subject: [PATCH 153/693] tests: Update layout of testing directory This changeset reorganizes the testing directory within gem5, removing the bigger config folders, then replacing them with smaller configs folders within each directory containing only the scripts necessary for that set of tests. It also changes the locations of the config scripts used in each set of tests, and updates the tests accordingly. Change-Id: I38297d4496f72bd5cf7200471acd5c4d93002b27 --- tests/configs/dram-lowp.py | 60 --- tests/configs/gpu-randomtest-ruby.py | 164 ------- tests/configs/gpu-ruby.py | 433 ------------------ tests/configs/memcheck.py | 60 --- tests/configs/memtest-filter.py | 83 ---- tests/configs/memtest-ruby.py | 122 ----- tests/configs/memtest.py | 77 ---- tests/configs/minor-timing-mp.py | 48 -- tests/configs/minor-timing.py | 44 -- tests/configs/o3-timing-checker.py | 44 -- tests/configs/o3-timing-mp-ruby.py | 68 --- tests/configs/o3-timing-mp.py | 48 -- tests/configs/o3-timing-mt.py | 63 --- tests/configs/o3-timing-ruby.py | 56 --- tests/configs/o3-timing.py | 57 --- tests/configs/pc-o3-timing.py | 41 -- tests/configs/pc-simple-atomic.py | 41 -- tests/configs/pc-simple-timing-ruby.py | 91 ---- tests/configs/pc-simple-timing.py | 41 -- tests/configs/pc-switcheroo-full.py | 48 -- tests/configs/rubytest-ruby.py | 136 ------ tests/configs/simple-atomic-dummychecker.py | 41 -- tests/configs/simple-atomic-mp-ruby.py | 66 --- tests/configs/simple-atomic-mp.py | 45 -- tests/configs/simple-atomic.py | 44 -- tests/configs/simple-timing-mp-ruby.py | 97 ---- tests/configs/simple-timing-mp.py | 45 -- tests/configs/simple-timing-ruby.py | 104 ----- tests/configs/simple-timing.py | 44 -- tests/configs/t1000-simple-atomic.py | 59 --- tests/configs/x86_generic.py | 123 ----- .../configs/arm_boot_exit_run.py | 0 tests/gem5/arm_boot_tests/test_linux_boot.py | 3 +- .../gem5/asmtest/configs/simple_binary_run.py | 184 ++++++++ tests/gem5/asmtest/tests.py | 1 + tests/gem5/configs/checkpoint.py | 133 ------ tests/gem5/configs/switcheroo.py | 148 ------ .../{ => fs/linux/arm}/configs/arm_generic.py | 0 .../{ => fs/linux/arm}/configs/base_caches.py | 0 .../{ => fs/linux/arm}/configs/base_config.py | 0 .../linux/arm}/configs/realview-minor-dual.py | 0 .../linux/arm}/configs/realview-minor.py | 0 .../linux/arm}/configs/realview-o3-checker.py | 0 .../linux/arm}/configs/realview-o3-dual.py | 0 .../{ => fs/linux/arm}/configs/realview-o3.py | 0 .../realview-simple-atomic-checkpoint.py | 0 .../configs/realview-simple-atomic-dual.py | 0 .../arm}/configs/realview-simple-atomic.py | 0 .../realview-simple-timing-dual-ruby.py | 0 .../configs/realview-simple-timing-dual.py | 0 .../configs/realview-simple-timing-ruby.py | 0 .../arm}/configs/realview-simple-timing.py | 0 .../configs/realview-switcheroo-atomic.py | 0 .../arm}/configs/realview-switcheroo-full.py | 0 .../realview-switcheroo-noncaching-timing.py | 0 .../arm}/configs/realview-switcheroo-o3.py | 0 .../configs/realview-switcheroo-timing.py | 0 .../linux/arm}/configs/realview64-kvm-dual.py | 0 .../linux/arm}/configs/realview64-kvm.py | 0 .../arm}/configs/realview64-minor-dual.py | 0 .../linux/arm}/configs/realview64-minor.py | 0 .../arm}/configs/realview64-o3-checker.py | 0 .../arm}/configs/realview64-o3-dual-ruby.py | 0 .../linux/arm}/configs/realview64-o3-dual.py | 0 .../linux/arm}/configs/realview64-o3.py | 0 .../realview64-simple-atomic-checkpoint.py | 0 .../configs/realview64-simple-atomic-dual.py | 0 .../arm}/configs/realview64-simple-atomic.py | 0 .../realview64-simple-timing-dual-ruby.py | 0 .../configs/realview64-simple-timing-dual.py | 0 .../configs/realview64-simple-timing-ruby.py | 0 .../arm}/configs/realview64-simple-timing.py | 0 .../configs/realview64-switcheroo-atomic.py | 0 .../configs/realview64-switcheroo-full.py | 0 .../arm}/configs/realview64-switcheroo-o3.py | 0 .../configs/realview64-switcheroo-timing.py | 0 tests/gem5/fs/linux/arm/run.py | 2 +- tests/gem5/fs/linux/arm/test.py | 33 +- .../configs/download_check.py | 0 .../gem5_resources/test_download_resources.py | 7 +- .../insttest_se/configs/simple_binary_run.py | 130 ++++++ tests/gem5/insttest_se/test.py | 1 + .../configs/boot_kvm_fork_run.py | 0 .../gem5/kvm_fork_tests/test_kvm_fork_run.py | 7 +- .../configs/boot_kvm_switch_exit.py | 0 .../kvm_switch_tests/test_kvm_cpu_switch.py | 1 + .../gem5/m5_util/configs/simple_binary_run.py | 103 +++++ tests/gem5/m5_util/test_exit.py | 9 +- .../configs/runtime_isa_check.py | 0 .../configs/supported_isa_check.py | 0 tests/gem5/multi_isa/test_multi_isa.py | 3 + .../configs/parsec_disk_run.py | 0 tests/gem5/parsec_benchmarks/test_parsec.py | 7 +- .../configs/run_replacement_policy.py | 94 ++++ .../test_replacement_policies.py | 3 +- .../configs/riscv_boot_exit_run.py | 0 .../gem5/riscv_boot_tests/test_linux_boot.py | 1 + .../hello_se}/configs/simple_binary_run.py | 49 +- tests/gem5/se_mode/hello_se/test_hello_se.py | 8 +- .../se_mode/hello_se/test_se_multicore.py | 8 +- tests/gem5/stats/configs/simple_binary_run.py | 112 +++++ tests/gem5/stats/test_hdf5.py | 9 +- .../{ => stdlib}/configs/requires_check.py | 0 .../gem5/stdlib/configs/simple_binary_run.py | 124 +++++ tests/gem5/stdlib/test_base_cpu_processor.py | 27 +- tests/gem5/stdlib/test_requires.py | 2 + .../{ => configs}/simple_traffic_run.py | 0 .../traffic_gen/test_memory_traffic_gen.py | 1 + .../configs/x86_boot_exit_run.py | 0 tests/gem5/x86_boot_tests/test_linux_boot.py | 7 +- 110 files changed, 883 insertions(+), 2827 deletions(-) delete mode 100644 tests/configs/dram-lowp.py delete mode 100644 tests/configs/gpu-randomtest-ruby.py delete mode 100644 tests/configs/gpu-ruby.py delete mode 100644 tests/configs/memcheck.py delete mode 100644 tests/configs/memtest-filter.py delete mode 100644 tests/configs/memtest-ruby.py delete mode 100644 tests/configs/memtest.py delete mode 100644 tests/configs/minor-timing-mp.py delete mode 100644 tests/configs/minor-timing.py delete mode 100644 tests/configs/o3-timing-checker.py delete mode 100644 tests/configs/o3-timing-mp-ruby.py delete mode 100644 tests/configs/o3-timing-mp.py delete mode 100644 tests/configs/o3-timing-mt.py delete mode 100644 tests/configs/o3-timing-ruby.py delete mode 100644 tests/configs/o3-timing.py delete mode 100644 tests/configs/pc-o3-timing.py delete mode 100644 tests/configs/pc-simple-atomic.py delete mode 100644 tests/configs/pc-simple-timing-ruby.py delete mode 100644 tests/configs/pc-simple-timing.py delete mode 100644 tests/configs/pc-switcheroo-full.py delete mode 100644 tests/configs/rubytest-ruby.py delete mode 100644 tests/configs/simple-atomic-dummychecker.py delete mode 100644 tests/configs/simple-atomic-mp-ruby.py delete mode 100644 tests/configs/simple-atomic-mp.py delete mode 100644 tests/configs/simple-atomic.py delete mode 100644 tests/configs/simple-timing-mp-ruby.py delete mode 100644 tests/configs/simple-timing-mp.py delete mode 100644 tests/configs/simple-timing-ruby.py delete mode 100644 tests/configs/simple-timing.py delete mode 100644 tests/configs/t1000-simple-atomic.py delete mode 100644 tests/configs/x86_generic.py rename tests/gem5/{ => arm_boot_tests}/configs/arm_boot_exit_run.py (100%) create mode 100644 tests/gem5/asmtest/configs/simple_binary_run.py delete mode 100644 tests/gem5/configs/checkpoint.py delete mode 100644 tests/gem5/configs/switcheroo.py rename tests/gem5/{ => fs/linux/arm}/configs/arm_generic.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/base_caches.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/base_config.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-minor-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-minor.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-o3-checker.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-o3-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-o3.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-atomic-checkpoint.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-atomic-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-atomic.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-timing-dual-ruby.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-timing-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-timing-ruby.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-simple-timing.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-switcheroo-atomic.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-switcheroo-full.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-switcheroo-noncaching-timing.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-switcheroo-o3.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview-switcheroo-timing.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-kvm-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-kvm.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-minor-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-minor.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-o3-checker.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-o3-dual-ruby.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-o3-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-o3.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-atomic-checkpoint.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-atomic-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-atomic.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-timing-dual-ruby.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-timing-dual.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-timing-ruby.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-simple-timing.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-switcheroo-atomic.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-switcheroo-full.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-switcheroo-o3.py (100%) rename tests/gem5/{ => fs/linux/arm}/configs/realview64-switcheroo-timing.py (100%) rename tests/gem5/{ => gem5_resources}/configs/download_check.py (100%) create mode 100644 tests/gem5/insttest_se/configs/simple_binary_run.py rename tests/gem5/{ => kvm_fork_tests}/configs/boot_kvm_fork_run.py (100%) rename tests/gem5/{ => kvm_switch_tests}/configs/boot_kvm_switch_exit.py (100%) create mode 100644 tests/gem5/m5_util/configs/simple_binary_run.py rename tests/gem5/{ => multi_isa}/configs/runtime_isa_check.py (100%) rename tests/gem5/{ => multi_isa}/configs/supported_isa_check.py (100%) rename tests/gem5/{ => parsec_benchmarks}/configs/parsec_disk_run.py (100%) create mode 100644 tests/gem5/replacement_policies/configs/run_replacement_policy.py rename tests/gem5/{ => riscv_boot_tests}/configs/riscv_boot_exit_run.py (100%) rename tests/gem5/{ => se_mode/hello_se}/configs/simple_binary_run.py (83%) create mode 100644 tests/gem5/stats/configs/simple_binary_run.py rename tests/gem5/{ => stdlib}/configs/requires_check.py (100%) create mode 100644 tests/gem5/stdlib/configs/simple_binary_run.py rename tests/gem5/traffic_gen/{ => configs}/simple_traffic_run.py (100%) rename tests/gem5/{ => x86_boot_tests}/configs/x86_boot_exit_run.py (100%) diff --git a/tests/configs/dram-lowp.py b/tests/configs/dram-lowp.py deleted file mode 100644 index 25e7cc3087..0000000000 --- a/tests/configs/dram-lowp.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) 2017 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) 2015 Jason Lowe-Power -# 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. -# -# A wrapper around configs/dram/low_power_sweep.py - -# For some reason, this is implicitly needed by run.py -root = None - -import m5 - - -def run_test(root): - # Called from tests/run.py - - import sys - - argv = [ - sys.argv[0], - # Add a specific page policy and specify the number of ranks - f"-p{page_policy}", - "-r 2", - ] - - # Execute the script we are wrapping - run_config("configs/dram/low_power_sweep.py", argv=argv) diff --git a/tests/configs/gpu-randomtest-ruby.py b/tests/configs/gpu-randomtest-ruby.py deleted file mode 100644 index cfc65526e5..0000000000 --- a/tests/configs/gpu-randomtest-ruby.py +++ /dev/null @@ -1,164 +0,0 @@ -# -# Copyright (c) 2010-2015 Advanced Micro Devices, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. 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. -# -# 3. Neither the name of the copyright holder 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 HOLDER 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. - -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -import os, argparse, sys - -m5.util.addToPath("../configs/") - -from ruby import Ruby -from common import Options - -parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) - -# add the gpu specific options expected by the the gpu and gpu_RfO -parser.add_argument( - "-u", - "--num-compute-units", - type=int, - default=8, - help="number of compute units in the GPU", -) -parser.add_argument( - "--num-cp", - type=int, - default=0, - help="Number of GPU Command Processors (CP)", -) -parser.add_argument( - "--simds-per-cu", type=int, default=4, help="SIMD unitsper CU" -) -parser.add_argument( - "--wf-size", type=int, default=64, help="Wavefront size(in workitems)" -) -parser.add_argument( - "--wfs-per-simd", - type=int, - default=10, - help="Number of WF slots per SIMD", -) - -# Add the ruby specific and protocol specific options -Ruby.define_options(parser) - -args = parser.parse_args() - -# -# Set the default cache size and associativity to be very small to encourage -# races between requests and writebacks. -# -args.l1d_size = "256B" -args.l1i_size = "256B" -args.l2_size = "512B" -args.l3_size = "1kB" -args.l1d_assoc = 2 -args.l1i_assoc = 2 -args.l2_assoc = 2 -args.l3_assoc = 2 -args.num_compute_units = 8 -args.num_sqc = 2 - -# Check to for the GPU_RfO protocol. Other GPU protocols are non-SC and will -# not work with the Ruby random tester. -assert buildEnv["PROTOCOL"] == "GPU_RfO" - -# -# create the tester and system, including ruby -# -tester = RubyTester( - check_flush=False, - checks_to_complete=100, - wakeup_frequency=10, - num_cpus=args.num_cpus, -) - -# We set the testers as cpu for ruby to find the correct clock domains -# for the L1 Objects. -system = System(cpu=tester) - -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain(voltage=args.sys_voltage) -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -system.mem_ranges = AddrRange("256MB") - -# the ruby tester reuses num_cpus to specify the -# number of cpu ports connected to the tester object, which -# is stored in system.cpu. because there is only ever one -# tester object, num_cpus is not necessarily equal to the -# size of system.cpu -cpu_list = [system.cpu] * args.num_cpus -Ruby.create_system(args, False, system, cpus=cpu_list) - -# Create a separate clock domain for Ruby -system.ruby.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -tester.num_cpus = len(system.ruby._cpu_ports) - -# -# The tester is most effective when randomization is turned on and -# artifical delay is randomly inserted on messages -# -system.ruby.randomization = True - -for ruby_port in system.ruby._cpu_ports: - # - # Tie the ruby tester ports to the ruby cpu read and write ports - # - if ruby_port.support_data_reqs and ruby_port.support_inst_reqs: - tester.cpuInstDataPort = ruby_port.in_ports - elif ruby_port.support_data_reqs: - tester.cpuDataPort = ruby_port.in_ports - elif ruby_port.support_inst_reqs: - tester.cpuInstPort = ruby_port.in_ports - - # Do not automatically retry stalled Ruby requests - ruby_port.no_retry_on_stall = True - - # - # Tell the sequencer this is the ruby tester so that it - # copies the subblock back to the checker - # - ruby_port.using_ruby_tester = True - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/gpu-ruby.py b/tests/configs/gpu-ruby.py deleted file mode 100644 index 7606168a98..0000000000 --- a/tests/configs/gpu-ruby.py +++ /dev/null @@ -1,433 +0,0 @@ -# -# Copyright (c) 2015 Advanced Micro Devices, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. 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. -# -# 3. Neither the name of the copyright holder 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 HOLDER 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. - -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -import os, argparse, sys, math, glob - -m5.util.addToPath("../configs/") - -from ruby import Ruby -from common import Options -from common import GPUTLBOptions, GPUTLBConfig - - -def run_test(root): - """gpu test requires a specialized run_test implementation to set up the - mmio space.""" - - # instantiate configuration - m5.instantiate() - - # Now that the system has been constructed, setup the mmio space - root.system.cpu[0].workload[0].map(0x10000000, 0x200000000, 4096) - - # simulate until program terminates - exit_event = m5.simulate(maxtick) - print("Exiting @ tick", m5.curTick(), "because", exit_event.getCause()) - - -parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) -Options.addSEOptions(parser) - -parser.add_argument( - "-k", - "--kernel-files", - help="file(s) containing GPU kernel code (colon separated)", -) -parser.add_argument( - "-u", - "--num-compute-units", - type=int, - default=2, - help="number of GPU compute units", -), -parser.add_argument( - "--num-cp", - type=int, - default=0, - help="Number of GPU Command Processors (CP)", -) -parser.add_argument( - "--simds-per-cu", type=int, default=4, help="SIMD unitsper CU" -) -parser.add_argument( - "--cu-per-sqc", - type=int, - default=4, - help="number of CUssharing an SQC (icache, and thus icache TLB)", -) -parser.add_argument( - "--wf-size", type=int, default=64, help="Wavefront size(in workitems)" -) -parser.add_argument( - "--wfs-per-simd", - type=int, - default=8, - help="Number of WF slots per SIMD", -) -parser.add_argument( - "--sp-bypass-path-length", - type=int, - default=4, - help="Number of stages of bypass path in vector ALU for Single " - "Precision ops", -) -parser.add_argument( - "--dp-bypass-path-length", - type=int, - default=4, - help="Number of stages of bypass path in vector ALU for Double " - "Precision ops", -) -parser.add_argument( - "--issue-period", - type=int, - default=4, - help="Number of cycles per vector instruction issue period", -) -parser.add_argument( - "--glbmem-wr-bus-width", - type=int, - default=32, - help="VGPR to Coalescer (Global Memory) data bus width in bytes", -) -parser.add_argument( - "--glbmem-rd-bus-width", - type=int, - default=32, - help="Coalescer to VGPR (Global Memory) data bus width in bytes", -) -parser.add_argument( - "--shr-mem-pipes-per-cu", - type=int, - default=1, - help="Number of Shared Memory pipelines per CU", -) -parser.add_argument( - "--glb-mem-pipes-per-cu", - type=int, - default=1, - help="Number of Global Memory pipelines per CU", -) -parser.add_argument( - "--vreg-file-size", - type=int, - default=2048, - help="number of physical vector registers per SIMD", -) -parser.add_argument( - "--bw-scalor", - type=int, - default=0, - help="bandwidth scalor for scalability analysis", -) -parser.add_argument("--CPUClock", type=str, default="2GHz", help="CPU clock") -parser.add_argument("--GPUClock", type=str, default="1GHz", help="GPU clock") -parser.add_argument( - "--cpu-voltage", - action="store", - type=str, - default="1.0V", - help="""CPU voltage domain""", -) -parser.add_argument( - "--gpu-voltage", - action="store", - type=str, - default="1.0V", - help="""CPU voltage domain""", -) -parser.add_argument( - "--CUExecPolicy", - type=str, - default="OLDEST-FIRST", - help="WF exec policy (OLDEST-FIRST, ROUND-ROBIN)", -) -parser.add_argument( - "--xact-cas-mode", - action="store_true", - help="enable load_compare mode (transactional CAS)", -) -parser.add_argument( - "--SegFaultDebug", - action="store_true", - help="checks for GPU seg fault before TLB access", -) -parser.add_argument( - "--LocalMemBarrier", - action="store_true", - help="Barrier does not wait for writethroughs to complete", -) -parser.add_argument( - "--countPages", - action="store_true", - help="Count Page Accesses and output in per-CU output files", -) -parser.add_argument("--TLB-prefetch", type=int, help="prefetch depth forTLBs") -parser.add_argument( - "--pf-type", - type=str, - help="type of prefetch: PF_CU, PF_WF, PF_PHASE, PF_STRIDE", -) -parser.add_argument("--pf-stride", type=int, help="set prefetch stride") -parser.add_argument( - "--numLdsBanks", - type=int, - default=32, - help="number of physical banks per LDS module", -) -parser.add_argument( - "--ldsBankConflictPenalty", - type=int, - default=1, - help="number of cycles per LDS bank conflict", -) - -# Add the ruby specific and protocol specific options -Ruby.define_options(parser) - -GPUTLBOptions.tlb_options(parser) - -args = parser.parse_args() - -# The GPU cache coherence protocols only work with the backing store -args.access_backing_store = True - -# Currently, the sqc (I-Cache of GPU) is shared by -# multiple compute units(CUs). The protocol works just fine -# even if sqc is not shared. Overriding this option here -# so that the user need not explicitly set this (assuming -# sharing sqc is the common usage) -n_cu = args.num_compute_units -num_sqc = int(math.ceil(float(n_cu) / args.cu_per_sqc)) -args.num_sqc = num_sqc # pass this to Ruby - -########################## Creating the GPU system ######################## -# shader is the GPU -shader = Shader( - n_wf=args.wfs_per_simd, - clk_domain=SrcClockDomain( - clock=args.GPUClock, - voltage_domain=VoltageDomain(voltage=args.gpu_voltage), - ), - timing=True, -) - -# GPU_RfO(Read For Ownership) implements SC/TSO memory model. -# Other GPU protocols implement release consistency at GPU side. -# So, all GPU protocols other than GPU_RfO should make their writes -# visible to the global memory and should read from global memory -# during kernal boundary. The pipeline initiates(or do not initiate) -# the acquire/release operation depending on this impl_kern_boundary_sync -# flag. This flag=true means pipeline initiates a acquire/release operation -# at kernel boundary. -if buildEnv["PROTOCOL"] == "GPU_RfO": - shader.impl_kern_boundary_sync = False -else: - shader.impl_kern_boundary_sync = True - -# Switching off per-lane TLB by default -per_lane = False -if args.TLB_config == "perLane": - per_lane = True - -# List of compute units; one GPU can have multiple compute units -compute_units = [] -for i in range(n_cu): - compute_units.append( - ComputeUnit( - cu_id=i, - perLaneTLB=per_lane, - num_SIMDs=args.simds_per_cu, - wfSize=args.wf_size, - spbypass_pipe_length=args.sp_bypass_path_length, - dpbypass_pipe_length=args.dp_bypass_path_length, - issue_period=args.issue_period, - coalescer_to_vrf_bus_width=args.glbmem_rd_bus_width, - vrf_to_coalescer_bus_width=args.glbmem_wr_bus_width, - num_global_mem_pipes=args.glb_mem_pipes_per_cu, - num_shared_mem_pipes=args.shr_mem_pipes_per_cu, - n_wf=args.wfs_per_simd, - execPolicy=args.CUExecPolicy, - xactCasMode=args.xact_cas_mode, - debugSegFault=args.SegFaultDebug, - functionalTLB=True, - localMemBarrier=args.LocalMemBarrier, - countPages=args.countPages, - localDataStore=LdsState( - banks=args.numLdsBanks, - bankConflictPenalty=args.ldsBankConflictPenalty, - ), - ) - ) - wavefronts = [] - vrfs = [] - for j in range(args.simds_per_cu): - for k in range(int(shader.n_wf)): - wavefronts.append(Wavefront(simdId=j, wf_slot_id=k)) - vrfs.append( - VectorRegisterFile( - simd_id=j, num_regs_per_simd=args.vreg_file_size - ) - ) - compute_units[-1].wavefronts = wavefronts - compute_units[-1].vector_register_file = vrfs - if args.TLB_prefetch: - compute_units[-1].prefetch_depth = args.TLB_prefetch - compute_units[-1].prefetch_prev_type = args.pf_type - - # attach the LDS and the CU to the bus (actually a Bridge) - compute_units[-1].ldsPort = compute_units[-1].ldsBus.slave - compute_units[-1].ldsBus.master = compute_units[-1].localDataStore.cuPort - -# Attach compute units to GPU -shader.CUs = compute_units - -# this is a uniprocessor only test, thus the shader is the second index in the -# list of "system.cpus" -args.num_cpus = 1 -shader_idx = 1 -cpu = TimingSimpleCPU(cpu_id=0) - -########################## Creating the GPU dispatcher ######################## -# Dispatcher dispatches work from host CPU to GPU -host_cpu = cpu -dispatcher = GpuDispatcher() - -# Currently does not test for command processors -cpu_list = [cpu] + [shader] + [dispatcher] - -system = System( - cpu=cpu_list, - mem_ranges=[AddrRange(args.mem_size)], - mem_mode="timing", - workload=SEWorkload(), -) - -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain(voltage=args.sys_voltage) -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu[0].clk_domain = SrcClockDomain( - clock="2GHz", voltage_domain=system.voltage_domain -) - -# configure the TLB hierarchy -GPUTLBConfig.config_tlb_hierarchy(args, system, shader_idx) - -# create Ruby system -system.piobus = IOXBar( - width=32, response_latency=0, frontend_latency=0, forward_latency=0 -) -Ruby.create_system(args, None, system) - -# Create a separate clock for Ruby -system.ruby.clk_domain = SrcClockDomain( - clock=args.ruby_clock, voltage_domain=system.voltage_domain -) - -# create the interrupt controller -cpu.createInterruptController() - -# -# Tie the cpu cache ports to the ruby cpu ports and -# physmem, respectively -# -cpu.connectAllPorts( - system.ruby._cpu_ports[0].in_ports, - system.ruby._cpu_ports[0].in_ports, - system.ruby._cpu_ports[0].interrupt_out_port, -) -system.ruby._cpu_ports[0].mem_request_port = system.piobus.cpu_side_ports - -# attach CU ports to Ruby -# Because of the peculiarities of the CP core, you may have 1 CPU but 2 -# sequencers and thus 2 _cpu_ports created. Your GPUs shouldn't be -# hooked up until after the CP. To make this script generic, figure out -# the index as below, but note that this assumes there is one sequencer -# per compute unit and one sequencer per SQC for the math to work out -# correctly. -gpu_port_idx = ( - len(system.ruby._cpu_ports) - args.num_compute_units - args.num_sqc -) -gpu_port_idx = gpu_port_idx - args.num_cp * 2 - -wavefront_size = args.wf_size -for i in range(n_cu): - # The pipeline issues wavefront_size number of uncoalesced requests - # in one GPU issue cycle. Hence wavefront_size mem ports. - for j in range(wavefront_size): - system.cpu[shader_idx].CUs[i].memory_port[j] = system.ruby._cpu_ports[ - gpu_port_idx - ].slave[j] - gpu_port_idx += 1 - -for i in range(n_cu): - if i > 0 and not i % args.cu_per_sqc: - gpu_port_idx += 1 - system.cpu[shader_idx].CUs[i].sqc_port = system.ruby._cpu_ports[ - gpu_port_idx - ].slave -gpu_port_idx = gpu_port_idx + 1 - -# Current regression tests do not support the command processor -assert args.num_cp == 0 - -# connect dispatcher to the system.piobus -dispatcher.pio = system.piobus.mem_side_ports -dispatcher.dma = system.piobus.cpu_side_ports - -################# Connect the CPU and GPU via GPU Dispatcher ################### -# CPU rings the GPU doorbell to notify a pending task -# using this interface. -# And GPU uses this interface to notify the CPU of task completion -# The communcation happens through emulated driver. - -# Note this implicit setting of the cpu_pointer, shader_pointer and tlb array -# parameters must be after the explicit setting of the System cpu list -shader.cpu_pointer = host_cpu -dispatcher.cpu = host_cpu -dispatcher.shader_pointer = shader - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -m5.ticks.setGlobalFrequency("1THz") -root.system.mem_mode = "timing" diff --git a/tests/configs/memcheck.py b/tests/configs/memcheck.py deleted file mode 100644 index 25a48f9f9d..0000000000 --- a/tests/configs/memcheck.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) 2016 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) 2015 Jason Lowe-Power -# 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. - -import m5 -from m5.objects import * - -# the traffic generator is only available if we have protobuf support, -# so potentially skip this test -require_sim_object("TrafficGen") - -# A wrapper around configs/example/memcheck.py - -# For some reason, this is implicitly needed by run.py -root = None - - -def run_test(root): - # Called from tests/run.py - - import sys - - argv = [sys.argv[0], "-m %d" % maxtick] - - # Execute the script we are wrapping - run_config("configs/example/memcheck.py", argv=argv) diff --git a/tests/configs/memtest-filter.py b/tests/configs/memtest-filter.py deleted file mode 100644 index 1080853f7b..0000000000 --- a/tests/configs/memtest-filter.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * - -m5.util.addToPath("../configs/") -from common.Caches import * - -# MAX CORES IS 8 with the fals sharing method -nb_cores = 8 -cpus = [MemTest() for i in range(nb_cores)] - -# system simulated -system = System( - cpu=cpus, - physmem=SimpleMemory(), - membus=SystemXBar(width=16, snoop_filter=SnoopFilter()), -) -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain() -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu_clk_domain = SrcClockDomain( - clock="2GHz", voltage_domain=system.voltage_domain -) - -system.toL2Bus = L2XBar( - clk_domain=system.cpu_clk_domain, snoop_filter=SnoopFilter() -) -system.l2c = L2Cache(clk_domain=system.cpu_clk_domain, size="64kB", assoc=8) -system.l2c.cpu_side = system.toL2Bus.mem_side_ports - -# connect l2c to membus -system.l2c.mem_side = system.membus.cpu_side_ports - -# add L1 caches -for cpu in cpus: - # All cpus are associated with cpu_clk_domain - cpu.clk_domain = system.cpu_clk_domain - cpu.l1c = L1Cache(size="32kB", assoc=4) - cpu.l1c.cpu_side = cpu.port - cpu.l1c.mem_side = system.toL2Bus.cpu_side_ports - -system.system_port = system.membus.cpu_side_ports - -# connect memory to membus -system.physmem.port = system.membus.mem_side_ports - - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/memtest-ruby.py b/tests/configs/memtest-ruby.py deleted file mode 100644 index dac165e288..0000000000 --- a/tests/configs/memtest-ruby.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# Copyright (c) 2010 Advanced Micro Devices, Inc. -# 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. - -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -import os, argparse, sys - -m5.util.addToPath("../configs/") - -from ruby import Ruby -from common import Options - -parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) - -# Add the ruby specific and protocol specific options -Ruby.define_options(parser) - -args = parser.parse_args() - -# -# Set the default cache size and associativity to be very small to encourage -# races between requests and writebacks. -# -args.l1d_size = "256B" -args.l1i_size = "256B" -args.l2_size = "512B" -args.l3_size = "1kB" -args.l1d_assoc = 2 -args.l1i_assoc = 2 -args.l2_assoc = 2 -args.l3_assoc = 2 -args.ports = 32 - -# MAX CORES IS 8 with the fals sharing method -nb_cores = 8 - -# ruby does not support atomic, functional, or uncacheable accesses -cpus = [ - MemTest( - percent_functional=50, percent_uncacheable=0, suppress_func_errors=True - ) - for i in range(nb_cores) -] - -# overwrite args.num_cpus with the nb_cores value -args.num_cpus = nb_cores - -# system simulated -system = System(cpu=cpus) -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain() -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu_clk_domain = SrcClockDomain( - clock="2GHz", voltage_domain=system.voltage_domain -) - -# All cpus are associated with cpu_clk_domain -for cpu in cpus: - cpu.clk_domain = system.cpu_clk_domain - -system.mem_ranges = AddrRange("256MB") - -Ruby.create_system(args, False, system) - -# Create a separate clock domain for Ruby -system.ruby.clk_domain = SrcClockDomain( - clock=args.ruby_clock, voltage_domain=system.voltage_domain -) - -assert len(cpus) == len(system.ruby._cpu_ports) - -for (i, ruby_port) in enumerate(system.ruby._cpu_ports): - # - # Tie the cpu port to the ruby cpu ports and - # physmem, respectively - # - cpus[i].port = ruby_port.in_ports - - # - # Since the memtester is incredibly bursty, increase the deadlock - # threshold to 1 million cycles - # - ruby_port.deadlock_threshold = 1000000 - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/memtest.py b/tests/configs/memtest.py deleted file mode 100644 index 10f3fbe50d..0000000000 --- a/tests/configs/memtest.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * - -m5.util.addToPath("../configs/") -from common.Caches import * - -# MAX CORES IS 8 with the fals sharing method -nb_cores = 8 -cpus = [MemTest() for i in range(nb_cores)] - -# system simulated -system = System(cpu=cpus, physmem=SimpleMemory(), membus=SystemXBar()) -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain() -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu_clk_domain = SrcClockDomain( - clock="2GHz", voltage_domain=system.voltage_domain -) - -system.toL2Bus = L2XBar(clk_domain=system.cpu_clk_domain) -system.l2c = L2Cache(clk_domain=system.cpu_clk_domain, size="64kB", assoc=8) -system.l2c.cpu_side = system.toL2Bus.mem_side_ports - -# connect l2c to membus -system.l2c.mem_side = system.membus.cpu_side_ports - -# add L1 caches -for cpu in cpus: - # All cpus are associated with cpu_clk_domain - cpu.clk_domain = system.cpu_clk_domain - cpu.l1c = L1Cache(size="32kB", assoc=4) - cpu.l1c.cpu_side = cpu.port - cpu.l1c.mem_side = system.toL2Bus.cpu_side_ports - -system.system_port = system.membus.cpu_side_ports - -# connect memory to membus -system.physmem.port = system.membus.mem_side_ports - - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/minor-timing-mp.py b/tests/configs/minor-timing-mp.py deleted file mode 100644 index b6c56de512..0000000000 --- a/tests/configs/minor-timing-mp.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -nb_cores = 4 -root = BaseSESystem( - mem_mode="timing", - mem_class=DDR3_1600_8x8, - cpu_class=MinorCPU, - num_cpus=nb_cores, -).create_root() diff --git a/tests/configs/minor-timing.py b/tests/configs/minor-timing.py deleted file mode 100644 index e6680d7702..0000000000 --- a/tests/configs/minor-timing.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -root = BaseSESystemUniprocessor( - mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=MinorCPU -).create_root() diff --git a/tests/configs/o3-timing-checker.py b/tests/configs/o3-timing-checker.py deleted file mode 100644 index 9b328ce9e8..0000000000 --- a/tests/configs/o3-timing-checker.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 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. -# -# 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 * -from base_config import * - -root = BaseSESystemUniprocessor( - mem_mode="timing", - mem_class=DDR3_1600_8x8, - cpu_class=DerivO3CPU, - checker=True, -).create_root() diff --git a/tests/configs/o3-timing-mp-ruby.py b/tests/configs/o3-timing-mp-ruby.py deleted file mode 100644 index 10725e36ad..0000000000 --- a/tests/configs/o3-timing-mp-ruby.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * - -nb_cores = 4 -cpus = [DerivO3CPU(cpu_id=i) for i in range(nb_cores)] - -import ruby_config - -ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", nb_cores) - -# system simulated -system = System( - cpu=cpus, - physmem=ruby_memory, - membus=SystemXBar(), - mem_mode="timing", - clk_domain=SrcClockDomain(clock="1GHz"), -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu_clk_domain = SrcClockDomain(clock="2GHz") - -for cpu in cpus: - # create the interrupt controller - cpu.createInterruptController() - cpu.connectBus(system.membus) - # All cpus are associated with cpu_clk_domain - cpu.clk_domain = system.cpu_clk_domain - -# connect memory to membus -system.physmem.port = system.membus.mem_side_ports - -# Connect the system port for loading of binaries etc -system.system_port = system.membus.cpu_side_ports - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/o3-timing-mp.py b/tests/configs/o3-timing-mp.py deleted file mode 100644 index 9b58c9d416..0000000000 --- a/tests/configs/o3-timing-mp.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -nb_cores = 4 -root = BaseSESystem( - mem_mode="timing", - mem_class=DDR3_1600_8x8, - cpu_class=DerivO3CPU, - num_cpus=nb_cores, -).create_root() diff --git a/tests/configs/o3-timing-mt.py b/tests/configs/o3-timing-mt.py deleted file mode 100644 index 9fda80de12..0000000000 --- a/tests/configs/o3-timing-mt.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2013, 2015 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from m5.defines import buildEnv -from base_config import * -from arm_generic import * -from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 -from gem5.isas import ISA -from gem5.runtime import get_runtime_isa - -# If we are running ARM regressions, use a more sensible CPU -# configuration. This makes the results more meaningful, and also -# increases the coverage of the regressions. -if get_runtime_isa() == ISA.ARM: - root = ArmSESystemUniprocessor( - mem_mode="timing", - mem_class=DDR3_1600_8x8, - cpu_class=O3_ARM_v7a_3, - num_threads=2, - ).create_root() -else: - root = BaseSESystemUniprocessor( - mem_mode="timing", - mem_class=DDR3_1600_8x8, - cpu_class=DerivO3CPU, - num_threads=2, - ).create_root() diff --git a/tests/configs/o3-timing-ruby.py b/tests/configs/o3-timing-ruby.py deleted file mode 100644 index 30ee69ef23..0000000000 --- a/tests/configs/o3-timing-ruby.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * - -import ruby_config - -ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", 1) - -cpu = DerivO3CPU(cpu_id=0) - -system = System( - cpu=cpu, - physmem=ruby_memory, - membus=SystemXBar(), - mem_mode="timing", - clk_domain=SrcClockDomain(clock="1GHz"), -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu.clk_domain = SrcClockDomain(clock="2GHz") - -system.physmem.port = system.membus.mem_side_ports -# create the interrupt controller -cpu.createInterruptController() -cpu.connectBus(system.membus) - -# Connect the system port for loading of binaries etc -system.system_port = system.membus.cpu_side_ports - -root = Root(full_system=False, system=system) diff --git a/tests/configs/o3-timing.py b/tests/configs/o3-timing.py deleted file mode 100644 index 26efe466d4..0000000000 --- a/tests/configs/o3-timing.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from m5.defines import buildEnv -from base_config import * -from arm_generic import * -from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 -from gem5.isas import ISA -from gem5.runtime import get_runtime_isa - -# If we are running ARM regressions, use a more sensible CPU -# configuration. This makes the results more meaningful, and also -# increases the coverage of the regressions. -if get_runtime_isa() == ISA.ARM: - root = ArmSESystemUniprocessor( - mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=O3_ARM_v7a_3 - ).create_root() -else: - root = BaseSESystemUniprocessor( - mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=DerivO3CPU - ).create_root() diff --git a/tests/configs/pc-o3-timing.py b/tests/configs/pc-o3-timing.py deleted file mode 100644 index 24abcd2de6..0000000000 --- a/tests/configs/pc-o3-timing.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2012 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. -# -# 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 * -from x86_generic import * - -root = LinuxX86FSSystemUniprocessor( - mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=DerivO3CPU -).create_root() diff --git a/tests/configs/pc-simple-atomic.py b/tests/configs/pc-simple-atomic.py deleted file mode 100644 index ac2c3c06b8..0000000000 --- a/tests/configs/pc-simple-atomic.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2012 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. -# -# 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 * -from x86_generic import * - -root = LinuxX86FSSystemUniprocessor( - mem_mode="atomic", mem_class=SimpleMemory, cpu_class=AtomicSimpleCPU -).create_root() diff --git a/tests/configs/pc-simple-timing-ruby.py b/tests/configs/pc-simple-timing-ruby.py deleted file mode 100644 index d0458b49cd..0000000000 --- a/tests/configs/pc-simple-timing-ruby.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) 2012 Mark D. Hill and David A. Wood -# 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. - -import m5, os, argparse, sys -from m5.objects import * - -m5.util.addToPath("../configs/") -from common.Benchmarks import SysConfig -from common import FSConfig, SysPaths -from ruby import Ruby -from common import Options - -# Add the ruby specific and protocol specific options -parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) -Ruby.define_options(parser) -args = parser.parse_args() - -# Set the default cache size and associativity to be very small to encourage -# races between requests and writebacks. -args.l1d_size = "32kB" -args.l1i_size = "32kB" -args.l2_size = "4MB" -args.l1d_assoc = 2 -args.l1i_assoc = 2 -args.l2_assoc = 2 -args.num_cpus = 2 - -# the system -mdesc = SysConfig(disks=["linux-x86.img"]) -system = FSConfig.makeLinuxX86System( - "timing", args.num_cpus, mdesc=mdesc, Ruby=True -) -system.kernel = SysPaths.binary("x86_64-vmlinux-2.6.22.9") -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain(voltage=args.sys_voltage) - -system.kernel = FSConfig.binary("x86_64-vmlinux-2.6.22.9.smp") -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) -system.cpu_clk_domain = SrcClockDomain( - clock="2GHz", voltage_domain=system.voltage_domain -) -system.cpu = [ - TimingSimpleCPU(cpu_id=i, clk_domain=system.cpu_clk_domain) - for i in range(args.num_cpus) -] - -Ruby.create_system(args, True, system, system.iobus, system._dma_ports) - -# Create a seperate clock domain for Ruby -system.ruby.clk_domain = SrcClockDomain( - clock=args.ruby_clock, voltage_domain=system.voltage_domain -) - -# Connect the ruby io port to the PIO bus, -# assuming that there is just one such port. -system.iobus.mem_side_ports = system.ruby._io_port.in_ports - -for (i, cpu) in enumerate(system.cpu): - # create the interrupt controller - cpu.createInterruptController() - # Tie the cpu ports to the correct ruby system ports - system.ruby._cpu_ports[i].connectCpuPorts(cpu) - -root = Root(full_system=True, system=system) -m5.ticks.setGlobalFrequency("1THz") diff --git a/tests/configs/pc-simple-timing.py b/tests/configs/pc-simple-timing.py deleted file mode 100644 index c095401381..0000000000 --- a/tests/configs/pc-simple-timing.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2012 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. -# -# 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 * -from x86_generic import * - -root = LinuxX86FSSystemUniprocessor( - mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=TimingSimpleCPU -).create_root() diff --git a/tests/configs/pc-switcheroo-full.py b/tests/configs/pc-switcheroo-full.py deleted file mode 100644 index a69f80c341..0000000000 --- a/tests/configs/pc-switcheroo-full.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2012 ARM Limited -# Copyright (c) 2013 Mark D. Hill and David A. Wood -# 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. -# -# 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 * -from x86_generic import * -import switcheroo - -root = LinuxX86FSSwitcheroo( - mem_class=DDR3_1600_8x8, - cpu_classes=(AtomicSimpleCPU, TimingSimpleCPU, DerivO3CPU), -).create_root() - -# Setup a custom test method that uses the switcheroo tester that -# switches between CPU models. -run_test = switcheroo.run_test diff --git a/tests/configs/rubytest-ruby.py b/tests/configs/rubytest-ruby.py deleted file mode 100644 index 9a382cce6e..0000000000 --- a/tests/configs/rubytest-ruby.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# Copyright (c) 2009 Advanced Micro Devices, Inc. -# 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. - -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -import os, argparse, sys - -m5.util.addToPath("../configs/") - -from ruby import Ruby -from common import Options - -parser = argparse.ArgumentParser() -Options.addNoISAOptions(parser) - -# Add the ruby specific and protocol specific options -Ruby.define_options(parser) - -args = parser.parse_args() - -# -# Set the default cache size and associativity to be very small to encourage -# races between requests and writebacks. -# -args.l1d_size = "256B" -args.l1i_size = "256B" -args.l2_size = "512B" -args.l3_size = "1kB" -args.l1d_assoc = 2 -args.l1i_assoc = 2 -args.l2_assoc = 2 -args.l3_assoc = 2 -args.ports = 32 - -# Turn on flush check for the hammer protocol -check_flush = False -if buildEnv["PROTOCOL"] == "MOESI_hammer": - check_flush = True - -# -# create the tester and system, including ruby -# -tester = RubyTester( - check_flush=check_flush, - checks_to_complete=100, - wakeup_frequency=10, - num_cpus=args.num_cpus, -) - -# We set the testers as cpu for ruby to find the correct clock domains -# for the L1 Objects. -system = System(cpu=tester) - -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain(voltage=args.sys_voltage) -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -system.mem_ranges = AddrRange("256MB") - -# the ruby tester reuses num_cpus to specify the -# number of cpu ports connected to the tester object, which -# is stored in system.cpu. because there is only ever one -# tester object, num_cpus is not necessarily equal to the -# size of system.cpu -cpu_list = [system.cpu] * args.num_cpus -Ruby.create_system(args, False, system, cpus=cpu_list) - -# Create a separate clock domain for Ruby -system.ruby.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -assert args.num_cpus == len(system.ruby._cpu_ports) - -tester.num_cpus = len(system.ruby._cpu_ports) - -# -# The tester is most effective when randomization is turned on and -# artifical delay is randomly inserted on messages -# -system.ruby.randomization = True - -for ruby_port in system.ruby._cpu_ports: - # - # Tie the ruby tester ports to the ruby cpu read and write ports - # - if ruby_port.support_data_reqs and ruby_port.support_inst_reqs: - tester.cpuInstDataPort = ruby_port.in_ports - elif ruby_port.support_data_reqs: - tester.cpuDataPort = ruby_port.in_ports - elif ruby_port.support_inst_reqs: - tester.cpuInstPort = ruby_port.in_ports - - # Do not automatically retry stalled Ruby requests - ruby_port.no_retry_on_stall = True - - # - # Tell the sequencer this is the ruby tester so that it - # copies the subblock back to the checker - # - ruby_port.using_ruby_tester = True - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/simple-atomic-dummychecker.py b/tests/configs/simple-atomic-dummychecker.py deleted file mode 100644 index 7ec004765a..0000000000 --- a/tests/configs/simple-atomic-dummychecker.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 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. -# -# 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 * -from base_config import * - -root = BaseSESystemUniprocessor( - mem_mode="atomic", cpu_class=AtomicSimpleCPU, checker=True -).create_root() diff --git a/tests/configs/simple-atomic-mp-ruby.py b/tests/configs/simple-atomic-mp-ruby.py deleted file mode 100644 index e3ac279022..0000000000 --- a/tests/configs/simple-atomic-mp-ruby.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * - -nb_cores = 4 -cpus = [AtomicSimpleCPU(cpu_id=i) for i in range(nb_cores)] - -import ruby_config - -ruby_memory = ruby_config.generate("TwoLevel_SplitL1UnifiedL2.rb", nb_cores) - -# system simulated -system = System( - cpu=cpus, - physmem=ruby_memory, - membus=SystemXBar(), - clk_domain=SrcClockDomain(clock="1GHz"), -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu.clk_domain = SrcClockDomain(clock="2GHz") - -# add L1 caches -for cpu in cpus: - cpu.connectBus(system.membus) - # All cpus are associated with cpu_clk_domain - cpu.clk_domain = system.cpu_clk_domain - -# connect memory to membus -system.physmem.port = system.membus.mem_side_ports - -# Connect the system port for loading of binaries etc -system.system_port = system.membus.cpu_side_ports - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "atomic" diff --git a/tests/configs/simple-atomic-mp.py b/tests/configs/simple-atomic-mp.py deleted file mode 100644 index 0d85b5af36..0000000000 --- a/tests/configs/simple-atomic-mp.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -nb_cores = 4 -root = BaseSESystem( - mem_mode="atomic", cpu_class=AtomicSimpleCPU, num_cpus=nb_cores -).create_root() diff --git a/tests/configs/simple-atomic.py b/tests/configs/simple-atomic.py deleted file mode 100644 index 6dd86ccf39..0000000000 --- a/tests/configs/simple-atomic.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -root = BaseSESystemUniprocessor( - mem_mode="atomic", cpu_class=AtomicSimpleCPU -).create_root() diff --git a/tests/configs/simple-timing-mp-ruby.py b/tests/configs/simple-timing-mp-ruby.py deleted file mode 100644 index 38488c409d..0000000000 --- a/tests/configs/simple-timing-mp-ruby.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -import os, argparse, sys - -m5.util.addToPath("../configs/") - -from common import Options -from ruby import Ruby - -parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) - -# Add the ruby specific and protocol specific options -Ruby.define_options(parser) - -args = parser.parse_args() - -# -# Set the default cache size and associativity to be very small to encourage -# races between requests and writebacks. -# -args.l1d_size = "256B" -args.l1i_size = "256B" -args.l2_size = "512B" -args.l3_size = "1kB" -args.l1d_assoc = 2 -args.l1i_assoc = 2 -args.l2_assoc = 2 -args.l3_assoc = 2 - -nb_cores = 4 -cpus = [TimingSimpleCPU(cpu_id=i) for i in range(nb_cores)] - -# overwrite the num_cpus to equal nb_cores -args.num_cpus = nb_cores - -# system simulated -system = System(cpu=cpus, clk_domain=SrcClockDomain(clock="1GHz")) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu.clk_domain = SrcClockDomain(clock="2GHz") - -Ruby.create_system(args, False, system) - -# Create a separate clock domain for Ruby -system.ruby.clk_domain = SrcClockDomain(clock=args.ruby_clock) - -assert args.num_cpus == len(system.ruby._cpu_ports) - -for (i, cpu) in enumerate(system.cpu): - # create the interrupt controller - cpu.createInterruptController() - - # - # Tie the cpu ports to the ruby cpu ports - # - cpu.connectAllPorts( - system.ruby._cpu_ports[i].in_ports, - system.ruby._cpu_ports[i].in_ports, - system.ruby._cpu_ports[i].interrupt_out_port, - ) - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/simple-timing-mp.py b/tests/configs/simple-timing-mp.py deleted file mode 100644 index 3988f4c2b9..0000000000 --- a/tests/configs/simple-timing-mp.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -nb_cores = 4 -root = BaseSESystem( - mem_mode="timing", cpu_class=TimingSimpleCPU, num_cpus=nb_cores -).create_root() diff --git a/tests/configs/simple-timing-ruby.py b/tests/configs/simple-timing-ruby.py deleted file mode 100644 index eb0f4e9ac7..0000000000 --- a/tests/configs/simple-timing-ruby.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -import os, argparse, sys - -m5.util.addToPath("../configs/") - -from ruby import Ruby -from common import Options - -parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) - -# Add the ruby specific and protocol specific options -Ruby.define_options(parser) - -args = parser.parse_args() - -# -# Set the default cache size and associativity to be very small to encourage -# races between requests and writebacks. -# -args.l1d_size = "256B" -args.l1i_size = "256B" -args.l2_size = "512B" -args.l3_size = "1kB" -args.l1d_assoc = 2 -args.l1i_assoc = 2 -args.l2_assoc = 2 -args.l3_assoc = 2 - -# this is a uniprocessor only test -args.num_cpus = 1 -cpu = TimingSimpleCPU(cpu_id=0) -system = System(cpu=cpu) - -# Dummy voltage domain for all our clock domains -system.voltage_domain = VoltageDomain(voltage=args.sys_voltage) -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) - -# Create a seperate clock domain for components that should run at -# CPUs frequency -system.cpu.clk_domain = SrcClockDomain( - clock="2GHz", voltage_domain=system.voltage_domain -) - -system.mem_ranges = AddrRange("256MB") -Ruby.create_system(args, False, system) - -# Create a separate clock for Ruby -system.ruby.clk_domain = SrcClockDomain( - clock=args.ruby_clock, voltage_domain=system.voltage_domain -) - -assert len(system.ruby._cpu_ports) == 1 - -# create the interrupt controller -cpu.createInterruptController() - -# -# Tie the cpu cache ports to the ruby cpu ports and -# physmem, respectively -# -cpu.connectAllPorts( - system.ruby._cpu_ports[0].in_ports, - system.ruby._cpu_ports[0].in_ports, - system.ruby._cpu_ports[0].interrupt_out_port, -) - -# ----------------------- -# run simulation -# ----------------------- - -root = Root(full_system=False, system=system) -root.system.mem_mode = "timing" diff --git a/tests/configs/simple-timing.py b/tests/configs/simple-timing.py deleted file mode 100644 index bf3ced4463..0000000000 --- a/tests/configs/simple-timing.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 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) 2006-2007 The Regents of The University of Michigan -# 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 * -from base_config import * - -root = BaseSESystemUniprocessor( - mem_mode="timing", cpu_class=TimingSimpleCPU -).create_root() diff --git a/tests/configs/t1000-simple-atomic.py b/tests/configs/t1000-simple-atomic.py deleted file mode 100644 index 76d39327d2..0000000000 --- a/tests/configs/t1000-simple-atomic.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2007 The Regents of The University of Michigan -# 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. - -import m5 -from m5.objects import * - -m5.util.addToPath("../configs/") -from common import FSConfig - -try: - system = FSConfig.makeSparcSystem("atomic") -except IOError as e: - skip_test(reason=str(e)) - -system.voltage_domain = VoltageDomain() -system.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) -system.cpu_clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=system.voltage_domain -) -cpu = AtomicSimpleCPU(cpu_id=0, clk_domain=system.cpu_clk_domain) -system.cpu = cpu -# create the interrupt controller -cpu.createInterruptController() -cpu.connectBus(system.membus) - -# create the memory controllers and connect them, stick with -# the physmem name to avoid bumping all the reference stats -system.physmem = [SimpleMemory(range=r) for r in system.mem_ranges] -for i in range(len(system.physmem)): - system.physmem[i].port = system.membus.mem_side_ports - -root = Root(full_system=True, system=system) - -m5.ticks.setGlobalFrequency("2GHz") diff --git a/tests/configs/x86_generic.py b/tests/configs/x86_generic.py deleted file mode 100644 index 3c590860de..0000000000 --- a/tests/configs/x86_generic.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (c) 2012 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. -# -# 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 ABCMeta, abstractmethod -import m5 -from m5.objects import * -from m5.proxy import * - -m5.util.addToPath("../configs/") -from common.Benchmarks import SysConfig -from common import FSConfig, SysPaths -from common.Caches import * -from base_config import * - - -class LinuxX86SystemBuilder(object): - """Mix-in that implements create_system. - - This mix-in is intended as a convenient way of adding an - X86-specific create_system method to a class deriving from one of - the generic base systems. - """ - - def __init__(self): - pass - - def create_system(self): - mdesc = SysConfig(disks=["linux-x86.img"]) - system = FSConfig.makeLinuxX86System( - self.mem_mode, numCPUs=self.num_cpus, mdesc=mdesc - ) - system.kernel = SysPaths.binary("x86_64-vmlinux-2.6.22.9") - - self.init_system(system) - return system - - -class LinuxX86FSSystem(LinuxX86SystemBuilder, BaseFSSystem): - """Basic X86 full system builder.""" - - def __init__(self, **kwargs): - """Initialize an X86 system that supports full system simulation. - - Note: Keyword arguments that are not listed below will be - passed to the BaseFSSystem. - - Keyword Arguments: - machine_type -- String describing the platform to simulate - """ - BaseSystem.__init__(self, **kwargs) - LinuxX86SystemBuilder.__init__(self) - - def create_caches_private(self, cpu): - cpu.addPrivateSplitL1Caches( - L1_ICache(size="32kB", assoc=1), - L1_DCache(size="32kB", assoc=4), - PageTableWalkerCache(), - PageTableWalkerCache(), - ) - - -class LinuxX86FSSystemUniprocessor( - LinuxX86SystemBuilder, BaseFSSystemUniprocessor -): - """Basic X86 full system builder for uniprocessor systems. - - Note: This class is a specialization of the X86FSSystem and is - only really needed to provide backwards compatibility for existing - test cases. - """ - - def __init__(self, **kwargs): - BaseFSSystemUniprocessor.__init__(self, **kwargs) - LinuxX86SystemBuilder.__init__(self) - - def create_caches_private(self, cpu): - cpu.addTwoLevelCacheHierarchy( - L1_ICache(size="32kB", assoc=1), - L1_DCache(size="32kB", assoc=4), - L2Cache(size="4MB", assoc=8), - PageTableWalkerCache(), - PageTableWalkerCache(), - ) - - -class LinuxX86FSSwitcheroo(LinuxX86SystemBuilder, BaseFSSwitcheroo): - """Uniprocessor X86 system prepared for CPU switching""" - - def __init__(self, **kwargs): - BaseFSSwitcheroo.__init__(self, **kwargs) - LinuxX86SystemBuilder.__init__(self) diff --git a/tests/gem5/configs/arm_boot_exit_run.py b/tests/gem5/arm_boot_tests/configs/arm_boot_exit_run.py similarity index 100% rename from tests/gem5/configs/arm_boot_exit_run.py rename to tests/gem5/arm_boot_tests/configs/arm_boot_exit_run.py diff --git a/tests/gem5/arm_boot_tests/test_linux_boot.py b/tests/gem5/arm_boot_tests/test_linux_boot.py index 9e04e24d62..b7c0fa86b0 100644 --- a/tests/gem5/arm_boot_tests/test_linux_boot.py +++ b/tests/gem5/arm_boot_tests/test_linux_boot.py @@ -46,7 +46,7 @@ def test_boot( ): name = f"{cpu}-cpu_{num_cpus}-cores_{mem_system}_{memory_class}_\ -arm-boot-test" +arm_boot_test" verifiers = [] @@ -90,6 +90,7 @@ arm-boot-test" config.base_dir, "tests", "gem5", + "arm_boot_tests", "configs", "arm_boot_exit_run.py", ), diff --git a/tests/gem5/asmtest/configs/simple_binary_run.py b/tests/gem5/asmtest/configs/simple_binary_run.py new file mode 100644 index 0000000000..5540e806ba --- /dev/null +++ b/tests/gem5/asmtest/configs/simple_binary_run.py @@ -0,0 +1,184 @@ +# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2022 Google Inc +# 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. + +""" +A run script for a very simple Syscall-Execution running simple binaries. +The system has no cache heirarchy and is as "bare-bones" as you can get in +gem5 while still being functinal. +""" + +from gem5.resources.resource import Resource +from gem5.components.processors.cpu_types import ( + get_cpu_types_str_set, + get_cpu_type_from_str, +) +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.boards.mem_mode import MemMode +from gem5.components.processors.cpu_types import CPUTypes +from gem5.simulate.simulator import Simulator +from gem5.isas import get_isa_from_str, get_isas_str_set, ISA + +from m5.util import fatal + +import argparse +import importlib + +cpu_types_string_map = { + CPUTypes.ATOMIC: "AtomicSimpleCPU", + CPUTypes.O3: "O3CPU", + CPUTypes.TIMING: "TimingSimpleCPU", + CPUTypes.KVM: "KvmCPU", + CPUTypes.MINOR: "MinorCPU", +} + +parser = argparse.ArgumentParser( + description="A gem5 script for running simple binaries in SE mode." +) + +parser.add_argument( + "resource", type=str, help="The gem5 resource binary to run." +) + +parser.add_argument( + "cpu", type=str, choices=get_cpu_types_str_set(), help="The CPU type used." +) + +parser.add_argument( + "isa", type=str, choices=get_isas_str_set(), help="The ISA used" +) + +parser.add_argument( + "-b", + "--base-cpu-processor", + action="store_true", + help="Use the BaseCPUProcessor instead of the SimpleProcessor.", +) + +parser.add_argument( + "--riscv-32bits", + action="store_true", + help="Use 32 bits core of Riscv CPU", +) + +parser.add_argument( + "-r", + "--resource-directory", + type=str, + required=False, + help="The directory in which resources will be downloaded or exist.", +) + +parser.add_argument( + "--arguments", + type=str, + action="append", + default=[], + required=False, + help="The input arguments for the binary.", +) + +parser.add_argument( + "-n", + "--num-cores", + type=int, + default=1, + required=False, + help="The number of CPU cores to run.", +) + +args = parser.parse_args() + +# Setup the system. +cache_hierarchy = NoCache() +memory = SingleChannelDDR3_1600() + +isa_enum = get_isa_from_str(args.isa) +cpu_enum = get_cpu_type_from_str(args.cpu) + +if isa_enum == ISA.RISCV and args.riscv_32bits and not args.base_cpu_processor: + fatal("To use Riscv 32 CPU, the base_cpu_processor must be specify!") + +if args.base_cpu_processor: + + if isa_enum == ISA.RISCV and args.riscv_32bits: + m5_objects = importlib.import_module("m5.objects") + cpu_class = getattr( + m5_objects, f"Riscv32{cpu_types_string_map[cpu_enum]}" + ) + cores = [ + BaseCPUCore(core=cpu_class(cpu_id=i), isa=isa_enum) + for i in range(args.num_cores) + ] + else: + cores = [ + BaseCPUCore( + core=SimpleCore.cpu_simobject_factory( + cpu_type=cpu_enum, + isa=isa_enum, + core_id=i, + ), + isa=isa_enum, + ) + for i in range(args.num_cores) + ] + + processor = BaseCPUProcessor( + cores=cores, + ) +else: + processor = SimpleProcessor( + cpu_type=cpu_enum, + isa=isa_enum, + num_cores=args.num_cores, + ) + +motherboard = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the workload +binary = Resource(args.resource, resource_directory=args.resource_directory) +motherboard.set_se_binary_workload(binary, arguments=args.arguments) + +# Run the simulation +simulator = Simulator(board=motherboard) +simulator.run() + +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), simulator.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/asmtest/tests.py b/tests/gem5/asmtest/tests.py index b2a5992da0..02283ec213 100644 --- a/tests/gem5/asmtest/tests.py +++ b/tests/gem5/asmtest/tests.py @@ -180,6 +180,7 @@ for cpu_type in cpu_types: config.base_dir, "tests", "gem5", + "asmtest", "configs", "simple_binary_run.py", ), diff --git a/tests/gem5/configs/checkpoint.py b/tests/gem5/configs/checkpoint.py deleted file mode 100644 index f1b8a1bf72..0000000000 --- a/tests/gem5/configs/checkpoint.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright (c) 2015, 2020 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. -# -# 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 multiprocessing import Process -import sys -import os - -import m5 - -_exit_normal = ("target called exit()", "m5_exit instruction encountered") - -_exit_limit = ("simulate() limit reached",) - -_exitcode_done = 0 -_exitcode_fail = 1 -_exitcode_checkpoint = 42 - - -def _run_step(name, restore=None, interval=0.5): - """ - Instantiate (optionally from a checkpoint if restore is set to the - checkpoitn name) the system and run for interval seconds of - simulated time. At the end of the simulation interval, create a - checkpoint and exit. - - As this function is intended to run in its own process using the - multiprocessing framework, the exit is a true call to exit which - terminates the process. Exit codes are used to pass information to - the parent. - """ - if restore is not None: - m5.instantiate(restore) - else: - m5.instantiate() - - e = m5.simulate(m5.ticks.fromSeconds(interval)) - cause = e.getCause() - if cause in _exit_limit: - m5.checkpoint(name) - sys.exit(_exitcode_checkpoint) - elif cause in _exit_normal: - sys.exit(_exitcode_done) - else: - print(f"Test failed: Unknown exit cause: {cause}") - sys.exit(_exitcode_fail) - - -def run_test(root, interval=0.5, max_checkpoints=5): - """ - Run the simulated system for a fixed amount of time and take a - checkpoint, then restore from the same checkpoint and run until - the system calls m5 exit. - """ - - cpt_name = os.path.join(m5.options.outdir, "test.cpt") - restore = None - checkpointed = False - - for cpt_no in range(max_checkpoints): - # Create a checkpoint from a separate child process. This enables - # us to get back to a (mostly) pristine state and restart - # simulation from the checkpoint. - p = Process( - target=_run_step, - args=(cpt_name,), - kwargs={"restore": restore, "interval": interval}, - ) - p.start() - - # Wait for the child to return - p.join() - - # Restore from the checkpoint next iteration - restore = cpt_name - - if p.exitcode == _exitcode_done: - if checkpointed: - print("Test done.", file=sys.stderr) - sys.exit(0) - else: - print( - "Test done, but no checkpoint was created.", - file=sys.stderr, - ) - sys.exit(1) - elif p.exitcode == _exitcode_checkpoint: - checkpointed = True - else: - print("Test failed.", file=sys.stderr) - sys.exit(1) - - # Maximum number of checkpoints reached. Just run full-speed from - # now on. - m5.instantiate() - e = m5.simulate() - cause = e.getCause() - if cause in _exit_normal: - sys.exit(0) - else: - print(f"Test failed: Unknown exit cause: {cause}") - sys.exit(1) diff --git a/tests/gem5/configs/switcheroo.py b/tests/gem5/configs/switcheroo.py deleted file mode 100644 index 72736a9d87..0000000000 --- a/tests/gem5/configs/switcheroo.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright (c) 2012 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. -# -# 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. - -import m5 -import _m5 -from m5.objects import * - -m5.util.addToPath("../configs/") -from base_caches import * - - -class Sequential: - """Sequential CPU switcher. - - The sequential CPU switches between all CPUs in a system in - order. The CPUs in the system must have been prepared for - switching, which in practice means that only one CPU is switched - in. base_config.BaseFSSwitcheroo can be used to create such a - system. - """ - - def __init__(self, cpus): - self.first_cpu = None - for (cpuno, cpu) in enumerate(cpus): - if not cpu.switched_out: - if self.first_cpu != None: - fatal("More than one CPU is switched in") - self.first_cpu = cpuno - - if self.first_cpu == None: - fatal("The system contains no switched in CPUs") - - self.cur_cpu = self.first_cpu - self.cpus = cpus - - def next(self): - self.cur_cpu = (self.cur_cpu + 1) % len(self.cpus) - return self.cpus[self.cur_cpu] - - def first(self): - return self.cpus[self.first_cpu] - - -def run_test(root, switcher=None, freq=1000, verbose=False): - """Test runner for CPU switcheroo tests. - - The switcheroo test runner is used to switch CPUs in a system that - has been prepared for CPU switching. Such systems should have - multiple CPUs when they are instantiated, but only one should be - switched in. Such configurations can be created using the - base_config.BaseFSSwitcheroo class. - - A CPU switcher object is used to control switching. The default - switcher sequentially switches between all CPUs in a system, - starting with the CPU that is currently switched in. - - Unlike most other test runners, this one automatically configures - the memory mode of the system based on the first CPU the switcher - reports. - - Keyword Arguments: - switcher -- CPU switcher implementation. See Sequential for - an example implementation. - period -- Switching frequency in Hz. - verbose -- Enable output at each switch (suppressed by default). - """ - - if switcher == None: - switcher = Sequential(root.system.cpu) - - current_cpu = switcher.first() - system = root.system - system.mem_mode = type(current_cpu).memory_mode() - - # Suppress "Entering event queue" messages since we get tons of them. - # Worse yet, they include the timestamp, which makes them highly - # variable and unsuitable for comparing as test outputs. - if not verbose: - _m5.core.setLogLevel(_m5.core.LogLevel.WARN) - - # instantiate configuration - m5.instantiate() - - # Determine the switching period, this has to be done after - # instantiating the system since the time base must be fixed. - period = m5.ticks.fromSeconds(1.0 / freq) - while True: - exit_event = m5.simulate(period) - exit_cause = exit_event.getCause() - - if exit_cause == "simulate() limit reached": - next_cpu = switcher.next() - - if verbose: - print("Switching CPUs...") - print(f"Next CPU: {type(next_cpu)}") - m5.drain() - if current_cpu != next_cpu: - m5.switchCpus( - system, [(current_cpu, next_cpu)], verbose=verbose - ) - else: - print( - "Source CPU and destination CPU are the same," - " skipping..." - ) - current_cpu = next_cpu - elif ( - exit_cause == "target called exit()" - or exit_cause == "m5_exit instruction encountered" - ): - - sys.exit(0) - else: - print(f"Test failed: Unknown exit cause: {exit_cause}") - sys.exit(1) diff --git a/tests/gem5/configs/arm_generic.py b/tests/gem5/fs/linux/arm/configs/arm_generic.py similarity index 100% rename from tests/gem5/configs/arm_generic.py rename to tests/gem5/fs/linux/arm/configs/arm_generic.py diff --git a/tests/gem5/configs/base_caches.py b/tests/gem5/fs/linux/arm/configs/base_caches.py similarity index 100% rename from tests/gem5/configs/base_caches.py rename to tests/gem5/fs/linux/arm/configs/base_caches.py diff --git a/tests/gem5/configs/base_config.py b/tests/gem5/fs/linux/arm/configs/base_config.py similarity index 100% rename from tests/gem5/configs/base_config.py rename to tests/gem5/fs/linux/arm/configs/base_config.py diff --git a/tests/gem5/configs/realview-minor-dual.py b/tests/gem5/fs/linux/arm/configs/realview-minor-dual.py similarity index 100% rename from tests/gem5/configs/realview-minor-dual.py rename to tests/gem5/fs/linux/arm/configs/realview-minor-dual.py diff --git a/tests/gem5/configs/realview-minor.py b/tests/gem5/fs/linux/arm/configs/realview-minor.py similarity index 100% rename from tests/gem5/configs/realview-minor.py rename to tests/gem5/fs/linux/arm/configs/realview-minor.py diff --git a/tests/gem5/configs/realview-o3-checker.py b/tests/gem5/fs/linux/arm/configs/realview-o3-checker.py similarity index 100% rename from tests/gem5/configs/realview-o3-checker.py rename to tests/gem5/fs/linux/arm/configs/realview-o3-checker.py diff --git a/tests/gem5/configs/realview-o3-dual.py b/tests/gem5/fs/linux/arm/configs/realview-o3-dual.py similarity index 100% rename from tests/gem5/configs/realview-o3-dual.py rename to tests/gem5/fs/linux/arm/configs/realview-o3-dual.py diff --git a/tests/gem5/configs/realview-o3.py b/tests/gem5/fs/linux/arm/configs/realview-o3.py similarity index 100% rename from tests/gem5/configs/realview-o3.py rename to tests/gem5/fs/linux/arm/configs/realview-o3.py diff --git a/tests/gem5/configs/realview-simple-atomic-checkpoint.py b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-checkpoint.py similarity index 100% rename from tests/gem5/configs/realview-simple-atomic-checkpoint.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-atomic-checkpoint.py diff --git a/tests/gem5/configs/realview-simple-atomic-dual.py b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-dual.py similarity index 100% rename from tests/gem5/configs/realview-simple-atomic-dual.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-atomic-dual.py diff --git a/tests/gem5/configs/realview-simple-atomic.py b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic.py similarity index 100% rename from tests/gem5/configs/realview-simple-atomic.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-atomic.py diff --git a/tests/gem5/configs/realview-simple-timing-dual-ruby.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual-ruby.py similarity index 100% rename from tests/gem5/configs/realview-simple-timing-dual-ruby.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual-ruby.py diff --git a/tests/gem5/configs/realview-simple-timing-dual.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual.py similarity index 100% rename from tests/gem5/configs/realview-simple-timing-dual.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual.py diff --git a/tests/gem5/configs/realview-simple-timing-ruby.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-ruby.py similarity index 100% rename from tests/gem5/configs/realview-simple-timing-ruby.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-timing-ruby.py diff --git a/tests/gem5/configs/realview-simple-timing.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing.py similarity index 100% rename from tests/gem5/configs/realview-simple-timing.py rename to tests/gem5/fs/linux/arm/configs/realview-simple-timing.py diff --git a/tests/gem5/configs/realview-switcheroo-atomic.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-atomic.py similarity index 100% rename from tests/gem5/configs/realview-switcheroo-atomic.py rename to tests/gem5/fs/linux/arm/configs/realview-switcheroo-atomic.py diff --git a/tests/gem5/configs/realview-switcheroo-full.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-full.py similarity index 100% rename from tests/gem5/configs/realview-switcheroo-full.py rename to tests/gem5/fs/linux/arm/configs/realview-switcheroo-full.py diff --git a/tests/gem5/configs/realview-switcheroo-noncaching-timing.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-noncaching-timing.py similarity index 100% rename from tests/gem5/configs/realview-switcheroo-noncaching-timing.py rename to tests/gem5/fs/linux/arm/configs/realview-switcheroo-noncaching-timing.py diff --git a/tests/gem5/configs/realview-switcheroo-o3.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-o3.py similarity index 100% rename from tests/gem5/configs/realview-switcheroo-o3.py rename to tests/gem5/fs/linux/arm/configs/realview-switcheroo-o3.py diff --git a/tests/gem5/configs/realview-switcheroo-timing.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-timing.py similarity index 100% rename from tests/gem5/configs/realview-switcheroo-timing.py rename to tests/gem5/fs/linux/arm/configs/realview-switcheroo-timing.py diff --git a/tests/gem5/configs/realview64-kvm-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-kvm-dual.py similarity index 100% rename from tests/gem5/configs/realview64-kvm-dual.py rename to tests/gem5/fs/linux/arm/configs/realview64-kvm-dual.py diff --git a/tests/gem5/configs/realview64-kvm.py b/tests/gem5/fs/linux/arm/configs/realview64-kvm.py similarity index 100% rename from tests/gem5/configs/realview64-kvm.py rename to tests/gem5/fs/linux/arm/configs/realview64-kvm.py diff --git a/tests/gem5/configs/realview64-minor-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-minor-dual.py similarity index 100% rename from tests/gem5/configs/realview64-minor-dual.py rename to tests/gem5/fs/linux/arm/configs/realview64-minor-dual.py diff --git a/tests/gem5/configs/realview64-minor.py b/tests/gem5/fs/linux/arm/configs/realview64-minor.py similarity index 100% rename from tests/gem5/configs/realview64-minor.py rename to tests/gem5/fs/linux/arm/configs/realview64-minor.py diff --git a/tests/gem5/configs/realview64-o3-checker.py b/tests/gem5/fs/linux/arm/configs/realview64-o3-checker.py similarity index 100% rename from tests/gem5/configs/realview64-o3-checker.py rename to tests/gem5/fs/linux/arm/configs/realview64-o3-checker.py diff --git a/tests/gem5/configs/realview64-o3-dual-ruby.py b/tests/gem5/fs/linux/arm/configs/realview64-o3-dual-ruby.py similarity index 100% rename from tests/gem5/configs/realview64-o3-dual-ruby.py rename to tests/gem5/fs/linux/arm/configs/realview64-o3-dual-ruby.py diff --git a/tests/gem5/configs/realview64-o3-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-o3-dual.py similarity index 100% rename from tests/gem5/configs/realview64-o3-dual.py rename to tests/gem5/fs/linux/arm/configs/realview64-o3-dual.py diff --git a/tests/gem5/configs/realview64-o3.py b/tests/gem5/fs/linux/arm/configs/realview64-o3.py similarity index 100% rename from tests/gem5/configs/realview64-o3.py rename to tests/gem5/fs/linux/arm/configs/realview64-o3.py diff --git a/tests/gem5/configs/realview64-simple-atomic-checkpoint.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-checkpoint.py similarity index 100% rename from tests/gem5/configs/realview64-simple-atomic-checkpoint.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-checkpoint.py diff --git a/tests/gem5/configs/realview64-simple-atomic-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-dual.py similarity index 100% rename from tests/gem5/configs/realview64-simple-atomic-dual.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-dual.py diff --git a/tests/gem5/configs/realview64-simple-atomic.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic.py similarity index 100% rename from tests/gem5/configs/realview64-simple-atomic.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-atomic.py diff --git a/tests/gem5/configs/realview64-simple-timing-dual-ruby.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual-ruby.py similarity index 100% rename from tests/gem5/configs/realview64-simple-timing-dual-ruby.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual-ruby.py diff --git a/tests/gem5/configs/realview64-simple-timing-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual.py similarity index 100% rename from tests/gem5/configs/realview64-simple-timing-dual.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual.py diff --git a/tests/gem5/configs/realview64-simple-timing-ruby.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-ruby.py similarity index 100% rename from tests/gem5/configs/realview64-simple-timing-ruby.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-timing-ruby.py diff --git a/tests/gem5/configs/realview64-simple-timing.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing.py similarity index 100% rename from tests/gem5/configs/realview64-simple-timing.py rename to tests/gem5/fs/linux/arm/configs/realview64-simple-timing.py diff --git a/tests/gem5/configs/realview64-switcheroo-atomic.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-atomic.py similarity index 100% rename from tests/gem5/configs/realview64-switcheroo-atomic.py rename to tests/gem5/fs/linux/arm/configs/realview64-switcheroo-atomic.py diff --git a/tests/gem5/configs/realview64-switcheroo-full.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-full.py similarity index 100% rename from tests/gem5/configs/realview64-switcheroo-full.py rename to tests/gem5/fs/linux/arm/configs/realview64-switcheroo-full.py diff --git a/tests/gem5/configs/realview64-switcheroo-o3.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-o3.py similarity index 100% rename from tests/gem5/configs/realview64-switcheroo-o3.py rename to tests/gem5/fs/linux/arm/configs/realview64-switcheroo-o3.py diff --git a/tests/gem5/configs/realview64-switcheroo-timing.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-timing.py similarity index 100% rename from tests/gem5/configs/realview64-switcheroo-timing.py rename to tests/gem5/fs/linux/arm/configs/realview64-switcheroo-timing.py diff --git a/tests/gem5/fs/linux/arm/run.py b/tests/gem5/fs/linux/arm/run.py index 18a4e5e268..e677297cad 100644 --- a/tests/gem5/fs/linux/arm/run.py +++ b/tests/gem5/fs/linux/arm/run.py @@ -62,7 +62,7 @@ gem5_root = sys.argv[3] # path setup sys.path.append(joinpath(gem5_root, "configs")) tests_root = joinpath(gem5_root, "tests") -sys.path.append(joinpath(tests_root, "gem5", "configs")) +sys.path.append(joinpath(tests_root, "gem5", "fs", "linux", "arm", "configs")) exec(compile(open(config).read(), config, "exec")) diff --git a/tests/gem5/fs/linux/arm/test.py b/tests/gem5/fs/linux/arm/test.py index 870024760e..f503f7ae02 100644 --- a/tests/gem5/fs/linux/arm/test.py +++ b/tests/gem5/fs/linux/arm/test.py @@ -129,7 +129,16 @@ for name in arm_fs_quick_tests: valid_hosts = constants.supported_hosts args = [ - joinpath(config.base_dir, "tests", "gem5", "configs", name + ".py"), + joinpath( + config.base_dir, + "tests", + "gem5", + "fs", + "linux", + "arm", + "configs", + name + ".py", + ), path, config.base_dir, ] @@ -147,7 +156,16 @@ for name in arm_fs_quick_tests: for name in arm_fs_long_tests: args = [ - joinpath(config.base_dir, "tests", "gem5", "configs", name + ".py"), + joinpath( + config.base_dir, + "tests", + "gem5", + "fs", + "linux", + "arm", + "configs", + name + ".py", + ), path, config.base_dir, ] @@ -164,7 +182,16 @@ for name in arm_fs_long_tests: for name in arm_fs_long_tests_arm_target: args = [ - joinpath(config.base_dir, "tests", "gem5", "configs", name + ".py"), + joinpath( + config.base_dir, + "tests", + "gem5", + "fs", + "linux", + "arm", + "configs", + name + ".py", + ), path, config.base_dir, ] diff --git a/tests/gem5/configs/download_check.py b/tests/gem5/gem5_resources/configs/download_check.py similarity index 100% rename from tests/gem5/configs/download_check.py rename to tests/gem5/gem5_resources/configs/download_check.py diff --git a/tests/gem5/gem5_resources/test_download_resources.py b/tests/gem5/gem5_resources/test_download_resources.py index c0efc8baad..0e406d69e7 100644 --- a/tests/gem5/gem5_resources/test_download_resources.py +++ b/tests/gem5/gem5_resources/test_download_resources.py @@ -38,7 +38,12 @@ gem5_verify_config( fixtures=(), verifiers=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "download_check.py" + config.base_dir, + "tests", + "gem5", + "gem5_resources", + "configs", + "download_check.py", ), config_args=["--download-directory", resource_path], valid_isas=(constants.all_compiled_tag,), diff --git a/tests/gem5/insttest_se/configs/simple_binary_run.py b/tests/gem5/insttest_se/configs/simple_binary_run.py new file mode 100644 index 0000000000..1a0f819a8f --- /dev/null +++ b/tests/gem5/insttest_se/configs/simple_binary_run.py @@ -0,0 +1,130 @@ +# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2022 Google Inc +# 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. + +""" +A run script for a very simple Syscall-Execution running simple binaries. +The system has no cache heirarchy and is as "bare-bones" as you can get in +gem5 while still being functinal. +""" + +from gem5.resources.resource import Resource +from gem5.components.processors.cpu_types import ( + get_cpu_types_str_set, + get_cpu_type_from_str, +) +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.boards.mem_mode import MemMode +from gem5.components.processors.cpu_types import CPUTypes +from gem5.simulate.simulator import Simulator +from gem5.isas import get_isa_from_str, get_isas_str_set, ISA + +from m5.util import fatal + +import argparse +import importlib + +cpu_types_string_map = { + CPUTypes.ATOMIC: "AtomicSimpleCPU", + CPUTypes.O3: "O3CPU", + CPUTypes.TIMING: "TimingSimpleCPU", + CPUTypes.KVM: "KvmCPU", + CPUTypes.MINOR: "MinorCPU", +} + +parser = argparse.ArgumentParser( + description="A gem5 script for running simple binaries in SE mode." +) + +parser.add_argument( + "resource", type=str, help="The gem5 resource binary to run." +) + +parser.add_argument( + "cpu", type=str, choices=get_cpu_types_str_set(), help="The CPU type used." +) + +parser.add_argument( + "isa", type=str, choices=get_isas_str_set(), help="The ISA used" +) + +parser.add_argument( + "--resource-directory", + type=str, + required=False, + help="The directory in which resources will be downloaded or exist.", +) + +parser.add_argument( + "--arguments", + type=str, + action="append", + default=[], + required=False, + help="The input arguments for the binary.", +) + +args = parser.parse_args() + +# Setup the system. +cache_hierarchy = NoCache() +memory = SingleChannelDDR3_1600() + +isa_enum = get_isa_from_str(args.isa) +cpu_enum = get_cpu_type_from_str(args.cpu) + +processor = SimpleProcessor( + cpu_type=cpu_enum, + isa=isa_enum, + num_cores=1, +) + +motherboard = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the workload +binary = Resource(args.resource, resource_directory=args.resource_directory) +motherboard.set_se_binary_workload(binary, arguments=args.arguments) + +# Run the simulation +simulator = Simulator(board=motherboard) +simulator.run() + +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), simulator.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/insttest_se/test.py b/tests/gem5/insttest_se/test.py index 4dde9d6e94..a9991b7102 100644 --- a/tests/gem5/insttest_se/test.py +++ b/tests/gem5/insttest_se/test.py @@ -52,6 +52,7 @@ for isa in test_progs: config.base_dir, "tests", "gem5", + "insttest_se", "configs", "simple_binary_run.py", ), diff --git a/tests/gem5/configs/boot_kvm_fork_run.py b/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py similarity index 100% rename from tests/gem5/configs/boot_kvm_fork_run.py rename to tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py diff --git a/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py b/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py index 7dcfc8517c..f5d407330e 100644 --- a/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py +++ b/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py @@ -64,7 +64,12 @@ def test_kvm_fork_run(cpu: str, num_cpus: int, mem_system: str, length: str): verifiers=verifiers, fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "boot_kvm_fork_run.py" + config.base_dir, + "tests", + "gem5", + "kvm_fork_tests", + "configs", + "boot_kvm_fork_run.py", ), config_args=[ "--cpu", diff --git a/tests/gem5/configs/boot_kvm_switch_exit.py b/tests/gem5/kvm_switch_tests/configs/boot_kvm_switch_exit.py similarity index 100% rename from tests/gem5/configs/boot_kvm_switch_exit.py rename to tests/gem5/kvm_switch_tests/configs/boot_kvm_switch_exit.py diff --git a/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py b/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py index 85e9268e2d..4beb60de64 100644 --- a/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py +++ b/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py @@ -67,6 +67,7 @@ def test_kvm_switch(cpu: str, num_cpus: int, mem_system: str, length: str): config.base_dir, "tests", "gem5", + "kvm_switch_tests", "configs", "boot_kvm_switch_exit.py", ), diff --git a/tests/gem5/m5_util/configs/simple_binary_run.py b/tests/gem5/m5_util/configs/simple_binary_run.py new file mode 100644 index 0000000000..ab12156ae2 --- /dev/null +++ b/tests/gem5/m5_util/configs/simple_binary_run.py @@ -0,0 +1,103 @@ +# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2022 Google Inc +# 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. + +""" +A run script for a very simple Syscall-Execution running simple binaries. +The system has no cache heirarchy and is as "bare-bones" as you can get in +gem5 while still being functinal. +""" + +from gem5.resources.resource import Resource +from gem5.components.processors.cpu_types import ( + get_cpu_types_str_set, + get_cpu_type_from_str, +) +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.boards.mem_mode import MemMode +from gem5.components.processors.cpu_types import CPUTypes +from gem5.simulate.simulator import Simulator +from gem5.isas import get_isa_from_str, get_isas_str_set, ISA + +from m5.util import fatal + +import argparse +import importlib + + +parser = argparse.ArgumentParser( + description="A gem5 script for running simple binaries in SE mode." +) + +parser.add_argument( + "resource", type=str, help="The gem5 resource binary to run." +) + +parser.add_argument( + "--resource-directory", + type=str, + required=False, + help="The directory in which resources will be downloaded or exist.", +) + +args = parser.parse_args() + +# Setup the system. +cache_hierarchy = NoCache() +memory = SingleChannelDDR3_1600() + +processor = SimpleProcessor( + cpu_type=CPUTypes.ATOMIC, + isa=ISA.X86, + num_cores=1, +) + +motherboard = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the workload +binary = Resource(args.resource, resource_directory=args.resource_directory) +motherboard.set_se_binary_workload(binary) + +# Run the simulation +simulator = Simulator(board=motherboard) +simulator.run() + +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), simulator.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/m5_util/test_exit.py b/tests/gem5/m5_util/test_exit.py index b79a8fadc2..214a20ada9 100644 --- a/tests/gem5/m5_util/test_exit.py +++ b/tests/gem5/m5_util/test_exit.py @@ -57,14 +57,17 @@ gem5_verify_config( verifiers=[a], fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "m5_util", + "configs", + "simple_binary_run.py", ), config_args=[ "x86-m5-exit", - "atomic", "--resource-directory", resource_path, - "x86", ], valid_isas=(constants.all_compiled_tag,), ) diff --git a/tests/gem5/configs/runtime_isa_check.py b/tests/gem5/multi_isa/configs/runtime_isa_check.py similarity index 100% rename from tests/gem5/configs/runtime_isa_check.py rename to tests/gem5/multi_isa/configs/runtime_isa_check.py diff --git a/tests/gem5/configs/supported_isa_check.py b/tests/gem5/multi_isa/configs/supported_isa_check.py similarity index 100% rename from tests/gem5/configs/supported_isa_check.py rename to tests/gem5/multi_isa/configs/supported_isa_check.py diff --git a/tests/gem5/multi_isa/test_multi_isa.py b/tests/gem5/multi_isa/test_multi_isa.py index 7d278b75ea..c9726174c0 100644 --- a/tests/gem5/multi_isa/test_multi_isa.py +++ b/tests/gem5/multi_isa/test_multi_isa.py @@ -49,6 +49,7 @@ for isa in isa_map.keys(): config.base_dir, "tests", "gem5", + "multi_isa", "configs", "runtime_isa_check.py", ), @@ -66,6 +67,7 @@ for isa in isa_map.keys(): config.base_dir, "tests", "gem5", + "multi_isa", "configs", "supported_isa_check.py", ), @@ -86,6 +88,7 @@ for isa in isa_map.keys(): config.base_dir, "tests", "gem5", + "multi_isa", "configs", "supported_isa_check.py", ), diff --git a/tests/gem5/configs/parsec_disk_run.py b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py similarity index 100% rename from tests/gem5/configs/parsec_disk_run.py rename to tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py diff --git a/tests/gem5/parsec_benchmarks/test_parsec.py b/tests/gem5/parsec_benchmarks/test_parsec.py index 11735ab43f..1f239dae1f 100644 --- a/tests/gem5/parsec_benchmarks/test_parsec.py +++ b/tests/gem5/parsec_benchmarks/test_parsec.py @@ -57,7 +57,12 @@ def test_parsec( verifiers=(), fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "parsec_disk_run.py" + config.base_dir, + "tests", + "gem5", + "parsec_benchmarks", + "configs", + "parsec_disk_run.py", ), config_args=[ "--cpu", diff --git a/tests/gem5/replacement_policies/configs/run_replacement_policy.py b/tests/gem5/replacement_policies/configs/run_replacement_policy.py new file mode 100644 index 0000000000..ec38bf382f --- /dev/null +++ b/tests/gem5/replacement_policies/configs/run_replacement_policy.py @@ -0,0 +1,94 @@ +# Copyright (c) 2022 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. + +import argparse +from importlib.machinery import SourceFileLoader + +from cache_hierarchies import ModMIExampleCacheHierarchy + +import m5 + +from m5.debug import flags +from m5.objects import Root +from gem5.components.boards.test_board import TestBoard +from gem5.components.memory.simple import SingleChannelSimpleMemory +from gem5.components.processors.complex_generator import ComplexGenerator + +argparser = argparse.ArgumentParser() + +argparser.add_argument( + "config_name", + type=str, + help="Name of the python file " + "including the defintion of a python generator and " + "importing the right replacement policy. The python " + "generator should only assume one positional argument " + "and be named python_generator. The replacement policy" + " should be imported as rp.", +) +argparser.add_argument( + "config_path", + type=str, + help="Path to the python file" "specified by config_name.", +) + +args = argparser.parse_args() + +module = SourceFileLoader(args.config_name, args.config_path).load_module() +python_generator = module.python_generator +rp_class = module.rp + +flags["RubyHitMiss"].enable() + +cache_hierarchy = ModMIExampleCacheHierarchy(rp_class) + +memory = SingleChannelSimpleMemory( + latency="30ns", + latency_var="0ns", + bandwidth="12.8GiB/s", + size="512MiB", +) + +generator = ComplexGenerator() +generator.set_traffic_from_python_generator(python_generator) + +# We use the Test Board. This is a special board to run traffic generation +# tasks +motherboard = TestBoard( + clk_freq="1GHz", + generator=generator, # We pass the traffic generator as the processor. + memory=memory, + cache_hierarchy=cache_hierarchy, +) +root = Root(full_system=False, system=motherboard) + +motherboard._pre_instantiate() +m5.instantiate() + +generator.start_traffic() +print("Beginning simulation!") +exit_event = m5.simulate() +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}.") diff --git a/tests/gem5/replacement_policies/test_replacement_policies.py b/tests/gem5/replacement_policies/test_replacement_policies.py index 4c74f72a2a..dd95c9c851 100644 --- a/tests/gem5/replacement_policies/test_replacement_policies.py +++ b/tests/gem5/replacement_policies/test_replacement_policies.py @@ -44,7 +44,8 @@ def test_replacement_policy(config_name: str, config_path: str) -> None: config.base_dir, "tests", "gem5", - "replacement-policies", + "replacement_policies", + "configs", "run_replacement_policy.py", ), config_args=[config_name, config_path], diff --git a/tests/gem5/configs/riscv_boot_exit_run.py b/tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py similarity index 100% rename from tests/gem5/configs/riscv_boot_exit_run.py rename to tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py diff --git a/tests/gem5/riscv_boot_tests/test_linux_boot.py b/tests/gem5/riscv_boot_tests/test_linux_boot.py index 55e0ae6109..42ae27730f 100644 --- a/tests/gem5/riscv_boot_tests/test_linux_boot.py +++ b/tests/gem5/riscv_boot_tests/test_linux_boot.py @@ -80,6 +80,7 @@ def test_boot( config.base_dir, "tests", "gem5", + "riscv_boot_tests", "configs", "riscv_boot_exit_run.py", ), diff --git a/tests/gem5/configs/simple_binary_run.py b/tests/gem5/se_mode/hello_se/configs/simple_binary_run.py similarity index 83% rename from tests/gem5/configs/simple_binary_run.py rename to tests/gem5/se_mode/hello_se/configs/simple_binary_run.py index 1ad4897415..19fd0e6b8c 100644 --- a/tests/gem5/configs/simple_binary_run.py +++ b/tests/gem5/se_mode/hello_se/configs/simple_binary_run.py @@ -1,4 +1,5 @@ # Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2022 Google Inc # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -45,9 +46,20 @@ from gem5.components.processors.simple_core import SimpleCore from gem5.components.boards.mem_mode import MemMode from gem5.components.processors.cpu_types import CPUTypes from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set +from gem5.isas import get_isa_from_str, get_isas_str_set, ISA + +from m5.util import fatal import argparse +import importlib + +cpu_types_string_map = { + CPUTypes.ATOMIC: "AtomicSimpleCPU", + CPUTypes.O3: "O3CPU", + CPUTypes.TIMING: "TimingSimpleCPU", + CPUTypes.KVM: "KvmCPU", + CPUTypes.MINOR: "MinorCPU", +} parser = argparse.ArgumentParser( description="A gem5 script for running simple binaries in SE mode." @@ -65,13 +77,6 @@ parser.add_argument( "isa", type=str, choices=get_isas_str_set(), help="The ISA used" ) -parser.add_argument( - "-b", - "--base-cpu-processor", - action="store_true", - help="Use the BaseCPUProcessor instead of the SimpleProcessor.", -) - parser.add_argument( "-r", "--resource-directory", @@ -104,28 +109,14 @@ args = parser.parse_args() cache_hierarchy = NoCache() memory = SingleChannelDDR3_1600() -if args.base_cpu_processor: - cores = [ - BaseCPUCore( - core=SimpleCore.cpu_simobject_factory( - cpu_type=get_cpu_type_from_str(args.cpu), - isa=get_isa_from_str(args.isa), - core_id=i, - ), - isa=get_isa_from_str(args.isa), - ) - for i in range(args.num_cores) - ] +isa_enum = get_isa_from_str(args.isa) +cpu_enum = get_cpu_type_from_str(args.cpu) - processor = BaseCPUProcessor( - cores=cores, - ) -else: - processor = SimpleProcessor( - cpu_type=get_cpu_type_from_str(args.cpu), - isa=get_isa_from_str(args.isa), - num_cores=args.num_cores, - ) +processor = SimpleProcessor( + cpu_type=cpu_enum, + isa=isa_enum, + num_cores=args.num_cores, +) motherboard = SimpleBoard( clk_freq="3GHz", diff --git a/tests/gem5/se_mode/hello_se/test_hello_se.py b/tests/gem5/se_mode/hello_se/test_hello_se.py index 1aaac4a435..5c6ab4ea07 100644 --- a/tests/gem5/se_mode/hello_se/test_hello_se.py +++ b/tests/gem5/se_mode/hello_se/test_hello_se.py @@ -96,7 +96,13 @@ def verify_config(isa, binary, cpu, hosts, verifier, input): fixtures=(), verifiers=(verifier,), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "se_mode", + "hello_se", + "configs", + "simple_binary_run.py", ), config_args=[ binary, diff --git a/tests/gem5/se_mode/hello_se/test_se_multicore.py b/tests/gem5/se_mode/hello_se/test_se_multicore.py index 55fc61fbf8..dc98a755f3 100644 --- a/tests/gem5/se_mode/hello_se/test_se_multicore.py +++ b/tests/gem5/se_mode/hello_se/test_se_multicore.py @@ -40,7 +40,13 @@ gem5_verify_config( fixtures=(), verifiers=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "se_mode", + "hello_se", + "configs", + "simple_binary_run.py", ), config_args=[ "x86-hello64-static", diff --git a/tests/gem5/stats/configs/simple_binary_run.py b/tests/gem5/stats/configs/simple_binary_run.py new file mode 100644 index 0000000000..b4d9d76d8d --- /dev/null +++ b/tests/gem5/stats/configs/simple_binary_run.py @@ -0,0 +1,112 @@ +# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2022 Google Inc +# 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. + +""" +A run script for a very simple Syscall-Execution running simple binaries. +The system has no cache heirarchy and is as "bare-bones" as you can get in +gem5 while still being functinal. +""" + +from gem5.resources.resource import Resource +from gem5.components.processors.cpu_types import ( + get_cpu_types_str_set, + get_cpu_type_from_str, +) +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.boards.mem_mode import MemMode +from gem5.components.processors.cpu_types import CPUTypes +from gem5.simulate.simulator import Simulator +from gem5.isas import get_isa_from_str, get_isas_str_set, ISA + +from m5.util import fatal + +import argparse +import importlib + +parser = argparse.ArgumentParser( + description="A gem5 script for running simple binaries in SE mode." +) + +parser.add_argument( + "resource", type=str, help="The gem5 resource binary to run." +) + +parser.add_argument( + "-r", + "--resource-directory", + type=str, + required=False, + help="The directory in which resources will be downloaded or exist.", +) + +parser.add_argument( + "--arguments", + type=str, + action="append", + default=[], + required=False, + help="The input arguments for the binary.", +) + +args = parser.parse_args() + +# Setup the system. +cache_hierarchy = NoCache() +memory = SingleChannelDDR3_1600() + +processor = SimpleProcessor( + cpu_type=CPUTypes.ATOMIC, + isa=ISA.ARM, + num_cores=1, +) + +motherboard = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the workload +binary = Resource(args.resource, resource_directory=args.resource_directory) +motherboard.set_se_binary_workload(binary, arguments=args.arguments) + +# Run the simulation +simulator = Simulator(board=motherboard) +simulator.run() + +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), simulator.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/stats/test_hdf5.py b/tests/gem5/stats/test_hdf5.py index 8775d22ad8..c226d717de 100644 --- a/tests/gem5/stats/test_hdf5.py +++ b/tests/gem5/stats/test_hdf5.py @@ -96,14 +96,17 @@ if have_hdf5(): verifiers=[ok_verifier, err_verifier, h5_verifier], fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "stats", + "configs", + "simple_binary_run.py", ), config_args=[ "arm-hello64-static", - "atomic", "--resource-directory", resource_path, - "arm", ], gem5_args=["--stats-file=h5://stats.h5"], valid_isas=(constants.all_compiled_tag,), diff --git a/tests/gem5/configs/requires_check.py b/tests/gem5/stdlib/configs/requires_check.py similarity index 100% rename from tests/gem5/configs/requires_check.py rename to tests/gem5/stdlib/configs/requires_check.py diff --git a/tests/gem5/stdlib/configs/simple_binary_run.py b/tests/gem5/stdlib/configs/simple_binary_run.py new file mode 100644 index 0000000000..a0e4c7f62a --- /dev/null +++ b/tests/gem5/stdlib/configs/simple_binary_run.py @@ -0,0 +1,124 @@ +# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2022 Google Inc +# 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. + +""" +A run script for a very simple Syscall-Execution running simple binaries. +The system has no cache heirarchy and is as "bare-bones" as you can get in +gem5 while still being functinal. +""" + +from gem5.resources.resource import Resource +from gem5.components.processors.cpu_types import ( + get_cpu_types_str_set, + get_cpu_type_from_str, +) +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.boards.mem_mode import MemMode +from gem5.components.processors.cpu_types import CPUTypes +from gem5.simulate.simulator import Simulator +from gem5.isas import get_isa_from_str, get_isas_str_set, ISA + +from m5.util import fatal + +import argparse +import importlib + +cpu_types_string_map = { + CPUTypes.ATOMIC: "AtomicSimpleCPU", + CPUTypes.O3: "O3CPU", + CPUTypes.TIMING: "TimingSimpleCPU", + CPUTypes.KVM: "KvmCPU", + CPUTypes.MINOR: "MinorCPU", +} + +parser = argparse.ArgumentParser( + description="A gem5 script for running simple binaries in SE mode." +) + +parser.add_argument( + "resource", type=str, help="The gem5 resource binary to run." +) + +parser.add_argument( + "cpu", type=str, choices=get_cpu_types_str_set(), help="The CPU type used." +) + +parser.add_argument( + "isa", type=str, choices=get_isas_str_set(), help="The ISA used" +) + +args = parser.parse_args() + +# Setup the system. +cache_hierarchy = NoCache() +memory = SingleChannelDDR3_1600() + +isa_enum = get_isa_from_str(args.isa) +cpu_enum = get_cpu_type_from_str(args.cpu) + +cores = [ + BaseCPUCore( + core=SimpleCore.cpu_simobject_factory( + cpu_type=cpu_enum, + isa=isa_enum, + core_id=i, + ), + isa=isa_enum, + ) + for i in range(1) +] + +processor = BaseCPUProcessor( + cores=cores, +) + +motherboard = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the workload +binary = Resource(args.resource) +motherboard.set_se_binary_workload(binary) + +# Run the simulation +simulator = Simulator(board=motherboard) +simulator.run() + +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), simulator.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/stdlib/test_base_cpu_processor.py b/tests/gem5/stdlib/test_base_cpu_processor.py index cbc6767481..554342b51f 100644 --- a/tests/gem5/stdlib/test_base_cpu_processor.py +++ b/tests/gem5/stdlib/test_base_cpu_processor.py @@ -37,9 +37,14 @@ gem5_verify_config( verifiers=(), fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "stdlib", + "configs", + "simple_binary_run.py", ), - config_args=["x86-hello64-static", "timing", "x86", "-b"], + config_args=["x86-hello64-static", "timing", "x86"], valid_isas=(constants.all_compiled_tag,), length=constants.quick_tag, ) @@ -49,9 +54,14 @@ gem5_verify_config( verifiers=(), fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "stdlib", + "configs", + "simple_binary_run.py", ), - config_args=["riscv-hello", "atomic", "riscv", "-b"], + config_args=["riscv-hello", "atomic", "riscv"], valid_isas=(constants.all_compiled_tag,), length=constants.quick_tag, ) @@ -61,9 +71,14 @@ gem5_verify_config( verifiers=(), fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "simple_binary_run.py" + config.base_dir, + "tests", + "gem5", + "stdlib", + "configs", + "simple_binary_run.py", ), - config_args=["arm-hello64-static", "o3", "arm", "-b"], + config_args=["arm-hello64-static", "o3", "arm"], valid_isas=(constants.all_compiled_tag,), length=constants.quick_tag, ) diff --git a/tests/gem5/stdlib/test_requires.py b/tests/gem5/stdlib/test_requires.py index b729050b47..3011180679 100644 --- a/tests/gem5/stdlib/test_requires.py +++ b/tests/gem5/stdlib/test_requires.py @@ -58,6 +58,7 @@ for isa in isa_map.keys(): config.base_dir, "tests", "gem5", + "stdlib", "configs", "requires_check.py", ), @@ -75,6 +76,7 @@ for isa in isa_map.keys(): config.base_dir, "tests", "gem5", + "stdlib", "configs", "requires_check.py", ), diff --git a/tests/gem5/traffic_gen/simple_traffic_run.py b/tests/gem5/traffic_gen/configs/simple_traffic_run.py similarity index 100% rename from tests/gem5/traffic_gen/simple_traffic_run.py rename to tests/gem5/traffic_gen/configs/simple_traffic_run.py diff --git a/tests/gem5/traffic_gen/test_memory_traffic_gen.py b/tests/gem5/traffic_gen/test_memory_traffic_gen.py index 122204e3e9..0dc5103011 100644 --- a/tests/gem5/traffic_gen/test_memory_traffic_gen.py +++ b/tests/gem5/traffic_gen/test_memory_traffic_gen.py @@ -72,6 +72,7 @@ def test_memory( "tests", "gem5", "traffic_gen", + "configs", "simple_traffic_run.py", ), config_args=[generator, generator_cores, cache, module] diff --git a/tests/gem5/configs/x86_boot_exit_run.py b/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py similarity index 100% rename from tests/gem5/configs/x86_boot_exit_run.py rename to tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py diff --git a/tests/gem5/x86_boot_tests/test_linux_boot.py b/tests/gem5/x86_boot_tests/test_linux_boot.py index 1907aaf0e4..3418e839ab 100644 --- a/tests/gem5/x86_boot_tests/test_linux_boot.py +++ b/tests/gem5/x86_boot_tests/test_linux_boot.py @@ -75,7 +75,12 @@ def test_boot( verifiers=verifiers, fixtures=(), config=joinpath( - config.base_dir, "tests", "gem5", "configs", "x86_boot_exit_run.py" + config.base_dir, + "tests", + "gem5", + "x86_boot_tests", + "configs", + "x86_boot_exit_run.py", ), config_args=[ "--cpu", From 0855c58538afa477200e829664cfbb3b1958b934 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 2 Aug 2023 18:56:02 -0700 Subject: [PATCH 154/693] tests: download_check.py to rm each resource after check "tests/gem5/configs/download_check.py" is used by the "test-resource-downloading" test (defined in "tests/gem5/gem5-resources/test_download_resources.py" and ran as part of the "very-long" suite). Prior to this change "download_check.py" would download each resource, check it's md5, then at the end of the script remove all the downloaded resources. This is inefficient on disk space and was causing our "very-long" suite of tests to require a machines with a lot of disk space to run. This change alters 'download_check.py" to remove each resource after the md5 check. Thus, only one resource is ever downloaded and present at any given time during the running of this script. Change-Id: I38fce100ab09f66c256ccddbcb6f29763839ac40 --- tests/gem5/configs/download_check.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/gem5/configs/download_check.py b/tests/gem5/configs/download_check.py index e3b06a578d..20081a46d5 100644 --- a/tests/gem5/configs/download_check.py +++ b/tests/gem5/configs/download_check.py @@ -127,9 +127,14 @@ for id in ids: + f"({md5(Path(download_path))}) differs to that recorded in " + f" gem5-resources ({resource_json['md5sum']}).{os.linesep}" ) + # Remove the downloaded resource. + if os.path.isfile(download_path): + os.remove(download_path) + elif os.path.isdir(download_path): + shutil.rmtree(download_path, ignore_errors=True) + else: + raise Exception("{download_path} is not a file or directory.") -# Remove the downloaded resource. -shutil.rmtree(args.download_directory, ignore_errors=True) # If errors exist, raise an exception highlighting them. if errors: From a25ca04851f007a6cb052ccc1440685b6a401d25 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Thu, 3 Aug 2023 10:59:11 -0700 Subject: [PATCH 155/693] stdlib, resources: Fixed keyerror: 'is_zipped' bug Change-Id: I68fffd880983ebc225ec6fc8c7f8d509759b581d --- src/python/gem5/resources/downloader.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index 1aeb487e61..b4f7a2f016 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -280,17 +280,21 @@ def get_resource( # string-based way of doing things. It can be refactored away over # time: # https://gem5-review.googlesource.com/c/public/gem5-resources/+/51168 - if isinstance(resource_json["is_zipped"], str): - run_unzip = unzip and resource_json["is_zipped"].lower() == "true" - elif isinstance(resource_json["is_zipped"], bool): - run_unzip = unzip and resource_json["is_zipped"] - else: - raise Exception( - "The resource.json entry for '{}' has a value for the " - "'is_zipped' field which is neither a string or a boolean.".format( - resource_name + run_unzip = False + if "is_zipped" in resource_json: + if isinstance(resource_json["is_zipped"], str): + run_unzip = ( + unzip and resource_json["is_zipped"].lower() == "true" + ) + elif isinstance(resource_json["is_zipped"], bool): + run_unzip = unzip and resource_json["is_zipped"] + else: + raise Exception( + "The resource.json entry for '{}' has a value for the " + "'is_zipped' field which is neither a string or a boolean.".format( + resource_name + ) ) - ) run_tar_extract = ( untar From 5cfac2cc943e837a379dd36f133b2dfba4c1f4aa Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Thu, 3 Aug 2023 13:04:17 -0700 Subject: [PATCH 156/693] stdlib: Fixed stype issue pcstate.hh - Changed _rv_type to _rvType. - Changed rv_type to rvType. Change-Id: I27bdf342b038f5ebae78b104a29892684265584a --- src/arch/riscv/pcstate.hh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh index de07145dc3..1c04cb5109 100644 --- a/src/arch/riscv/pcstate.hh +++ b/src/arch/riscv/pcstate.hh @@ -58,12 +58,12 @@ class PCState : public GenericISA::UPCState<4> { private: bool _compressed = false; - RiscvType _rv_type = RV64; + RiscvType _rvType = RV64; public: PCState() = default; PCState(const PCState &other) = default; - PCState(Addr addr, RiscvType rv_type) : UPCState(addr), _rv_type(rv_type) + PCState(Addr addr, RiscvType rvType) : UPCState(addr), _rvType(rvType) { } @@ -75,14 +75,14 @@ class PCState : public GenericISA::UPCState<4> Base::update(other); auto &pcstate = other.as(); _compressed = pcstate._compressed; - _rv_type = pcstate._rv_type; + _rvType = pcstate._rvType; } void compressed(bool c) { _compressed = c; } bool compressed() const { return _compressed; } - void rvType(RiscvType rv_type) { _rv_type = rv_type; } - RiscvType rvType() const { return _rv_type; } + void rvType(RiscvType rvType) { _rvType = rvType; } + RiscvType rvType() const { return _rvType; } bool branching() const override From 5e6095feccb371e9bce3faa6eff3439a92bab48b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 3 Aug 2023 13:02:25 -0700 Subject: [PATCH 157/693] misc: Update MAINTAINERS.yaml documentation comment This comment is updated to reflect new gem5 policy and its move to GitHub and a Pull Request contribution model. Change-Id: Iec909ffa0cca254fdbe56ce3165cb948cdd0cbce --- MAINTAINERS.yaml | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index c8b8957496..f7a00c8c95 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -1,23 +1,22 @@ # See CONTRIBUTING.md for details of gem5's contribution process. # # This file contains a list of gem5's subsystems and their -# maintainers. The key used to identifity a subsystem should be used -# as a tag in commit messages targetting that subsystem. At least one -# (not all) of these maintainers must review the patch before it can -# be pushed. These people will automatically be emailed when you -# upload the patch to Gerrit (https://gem5-review.googlesource.com). -# These subsystem keys mostly follow the directory structure. +# maintainers. The key used to identify a subsystem should be used +# as a tag in commit messages targeting that subsystem. Via our GitHub +# Pull Request system (https://github.com/gem5/gem5/pulls) a maintainer +# of the subsystem impacted by a pull request contribution will be added +# as an assignee to that pull request. Their role is be to referee the +# contribution (add a review, assign reviewers, suggest changes, etc.), then +# merge the contribution into the gem5 develop branch when they are satisfied +# with the change. # -# Maintainers have the following responsibilities: -# 1. That at least one maintainer of each subsystem reviews all -# changes to that subsystem (they will be automatically tagged and -# emailed on each new change). -# 2. They will complete your reviews in a timely manner (within a few -# business days). -# 3. They pledge to uphold gem5's community standards and its code of -# conduct by being polite and professional in their code -# reviews. See CODE-OF-CONDUCT.md. +# Maintainers assigned to a pull request are expected to acknowledge their +# assignment in 2 business days and to fully begin refereeing the contribution +# within a business week. # +# Maintainers pledge to uphold gem5's community standards and its code of +# conduct by being polite and professional in their interactions with +# contributors. See CODE-OF-CONDUCT.md. # # Entries in this file have the following format: # key: From 3f1518a1c213cf6e69abdf99ecb2f69cfa508b5e Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 3 Aug 2023 13:57:59 -0700 Subject: [PATCH 158/693] misc: Update subsystem maintainers in MAINTAINERS.yaml This change incorporates changes to the set of maintainers and the maintainers assigned to each subsystem based on individual maintainers' preferences. Change-Id: Ic2c39907763282e89936fa0d90e3c1a105a0d917 --- MAINTAINERS.yaml | 160 +++++++++++++---------------------------------- 1 file changed, 43 insertions(+), 117 deletions(-) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index f7a00c8c95..25835d393b 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -39,82 +39,65 @@ pmc: status: maintained maintainers: - Andreas Sandberg - - Brad Beckmann - - David Wood - - Gabe Black - Giacomo Travaglini + - Matt Poremba - Jason Lowe-Power (chair) + - Zhengrong Wang + - Borius Shingarov - Matt Sinclair - - Tony Gutierrez - - Steve Reinhardt + - Bobby R. Bruce arch: desc: >- General architecture-specific components - status: maintained - maintainers: - - Gabe Black + status: orphaned arch-arm: status: maintained maintainers: - - Andreas Sandberg - Giacomo Travaglini + - Andreas Sandberg arch-gcn3: status: maintained maintainers: - - Matt Poremba - Matt Sinclair + - Matt Porema arch-vega: status: maintained maintainers: - - Matt Poremba - Matt Sinclair + - Matt Porema arch-mips: status: orphaned arch-power: - status: maintained - maintainers: - - Boris Shingarov + status: orphaned arch-riscv: status: orphaned arch-sparc: - status: maintained - maintainers: - - Gabe Black + status: orphaned arch-x86: - status: maintained - maintainers: - - Gabe Black + status: orphaned base: - status: maintained - maintainers: - - Bobby Bruce - - Daniel Carvalho + status: orphaned base-stats: status: orphaned configs: - status: maintained - maintainers: - - Jason Lowe-Power + status: orphaned cpu: desc: >- General changes to all CPU models (e.g., BaseCPU) - status: maintained - maintainers: - - Gabe Black - - Jason Lowe-Power + status: orphaned cpu-kvm: status: maintained @@ -122,33 +105,22 @@ cpu-kvm: - Andreas Sandberg cpu-minor: - status: maintained - maintainers: - - Zhengrong Wang + status: orphaned cpu-o3: status: orphaned cpu-simple: - status: maintained - maintainers: - - Jason Lowe-Power - - Gabe Black + status: orphaned dev: - status: maintained - maintainers: - - Gabe Black + status: orphaned dev-hsa: - status: maintained - maintainers: - - Matt Poremba + status: orphaned dev-amdgpu: - status: maintained - maintainers: - - Matt Poremba + status: orphaned dev-virtio: status: maintained @@ -158,47 +130,32 @@ dev-virtio: dev-arm: status: maintained maintainers: - - Andreas Sandberg - Giacomo Travaglini + - Andreas Sandberg doc: - status: maintained - maintainers: - - Bobby Bruce + status: orphaned ext: desc: >- Components external to gem5 - status: maintained - maintainers: - - Bobby Bruce - - Jason Lowe-Power + status: orphaned ext-testlib: - status: maintained - maintainers: - - Bobby Bruce - - Hoa Nguyen + status: orphaned fastmodel: desc: >- Changes relating to ARM Fast Models - status: maintained - maintainers: - - Gabe Black + status: orphaned gpu-compute: - status: maintained - maintainers: - - Matt Poremba - - Matt Sinclair + status: orphaned learning-gem5: desc: >- The code and configs for the Learning gem5 book - status: maintained - maintainers: - - Jason Lowe-Power + status: orphaned stdlib: desc: >- @@ -210,75 +167,54 @@ stdlib: mem: desc: >- General memory system (e.g., XBar, Packet) - status: maintained - maintainers: - - Nikos Nikoleris + status: orphaned mem-cache: desc: >- Classic caches and coherence - status: maintained - maintainers: - - Nikos Nikoleris - - Daniel Carvalho + status: orphaned mem-dram: - status: maintained - maintainers: - - Nikos Nikoleris + status: orphaned mem-garnet: desc: >- Garnet subcomponent of Ruby - status: maintained - maintainers: - - Srikant Bharadwaj + status: orphaned mem-ruby: desc: >- Ruby structures and protocols status: maintained maintainers: - - Jason Lowe-Power - Matt Sinclair misc: desc: >- Anything outside of the other categories - status: maintained - maintainers: - - Bobby Bruce - - Jason Lowe-Power + status: orphaned python: desc: >- Python SimObject wrapping and infrastructure - status: maintained - maintainers: - - Andreas Sandberg - - Jason Lowe-Power + status: orphaned resources: desc: >- The gem5-resources repo with auxiliary resources for simulation status: maintained maintainers: - - Bobby Bruce - - Jason Lowe-Power + - Bobby R. Bruce scons: desc: >- Build system - status: maintained - maintainers: - - Gabe Black + status: orphaned sim: desc: >- General simulation components - status: maintained - maintainers: - - Jason Lowe-Power + status: orphaned sim-se: desc: >- @@ -288,48 +224,38 @@ sim-se: system-arm: status: maintained maintainers: - - Andreas Sandberg - Giacomo Travaglini + - Andreas Sandberg systemc: desc: >- Code for the gem5 SystemC implementation and interface - status: maintained - maintainers: - - Gabe Black + status: orphaned tests: desc: >- testing changes status: maintained maintainers: - - Bobby Bruce + - Bobby R. Bruce util: - status: maintained - maintainers: - - Gabe Black + status: orphaned util-docker: status: maintained maintainers: - - Bobby Bruce + - Bobby R. Bruce util-m5: - status: maintained - maintainers: - - Gabe Black + status: orphaned util-gem5art: - status: maintained - maintainers: - - Bobby Bruce - - Jason Lowe-Power + status: orphaned website: desc: >- The gem5-website repo which contains the gem5.org site status: maintained maintainers: - - Bobby Bruce - - Hoa Nguyen + - Bobby R. Bruce From 23f78159ec443b907eb79eb1e3bea9151f98f928 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 3 Aug 2023 14:14:20 -0700 Subject: [PATCH 159/693] misc: Add 'experts' field to MAINTAINERS.yaml This field was added to give gem5 community members a change to register that they have expertise in a particular subsystem but do not much to assign themselves the responsibilities of a subsystem maintainer. Those who have registered interest on being an subsystem expert have been added. Change-Id: I8f532e381e8e42257b2a68ac48204131479d8cd0 --- MAINTAINERS.yaml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index 25835d393b..e5e8d1b968 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -26,11 +26,18 @@ # maintainers: # - John Doe # - Jane Doe -# +# experts: +# - Jack Doe +# - Jill Doe # # The status field should have one of the following values: # - maintained: The component has an active maintainer. # - orphaned: The component is looking for a new owner. +# +# The experts field is optional and used to identify people who are +# knowledgeable about the subsystem but are not responsible for it. Those +# listed as an expert are typically good to add as a reviewer for pull requests +# targeting that subsystem. pmc: @@ -93,11 +100,15 @@ base-stats: configs: status: orphaned + experts: + - Jason Lowe-Power cpu: desc: >- General changes to all CPU models (e.g., BaseCPU) status: orphaned + experts: + - Jason Lowe-Power cpu-kvm: status: maintained @@ -112,6 +123,8 @@ cpu-o3: cpu-simple: status: orphaned + experts: + - Jason Lowe-Power dev: status: orphaned @@ -140,9 +153,13 @@ ext: desc: >- Components external to gem5 status: orphaned + experts: + - Jason Lowe-Power ext-testlib: status: orphaned + experts: + - Bobby R. Bruce fastmodel: desc: >- @@ -156,6 +173,9 @@ learning-gem5: desc: >- The code and configs for the Learning gem5 book status: orphaned + experts: + - Jason Lowe-Power + - Bobby R. Bruce stdlib: desc: >- @@ -188,16 +208,23 @@ mem-ruby: status: maintained maintainers: - Matt Sinclair + experts: + - Jason Lowe-Power misc: desc: >- Anything outside of the other categories status: orphaned + experts: + - Jason Lowe-Power python: desc: >- Python SimObject wrapping and infrastructure status: orphaned + experts: + - Jason Lowe-Power + - Andreas Sandberg resources: desc: >- @@ -205,6 +232,8 @@ resources: status: maintained maintainers: - Bobby R. Bruce + experts: + - Jason Lowe-Power scons: desc: >- @@ -215,6 +244,8 @@ sim: desc: >- General simulation components status: orphaned + experts: + - Jason Lowe-Power sim-se: desc: >- From 298b1fafb4ae646745ce28ac3cd0949cf6db6aa5 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Wed, 2 Aug 2023 15:07:33 -0700 Subject: [PATCH 160/693] misc: Update test names in daily and weekly yaml files Updates the directories in which tests are run in accordance with the refactoring of the testing directory Change-Id: I93f5c5b0236c5180da04deb425ec2ed6804fa003 --- .github/workflows/daily-tests.yaml | 2 +- .github/workflows/weekly-tests.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 0384bfeadb..60203f1017 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -74,7 +74,7 @@ jobs: testlib-long-tests: strategy: matrix: - test-type: [arm-boot-tests, fs, gem5_library_example_tests, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement-policies, riscv-boot-tests, stdlib, x86-boot-tests] + test-type: [arm_boot_tests, fs, gem5_library_example_tests, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index dd81555f00..fad5d6f327 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -93,7 +93,7 @@ jobs: - run: chmod u+x build/ALL/gem5.opt - name: very-long gem5-resources tests working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/gem5-resources --length very-long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/gem5_resources --length very-long --skip-build -vv -t $(nproc) - name: create zip of results if: success() || failure() run: | @@ -131,9 +131,9 @@ jobs: name: ${{needs.build-gem5.outputs.build-name}} path: build/ALL - run: chmod u+x build/ALL/gem5.opt - - name: very-long x86-boot-tests + - name: very-long parsec_benchmarks working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/x86-boot-tests --length very-long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/parsec_benchmarks --length very-long --skip-build -vv -t $(nproc) - name: create zip of results if: success() || failure() run: | @@ -173,7 +173,7 @@ jobs: - run: chmod u+x build/ALL/gem5.opt - name: very-long x86-boot-tests working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/x86-boot-tests --length very-long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/x86_boot_tests --length very-long --skip-build -vv -t $(nproc) - name: create zip of results if: success() || failure() run: | From e7c8a123499494f29a35a4433ab328d6c6276205 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Thu, 3 Aug 2023 17:00:07 -0700 Subject: [PATCH 161/693] misc: Fix daily tests The dailies timed out as they were running the entire directory of tests due to a wrong variable named being used. In addition, the names of tests were adjusted to include the matrix type so the artifacts won't overwrite each other Change-Id: Iaa1be8e0cfcbf9d64f1a674590bfe2bf1f0dae90 --- .github/workflows/daily-tests.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 679dba2978..c1e8e7fa5c 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -137,7 +137,7 @@ jobs: # run test - name: long ${{ matrix.test-type }} tests working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/${{ matrix.image }} --length=long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/${{ matrix.test-type }} --length=long --skip-build -vv -t $(nproc) - name: create zip of results if: success() || failure() run: | @@ -147,7 +147,7 @@ jobs: if: success() || failure() uses: actions/upload-artifact@v3 env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} with: name: ${{ env.MY_STEP_VAR }} path: output.zip @@ -193,7 +193,7 @@ jobs: if: success() || failure() uses: actions/upload-artifact@v3 env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} with: name: ${{ env.MY_STEP_VAR }} path: output.zip From 14c25a383cfbb5e76e041ef13763abbe020cf5ed Mon Sep 17 00:00:00 2001 From: zmckevitt Date: Thu, 29 Jun 2023 23:23:02 +0000 Subject: [PATCH 162/693] arch-riscv: Implemented zicbom/zicboz extensions for RISC V Change-Id: I79d0e6059a2dbb5a0057c4f7489b999f9e803684 --- src/arch/riscv/isa/decoder.isa | 17 +++++++++++++++++ src/arch/riscv/isa/formats/mem.isa | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index d34adfaa02..71efac5958 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -677,6 +677,23 @@ decode QUADRANT default Unknown::unknown() { 0x1: fence_i({{ }}, uint64_t, IsNonSpeculative, IsSerializeAfter, No_OpClass); } + + 0x2: decode FUNCT12 { + format CBMOp { + 0x0: cbo_inval({{ + Mem = 0; + }}, mem_flags=[INVALIDATE, DST_POC]); + 0x1: cbo_clean({{ + Mem = 0; + }}, mem_flags=[CLEAN, DST_POC]); + 0x2: cbo_flush({{ + Mem = 0; + }}, mem_flags=[CLEAN, INVALIDATE, DST_POC]); + 0x4: cbo_zero({{ + Mem = 0; + }}, mem_flags=[CACHE_BLOCK_ZERO]); + } + } } 0x04: decode FUNCT3 { diff --git a/src/arch/riscv/isa/formats/mem.isa b/src/arch/riscv/isa/formats/mem.isa index 0d80260a25..7cec113ba1 100644 --- a/src/arch/riscv/isa/formats/mem.isa +++ b/src/arch/riscv/isa/formats/mem.isa @@ -243,3 +243,10 @@ def format Store(memacc_code, ea_code={{EA = rvZext(Rs1 + offset);}}, LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags, inst_flags, 'Store', exec_template_base='Store') }}; + +def format CBMOp(memacc_code, ea_code={{EA = rvZext(Rs1 + offset);}}, + offset_code={{offset = 0;}}, mem_flags=[], inst_flags=[]) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags, + inst_flags, 'Store', exec_template_base='Store') +}}; From f777cc143cad55af7ee6434b58deb7fe61e5a16f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= Date: Mon, 24 Jul 2023 12:58:36 +0200 Subject: [PATCH 163/693] util: fix cpt upgrader for rvv changes in PR #83 * Solves issue #106 by updating the cpts with the necessary vector registers. Change-Id: Ifeda90e96097f0b0a65338c6b22a8258c932c585 util: clear vector_element field Change-Id: I6c9ec4e71f66722b26de030fa139cd626bdb24dc --- util/cpt_upgraders/riscv-vext.py | 86 ++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 util/cpt_upgraders/riscv-vext.py diff --git a/util/cpt_upgraders/riscv-vext.py b/util/cpt_upgraders/riscv-vext.py new file mode 100644 index 0000000000..ada492fe1e --- /dev/null +++ b/util/cpt_upgraders/riscv-vext.py @@ -0,0 +1,86 @@ +# Copyright (c) 2023 Barcelona Supercomputing Center (BSC) +# 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. + + +def upgrader(cpt): + """ + Update the checkpoint to support initial RVV implemtation. + The updater is taking the following steps. + + 1) Set vector registers to occupy 1280 bytes (40regs * 32bytes) + 2) Clear vector_element, vector_predicate and matrix registers + 3) Add RVV misc registers in the checkpoint + """ + + for sec in cpt.sections(): + import re + + # Search for all XC sections + if re.search(".*processor.*\.core.*\.xc.*", sec): + + # Updating RVV vector registers (dummy values) + # Assuming VLEN = 256 bits (32 bytes) + mr = cpt.get(sec, "regs.vector").split() + if len(mr) <= 8: + cpt.set(sec, "regs.vector", " ".join("0" for i in range(1280))) + + # Updating RVV vector element (dummy values) + cpt.set(sec, "regs.vector_element", "") + + # Updating RVV vector predicate (dummy values) + cpt.set(sec, "regs.vector_predicate", "") + + # Updating RVV matrix (dummy values) + cpt.set(sec, "regs.matrix", "") + + # Search for all ISA sections + if re.search(".*processor.*\.core.*\.isa$", sec): + + # Updating RVV misc registers (dummy values) + mr = cpt.get(sec, "miscRegFile").split() + if len(mr) == 164: + print( + "MISCREG_* RVV registers already seem " "to be inserted." + ) + else: + # Add dummy value for MISCREG_VSTART + mr.insert(121, 0) + # Add dummy value for MISCREG_VXSAT + mr.insert(121, 0) + # Add dummy value for MISCREG_VXRM + mr.insert(121, 0) + # Add dummy value for MISCREG_VCSR + mr.insert(121, 0) + # Add dummy value for MISCREG_VL + mr.insert(121, 0) + # Add dummy value for MISCREG_VTYPE + mr.insert(121, 0) + # Add dummy value for MISCREG_VLENB + mr.insert(121, 0) + cpt.set(sec, "miscRegFile", " ".join(str(x) for x in mr)) + + +legacy_version = 17 From cf1678f43f6faab30e2195040dbb235b08a350e9 Mon Sep 17 00:00:00 2001 From: Leo Redivo Date: Fri, 4 Aug 2023 13:08:41 -0700 Subject: [PATCH 164/693] misc: Fix pre-commit formatting issues Change-Id: I50e71cfc21d43c2c17da52cf2f40591599907548 --- .../gem5/components/boards/arm_board.py | 2 +- .../boards/experimental/lupv_board.py | 2 +- .../components/boards/kernel_disk_workload.py | 19 +++++++++---------- .../gem5/components/boards/riscv_board.py | 2 +- .../gem5/components/boards/x86_board.py | 2 +- .../riscvmatched/riscvmatched_board.py | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index 82b7a39107..451bb8d7dc 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -354,7 +354,7 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): ) @overrides(KernelDiskWorkload) - def _get_default_disk_device(self): + def get_default_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index cba50a1d56..f56a8804ed 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -539,7 +539,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): return ["console=ttyLIO0", "root={root_value}", "rw"] @overrides(KernelDiskWorkload) - def set_default_disk_device(self) -> str: + def get_default_disk_device(self) -> str: return "/dev/lda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 79d55ba8b4..435de35f82 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -39,7 +39,7 @@ import os from pathlib import Path import m5 -from m5 import warn +from m5.util import inform class KernelDiskWorkload: @@ -92,15 +92,15 @@ class KernelDiskWorkload: :returns: The disk device. """ if self._disk_device is None: - warn("No disk device set, ie where the disk image is located. Defaulting to board disk device") - return _get_default_disk_device() - else: + self._disk_device = get_default_disk_device() + inform(f"Disk Device set to {self._disk_device}") + return self._disk_device + else: + inform(f"Disk Device set to {self._disk_device}") return self._disk_device - - @abstractmethod - def _get_default_disk_device(self) -> str: + def get_default_disk_device(self) -> str: """ Set a default disk device, in case user does not specify a disk device. @@ -154,7 +154,7 @@ class KernelDiskWorkload: kernel: KernelResource, disk_image: DiskImageResource, bootloader: Optional[BootloaderResource] = None, - _disk_device: Optional[str] = None, + disk_device: Optional[str] = None, readfile: Optional[str] = None, readfile_contents: Optional[str] = None, kernel_args: Optional[List[str]] = None, @@ -188,7 +188,7 @@ class KernelDiskWorkload: assert isinstance(self, AbstractBoard) # Set the disk device - self._disk_device = _disk_device + self._disk_device = disk_device # If we are setting a workload of this type, we need to run as a # full-system simulation. @@ -211,7 +211,6 @@ class KernelDiskWorkload: if bootloader is not None: self._bootloader = [bootloader.get_local_path()] - # Set the readfile. if readfile: self.readfile = readfile diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index d8020d1974..c12ad21e70 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -467,7 +467,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def _get_default_disk_device(self): + def get_default_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index 1a3b9fa1c8..7541cdc415 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -296,7 +296,7 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): ] @overrides(KernelDiskWorkload) - def _get_default_disk_device(self): + def get_default_disk_device(self): return "/dev/hda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index 3411ea61be..5f26d0500d 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -539,7 +539,7 @@ class RISCVMatchedBoard( fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def _get_default_disk_device(self): + def get_default_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) From 4376e5fa9f8b0b1499c0379d6d3752585e4f62d6 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 4 Aug 2023 14:19:49 -0700 Subject: [PATCH 165/693] tests: Add checkpoint.py to fs tests directory The configs directory for the fs tests was missing the checkpoint.py file, causing some of the CI tests to fail. Change-Id: Ifbd775ad658f96d06bea7bee554fe3bedcf5a5b5 --- tests/gem5/fs/linux/arm/configs/checkpoint.py | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tests/gem5/fs/linux/arm/configs/checkpoint.py diff --git a/tests/gem5/fs/linux/arm/configs/checkpoint.py b/tests/gem5/fs/linux/arm/configs/checkpoint.py new file mode 100644 index 0000000000..f1b8a1bf72 --- /dev/null +++ b/tests/gem5/fs/linux/arm/configs/checkpoint.py @@ -0,0 +1,133 @@ +# Copyright (c) 2015, 2020 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. +# +# 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 multiprocessing import Process +import sys +import os + +import m5 + +_exit_normal = ("target called exit()", "m5_exit instruction encountered") + +_exit_limit = ("simulate() limit reached",) + +_exitcode_done = 0 +_exitcode_fail = 1 +_exitcode_checkpoint = 42 + + +def _run_step(name, restore=None, interval=0.5): + """ + Instantiate (optionally from a checkpoint if restore is set to the + checkpoitn name) the system and run for interval seconds of + simulated time. At the end of the simulation interval, create a + checkpoint and exit. + + As this function is intended to run in its own process using the + multiprocessing framework, the exit is a true call to exit which + terminates the process. Exit codes are used to pass information to + the parent. + """ + if restore is not None: + m5.instantiate(restore) + else: + m5.instantiate() + + e = m5.simulate(m5.ticks.fromSeconds(interval)) + cause = e.getCause() + if cause in _exit_limit: + m5.checkpoint(name) + sys.exit(_exitcode_checkpoint) + elif cause in _exit_normal: + sys.exit(_exitcode_done) + else: + print(f"Test failed: Unknown exit cause: {cause}") + sys.exit(_exitcode_fail) + + +def run_test(root, interval=0.5, max_checkpoints=5): + """ + Run the simulated system for a fixed amount of time and take a + checkpoint, then restore from the same checkpoint and run until + the system calls m5 exit. + """ + + cpt_name = os.path.join(m5.options.outdir, "test.cpt") + restore = None + checkpointed = False + + for cpt_no in range(max_checkpoints): + # Create a checkpoint from a separate child process. This enables + # us to get back to a (mostly) pristine state and restart + # simulation from the checkpoint. + p = Process( + target=_run_step, + args=(cpt_name,), + kwargs={"restore": restore, "interval": interval}, + ) + p.start() + + # Wait for the child to return + p.join() + + # Restore from the checkpoint next iteration + restore = cpt_name + + if p.exitcode == _exitcode_done: + if checkpointed: + print("Test done.", file=sys.stderr) + sys.exit(0) + else: + print( + "Test done, but no checkpoint was created.", + file=sys.stderr, + ) + sys.exit(1) + elif p.exitcode == _exitcode_checkpoint: + checkpointed = True + else: + print("Test failed.", file=sys.stderr) + sys.exit(1) + + # Maximum number of checkpoints reached. Just run full-speed from + # now on. + m5.instantiate() + e = m5.simulate() + cause = e.getCause() + if cause in _exit_normal: + sys.exit(0) + else: + print(f"Test failed: Unknown exit cause: {cause}") + sys.exit(1) From effca10cb4c9013839d2bb861abc23ab47794cbb Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 4 Aug 2023 17:56:56 -0700 Subject: [PATCH 166/693] tests: Add switcheroo.py to fs configs directory There was another missing file in the configs for the fs tests, so this should allow the switcheroo tests to pass. Change-Id: Ic4e26cceeb9209f176158b80eaaba88b47968c39 --- tests/gem5/fs/linux/arm/configs/switcheroo.py | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 tests/gem5/fs/linux/arm/configs/switcheroo.py diff --git a/tests/gem5/fs/linux/arm/configs/switcheroo.py b/tests/gem5/fs/linux/arm/configs/switcheroo.py new file mode 100644 index 0000000000..72736a9d87 --- /dev/null +++ b/tests/gem5/fs/linux/arm/configs/switcheroo.py @@ -0,0 +1,148 @@ +# Copyright (c) 2012 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. +# +# 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. + +import m5 +import _m5 +from m5.objects import * + +m5.util.addToPath("../configs/") +from base_caches import * + + +class Sequential: + """Sequential CPU switcher. + + The sequential CPU switches between all CPUs in a system in + order. The CPUs in the system must have been prepared for + switching, which in practice means that only one CPU is switched + in. base_config.BaseFSSwitcheroo can be used to create such a + system. + """ + + def __init__(self, cpus): + self.first_cpu = None + for (cpuno, cpu) in enumerate(cpus): + if not cpu.switched_out: + if self.first_cpu != None: + fatal("More than one CPU is switched in") + self.first_cpu = cpuno + + if self.first_cpu == None: + fatal("The system contains no switched in CPUs") + + self.cur_cpu = self.first_cpu + self.cpus = cpus + + def next(self): + self.cur_cpu = (self.cur_cpu + 1) % len(self.cpus) + return self.cpus[self.cur_cpu] + + def first(self): + return self.cpus[self.first_cpu] + + +def run_test(root, switcher=None, freq=1000, verbose=False): + """Test runner for CPU switcheroo tests. + + The switcheroo test runner is used to switch CPUs in a system that + has been prepared for CPU switching. Such systems should have + multiple CPUs when they are instantiated, but only one should be + switched in. Such configurations can be created using the + base_config.BaseFSSwitcheroo class. + + A CPU switcher object is used to control switching. The default + switcher sequentially switches between all CPUs in a system, + starting with the CPU that is currently switched in. + + Unlike most other test runners, this one automatically configures + the memory mode of the system based on the first CPU the switcher + reports. + + Keyword Arguments: + switcher -- CPU switcher implementation. See Sequential for + an example implementation. + period -- Switching frequency in Hz. + verbose -- Enable output at each switch (suppressed by default). + """ + + if switcher == None: + switcher = Sequential(root.system.cpu) + + current_cpu = switcher.first() + system = root.system + system.mem_mode = type(current_cpu).memory_mode() + + # Suppress "Entering event queue" messages since we get tons of them. + # Worse yet, they include the timestamp, which makes them highly + # variable and unsuitable for comparing as test outputs. + if not verbose: + _m5.core.setLogLevel(_m5.core.LogLevel.WARN) + + # instantiate configuration + m5.instantiate() + + # Determine the switching period, this has to be done after + # instantiating the system since the time base must be fixed. + period = m5.ticks.fromSeconds(1.0 / freq) + while True: + exit_event = m5.simulate(period) + exit_cause = exit_event.getCause() + + if exit_cause == "simulate() limit reached": + next_cpu = switcher.next() + + if verbose: + print("Switching CPUs...") + print(f"Next CPU: {type(next_cpu)}") + m5.drain() + if current_cpu != next_cpu: + m5.switchCpus( + system, [(current_cpu, next_cpu)], verbose=verbose + ) + else: + print( + "Source CPU and destination CPU are the same," + " skipping..." + ) + current_cpu = next_cpu + elif ( + exit_cause == "target called exit()" + or exit_cause == "m5_exit instruction encountered" + ): + + sys.exit(0) + else: + print(f"Test failed: Unknown exit cause: {exit_cause}") + sys.exit(1) From eb541da32c0142911f67ac2d0cf6e84841a42986 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 4 Aug 2023 16:57:57 -0700 Subject: [PATCH 167/693] misc: Refactor weekly-tests.yaml This adds a matrix to the weekly tests in order to make the file cleaner. Change-Id: I830a0bf8b7d0406e9c377fedf2a7edfa5beabf40 --- .github/workflows/weekly-tests.yaml | 134 ++-------------------------- 1 file changed, 8 insertions(+), 126 deletions(-) diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index dd81555f00..3d83138d42 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -33,8 +33,11 @@ jobs: retention-days: 5 - run: echo "This job's status is ${{ job.status }}." -# start running the very-long tests - testlib-very-long-gem5_library_example_tests: + # start running the very-long tests + testlib-very-long-tests: + strategy: + matrix: + test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [build-gem5] @@ -50,9 +53,9 @@ jobs: name: ${{needs.build-gem5.outputs.build-name}} path: build/ALL - run: chmod u+x build/ALL/gem5.opt - - name: very-long gem5_library_example_tests + - name: very-long ${{ matrix.test-type }} working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/gem5_library_example_tests --length very-long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/${{ matrix.test-type }} --length very-long --skip-build -vv -t $(nproc) - name: create zip of results if: success() || failure() run: | @@ -62,128 +65,7 @@ jobs: if: success() || failure() uses: actions/upload-artifact@v3 env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - - testlib-long-gem5-resources: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5] - timeout-minutes: 4320 # 3 days - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: very-long gem5-resources tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/gem5-resources --length very-long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-very-long-parsec-benchmarks: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 - timeout-minutes: 4320 # 3 days - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: very-long x86-boot-tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/x86-boot-tests --length very-long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - run: echo "This job's status is ${{ job.status }}." - - testlib-very-long-x86-boot-tests: - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: build-gem5 - timeout-minutes: 4320 # 3 days - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: very-long x86-boot-tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/x86-boot-tests --length very-long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} with: name: ${{ env.MY_STEP_VAR }} path: output.zip From 8b6912f3315c397a8c6edec403cdc9046d0a850e Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Mon, 7 Aug 2023 14:59:23 -0700 Subject: [PATCH 168/693] misc: Update where runners are cleaned in workflow files This moves the clean runner step in our yaml files to be at the beginning of a job, so that if a runner goes down and is unable to clean at the end, we can ensure that subsequent jobs still run as expected. Change-Id: Iba52694aefe03c550ad0bfdb5b5f938305273988 --- .github/workflows/ci-tests.yaml | 11 +++++------ .github/workflows/daily-tests.yaml | 22 ++++++++++------------ .github/workflows/weekly-tests.yaml | 10 +++++----- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 9894716665..2fb5910d44 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -79,6 +79,11 @@ jobs: needs: [pre-commit, build-gem5, check-for-change-id] timeout-minutes: 360 # 6 hours steps: + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 with: @@ -102,10 +107,4 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 - - name: Clean runner - if: success() || failure() - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 67024e6ee5..595650e203 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -80,6 +80,11 @@ jobs: needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours for entire matrix to run steps: + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - uses: actions/checkout@v3 with: # Scheduled workflows run on the default branch by default. We @@ -152,12 +157,6 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 - - name: Clean runner - if: success() || failure() - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." # split library example tests into runs based on Suite UID @@ -171,6 +170,11 @@ jobs: needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours steps: + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - uses: actions/checkout@v3 with: # Scheduled workflows run on the default branch by default. We @@ -198,12 +202,6 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 - - name: Clean runner - if: success() || failure() - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." # This runs the SST-gem5 integration compilation and tests it with diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 3d83138d42..5ec65a9e5a 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -43,6 +43,11 @@ jobs: needs: [build-gem5] timeout-minutes: 4320 # 3 days steps: + - name: Clean runner + run: + rm -rf ./* || true + rm -rf ./.??* || true + rm -rf ~/.cache || true - uses: actions/checkout@v3 with: # Scheduled workflows run on the default branch by default. We @@ -70,9 +75,4 @@ jobs: name: ${{ env.MY_STEP_VAR }} path: output.zip retention-days: 7 - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - run: echo "This job's status is ${{ job.status }}." From f21c5d0d780bd10ba9c4a92686e8eb8c43d7e395 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 7 Aug 2023 14:53:26 -0700 Subject: [PATCH 169/693] tests: Disable PARSEC benchmark tests These tests are disabled due our GitHub Actions self-hosted Runners having a 60GB of disk space. The PARSEC Disk Image Resource (v1.0.0, http://resources.gem5.org/resources/x86-parsec?version=1.0.0) is 33GB and is simply too big to download and unzip for these tests. These tests can be reenabled when this issue is resolved. Change-Id: I9a63aa1903cea3ce7942bdc85bcd0b24761d2f29 --- .../test_gem5_library_examples.py | 9 ++++++++- tests/gem5/parsec_benchmarks/test_parsec.py | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py index e43d461b35..b88862fc0d 100644 --- a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py +++ b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py @@ -171,7 +171,14 @@ gem5_verify_config( length=constants.long_tag, ) -if os.access("/dev/kvm", mode=os.R_OK | os.W_OK): +print( + "WARNING: PARSEC tests are disabled. This is due to our GitHub " + "Actions self-hosted runners only having 60GB of disk space. The " + "PARSEC Disk image is too big to use." +) +# 'False' is used to disable the tests. +if False: # os.access("/dev/kvm", mode=os.R_OK | os.W_OK): + # The x86-parsec-benchmarks uses KVM cores, this test will therefore only # be run on systems that support KVM. gem5_verify_config( diff --git a/tests/gem5/parsec_benchmarks/test_parsec.py b/tests/gem5/parsec_benchmarks/test_parsec.py index 1f239dae1f..fee8e7134a 100644 --- a/tests/gem5/parsec_benchmarks/test_parsec.py +++ b/tests/gem5/parsec_benchmarks/test_parsec.py @@ -50,6 +50,13 @@ def test_parsec( # Don't run the tests if KVM is unavailable. return + print( + "WARNING: PARSEC tests are disabled. This is due to our GitHub " + "Actions self-hosted runners only having 60GB of disk space. The " + "PARSEC Disk image is too big to use." + ) + return # Remove this line to re-enable PARSEC tests. + gem5_verify_config( name="{}-boot-cpu_{}-detailed-cpu_{}-cores_{}_{}_{}_parsec-test".format( boot_cpu, detailed_cpu, str(num_cpus), mem_system, benchmark, size From b86bc7b1edaa540faee7d6d0296a1ac63da4f70c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 7 Aug 2023 15:05:33 -0700 Subject: [PATCH 170/693] tests: Add '--skip' arg to "download_check.py" This argument allows the passing of IDs of resources which should be skipped for this check. Note: A current limitation here is you cannot specify the version of a resource. Passing the ID of a resource to this will skip the downloading for all versions of that resource. Change-Id: Ifdb7c2b71553126fd52a3d286897ed5dd8e98f7c --- tests/gem5/gem5_resources/configs/download_check.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/gem5/gem5_resources/configs/download_check.py b/tests/gem5/gem5_resources/configs/download_check.py index 20081a46d5..7dc71908b1 100644 --- a/tests/gem5/gem5_resources/configs/download_check.py +++ b/tests/gem5/gem5_resources/configs/download_check.py @@ -52,6 +52,14 @@ parser.add_argument( "checked", ) +parser.add_argument( + "--skip", + nargs="+", # Accepts 1 or more arguments. + type=str, + help="The resource IDs to skip. If not set, no resources will be skipped.", + required=False, +) + parser.add_argument( "--gem5-version", type=str, @@ -86,6 +94,8 @@ if len(ids) == 0: errors = str() for id in ids: + if args.skip and id in args.skip: + continue if id not in resource_list: errors += ( f"Resource with ID '{id}' not found in " From dc31883a2dfbbcf96fcc8ad44e967346279b42a8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 7 Aug 2023 15:15:48 -0700 Subject: [PATCH 171/693] tests: Update resource downloading test to skip x86-parsec The x86-parsec gem5 Resource (v1.0.0, http://resources.gem5.org/resources/x86-parsec?version=1.0.0) is 33GB. The gem5 GitHub Actions self-hosted runners do not have enough Disk Space in the VMs they are run to download this. Ergo we skip it. Change-Id: I290fe265f03ceca65b2bed87e9f4a4ad601e0fc1 --- tests/gem5/gem5_resources/test_download_resources.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/gem5/gem5_resources/test_download_resources.py b/tests/gem5/gem5_resources/test_download_resources.py index 0e406d69e7..a15d498717 100644 --- a/tests/gem5/gem5_resources/test_download_resources.py +++ b/tests/gem5/gem5_resources/test_download_resources.py @@ -45,7 +45,12 @@ gem5_verify_config( "configs", "download_check.py", ), - config_args=["--download-directory", resource_path], + config_args=[ + "--download-directory", + resource_path, + "--skip", + "x86-parsec", + ], valid_isas=(constants.all_compiled_tag,), length=constants.very_long_tag, ) From a903ff43f2cfd983d95e0ac21a3025928d8f6a52 Mon Sep 17 00:00:00 2001 From: Harshil Patel <91860903+Harshil2107@users.noreply.github.com> Date: Tue, 8 Aug 2023 09:40:07 -0700 Subject: [PATCH 172/693] tests: Add checkpoint tests for all ISAs Added save and restore checkpoint tests for arm-hello, x86-hello, x86-fs, power-hello Added mips and sparc test but mips does not support checkpoint and there is a bug in sparc. Added test file to run the tests. Change-Id: I2d3b96f95ee08aae921de9a885ac5be77d49f326 --- .../arm-hello-restore-checkpoint.py | 80 ++++++ .../arm-hello-save-checkpoint.py | 77 +++++ .../mips-hello-restore-checkpoint.py | 72 +++++ .../mips-hello-save-checkpoint.py | 89 ++++++ .../power-hello-restore-checkpoint.py | 72 +++++ .../power-hello-save-checkpoint.py | 83 ++++++ .../sparc-hello-restore-checkpoint.py | 72 +++++ .../sparc-hello-save-checkpoint.py | 80 ++++++ .../gem5/checkpoint-tests/test-checkpoints.py | 266 ++++++++++++++++++ .../x86-fs-restore-checkpoint.py | 88 ++++++ .../x86-fs-save-checkpoint.py | 101 +++++++ .../x86-hello-restore-checkpoint.py | 72 +++++ .../x86-hello-save-checkpoint.py | 83 ++++++ 13 files changed, 1235 insertions(+) create mode 100644 tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/test-checkpoints.py create mode 100644 tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py create mode 100644 tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py diff --git a/tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py b/tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py new file mode 100644 index 0000000000..2076c8965e --- /dev/null +++ b/tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py @@ -0,0 +1,80 @@ +# Copyright (c) 2022 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. + + +""" +This gem5 configuation script creates a simple board sharing the same +structure as the one in +tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py. +This script restores the checkpoint generated by the above script, and +runs the rest of "arm-hello64-static" binary simulation. +This configuration serves as a test of restoring a checkpoint with ARM ISA. +""" + +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource, CheckpointResource + +from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( + PrivateL1PrivateL2CacheHierarchy, +) +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + + +requires(isa_required=ISA.ARM) + +cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( + l1d_size="16kB", l1i_size="16kB", l2_size="256kB" +) + +memory = SingleChannelDDR3_1600(size="32MB") + +processor = SimpleProcessor(cpu_type=CPUTypes.ATOMIC, isa=ISA.ARM, num_cores=2) + +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +board.set_se_binary_workload( + obtain_resource("arm-hello64-static"), + checkpoint=obtain_resource("arm-hello-test-checkpoint"), +) + +sim = Simulator(board=board, full_system=False) +sim.run() + +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py b/tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py new file mode 100644 index 0000000000..d0ebf7afe0 --- /dev/null +++ b/tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py @@ -0,0 +1,77 @@ +# Copyright (c) 2022 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. + +import argparse +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource +from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( + PrivateL1PrivateL2CacheHierarchy, +) +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--checkpoint-path", + type=str, + required=False, + default="arm-hello-test-checkpoint/", + help="The directory to store the checkpoint.", +) + +args = parser.parse_args() +requires(isa_required=ISA.ARM) + +cache_hierarchy = PrivateL1PrivateL2CacheHierarchy( + l1d_size="16kB", l1i_size="16kB", l2_size="256kB" +) + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor(cpu_type=CPUTypes.ATOMIC, isa=ISA.ARM, num_cores=2) +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload(obtain_resource("arm-hello64-static")) + +sim = Simulator(board=board, full_system=False) +max_ticks = 10**6 +sim.run(max_ticks=max_ticks) +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) +print("Taking checkpoint at", args.checkpoint_path) +sim.save_checkpoint(args.checkpoint_path) +print("Done taking checkpoint") diff --git a/tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py b/tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py new file mode 100644 index 0000000000..5e42f4d9b6 --- /dev/null +++ b/tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py @@ -0,0 +1,72 @@ +# Copyright (c) 2022 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. + +""" +This gem5 configuation script creates a simple board sharing the same +structure as the one in +tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py. +This script restores the checkpoint generated by the above script, and +runs the rest of "mips-hello" binary simulation. +This configuration serves as a test of restoring a checkpoint with MIPS ISA. +""" + +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + + +requires(isa_required=ISA.MIPS) + +cache_hierarchy = NoCache() + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, isa=ISA.MIPS, num_cores=2 +) +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload( + obtain_resource("mips-hello"), + checkpoint=CheckpointResource(local_path="./mips-hello-test-checkpoint"), +) + +sim = Simulator(board=board, full_system=False) +sim.run() +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py b/tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py new file mode 100644 index 0000000000..271d900304 --- /dev/null +++ b/tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py @@ -0,0 +1,89 @@ +# Copyright (c) 2022 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. + +""" +This gem5 test script creates a simple board to run the first +10^6 ticks of "mips-hello" binary simulation and saves a checkpoint. +This configuration serves as a test to ensure that checkpoints work +with MIPS ISA. +""" + +import argparse +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--checkpoint-path", + type=str, + required=False, + default="mips-hello-test-checkpoint/", + help="The directory to store the checkpoint.", +) + +args = parser.parse_args() + +# This check ensures that the gem5 binary is compiled to the MIPS ISA. +# If not, an exception is thrown. +requires(isa_required=ISA.MIPS) + +cache_hierarchy = NoCache() + +memory = SingleChannelDDR3_1600(size="32MB") + +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, isa=ISA.MIPS, num_cores=2 +) + +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + + +board.set_se_binary_workload(obtain_resource("mips-hello")) + +sim = Simulator(board=board, full_system=False) +max_ticks = 10**6 +sim.run(max_ticks=max_ticks) +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) +print("Taking checkpoint at", args.checkpoint_path) +sim.save_checkpoint(args.checkpoint_path) +print("Done taking checkpoint") diff --git a/tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py b/tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py new file mode 100644 index 0000000000..191cd50ec7 --- /dev/null +++ b/tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py @@ -0,0 +1,72 @@ +# Copyright (c) 2022 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. + +""" +This gem5 configuation script creates a simple board sharing the same +structure as the one in +tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py. +This script restores the checkpoint generated by the above script, and +runs the rest of "power-hello" binary simulation. +This configuration serves as a test of restoring a checkpoint with POWER ISA. +""" + +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + + +requires(isa_required=ISA.POWER) + +cache_hierarchy = NoCache() + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, isa=ISA.POWER, num_cores=2 +) +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload( + obtain_resource("power-hello"), + checkpoint=obtain_resource("power-hello-test-checkpoint"), +) + +sim = Simulator(board=board, full_system=False) +sim.run() +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py b/tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py new file mode 100644 index 0000000000..1dcd421830 --- /dev/null +++ b/tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py @@ -0,0 +1,83 @@ +# Copyright (c) 2022 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. + +""" +This gem5 test script creates a simple board to run the first +10^6 ticks of "power-hello" binary simulation and saves a checkpoint. +This configuration serves as a test to ensure that checkpoints work +with POWER ISA. +""" + +import argparse +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--checkpoint-path", + type=str, + required=False, + default="power-hello-test-checkpoint/", + help="The directory to store the checkpoint.", +) + +args = parser.parse_args() +requires(isa_required=ISA.POWER) + +cache_hierarchy = NoCache() + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, isa=ISA.POWER, num_cores=2 +) + +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload(obtain_resource("power-hello")) + +sim = Simulator(board=board, full_system=False) +max_ticks = 10**6 +sim.run(max_ticks=max_ticks) +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) +print("Taking checkpoint at", args.checkpoint_path) +sim.save_checkpoint(args.checkpoint_path) +print("Done taking checkpoint") diff --git a/tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py b/tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py new file mode 100644 index 0000000000..f8bc3949a5 --- /dev/null +++ b/tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py @@ -0,0 +1,72 @@ +# Copyright (c) 2022 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. + +""" +This gem5 configuation script creates a simple board sharing the same +structure as the one in +tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py. +This script restores the checkpoint generated by the above script, and +runs the rest of "sparc-hello" binary simulation. +This configuration serves as a test of restoring a checkpoint with SPARC ISA. +""" + +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + + +requires(isa_required=ISA.SPARC) + +cache_hierarchy = NoCache() + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, isa=ISA.SPARC, num_cores=2 +) +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload( + obtain_resource("sparc-hello"), + checkpoint=CheckpointResource(local_path="./sparc-hello-test-checkpoint"), +) + +sim = Simulator(board=board, full_system=False) +sim.run() +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py b/tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py new file mode 100644 index 0000000000..9c50b5cff9 --- /dev/null +++ b/tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py @@ -0,0 +1,80 @@ +# Copyright (c) 2022 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. + +""" +This gem5 test script creates a simple board to run the first +10^6 ticks of "sparc-hello" binary simulation and saves a checkpoint. +This configuration serves as a test to ensure that checkpoints work +with SPARC ISA. +""" + +import argparse +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--checkpoint-path", + type=str, + required=False, + default="sparc-hello-test-checkpoint/", + help="The directory to store the checkpoint.", +) + +args = parser.parse_args() +requires(isa_required=ISA.SPARC) + +cache_hierarchy = NoCache() + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor( + cpu_type=CPUTypes.TIMING, isa=ISA.SPARC, num_cores=2 +) + +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload(obtain_resource("sparc-hello")) + +sim = Simulator(board=board, full_system=False) +max_ticks = 10**6 +sim.run(max_ticks=max_ticks) +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/test-checkpoints.py b/tests/gem5/checkpoint-tests/test-checkpoints.py new file mode 100644 index 0000000000..2edc5785c1 --- /dev/null +++ b/tests/gem5/checkpoint-tests/test-checkpoints.py @@ -0,0 +1,266 @@ +# Copyright (c) 2021-2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +This runs simple tests to ensure the examples in `configs/example/gem5_library` +still function. They simply check the simulation completed. +""" +from testlib import * +import re +import os + +if config.bin_path: + resource_path = config.bin_path +else: + resource_path = joinpath(absdirpath(__file__), "..", "resources") + +hello_verifier = verifier.MatchRegex(re.compile(r"Hello world!")) +save_checkpoint_verifier = verifier.MatchRegex( + re.compile(r"Done taking checkpoint") +) + + +gem5_verify_config( + name="test-checkpoint-arm-hello-save-checkpoint", + fixtures=(), + verifiers=(save_checkpoint_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "arm-hello-save-checkpoint.py", + ), + config_args=[ + "--checkpoint-path", + joinpath(resource_path, "arm-hello-test-checkpoint"), + ], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-arm-hello-restore-checkpoint", + fixtures=(), + verifiers=(hello_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "arm-hello-restore-checkpoint.py", + ), + config_args=[], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-x86-hello-save-checkpoint", + fixtures=(), + verifiers=(save_checkpoint_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "x86-hello-save-checkpoint.py", + ), + config_args=[ + "--checkpoint-path", + joinpath(resource_path, "x86-hello-test-checkpoint"), + ], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-x86-hello-restore-checkpoint", + fixtures=(), + verifiers=(hello_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "x86-hello-restore-checkpoint.py", + ), + config_args=[], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-x86-fs-save-checkpoint", + fixtures=(), + verifiers=(save_checkpoint_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "x86-fs-save-checkpoint.py", + ), + config_args=[ + "--checkpoint-path", + joinpath(resource_path, "x86-fs-test-checkpoint"), + ], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-x86-fs-restore-checkpoint", + fixtures=(), + verifiers=(), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "x86-fs-restore-checkpoint.py", + ), + config_args=[], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-power-hello-save-checkpoint", + fixtures=(), + verifiers=(save_checkpoint_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "power-hello-save-checkpoint.py", + ), + config_args=[ + "--checkpoint-path", + joinpath(resource_path, "power-hello-test-checkpoint"), + ], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +gem5_verify_config( + name="test-checkpoint-power-hello-restore-checkpoint", + fixtures=(), + verifiers=(hello_verifier,), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "checkpoint-tests", + "power-hello-restore-checkpoint.py", + ), + config_args=[], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.quick_tag, +) + +# gem5_verify_config( +# name="test-checkpoint-mips-hello-save-checkpoint", +# fixtures=(), +# verifiers=(save_checkpoint_verifier,), +# config=joinpath( +# config.base_dir, +# "tests", +# "gem5", +# "checkpoint-tests", +# "mips-hello-save-checkpoint.py", +# ), +# config_args=[ +# # "--checkpoint-path", +# # joinpath(resource_path, "mips-hello-test-checkpoint"), +# ], +# valid_isas=(constants.all_compiled_tag,), +# valid_hosts=constants.supported_hosts, +# length=constants.quick_tag, +# ) + +# gem5_verify_config( +# name="test-checkpoint-mips-hello-restore-checkpoint", +# fixtures=(), +# verifiers=(hello_verifier,), +# config=joinpath( +# config.base_dir, +# "tests", +# "gem5", +# "checkpoint-tests", +# "mips-hello-restore-checkpoint.py", +# ), +# config_args=[], +# valid_isas=(constants.all_compiled_tag,), +# valid_hosts=constants.supported_hosts, +# length=constants.quick_tag, +# ) + +# gem5_verify_config( +# name="test-checkpoint-sparc-hello-save-checkpoint", +# fixtures=(), +# verifiers=(save_checkpoint_verifier,), +# config=joinpath( +# config.base_dir, +# "tests", +# "gem5", +# "checkpoint-tests", +# "sparc-hello-save-checkpoint.py", +# ), +# config_args=[ +# # "--checkpoint-path", +# # joinpath(resource_path, "sparc-hello-test-checkpoint"), +# ], +# valid_isas=(constants.all_compiled_tag,), +# valid_hosts=constants.supported_hosts, +# length=constants.quick_tag, +# ) + +# gem5_verify_config( +# name="test-checkpoint-sparc-hello-restore-checkpoint", +# fixtures=(), +# verifiers=(hello_verifier,), +# config=joinpath( +# config.base_dir, +# "tests", +# "gem5", +# "checkpoint-tests", +# "sparc-hello-restore-checkpoint.py", +# ), +# config_args=[], +# valid_isas=(constants.all_compiled_tag,), +# valid_hosts=constants.supported_hosts, +# length=constants.quick_tag, +# ) diff --git a/tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py b/tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py new file mode 100644 index 0000000000..f43b931135 --- /dev/null +++ b/tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py @@ -0,0 +1,88 @@ +# Copyright (c) 2022 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. + +""" +This gem5 configuation script creates a simple board sharing the same +structure as the one in +tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py. +This script restores the checkpoint generated by the above script, and +runs the rest of full system simulation. +This configuration serves as a test of restoring a checkpoint with X86 ISA in fs mode. +""" + +from gem5.components.boards.x86_board import X86Board +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( + PrivateL1PrivateL2CacheHierarchy, +) +from gem5.components.processors.cpu_types import CPUTypes +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.simulate.simulator import Simulator + +# Run a check to ensure the right version of gem5 is being used. +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( + l1d_size="32kB", l1i_size="32kB", l2_size="512kB" +) + +# Setup the system memory. +memory = SingleChannelDDR3_1600(size="1GB") + +# Setup a single core Processor. +processor = SimpleProcessor(cpu_type=CPUTypes.O3, isa=ISA.X86, num_cores=1) + +# Setup the board. +board = X86Board( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the Full System workload. +board.set_kernel_disk_workload( + kernel=obtain_resource("x86-linux-kernel-5.4.49"), + disk_image=obtain_resource("x86-ubuntu-18.04-img"), + checkpoint=obtain_resource("x86-fs-test-checkpoint"), +) + +sim = Simulator(board=board, full_system=True) +print("Beginning simulation!") + +sim.run(max_ticks=10**10) + +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py b/tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py new file mode 100644 index 0000000000..87741235f0 --- /dev/null +++ b/tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py @@ -0,0 +1,101 @@ +# 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. + +""" +This gem5 test script creates a simple board to run the first +10^6 ticks of x86 full system kernel disk workload simulation and saves a checkpoint. +This configuration serves as a test to ensure that checkpoints work +with X86 ISA in fs mode. +""" + +import argparse +from gem5.components.boards.x86_board import X86Board +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( + PrivateL1PrivateL2CacheHierarchy, +) +from gem5.components.processors.cpu_types import CPUTypes +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--checkpoint-path", + type=str, + required=False, + default="x86-fs-test-checkpoint/", + help="The directory to store the checkpoint.", +) + +args = parser.parse_args() + +# Run a check to ensure the right version of gem5 is being used. +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( + l1d_size="32kB", l1i_size="32kB", l2_size="512kB" +) + +# Setup the system memory. +memory = SingleChannelDDR3_1600(size="1GB") + +# Setup a single core Processor. +processor = SimpleProcessor(cpu_type=CPUTypes.O3, isa=ISA.X86, num_cores=1) + +# Setup the board. +board = X86Board( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) + +# Set the Full System workload. +board.set_kernel_disk_workload( + kernel=obtain_resource("x86-linux-kernel-5.4.49"), + disk_image=obtain_resource("x86-ubuntu-18.04-img"), +) + +sim = Simulator(board=board, full_system=True) +print("Beginning simulation!") + +max_ticks = 10**6 +sim.run(max_ticks=max_ticks) +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) +print("Taking checkpoint at", args.checkpoint_path) +sim.save_checkpoint(args.checkpoint_path) +print("Done taking checkpoint") diff --git a/tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py b/tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py new file mode 100644 index 0000000000..8562751708 --- /dev/null +++ b/tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py @@ -0,0 +1,72 @@ +# Copyright (c) 2022 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. + +""" +This gem5 configuation script creates a simple board sharing the same +structure as the one in +tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py. +This script restores the checkpoint generated by the above script, and +runs the rest of "x86-hello64-static" binary simulation. +This configuration serves as a test of restoring a checkpoint with X86 ISA. +""" + +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.components.cachehierarchies.classic.private_l1_cache_hierarchy import ( + PrivateL1CacheHierarchy, +) +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + + +requires(isa_required=ISA.X86) + +cache_hierarchy = PrivateL1CacheHierarchy(l1d_size="16kB", l1i_size="16kB") + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor(cpu_type=CPUTypes.TIMING, isa=ISA.X86, num_cores=4) +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload( + obtain_resource("x86-hello64-static"), + checkpoint=obtain_resource("x86-hello-test-checkpoint"), +) + +sim = Simulator(board=board, full_system=False) +sim.run() +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) diff --git a/tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py b/tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py new file mode 100644 index 0000000000..5211230af6 --- /dev/null +++ b/tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py @@ -0,0 +1,83 @@ +# Copyright (c) 2022 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. + +""" +This gem5 test script creates a simple board to run the first +10^6 ticks of "x86-hello64-static" binary simulation and saves a checkpoint. +This configuration serves as a test to ensure that checkpoints work +with X86 ISA. +""" + +import argparse +from gem5.isas import ISA +from gem5.utils.requires import requires +from gem5.resources.resource import obtain_resource +from gem5.components.cachehierarchies.classic.private_l1_cache_hierarchy import ( + PrivateL1CacheHierarchy, +) +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.simulate.simulator import Simulator +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--checkpoint-path", + type=str, + required=False, + default="x86-hello-test-checkpoint/", + help="The directory to store the checkpoint.", +) + +args = parser.parse_args() +requires(isa_required=ISA.X86) + +cache_hierarchy = PrivateL1CacheHierarchy(l1d_size="16kB", l1i_size="16kB") + +memory = SingleChannelDDR3_1600(size="32MB") +processor = SimpleProcessor(cpu_type=CPUTypes.TIMING, isa=ISA.X86, num_cores=4) + +board = SimpleBoard( + clk_freq="3GHz", + processor=processor, + memory=memory, + cache_hierarchy=cache_hierarchy, +) +board.set_se_binary_workload(obtain_resource("x86-hello64-static")) + +sim = Simulator(board=board, full_system=False) +max_ticks = 10**6 +sim.run(max_ticks=max_ticks) +print( + "Exiting @ tick {} because {}.".format( + sim.get_current_tick(), sim.get_last_exit_event_cause() + ) +) +print("Taking checkpoint at", args.checkpoint_path) +sim.save_checkpoint(args.checkpoint_path) +print("Done taking checkpoint") From a880ff1e154e419a3a4bb35287a7bb208850fbf1 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 8 Aug 2023 13:38:56 -0700 Subject: [PATCH 173/693] tests: Updated directory structure -Changed copyright message to reflect correct year. - Updated directory structure. - Changed directory name to snake case. - Added a README.md for checkpoint tests. Change-Id: Id350addb9cce6740a20a5a45171f80306b711efa --- tests/gem5/checkpoint_tests/README.md | 11 ++++++ .../configs}/arm-hello-restore-checkpoint.py | 2 +- .../configs}/arm-hello-save-checkpoint.py | 2 +- .../configs}/mips-hello-restore-checkpoint.py | 2 +- .../configs}/mips-hello-save-checkpoint.py | 2 +- .../power-hello-restore-checkpoint.py | 2 +- .../configs}/power-hello-save-checkpoint.py | 2 +- .../sparc-hello-restore-checkpoint.py | 2 +- .../configs}/sparc-hello-save-checkpoint.py | 2 +- .../configs}/x86-fs-restore-checkpoint.py | 2 +- .../configs}/x86-fs-save-checkpoint.py | 2 +- .../configs}/x86-hello-restore-checkpoint.py | 2 +- .../configs}/x86-hello-save-checkpoint.py | 2 +- .../test-checkpoints.py | 38 ++++++++++++------- 14 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 tests/gem5/checkpoint_tests/README.md rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/arm-hello-restore-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/arm-hello-save-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/mips-hello-restore-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/mips-hello-save-checkpoint.py (98%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/power-hello-restore-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/power-hello-save-checkpoint.py (98%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/sparc-hello-restore-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/sparc-hello-save-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/x86-fs-restore-checkpoint.py (98%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/x86-fs-save-checkpoint.py (98%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/x86-hello-restore-checkpoint.py (97%) rename tests/gem5/{checkpoint-tests => checkpoint_tests/configs}/x86-hello-save-checkpoint.py (98%) rename tests/gem5/{checkpoint-tests => checkpoint_tests}/test-checkpoints.py (92%) diff --git a/tests/gem5/checkpoint_tests/README.md b/tests/gem5/checkpoint_tests/README.md new file mode 100644 index 0000000000..64767169ba --- /dev/null +++ b/tests/gem5/checkpoint_tests/README.md @@ -0,0 +1,11 @@ +# Checkpoint tests + +These tests run hello world binary for arm, x86, and power isa and ubuntuboot workload for x86 isa using checkpoints. +Each binary is run in two parts: +- Save checkpoint: A binary is run for a set amount of ticks and then a checkpoint is taken. This test checks if the checkpoint is taken. + +- Resotre checkpoint: The same binary and board in the respective save test are used with the saved checkpoint (the checkpoint is uploaded to gem5 resources). This test checks if the binary ran properly. + +```bash +./main.py run gem5/checkpoint_tests/ +``` diff --git a/tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py index 2076c8965e..0ce9a7606a 100644 --- a/tests/gem5/checkpoint-tests/arm-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py index d0ebf7afe0..a731b38a58 100644 --- a/tests/gem5/checkpoint-tests/arm-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py index 5e42f4d9b6..167c026f04 100644 --- a/tests/gem5/checkpoint-tests/mips-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py similarity index 98% rename from tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py index 271d900304..afcf237818 100644 --- a/tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py index 191cd50ec7..05479bcca7 100644 --- a/tests/gem5/checkpoint-tests/power-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py similarity index 98% rename from tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py index 1dcd421830..6fb99a2534 100644 --- a/tests/gem5/checkpoint-tests/power-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py index f8bc3949a5..0bc2e122cd 100644 --- a/tests/gem5/checkpoint-tests/sparc-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py index 9c50b5cff9..2f995e5a53 100644 --- a/tests/gem5/checkpoint-tests/sparc-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py similarity index 98% rename from tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py index f43b931135..0a3264d576 100644 --- a/tests/gem5/checkpoint-tests/x86-fs-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py similarity index 98% rename from tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py index 87741235f0..891130af2b 100644 --- a/tests/gem5/checkpoint-tests/x86-fs-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py similarity index 97% rename from tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py index 8562751708..c60675eb24 100644 --- a/tests/gem5/checkpoint-tests/x86-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py similarity index 98% rename from tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py rename to tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py index 5211230af6..5611e795d4 100644 --- a/tests/gem5/checkpoint-tests/x86-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tests/gem5/checkpoint-tests/test-checkpoints.py b/tests/gem5/checkpoint_tests/test-checkpoints.py similarity index 92% rename from tests/gem5/checkpoint-tests/test-checkpoints.py rename to tests/gem5/checkpoint_tests/test-checkpoints.py index 2edc5785c1..903a777deb 100644 --- a/tests/gem5/checkpoint-tests/test-checkpoints.py +++ b/tests/gem5/checkpoint_tests/test-checkpoints.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2023 The Regents of the University of California +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -51,7 +51,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "arm-hello-save-checkpoint.py", ), config_args=[ @@ -71,7 +72,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "arm-hello-restore-checkpoint.py", ), config_args=[], @@ -88,7 +90,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "x86-hello-save-checkpoint.py", ), config_args=[ @@ -108,7 +111,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "x86-hello-restore-checkpoint.py", ), config_args=[], @@ -125,7 +129,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "x86-fs-save-checkpoint.py", ), config_args=[ @@ -145,7 +150,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "x86-fs-restore-checkpoint.py", ), config_args=[], @@ -162,7 +168,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "power-hello-save-checkpoint.py", ), config_args=[ @@ -182,7 +189,8 @@ gem5_verify_config( config.base_dir, "tests", "gem5", - "checkpoint-tests", + "checkpoint_tests", + "configs", "power-hello-restore-checkpoint.py", ), config_args=[], @@ -199,7 +207,8 @@ gem5_verify_config( # config.base_dir, # "tests", # "gem5", -# "checkpoint-tests", +# "checkpoint_tests", +# "configs", # "mips-hello-save-checkpoint.py", # ), # config_args=[ @@ -219,7 +228,8 @@ gem5_verify_config( # config.base_dir, # "tests", # "gem5", -# "checkpoint-tests", +# "checkpoint_tests", +# "configs", # "mips-hello-restore-checkpoint.py", # ), # config_args=[], @@ -236,7 +246,8 @@ gem5_verify_config( # config.base_dir, # "tests", # "gem5", -# "checkpoint-tests", +# "checkpoint_tests", +# "configs", # "sparc-hello-save-checkpoint.py", # ), # config_args=[ @@ -256,7 +267,8 @@ gem5_verify_config( # config.base_dir, # "tests", # "gem5", -# "checkpoint-tests", +# "checkpoint_tests", +# "configs", # "sparc-hello-restore-checkpoint.py", # ), # config_args=[], From c18e43a0ab261fc2c9238d81d7586b5b78fd88f2 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 9 Aug 2023 16:35:19 +0800 Subject: [PATCH 174/693] arch-riscv: Add Illegal Instruction Fault Condition for Arith RVV Check the status.vs and misa.rvv CSR registers before executing RVV instructions Change-Id: Idc143e1ba90320254926de9fa7a7b343bb96ba88 --- src/arch/riscv/isa/templates/vector_arith.isa | 153 +++++++++++++++++- 1 file changed, 148 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa index d15ab70f20..1bc7b110f8 100644 --- a/src/arch/riscv/isa/templates/vector_arith.isa +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -158,6 +158,13 @@ Fault using vi [[maybe_unused]] = std::make_signed_t; [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -230,6 +237,13 @@ Fault using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -389,6 +403,13 @@ Fault using vwi [[maybe_unused]] = typename double_width::type; [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); const int64_t vlmul = vtype_vlmul(machInst.vtype8); @@ -421,6 +442,13 @@ Fault using vwi [[maybe_unused]] = typename double_width::type; [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); const int64_t vlmul = vtype_vlmul(machInst.vtype8); @@ -538,6 +566,14 @@ Fault { using et = ElemType; using vu = decltype(et::v); + + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -625,6 +661,13 @@ Fault using ewt = typename double_width::type; using vwu = decltype(ewt::v); + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -659,6 +702,13 @@ Fault using ewt = typename double_width::type; using vwu = decltype(ewt::v); + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -783,6 +833,13 @@ Fault { using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; + + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_decl)s; @@ -820,6 +877,12 @@ Fault trace::InstRecord* traceData) const { using vu = uint8_t; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_decl)s; @@ -872,6 +935,12 @@ Fault { using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_rd)s; @@ -978,6 +1047,12 @@ Fault { using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1089,6 +1164,12 @@ Fault { using et = ElemType; using vu = decltype(et::v); + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1182,6 +1263,13 @@ Fault { // TODO: Check register alignment. // TODO: If vd is equal to vs2 the instruction is an architectural NOP. + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } + %(op_decl)s; %(op_rd)s; for (size_t i = 0; i < (VLEN / 64); i++) { @@ -1229,6 +1317,12 @@ Fault trace::InstRecord* traceData) const { using vu = uint8_t; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1288,6 +1382,12 @@ Fault { using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_decl)s; @@ -1309,7 +1409,12 @@ Fault { using et = ElemType; using vu = decltype(et::v); - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_decl)s; @@ -1410,6 +1515,12 @@ Fault trace::InstRecord* traceData) const { %(type_def)s; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1445,6 +1556,12 @@ Fault trace::InstRecord* traceData) const { %(type_def)s; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1482,6 +1599,12 @@ Fault trace::InstRecord* traceData) const { %(type_def)s; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1626,7 +1749,12 @@ Fault { using vu [[maybe_unused]] = std::make_unsigned_t; [[maybe_unused]] constexpr size_t sew = sizeof(vu) * 8; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1785,7 +1913,12 @@ Fault using vi [[maybe_unused]] = std::make_signed_t; using vwu [[maybe_unused]] = typename double_width::type; using vwi [[maybe_unused]] = typename double_width::type; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -1945,7 +2078,12 @@ Fault { using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); @@ -1971,7 +2109,12 @@ Fault { using et = ElemType; using vu = decltype(et::v); - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); From 85549842c7b3340529f5d75c6e634ac03ef5d921 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 9 Aug 2023 16:39:13 +0800 Subject: [PATCH 175/693] arch-riscv: Add Illegal Instruction Fault Condition for Mem RVV Check the status.vs and misa.rvv CSR registers before executing RVV instructions Change-Id: If1f6a440713612b9a044de4f320997e99722c06c --- src/arch/riscv/isa/templates/vector_mem.isa | 52 +++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index f8be1e555b..4eebb477f3 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -131,6 +131,12 @@ Fault RiscvISA::vreg_t tmp_v0; uint8_t *v0; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if(!machInst.vm) { xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); v0 = tmp_v0.as(); @@ -285,6 +291,12 @@ Fault RiscvISA::vreg_t tmp_v0; uint8_t *v0; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if(!machInst.vm) { xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); v0 = tmp_v0.as(); @@ -482,6 +494,12 @@ Fault %(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const { Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -591,6 +609,12 @@ Fault %(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const { Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -731,7 +755,12 @@ Fault { Fault fault = NoFault; Addr EA; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vd[0]); @@ -918,7 +947,12 @@ Fault { Fault fault = NoFault; Addr EA; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vs3[0]); @@ -1086,7 +1120,12 @@ Fault using vu = std::make_unsigned_t; Fault fault = NoFault; Addr EA; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -1282,7 +1321,12 @@ Fault using vu = std::make_unsigned_t; Fault fault = NoFault; Addr EA; - + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; %(ea_code)s; From 43adc5309a86b49d322781578666d21d55be76d4 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 9 Aug 2023 16:46:57 +0800 Subject: [PATCH 176/693] arch-riscv: Add Illegal Instruction Fault Condition for RVV Config Check the status.vs and misa.rvv CSR registers before executing RVV instructions Change-Id: I0355b94ea8ee4018be11a75aab8c19b10cb36126 --- src/arch/riscv/isa/formats/vector_conf.isa | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa index 556e230075..84e2f26783 100644 --- a/src/arch/riscv/isa/formats/vector_conf.isa +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -41,6 +41,12 @@ def template VConfExecute {{ trace::InstRecord *traceData) const { auto tc = xc->tcBase(); + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; From 42c2ed6c2d0c0bbb2db963b5e135b4ee6e073934 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 9 Aug 2023 17:07:54 +0800 Subject: [PATCH 177/693] arch-riscv: Add condition for setting misa and mstatus CSR Change-Id: I7e03b60d0de32fe8169dd79ded485d560aca64aa --- src/arch/riscv/isa.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 4b6f49d807..14d741e9e4 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -671,6 +671,9 @@ ISA::setMiscReg(RegIndex idx, RegVal val) 2, 0) != 0) { new_misa.rvc = new_misa.rvc | cur_misa.rvc; } + if (!getEnableRvv()) { + new_misa.rvv = 0; + } setMiscRegNoEffect(idx, new_misa); } break; @@ -682,6 +685,10 @@ ISA::setMiscReg(RegIndex idx, RegVal val) val &= ~(STATUS_SXL_MASK | STATUS_UXL_MASK); val |= cur & (STATUS_SXL_MASK | STATUS_UXL_MASK); } + if (!getEnableRvv()) { + // Always OFF is rvv is disabled. + val &= ~STATUS_VS_MASK; + } setMiscRegNoEffect(idx, val); } break; From 97e55fc173d6c934a640888ee220d7f75d56a23b Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 9 Aug 2023 15:40:37 +0800 Subject: [PATCH 178/693] cpu: Fix segment fault when using debug flags Branch Change-Id: I36624b93f53aa101a57d51f3b917696cb2809136 --- src/cpu/pred/bpred_unit.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index ec751f7dc6..1bf51afe48 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -503,10 +503,12 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, "return [sn:%llu] PC: %#x Restoring RAS\n", tid, squashed_sn, hist_it->seqNum, hist_it->pc); - DPRINTF(Branch, - "[tid:%i] [squash sn:%llu] Restoring top of RAS " - "to: %i, target: %s\n", tid, squashed_sn, - hist_it->RASIndex, *hist_it->RASTarget); + if (hist_it->RASTarget != nullptr) { + DPRINTF(Branch, + "[tid:%i] [squash sn:%llu] Restoring top of RAS " + "to: %i, target: %s\n", tid, squashed_sn, + hist_it->RASIndex, *hist_it->RASTarget.get()); + } RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get()); hist_it->usedRAS = false; } From da87f65e4a36b9bdececf201b96e2e4587864ad2 Mon Sep 17 00:00:00 2001 From: James Braun Date: Wed, 9 Aug 2023 23:05:58 -0500 Subject: [PATCH 179/693] Updating weekly.sh to use mmapped version of FW Change-Id: Id0059d9b3e9e4a4db3ba59793c41ae71269666ae --- tests/deprecated/weekly.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/deprecated/weekly.sh b/tests/deprecated/weekly.sh index 2bfd33741d..809c9a1427 100755 --- a/tests/deprecated/weekly.sh +++ b/tests/deprecated/weekly.sh @@ -296,10 +296,15 @@ docker run --rm -v ${gem5_root}:${gem5_root} -w ${gem5_root} -u $UID:$GID \ -c color_maxmin.gem5 --options="1k_128k.gr 0" # build FW -docker run --rm -v ${gem5_root}:${gem5_root} -w \ - ${gem5_root}/gem5-resources/src/gpu/pannotia/fw -u $UID:$GID \ +docker run --rm -v ${gem5_root}:${gem5_root} -w ${gem5_root} -u $UID:$GID \ + ${gem5_root}/gem5-resources/src/gpu/pannotia/fw \ --memory="${docker_mem_limit}" hacc-test-weekly bash -c \ - "export GEM5_PATH=${gem5_root} ; make gem5-fusion" + "export GEM5_PATH=${gem5_root} ; make default; make gem5-fusion" + +# create input mmap file for FW +docker run --rm -v ${gem5_root}:${gem5_root} -w ${gem5_root} -u $UID:$GID \ + --memory="${docker_mem_limit}" hacc-test-weekly bash -c\ + "./gem5-resources/src/gpu/pannotia/fw/bin/fw_hip ./gem5-resources/src/gpu/pannotia/fw/1k_128k.gr 1" # run FW (use same input dataset as BC for faster testing) docker run --rm -v ${gem5_root}:${gem5_root} -w ${gem5_root} -u $UID:$GID \ @@ -308,7 +313,7 @@ docker run --rm -v ${gem5_root}:${gem5_root} -w ${gem5_root} -u $UID:$GID \ ${gem5_root}/configs/example/apu_se.py -n3 --mem-size=8GB \ --reg-alloc-policy=dynamic \ --benchmark-root=${gem5_root}/gem5-resources/src/gpu/pannotia/fw/bin \ - -c fw_hip.gem5 --options="1k_128k.gr" + -c fw_hip.gem5 --options="1k_128k.gr 2" # build MIS docker run --rm -v ${gem5_root}:${gem5_root} -w \ From 81e3bfcdc385a4cdb506bb74fc66eec9c2d1bc3e Mon Sep 17 00:00:00 2001 From: rogerchang23424 Date: Thu, 10 Aug 2023 07:21:17 +0800 Subject: [PATCH 180/693] cpu: Update src/cpu/pred/bpred_unit.cc Change-Id: I0cf177676d0f9fb9db4b127d5507ba66904739c4 Co-authored-by: Jason Lowe-Power --- src/cpu/pred/bpred_unit.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index 1bf51afe48..a395e7cad7 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -503,12 +503,11 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, "return [sn:%llu] PC: %#x Restoring RAS\n", tid, squashed_sn, hist_it->seqNum, hist_it->pc); - if (hist_it->RASTarget != nullptr) { - DPRINTF(Branch, - "[tid:%i] [squash sn:%llu] Restoring top of RAS " - "to: %i, target: %s\n", tid, squashed_sn, - hist_it->RASIndex, *hist_it->RASTarget.get()); - } + DPRINTF(Branch, + "[tid:%i] [squash sn:%llu] Restoring top of RAS " + "to: %i, target: %s\n", tid, squashed_sn, + hist_it->RASIndex, + hist_it->RASIndex ? *hist_it->RASTarget.get() : "no RAS"); RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get()); hist_it->usedRAS = false; } From f54777419d018f27f0a9178e23ec59a7e0869219 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 10 Aug 2023 14:35:19 +0800 Subject: [PATCH 181/693] cpu: Fix ?: error due to different type Change-Id: I35c50fbba047fe05cc0cc29c631002a9b68795fd --- src/cpu/pred/bpred_unit.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index a395e7cad7..ed8d6c8b08 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -498,16 +498,25 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, hist_it->pushedRAS = false; } if (hist_it->usedRAS) { + + std::string RASTarget; + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrectly predicted " "return [sn:%llu] PC: %#x Restoring RAS\n", tid, squashed_sn, hist_it->seqNum, hist_it->pc); - DPRINTF(Branch, + if (hist_it->RASTarget) { + std::ostringstream os; + os << *hist_it->RASTarget.get(); + RASTarget = os.str(); + } else { + RASTarget = "no RAS"; + } + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Restoring top of RAS " "to: %i, target: %s\n", tid, squashed_sn, - hist_it->RASIndex, - hist_it->RASIndex ? *hist_it->RASTarget.get() : "no RAS"); + hist_it->RASIndex, RASTarget.c_str()); RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get()); hist_it->usedRAS = false; } From 03c2b4692c16b6a0d73a0eabd40e9e0d80ebbba3 Mon Sep 17 00:00:00 2001 From: "He, Wenjian" Date: Sat, 5 Aug 2023 22:09:08 +0800 Subject: [PATCH 182/693] cpu-o3: bugfix of rename squash when SMT In an SMT CPU, upon a squash, the phys regs used by mispredicted instructions can still be owned by executing instructions in IEW. If the regs are added back to freelist on this tick, the reg may be renamed to be used by another SMT thread. This causes reg ownership hazard, which may eventually freeze the CPU. This patch delays the freelist update to avoid the hazard. Change-Id: I993b3c7d357269f01146db61fc8a7b83a989ea45 --- src/cpu/o3/rename.cc | 19 +++++++++++++++++-- src/cpu/o3/rename.hh | 3 +++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/cpu/o3/rename.cc b/src/cpu/o3/rename.cc index f8c305eb1c..3a78efb1b0 100644 --- a/src/cpu/o3/rename.cc +++ b/src/cpu/o3/rename.cc @@ -940,8 +940,11 @@ Rename::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid) // previous physical register that it was renamed to. renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg); - // Put the renamed physical register back on the free list. - freeList->addReg(hb_it->newPhysReg); + // The phys regs can still be owned by squashing but + // executing instructions in IEW at this moment. To avoid + // ownership hazard in SMT CPU, we delay the freelist update + // until they are indeed squashed in the commit stage. + freeingInProgress[tid].push_back(hb_it->newPhysReg); } // Notify potential listeners that the register mapping needs to be @@ -1296,6 +1299,18 @@ Rename::checkSignalsAndUpdate(ThreadID tid) squash(fromCommit->commitInfo[tid].doneSeqNum, tid); return true; + } else if (!fromCommit->commitInfo[tid].robSquashing && + !freeingInProgress[tid].empty()) { + DPRINTF(Rename, "[tid:%i] Freeing phys regs of misspeculated " + "instructions.\n", tid); + + auto reg_it = freeingInProgress[tid].cbegin(); + while ( reg_it != freeingInProgress[tid].cend()){ + // Put the renamed physical register back on the free list. + freeList->addReg(*reg_it); + ++reg_it; + } + freeingInProgress[tid].clear(); } if (checkStall(tid)) { diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 61ef476501..81e63e5019 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -359,6 +359,9 @@ class Rename /** Free list interface. */ UnifiedFreeList *freeList; + /** Hold phys regs to be released after squash finish */ + std::vector freeingInProgress[MaxThreads]; + /** Pointer to the list of active threads. */ std::list *activeThreads; From 557d532bc3d170f4544f7426b98b5f0a83716b2d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 10 Aug 2023 15:46:02 -0700 Subject: [PATCH 183/693] misc: Add Jason Lowe-Power as website expert Change-Id: I52ebce434732bb921efc040397a9aa9538a6d1d9 --- MAINTAINERS.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index e5e8d1b968..79d738cdaa 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -290,3 +290,5 @@ website: status: maintained maintainers: - Bobby R. Bruce + experts: + - Jason Lowe-Power From a41c6f8d84003fde6d81f0a0ee00ce95b565e910 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 10 Aug 2023 15:48:05 -0700 Subject: [PATCH 184/693] misc: Remove PMC/Maintainers list from MAINTAINERS.yaml Change-Id: I772fa31d0aeea5534355731d841cf2d118fa0df4 --- MAINTAINERS.yaml | 15 --------------- util/git-commit-msg.py | 3 +-- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index 79d738cdaa..bbf6e50ddf 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -39,21 +39,6 @@ # listed as an expert are typically good to add as a reviewer for pull requests # targeting that subsystem. - -pmc: - desc: >- - PMC Members (general maintainers): - status: maintained - maintainers: - - Andreas Sandberg - - Giacomo Travaglini - - Matt Poremba - - Jason Lowe-Power (chair) - - Zhengrong Wang - - Borius Shingarov - - Matt Sinclair - - Bobby R. Bruce - arch: desc: >- General architecture-specific components diff --git a/util/git-commit-msg.py b/util/git-commit-msg.py index 12baad8c19..c12b0cd215 100755 --- a/util/git-commit-msg.py +++ b/util/git-commit-msg.py @@ -100,8 +100,7 @@ def _validateTags(commit_header): maintainer_dict = maintainers.Maintainers.from_file() valid_tags = [tag for tag, _ in maintainer_dict] - # Remove non-tag 'pmc' and add special tags not in MAINTAINERS.yaml - valid_tags.remove("pmc") + # Add special tags not in MAINTAINERS.yaml valid_tags.extend(["RFC", "WIP"]) tags = "".join(commit_header.split(":")[0].split()).split(",") From 6ca94359614a4628362e9ff3d6333a0979adf080 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 10 Aug 2023 15:52:00 -0700 Subject: [PATCH 185/693] misc: Add Matt P. as maintainer to requested tags Change-Id: Ifffb34acbf9ebf313e5bc09ebbfd2a44a017359a --- MAINTAINERS.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index bbf6e50ddf..02a8b3eb7b 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -115,10 +115,14 @@ dev: status: orphaned dev-hsa: - status: orphaned + status: maintained + maintainers: + - Matt Poremba dev-amdgpu: - status: orphaned + status: maintained + maintainers: + - Matt Poremba dev-virtio: status: maintained @@ -152,7 +156,9 @@ fastmodel: status: orphaned gpu-compute: - status: orphaned + status: maintained + maintainers: + - Matt Poremba learning-gem5: desc: >- From 912b7c06dda7ec4578acc3907a56fc895ee8af20 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Thu, 10 Aug 2023 16:37:25 -0700 Subject: [PATCH 186/693] tests: Move replacement policy and simulator config files Moving these files should address the failures in the daily tests. Change-Id: I438adba1a45bdf6083651b6b3f610c8bbe4ebdf0 --- .../replacement_policies/{ => configs}/cache_hierarchies.py | 0 tests/gem5/{ => stdlib}/configs/simulator_exit_event_run.py | 0 tests/gem5/stdlib/simulator/test_event_event.py | 2 ++ 3 files changed, 2 insertions(+) rename tests/gem5/replacement_policies/{ => configs}/cache_hierarchies.py (100%) rename tests/gem5/{ => stdlib}/configs/simulator_exit_event_run.py (100%) diff --git a/tests/gem5/replacement_policies/cache_hierarchies.py b/tests/gem5/replacement_policies/configs/cache_hierarchies.py similarity index 100% rename from tests/gem5/replacement_policies/cache_hierarchies.py rename to tests/gem5/replacement_policies/configs/cache_hierarchies.py diff --git a/tests/gem5/configs/simulator_exit_event_run.py b/tests/gem5/stdlib/configs/simulator_exit_event_run.py similarity index 100% rename from tests/gem5/configs/simulator_exit_event_run.py rename to tests/gem5/stdlib/configs/simulator_exit_event_run.py diff --git a/tests/gem5/stdlib/simulator/test_event_event.py b/tests/gem5/stdlib/simulator/test_event_event.py index cb70a5d90e..c71f0b2fb9 100644 --- a/tests/gem5/stdlib/simulator/test_event_event.py +++ b/tests/gem5/stdlib/simulator/test_event_event.py @@ -43,6 +43,7 @@ gem5_verify_config( config.base_dir, "tests", "gem5", + "stdlib", "configs", "simulator_exit_event_run.py", ), @@ -59,6 +60,7 @@ gem5_verify_config( config.base_dir, "tests", "gem5", + "stdlib", "configs", "simulator_exit_event_run.py", ), From b08bc5ff5645251624f9a32dc62c81b0fa3371c6 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Thu, 10 Aug 2023 16:58:22 -0700 Subject: [PATCH 187/693] misc: Add continue-on-error to matrix runs This sets continue-on-error to true on any scheduled test that uses a matrix so we can have all sets of tests run regardless if one of them fails or not. Change-Id: I8f6137ebdf62a5cecd582387316c330c8a1401ca --- .github/workflows/compiler-tests.yaml | 2 ++ .github/workflows/daily-tests.yaml | 3 +++ .github/workflows/weekly-tests.yaml | 1 + 3 files changed, 6 insertions(+) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 3b5ed1c901..3ae771b017 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -19,6 +19,7 @@ jobs: image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] runs-on: [self-hosted, linux, x64, run] + continue-on-error: true timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: @@ -39,6 +40,7 @@ jobs: image: [gcc-version-12, clang-version-14] opts: [.opt] runs-on: [self-hosted, linux, x64, run] + continue-on-error: true timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 595650e203..4f9b0540e5 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -36,6 +36,7 @@ jobs: - image: NULL_MI_example command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) runs-on: [self-hosted, linux, x64, build] + continue-on-error: true needs: name-artifacts container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest steps: @@ -76,6 +77,7 @@ jobs: matrix: test-type: [arm_boot_tests, fs, gem5_library_example_tests, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] + continue-on-error: true container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours for entire matrix to run @@ -167,6 +169,7 @@ jobs: matrix: test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + continue-on-error: true needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours steps: diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 5ec65a9e5a..ba7038006c 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -39,6 +39,7 @@ jobs: matrix: test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] + continue-on-error: true container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [build-gem5] timeout-minutes: 4320 # 3 days From b19d4beeb8a28e8278c097080f2397221dfd9ee9 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 11 Aug 2023 09:00:11 -0700 Subject: [PATCH 188/693] tests: Removed mips checkpoint tests Change-Id: I03ad0025ec982245721fd7faad8d75cdbb99cf81 --- .../configs/mips-hello-restore-checkpoint.py | 72 --------------- .../configs/mips-hello-save-checkpoint.py | 89 ------------------- 2 files changed, 161 deletions(-) delete mode 100644 tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py delete mode 100644 tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py diff --git a/tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py deleted file mode 100644 index 167c026f04..0000000000 --- a/tests/gem5/checkpoint_tests/configs/mips-hello-restore-checkpoint.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (c) 2023 The Regents of the University of California -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -This gem5 configuation script creates a simple board sharing the same -structure as the one in -tests/gem5/checkpoint-tests/mips-hello-save-checkpoint.py. -This script restores the checkpoint generated by the above script, and -runs the rest of "mips-hello" binary simulation. -This configuration serves as a test of restoring a checkpoint with MIPS ISA. -""" - -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource, CheckpointResource -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.cpu_types import CPUTypes - - -requires(isa_required=ISA.MIPS) - -cache_hierarchy = NoCache() - -memory = SingleChannelDDR3_1600(size="32MB") -processor = SimpleProcessor( - cpu_type=CPUTypes.TIMING, isa=ISA.MIPS, num_cores=2 -) -board = SimpleBoard( - clk_freq="3GHz", - processor=processor, - memory=memory, - cache_hierarchy=cache_hierarchy, -) -board.set_se_binary_workload( - obtain_resource("mips-hello"), - checkpoint=CheckpointResource(local_path="./mips-hello-test-checkpoint"), -) - -sim = Simulator(board=board, full_system=False) -sim.run() -print( - "Exiting @ tick {} because {}.".format( - sim.get_current_tick(), sim.get_last_exit_event_cause() - ) -) diff --git a/tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py deleted file mode 100644 index afcf237818..0000000000 --- a/tests/gem5/checkpoint_tests/configs/mips-hello-save-checkpoint.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2023 The Regents of the University of California -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -This gem5 test script creates a simple board to run the first -10^6 ticks of "mips-hello" binary simulation and saves a checkpoint. -This configuration serves as a test to ensure that checkpoints work -with MIPS ISA. -""" - -import argparse -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.cpu_types import CPUTypes - -parser = argparse.ArgumentParser() - -parser.add_argument( - "--checkpoint-path", - type=str, - required=False, - default="mips-hello-test-checkpoint/", - help="The directory to store the checkpoint.", -) - -args = parser.parse_args() - -# This check ensures that the gem5 binary is compiled to the MIPS ISA. -# If not, an exception is thrown. -requires(isa_required=ISA.MIPS) - -cache_hierarchy = NoCache() - -memory = SingleChannelDDR3_1600(size="32MB") - -processor = SimpleProcessor( - cpu_type=CPUTypes.TIMING, isa=ISA.MIPS, num_cores=2 -) - -board = SimpleBoard( - clk_freq="3GHz", - processor=processor, - memory=memory, - cache_hierarchy=cache_hierarchy, -) - - -board.set_se_binary_workload(obtain_resource("mips-hello")) - -sim = Simulator(board=board, full_system=False) -max_ticks = 10**6 -sim.run(max_ticks=max_ticks) -print( - "Exiting @ tick {} because {}.".format( - sim.get_current_tick(), sim.get_last_exit_event_cause() - ) -) -print("Taking checkpoint at", args.checkpoint_path) -sim.save_checkpoint(args.checkpoint_path) -print("Done taking checkpoint") From 576e8c1897f187ecdd69d8e753abbc97861b380a Mon Sep 17 00:00:00 2001 From: Leo Redivo Date: Fri, 11 Aug 2023 15:07:41 -0700 Subject: [PATCH 189/693] misc: Move inform to get_default_kernel_args() and fix formatting Change-Id: I788b630d811f8268da0e87923741cf9afdef0a3e --- src/python/gem5/components/boards/arm_board.py | 1 + .../boards/experimental/lupv_board.py | 13 +++++++++---- .../components/boards/kernel_disk_workload.py | 17 +++++++++-------- .../gem5/components/boards/riscv_board.py | 7 ++++++- src/python/gem5/components/boards/x86_board.py | 1 + .../prebuilt/riscvmatched/riscvmatched_board.py | 7 ++++++- 6 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index 451bb8d7dc..ae4b84f859 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -386,6 +386,7 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): "lpj=19988480", "norandmaps", "root={root_value}", + "disk_device={disk_device}", "rw", f"mem={self.get_memory().get_size()}", ] diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index f56a8804ed..9136c5b797 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -534,14 +534,19 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): fdt.writeDtsFile(os.path.join(outdir, "device.dts")) fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) - @overrides(KernelDiskWorkload) - def get_default_kernel_args(self) -> List[str]: - return ["console=ttyLIO0", "root={root_value}", "rw"] - @overrides(KernelDiskWorkload) def get_default_disk_device(self) -> str: return "/dev/lda" + @overrides(KernelDiskWorkload) + def get_default_kernel_args(self) -> List[str]: + return [ + "console=ttyLIO0", + "root={root_value}", + "disk_device={disk_device}", + "rw", + ] + @overrides(KernelDiskWorkload) def _add_disk_to_board(self, disk_image: AbstractResource) -> None: # Note: This must be called after set_workload because it looks for an diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 435de35f82..ed12d33ac1 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -91,13 +91,13 @@ class KernelDiskWorkload: :returns: The disk device. """ - if self._disk_device is None: - self._disk_device = get_default_disk_device() - inform(f"Disk Device set to {self._disk_device}") - return self._disk_device - else: - inform(f"Disk Device set to {self._disk_device}") - return self._disk_device + to_return = ( + self._disk_device + if self._disk_device + else self.get_default_disk_device() + ) + assert to_return is not None + return to_return @abstractmethod def get_default_disk_device(self) -> str: @@ -201,7 +201,8 @@ class KernelDiskWorkload: self.workload.command_line = ( " ".join(kernel_args or self.get_default_kernel_args()) ).format( - root_value=self.get_default_kernel_root_val(disk_image=disk_image) + root_value=self.get_default_kernel_root_val(disk_image=disk_image), + disk_device=self.get_disk_device(), ) # Setting the bootloader information for ARM board. The current diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index c12ad21e70..c70216c52d 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -494,4 +494,9 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): @overrides(KernelDiskWorkload) def get_default_kernel_args(self) -> List[str]: - return ["console=ttyS0", "root={root_value}", "rw"] + return [ + "console=ttyS0", + "root={root_value}", + "disk_device={disk_device}", + "rw", + ] diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index 7541cdc415..a0db8da10f 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -318,4 +318,5 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): "console=ttyS0", "lpj=7999923", "root={root_value}", + "disk_device={disk_device}", ] diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index 5f26d0500d..bd7d0acc27 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -566,7 +566,12 @@ class RISCVMatchedBoard( @overrides(KernelDiskWorkload) def get_default_kernel_args(self) -> List[str]: - return ["console=ttyS0", "root={root_value}", "rw"] + return [ + "console=ttyS0", + "root={root_value}", + "disk_device={disk_device}", + "rw", + ] @overrides(KernelDiskWorkload) def set_kernel_disk_workload( From 5edb7604146e6b64be2062eecb4e106d8360042b Mon Sep 17 00:00:00 2001 From: Yan Lee Date: Tue, 15 Aug 2023 00:31:57 -0700 Subject: [PATCH 190/693] mem: port: add address value in the port trace Add the address value from the packet with the request port name. Change-Id: I3d4c75f48ca6fbdbd5656e594d5f85f9e5626be8 --- src/mem/port.cc | 2 +- src/mem/port.hh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mem/port.cc b/src/mem/port.cc index 2f754c89df..e597255dfb 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -197,7 +197,7 @@ RequestPort::addTrace(PacketPtr pkt) const ext = std::make_shared(); pkt->setExtension(ext); } - ext->add(name(), _responsePort->name()); + ext->add(name(), _responsePort->name(), pkt->getAddr()); } void diff --git a/src/mem/port.hh b/src/mem/port.hh index 2555706444..da4addf375 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -85,9 +85,9 @@ class TracingExtension : public gem5::Extension } void - add(std::string request_port, std::string response_port) + add(std::string request_port, std::string response_port, gem5::Addr addr) { - trace_.push(request_port); + trace_.push(request_port + csprintf(" addr=%#llx", addr)); trace_.push(response_port); } From b01590fdf4cb18198e3d677e07c5929694630601 Mon Sep 17 00:00:00 2001 From: Yan Lee Date: Tue, 15 Aug 2023 00:40:29 -0700 Subject: [PATCH 191/693] mem: port: add getTraceInString() method Return the whole port trace of the packet as a string. Change-Id: I7b1b1fef628a47a6ce147cb5fb75af81948c1d89 --- src/mem/port.hh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/mem/port.hh b/src/mem/port.hh index da4addf375..5f977aaab8 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -47,6 +47,7 @@ #define __MEM_PORT_HH__ #include +#include #include #include @@ -100,6 +101,21 @@ class TracingExtension : public gem5::Extension bool empty() { return trace_.empty(); } std::stack& getTrace() { return trace_; } + std::string getTraceInString() + { + std::stringstream port_trace; + std::stack copy_stack = trace_; + port_trace << "Port trace of the Packet (" << std::endl + << "[Destination] "; + while (!copy_stack.empty()) { + if (copy_stack.size() == 1) + port_trace << "[Source] "; + port_trace << copy_stack.top() << std::endl; + copy_stack.pop(); + } + port_trace << ")"; + return port_trace.str(); + } private: std::stack trace_; From 96d80a41d26eb2a1b2476edebbcf867c3c59af69 Mon Sep 17 00:00:00 2001 From: Yan Lee Date: Tue, 15 Aug 2023 00:25:38 -0700 Subject: [PATCH 192/693] mem: dump out port trace when address decode error 1. Add findPort(PacketPtr pkt) for getting the port trace from the Packet. Keep the findPort(AddrRange addr_range) for recvMemBackdoorReq(...) 2. With the debug flag `PortTrace` enabled, user can see the full path of the packet with the corresponding address when address error in xbar. Change-Id: Iaf43ee2d7f8c46b9b84b2bc421a6bc3b02e01b3e --- src/mem/coherent_xbar.cc | 8 ++++---- src/mem/noncoherent_xbar.cc | 8 ++++---- src/mem/xbar.cc | 20 +++++++++++++++----- src/mem/xbar.hh | 11 +++++++++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/mem/coherent_xbar.cc b/src/mem/coherent_xbar.cc index 8163299a09..74ef1ead36 100644 --- a/src/mem/coherent_xbar.cc +++ b/src/mem/coherent_xbar.cc @@ -159,7 +159,7 @@ CoherentXBar::recvTimingReq(PacketPtr pkt, PortID cpu_side_port_id) assert(is_express_snoop == cache_responding); // determine the destination based on the destination address range - PortID mem_side_port_id = findPort(pkt->getAddrRange()); + PortID mem_side_port_id = findPort(pkt); // test if the crossbar should be considered occupied for the current // port, and exclude express snoops from the check @@ -563,7 +563,7 @@ CoherentXBar::recvTimingSnoopReq(PacketPtr pkt, PortID mem_side_port_id) // device responsible for the address range something is // wrong, hence there is nothing further to do as the packet // would be going back to where it came from - assert(findPort(pkt->getAddrRange()) == mem_side_port_id); + assert(findPort(pkt) == mem_side_port_id); } bool @@ -799,7 +799,7 @@ CoherentXBar::recvAtomicBackdoor(PacketPtr pkt, PortID cpu_side_port_id, // even if we had a snoop response, we must continue and also // perform the actual request at the destination - PortID mem_side_port_id = findPort(pkt->getAddrRange()); + PortID mem_side_port_id = findPort(pkt); if (sink_packet) { DPRINTF(CoherentXBar, "%s: Not forwarding %s\n", __func__, @@ -1035,7 +1035,7 @@ CoherentXBar::recvFunctional(PacketPtr pkt, PortID cpu_side_port_id) } } - PortID dest_id = findPort(pkt->getAddrRange()); + PortID dest_id = findPort(pkt); memSidePorts[dest_id]->sendFunctional(pkt); } diff --git a/src/mem/noncoherent_xbar.cc b/src/mem/noncoherent_xbar.cc index 0a378e2c63..12b62974b7 100644 --- a/src/mem/noncoherent_xbar.cc +++ b/src/mem/noncoherent_xbar.cc @@ -107,8 +107,8 @@ NoncoherentXBar::recvTimingReq(PacketPtr pkt, PortID cpu_side_port_id) // we should never see express snoops on a non-coherent crossbar assert(!pkt->isExpressSnoop()); - // determine the destination based on the address - PortID mem_side_port_id = findPort(pkt->getAddrRange()); + // determine the destination port + PortID mem_side_port_id = findPort(pkt); // test if the layer should be considered occupied for the current // port @@ -255,7 +255,7 @@ NoncoherentXBar::recvAtomicBackdoor(PacketPtr pkt, PortID cpu_side_port_id, unsigned int pkt_cmd = pkt->cmdToIndex(); // determine the destination port - PortID mem_side_port_id = findPort(pkt->getAddrRange()); + PortID mem_side_port_id = findPort(pkt); // stats updates for the request pktCount[cpu_side_port_id][mem_side_port_id]++; @@ -316,7 +316,7 @@ NoncoherentXBar::recvFunctional(PacketPtr pkt, PortID cpu_side_port_id) } // determine the destination port - PortID dest_id = findPort(pkt->getAddrRange()); + PortID dest_id = findPort(pkt); // forward the request to the appropriate destination memSidePorts[dest_id]->sendFunctional(pkt); diff --git a/src/mem/xbar.cc b/src/mem/xbar.cc index e1b2a8b521..0d4b2fca97 100644 --- a/src/mem/xbar.cc +++ b/src/mem/xbar.cc @@ -45,6 +45,9 @@ #include "mem/xbar.hh" +#include +#include + #include "base/logging.hh" #include "base/trace.hh" #include "debug/AddrRanges.hh" @@ -328,7 +331,7 @@ BaseXBar::Layer::recvRetry() } PortID -BaseXBar::findPort(AddrRange addr_range) +BaseXBar::findPort(AddrRange addr_range, PacketPtr pkt) { // we should never see any address lookups before we've got the // ranges of all connected CPU-side-port modules @@ -353,10 +356,17 @@ BaseXBar::findPort(AddrRange addr_range) return defaultPortID; } - // we should use the range for the default port and it did not - // match, or the default port is not set - fatal("Unable to find destination for %s on %s\n", addr_range.to_string(), - name()); + // We should use the range for the default port and it did not match, + // or the default port is not set. Dump out the port trace if possible. + std::string port_trace = ""; + if (pkt) { + std::shared_ptr ext = + pkt->getExtension(); + port_trace = ext ? ext->getTraceInString() : + "Use --debug-flags=PortTrace to see the port trace of the packet."; + } + fatal("Unable to find destination for %s on %s\n%s\n", + addr_range.to_string(), name(), port_trace); } /** Function called by the port when the crossbar is receiving a range change.*/ diff --git a/src/mem/xbar.hh b/src/mem/xbar.hh index 1df8b7ea13..b7f763a15a 100644 --- a/src/mem/xbar.hh +++ b/src/mem/xbar.hh @@ -344,9 +344,16 @@ class BaseXBar : public ClockedObject * given a packet with this address range. * * @param addr_range Address range to find port for. - * @return id of port that the packet should be sent out of. + * @param pkt Packet that containing the address range. + * @return id of port that the packet should be sent ou of. */ - PortID findPort(AddrRange addr_range); + PortID findPort(AddrRange addr_range, PacketPtr pkt=nullptr); + + PortID + findPort(PacketPtr pkt) + { + return findPort(pkt->getAddrRange(), pkt); + } /** * Return the address ranges the crossbar is responsible for. From 3ea7a792b0c8d29cd4f43ec007e9919d1d698b1f Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Thu, 20 Jul 2023 12:31:43 +0000 Subject: [PATCH 193/693] fastmodel: Add option to retry licence server connection. We're seeing some occasional connection timeouts in CI, possibly when we aggressively hit the license server, so let's add a parameter to retry the connection a few times. Also, print the time required to connect to the server to help debug issues. Change-Id: I804af28f79f893fcdca615d7bf82dd9b8686a74c --- src/arch/arm/fastmodel/arm_fast_model.py | 79 +++++++++++++++--------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/src/arch/arm/fastmodel/arm_fast_model.py b/src/arch/arm/fastmodel/arm_fast_model.py index 5a38eb132b..45a97d7957 100644 --- a/src/arch/arm/fastmodel/arm_fast_model.py +++ b/src/arch/arm/fastmodel/arm_fast_model.py @@ -23,6 +23,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import datetime import logging import os import socket @@ -44,11 +45,46 @@ def set_armlmd_license_file(force=False): os.environ[ARM_LICENSE_ENV] = license_file -def check_armlmd_license(timeout): +def check_armlmd_server(server, timeout): + """Check if the "server" passed as parameter is available. server + can also be a license file""" + if os.path.exists(server): + logging.debug(f"License file {server} exists.") + return True + + tuple = server.split("@") + if len(tuple) != 2: + # Probably not a server, and we know the file doesn't exist. + logging.debug(f'License file "{server}" does not exist.') + return False + + try: + start = datetime.datetime.now() + # Try to connect to license server. This doesn't attempt to + # communicate with it, just checking reachability. + s = socket.create_connection( + (tuple[1], int(tuple[0])), timeout=timeout + ) + end = datetime.datetime.now() + s.close() + time = end - start + logging.info( + f"License server {server} is reachable ({time.total_seconds()} seconds)." + ) + return True + except Exception as e: + logging.debug( + f"Cannot connect to license server {server} ({type(e).__name__}: {e})." + ) + return False + + +def check_armlmd_license(timeout, tries): """Check if any of the provided license server can be reached, or if a license file is provided. This allows to fail early and fast, as fastmodel code makes multiple lengthy attempts to connect to - license server. "timeout" is in seconds. + license server. "timeout" is in seconds. Makes "retries" attempt to + connect. """ servers = os.environ[ARM_LICENSE_ENV].split(":") @@ -62,33 +98,17 @@ def check_armlmd_license(timeout): if extra not in servers: servers.append(extra) - for server in servers: - if os.path.exists(server): - logging.debug(f"License file {server} exists.") - break - - tuple = server.split("@") - if len(tuple) != 2: - # Probably not a server, and we know the file doesn't exist. - logging.debug(f'License file "{server}" does not exist.') - continue - - try: - # Try to connect to license server. This doesn't attempt to - # communicate with it, just checking reachability. - s = socket.create_connection( - (tuple[1], int(tuple[0])), timeout=timeout + for try_count in range(1, tries + 1): + for server in servers: + if check_armlmd_server(server, timeout): + return + if try_count == tries: + raise ConnectionError( + f"Cannot connect to any of the license servers ({', '.join(servers)})." ) - s.close() - logging.debug(f"License server {server} is reachable.") - break - except Exception as e: - logging.debug( - f"Cannot connect to license server {server} ({type(e).__name__}: {e})." - ) - else: - raise ConnectionError( - f"Cannot connect to any of the license servers ({', '.join(servers)})." + # retry + logging.warning( + "Cannot connect to any of the license servers, retrying..." ) @@ -199,10 +219,11 @@ def setup_simulation( exit_on_dmi_warning=False, license_precheck=False, license_precheck_timeout=1, + license_precheck_tries=3, ): set_armlmd_license_file() if license_precheck: - check_armlmd_license(license_precheck_timeout) + check_armlmd_license(license_precheck_timeout, license_precheck_tries) scx_initialize(sim_name) scx_set_min_sync_latency(min_sync_latency) if exit_on_dmi_warning: From df4739929d063c8aa78b29d5912a13e9bcbbee76 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 28 Jul 2023 11:51:11 -0500 Subject: [PATCH 194/693] gpu-compute: Change kernel-based exit location The previous exit event occurs when the dispatcher sends a completion signal for a kernel, but gem5 does some kernel-based stats updates after the signal is sent. Therefore, if these exit events are used as a way to dump per-kernel stats, some of the stats for the kernel that just ended will be in the next kernel's stat dump which is misleading. This patch moves the exit event to where the stats are updated and only exits if the dispatcher has requested a stat dump to prevent situations where stats are updated mid-kernel. Change-Id: I74dc1cad5fc90382a2a80564764b3e7c9fb65521 --- src/gpu-compute/dispatcher.cc | 2 +- src/gpu-compute/shader.cc | 8 +++++++- src/gpu-compute/shader.hh | 10 ++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/gpu-compute/dispatcher.cc b/src/gpu-compute/dispatcher.cc index 7b36bce591..babc938489 100644 --- a/src/gpu-compute/dispatcher.cc +++ b/src/gpu-compute/dispatcher.cc @@ -334,7 +334,7 @@ GPUDispatcher::notifyWgCompl(Wavefront *wf) DPRINTF(GPUKernelInfo, "Completed kernel %d\n", kern_id); if (kernelExitEvents) { - exitSimLoop("GPU Kernel Completed"); + shader->requestKernelExitEvent(); } } diff --git a/src/gpu-compute/shader.cc b/src/gpu-compute/shader.cc index 73d2366b74..620d0152c1 100644 --- a/src/gpu-compute/shader.cc +++ b/src/gpu-compute/shader.cc @@ -519,8 +519,14 @@ Shader::notifyCuSleep() { panic_if(_activeCus <= 0 || _activeCus > cuList.size(), "Invalid activeCu size\n"); _activeCus--; - if (!_activeCus) + if (!_activeCus) { stats.shaderActiveTicks += curTick() - _lastInactiveTick; + + if (kernelExitRequested) { + kernelExitRequested = false; + exitSimLoop("GPU Kernel Completed"); + } + } } /** diff --git a/src/gpu-compute/shader.hh b/src/gpu-compute/shader.hh index 08dfd24b76..32ddf3d15b 100644 --- a/src/gpu-compute/shader.hh +++ b/src/gpu-compute/shader.hh @@ -97,6 +97,10 @@ class Shader : public ClockedObject // Last tick that all CUs attached to this shader were inactive Tick _lastInactiveTick; + // If a kernel-based exit event was requested, wait for all CUs in the + // shader to complete before actually exiting so that stats are updated. + bool kernelExitRequested = false; + public: typedef ShaderParams Params; enum hsail_mode_e {SIMT,VECTOR_SCALAR}; @@ -314,6 +318,12 @@ class Shader : public ClockedObject stats.vectorInstDstOperand[num_operands]++; } + void + requestKernelExitEvent() + { + kernelExitRequested = true; + } + protected: struct ShaderStats : public statistics::Group { From d869018226173f92718625d7b4af86b976411274 Mon Sep 17 00:00:00 2001 From: Mahyar Samani Date: Tue, 15 Aug 2023 12:37:11 -0700 Subject: [PATCH 195/693] mem: Fixing memory size type issue in port proxy. This patch changes the data type used for image size from int to uint64_t. Current version allows initializing AbstractMemory types with a maximum binary size of 2GiB. This will be limiting in many studies. Change-Id: Iea3bbd525d4a67aa7cf606f6311aef66c9b4a52c --- src/mem/port_proxy.cc | 6 +++--- src/mem/port_proxy.hh | 18 +++++++++--------- src/mem/translating_port_proxy.cc | 6 +++--- src/mem/translating_port_proxy.hh | 6 +++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/mem/port_proxy.cc b/src/mem/port_proxy.cc index 19e1a53e84..44e8fbbc90 100644 --- a/src/mem/port_proxy.cc +++ b/src/mem/port_proxy.cc @@ -56,7 +56,7 @@ PortProxy::PortProxy(const RequestPort &port, unsigned int cache_line_size) : void PortProxy::readBlobPhys(Addr addr, Request::Flags flags, - void *p, int size) const + void *p, uint64_t size) const { for (ChunkGenerator gen(addr, size, _cacheLineSize); !gen.done(); gen.next()) { @@ -73,7 +73,7 @@ PortProxy::readBlobPhys(Addr addr, Request::Flags flags, void PortProxy::writeBlobPhys(Addr addr, Request::Flags flags, - const void *p, int size) const + const void *p, uint64_t size) const { for (ChunkGenerator gen(addr, size, _cacheLineSize); !gen.done(); gen.next()) { @@ -90,7 +90,7 @@ PortProxy::writeBlobPhys(Addr addr, Request::Flags flags, void PortProxy::memsetBlobPhys(Addr addr, Request::Flags flags, - uint8_t v, int size) const + uint8_t v, uint64_t size) const { // quick and dirty... uint8_t *buf = new uint8_t[size]; diff --git a/src/mem/port_proxy.hh b/src/mem/port_proxy.hh index 29f6ba60a4..2e60a527cd 100644 --- a/src/mem/port_proxy.hh +++ b/src/mem/port_proxy.hh @@ -120,19 +120,19 @@ class PortProxy : FunctionalRequestProtocol * Read size bytes memory at physical address and store in p. */ void readBlobPhys(Addr addr, Request::Flags flags, - void *p, int size) const; + void *p, uint64_t size) const; /** * Write size bytes from p to physical address. */ void writeBlobPhys(Addr addr, Request::Flags flags, - const void *p, int size) const; + const void *p, uint64_t size) const; /** * Fill size bytes starting at physical addr with byte value val. */ void memsetBlobPhys(Addr addr, Request::Flags flags, - uint8_t v, int size) const; + uint8_t v, uint64_t size) const; @@ -143,7 +143,7 @@ class PortProxy : FunctionalRequestProtocol * Returns true on success and false on failure. */ virtual bool - tryReadBlob(Addr addr, void *p, int size) const + tryReadBlob(Addr addr, void *p, uint64_t size) const { readBlobPhys(addr, 0, p, size); return true; @@ -154,7 +154,7 @@ class PortProxy : FunctionalRequestProtocol * Returns true on success and false on failure. */ virtual bool - tryWriteBlob(Addr addr, const void *p, int size) const + tryWriteBlob(Addr addr, const void *p, uint64_t size) const { writeBlobPhys(addr, 0, p, size); return true; @@ -165,7 +165,7 @@ class PortProxy : FunctionalRequestProtocol * Returns true on success and false on failure. */ virtual bool - tryMemsetBlob(Addr addr, uint8_t val, int size) const + tryMemsetBlob(Addr addr, uint8_t val, uint64_t size) const { memsetBlobPhys(addr, 0, val, size); return true; @@ -179,7 +179,7 @@ class PortProxy : FunctionalRequestProtocol * Same as tryReadBlob, but insists on success. */ void - readBlob(Addr addr, void *p, int size) const + readBlob(Addr addr, void *p, uint64_t size) const { if (!tryReadBlob(addr, p, size)) fatal("readBlob(%#x, ...) failed", addr); @@ -189,7 +189,7 @@ class PortProxy : FunctionalRequestProtocol * Same as tryWriteBlob, but insists on success. */ void - writeBlob(Addr addr, const void *p, int size) const + writeBlob(Addr addr, const void *p, uint64_t size) const { if (!tryWriteBlob(addr, p, size)) fatal("writeBlob(%#x, ...) failed", addr); @@ -199,7 +199,7 @@ class PortProxy : FunctionalRequestProtocol * Same as tryMemsetBlob, but insists on success. */ void - memsetBlob(Addr addr, uint8_t v, int size) const + memsetBlob(Addr addr, uint8_t v, uint64_t size) const { if (!tryMemsetBlob(addr, v, size)) fatal("memsetBlob(%#x, ...) failed", addr); diff --git a/src/mem/translating_port_proxy.cc b/src/mem/translating_port_proxy.cc index 8ab859f40d..8daa390d80 100644 --- a/src/mem/translating_port_proxy.cc +++ b/src/mem/translating_port_proxy.cc @@ -86,7 +86,7 @@ TranslatingPortProxy::tryOnBlob(BaseMMU::Mode mode, TranslationGenPtr gen, } bool -TranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const +TranslatingPortProxy::tryReadBlob(Addr addr, void *p, uint64_t size) const { constexpr auto mode = BaseMMU::Read; return tryOnBlob(mode, _tc->getMMUPtr()->translateFunctional( @@ -99,7 +99,7 @@ TranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const bool TranslatingPortProxy::tryWriteBlob( - Addr addr, const void *p, int size) const + Addr addr, const void *p, uint64_t size) const { constexpr auto mode = BaseMMU::Write; return tryOnBlob(mode, _tc->getMMUPtr()->translateFunctional( @@ -111,7 +111,7 @@ TranslatingPortProxy::tryWriteBlob( } bool -TranslatingPortProxy::tryMemsetBlob(Addr addr, uint8_t v, int size) const +TranslatingPortProxy::tryMemsetBlob(Addr addr, uint8_t v, uint64_t size) const { constexpr auto mode = BaseMMU::Write; return tryOnBlob(mode, _tc->getMMUPtr()->translateFunctional( diff --git a/src/mem/translating_port_proxy.hh b/src/mem/translating_port_proxy.hh index bedb57a3ce..9e60a858b9 100644 --- a/src/mem/translating_port_proxy.hh +++ b/src/mem/translating_port_proxy.hh @@ -77,16 +77,16 @@ class TranslatingPortProxy : public PortProxy /** Version of tryReadblob that translates virt->phys and deals * with page boundries. */ - bool tryReadBlob(Addr addr, void *p, int size) const override; + bool tryReadBlob(Addr addr, void *p, uint64_t size) const override; /** Version of tryWriteBlob that translates virt->phys and deals * with page boundries. */ - bool tryWriteBlob(Addr addr, const void *p, int size) const override; + bool tryWriteBlob(Addr addr, const void *p, uint64_t size) const override; /** * Fill size bytes starting at addr with byte value val. */ - bool tryMemsetBlob(Addr address, uint8_t v, int size) const override; + bool tryMemsetBlob(Addr address, uint8_t v, uint64_t size) const override; }; } // namespace gem5 From 74f6fa34af2f400c7b8383b7e60e8223543aa632 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 14 Aug 2023 17:52:40 -0700 Subject: [PATCH 196/693] util-docker: Fix clang-version-8 docker container clang v8, when installed in this manner via Docker, did not install the libstdc++. This caused compilation errors. This patch adds the libstdc++-10-dev package to this Dockerfile. Change-Id: Ia0f41e82b3df2d4bf32b418b0cb78111a35e0b9f --- util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile b/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile index 00f34c4d9e..f1ecf89105 100644 --- a/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile @@ -40,7 +40,10 @@ RUN apt -y update && apt -y upgrade && \ apt -y install git m4 scons zlib1g zlib1g-dev libprotobuf-dev \ protobuf-compiler libprotoc-dev libgoogle-perftools-dev python3-dev \ python-is-python3 doxygen libboost-all-dev libhdf5-serial-dev \ - python3-pydot libpng-dev clang-${version} make + python3-pydot libpng-dev clang-${version} make \ + # This is needed as clang-8 does not have the libstdc++-10-dev package. + # It is necessary for compilation. + libstdc++-10-dev RUN apt-get --purge -y remove gcc From c835c9faa33909024e343fab0ec93b4ba9c8d06b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 16 Aug 2023 01:17:19 -0500 Subject: [PATCH 197/693] arch-x86,cpu-kvm: Fix gem5.fast due to unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detected via this failing workload: https://github.com/gem5/gem5/actions/runs/5861958237 It caused the following compilation error to be thrown: ``` src/arch/x86/kvm/x86_cpu.cc:1462:22: error: unused variable ‘rv’ [-Werror=unused-variable] 1462 | bool rv = isa->cpuid->doCpuid(tc, function, idx, cpuid); | ^~ ``` `rv` is unused in the .fast compilation as it's only used in the `assert` statement immediately after. To fix this, the `[[maybe_unused]]` annotation is used Change-Id: Ib98dd859c62f171c8eeefae93502f92a8f133776 --- src/arch/x86/kvm/x86_cpu.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/kvm/x86_cpu.cc b/src/arch/x86/kvm/x86_cpu.cc index e1c1b0dfc0..b88a96a2b9 100644 --- a/src/arch/x86/kvm/x86_cpu.cc +++ b/src/arch/x86/kvm/x86_cpu.cc @@ -1459,7 +1459,8 @@ X86KvmCPU::updateCPUID() m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); } else { while (true) { - bool rv = isa->cpuid->doCpuid(tc, function, idx, cpuid); + [[maybe_unused]] bool rv = isa->cpuid->doCpuid( + tc, function, idx, cpuid); assert(rv); if (idx && @@ -1493,7 +1494,8 @@ X86KvmCPU::updateCPUID() m5_supported.push_back(makeKvmCpuid(function, idx, cpuid)); } else { while (true) { - bool rv = isa->cpuid->doCpuid(tc, function, idx, cpuid); + [[maybe_unused]] bool rv = isa->cpuid->doCpuid( + tc, function, idx, cpuid); assert(rv); if (idx && From 35a6fe6f3db47241dd6825225da687ee0f4c8902 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 14 Aug 2023 13:58:04 +0800 Subject: [PATCH 198/693] arhc-riscv: Check vill in vector mem instructions Any vector instructions using vtype should check vill flag is set Change-Id: Ia9a2695f3005a176422da78e6f413cc789116faa --- src/arch/riscv/isa/templates/vector_mem.isa | 29 ++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index 4eebb477f3..c2b382043c 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -137,6 +137,8 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) + return std::make_shared("VILL is set", machInst); if(!machInst.vm) { xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); v0 = tmp_v0.as(); @@ -175,6 +177,9 @@ Fault %(op_rd)s; %(ea_code)s; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); + uint32_t mem_size = width_EEW(this->machInst.width) / 8 * this->microVl; const std::vector byte_enable(mem_size, true); Fault fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, @@ -297,6 +302,8 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) + return std::make_shared("VILL is set", machInst); if(!machInst.vm) { xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); v0 = tmp_v0.as(); @@ -338,6 +345,8 @@ Fault RiscvISA::vreg_t tmp_v0; uint8_t *v0; + if (machInst.vill) + return std::make_shared("VILL is set", machInst); if(!machInst.vm) { xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); v0 = tmp_v0.as(); @@ -761,6 +770,8 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vd[0]); @@ -799,7 +810,8 @@ Fault { Fault fault = NoFault; Addr EA; - + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_src_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vd[0]); @@ -953,6 +965,8 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vs3[0]); @@ -987,7 +1001,8 @@ Fault { Fault fault = NoFault; Addr EA; - + if (machInst.vill) + return std::make_shared("VILL is set", machInst); RiscvISA::vreg_t tmp_v0; uint8_t *v0; if(!machInst.vm) { @@ -1126,6 +1141,8 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -1165,7 +1182,8 @@ Fault using vu = std::make_unsigned_t; Fault fault = NoFault; Addr EA; - + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_src_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vd[0]); @@ -1327,6 +1345,8 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -1362,7 +1382,8 @@ Fault using vu = std::make_unsigned_t; Fault fault = NoFault; Addr EA; - + if (machInst.vill) + return std::make_shared("VILL is set", machInst); %(op_src_decl)s; %(op_rd)s; %(ea_code)s; From fe142f485ae0996009b47893f26c68985adb25c8 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 15 Aug 2023 14:13:44 +0800 Subject: [PATCH 199/693] arch-riscv: Add missing vector required check for vmem instructions The mem instructions usually executed from initiateAcc. We also need to check vector required in those instructions Change-Id: I97b4fec7fada432abb55ca58050615e12e00d1ca --- src/arch/riscv/isa/templates/vector_mem.isa | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index c2b382043c..1fe989ffce 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -177,6 +177,12 @@ Fault %(op_rd)s; %(ea_code)s; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -345,6 +351,12 @@ Fault RiscvISA::vreg_t tmp_v0; uint8_t *v0; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); if(!machInst.vm) { @@ -531,6 +543,12 @@ Fault trace::InstRecord* traceData) const { Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -651,6 +669,12 @@ Fault trace::InstRecord* traceData) const { Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } %(op_src_decl)s; %(op_rd)s; %(ea_code)s; @@ -810,6 +834,12 @@ Fault { Fault fault = NoFault; Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_src_decl)s; @@ -1001,6 +1031,12 @@ Fault { Fault fault = NoFault; Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); RiscvISA::vreg_t tmp_v0; @@ -1182,6 +1218,12 @@ Fault using vu = std::make_unsigned_t; Fault fault = NoFault; Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_src_decl)s; @@ -1382,6 +1424,12 @@ Fault using vu = std::make_unsigned_t; Fault fault = NoFault; Addr EA; + MISA misa = xc->readMiscReg(MISCREG_ISA); + STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { + return std::make_shared( + "RVV is disabled or VPU is off", machInst); + } if (machInst.vill) return std::make_shared("VILL is set", machInst); %(op_src_decl)s; From fde58a43659d6674b263ac6ec65d6570cfedadb0 Mon Sep 17 00:00:00 2001 From: Jan Vrany Date: Tue, 8 Aug 2023 14:36:23 +0100 Subject: [PATCH 200/693] arch-power: Fix reporting traps to GDB Due to inverted logic in POWER fault handlers, unimplemented opcode and trap faults did not report trap to GDB (if connected). This commit fixes the problem. While at it, I opted to use `if (! ...) { panic(...) }` rather than `panic_if(...)`. I find it easier to understand in this case. Change-Id: I6cd5dfd5f6546b8541d685e877afef21540d6824 --- src/arch/power/faults.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/arch/power/faults.cc b/src/arch/power/faults.cc index 0d8f2ddd68..77fc8cba96 100644 --- a/src/arch/power/faults.cc +++ b/src/arch/power/faults.cc @@ -42,24 +42,28 @@ namespace PowerISA void UnimplementedOpcodeFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) { - panic_if(tc->getSystemPtr()->trapToGdb(GDBSignal::ILL, tc->contextId()), - "Unimplemented opcode encountered at virtual address %#x\n", - tc->pcState().instAddr()); + if (! tc->getSystemPtr()->trapToGdb(GDBSignal::ILL, tc->contextId()) ) { + panic("Unimplemented opcode encountered at virtual address %#x\n", + tc->pcState().instAddr()); + } } void AlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) { - panic_if(!tc->getSystemPtr()->trapToGdb(GDBSignal::BUS, tc->contextId()), - "Alignment fault when accessing virtual address %#x\n", vaddr); + if (! tc->getSystemPtr()->trapToGdb(GDBSignal::BUS, tc->contextId()) ) { + panic("Alignment fault when accessing virtual address %#x\n", + vaddr); + } } void TrapFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) { - panic_if(tc->getSystemPtr()->trapToGdb(GDBSignal::TRAP, tc->contextId()), - "Trap encountered at virtual address %#x\n", - tc->pcState().instAddr()); + if (! tc->getSystemPtr()->trapToGdb(GDBSignal::TRAP, tc->contextId()) ) { + panic("Trap encountered at virtual address %#x\n", + tc->pcState().instAddr()); + } } } // namespace PowerISA From 546b3eac7df292afc387067216b49a485e357923 Mon Sep 17 00:00:00 2001 From: Jan Vrany Date: Tue, 8 Aug 2023 15:07:06 +0100 Subject: [PATCH 201/693] arch-riscv: Do not advance PC when handling faults in SE mode On RISC-V when trap occurs the contents of PC register contains the address of instruction that caused that trap (as opposed to the address of instruction following it in instruction stream). Therefore this commit does not advance the PC before reporting trap in SE mode. Change-Id: I83f3766cff276312cefcf1b4ac6e78a6569846b9 --- src/arch/riscv/faults.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index a929902e8b..9bea0668e8 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -164,8 +164,6 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) pc_state.set(addr); tc->pcState(pc_state); } else { - inst->advancePC(pc_state); - tc->pcState(pc_state); invokeSE(tc, inst); } } @@ -234,6 +232,12 @@ BreakpointFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) void SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) { + /* Advance the PC to next instruction so - once (simulated) syscall + is executed - execution continues. */ + auto pc_state = tc->pcState().as(); + inst->advancePC(pc_state); + tc->pcState(pc_state); + tc->getSystemPtr()->workload->syscall(tc); } From 3564348eecfcf73e2105ea4ca954dd53e9fe89d9 Mon Sep 17 00:00:00 2001 From: Jan Vrany Date: Tue, 8 Aug 2023 15:19:30 +0100 Subject: [PATCH 202/693] arch-riscv: Report traps to GDB in SE mode This commit add code to report illegal instruction and breakpoint traps to GDB (if connected). This merely follows what POWER does. --- src/arch/riscv/faults.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 9bea0668e8..89bb838f88 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -205,9 +205,11 @@ UnknownInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) void IllegalInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) { - auto *rsi = static_cast(inst.get()); - panic("Illegal instruction 0x%08x at pc %s: %s", rsi->machInst, - tc->pcState(), reason.c_str()); + if (! tc->getSystemPtr()->trapToGdb(GDBSignal::ILL, tc->contextId()) ) { + auto *rsi = static_cast(inst.get()); + panic("Illegal instruction 0x%08x at pc %s: %s", rsi->machInst, + tc->pcState(), reason.c_str()); + } } void @@ -226,7 +228,9 @@ IllegalFrmFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) void BreakpointFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) { - schedRelBreak(0); + if (! tc->getSystemPtr()->trapToGdb(GDBSignal::TRAP, tc->contextId()) ) { + schedRelBreak(0); + } } void From fa49de5b982cfa59bc26d5442b4bdaf6b5495670 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Thu, 17 Aug 2023 15:56:02 -0700 Subject: [PATCH 203/693] misc: Update matrix runs in scheduled tests This changes continue-on-error to be fail-fast instead, as continue-on-error will mark failed matrix runs as successful, whereas fail-fast makes sure everything in the matrix runs, but gets marked as failed if part of it fails. Change-Id: Ie20652c229b6cce9f1c0a45958b088391e7aae97 --- .github/workflows/compiler-tests.yaml | 4 ++-- .github/workflows/daily-tests.yaml | 6 +++--- .github/workflows/weekly-tests.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 3ae771b017..39367ab898 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -15,11 +15,11 @@ jobs: # replication of compiler-tests.sh all-compilers: strategy: + fail-fast: false matrix: image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] runs-on: [self-hosted, linux, x64, run] - continue-on-error: true timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: @@ -35,12 +35,12 @@ jobs: # Tests the two latest gcc and clang supported compilers against all gem5 compilations. latest-compilers-all-gem5-builds: strategy: + fail-fast: false matrix: gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, GCN3_X86] image: [gcc-version-12, clang-version-14] opts: [.opt] runs-on: [self-hosted, linux, x64, run] - continue-on-error: true timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 4f9b0540e5..cf57d804bc 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -19,6 +19,7 @@ jobs: build-gem5: strategy: + fail-fast: false matrix: # NULL is in quotes since it is considered a keyword in yaml files image: [ALL, ALL_CHI, ARM, ALL_MSI, ALL_MESI_Two_Level, "NULL", NULL_MI_example, RISCV, VEGA_X86] @@ -36,7 +37,6 @@ jobs: - image: NULL_MI_example command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) runs-on: [self-hosted, linux, x64, build] - continue-on-error: true needs: name-artifacts container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest steps: @@ -74,10 +74,10 @@ jobs: # start running all of the long tests testlib-long-tests: strategy: + fail-fast: false matrix: test-type: [arm_boot_tests, fs, gem5_library_example_tests, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] - continue-on-error: true container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours for entire matrix to run @@ -166,10 +166,10 @@ jobs: testlib-long-gem5_library_example_tests: runs-on: [self-hosted, linux, x64, run] strategy: + fail-fast: false matrix: test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - continue-on-error: true needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours steps: diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index ba7038006c..9447d84888 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -36,10 +36,10 @@ jobs: # start running the very-long tests testlib-very-long-tests: strategy: + fail-fast: false matrix: test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] - continue-on-error: true container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [build-gem5] timeout-minutes: 4320 # 3 days From c0216dbe48c39b487245e8a94ac3649768305cd0 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 17 Aug 2023 16:48:33 -0700 Subject: [PATCH 204/693] stdlib: Allow passing of func as Exit Event generator In this case the function is turned into a generator with the "yield" of the generator the return the function's execution. Change-Id: I4b06d64c5479638712a11e3c1a2f7bd30f60d188 --- src/python/gem5/simulate/simulator.py | 63 +++++++++++++++---- .../configs/simulator_exit_event_run.py | 39 ++++++++---- .../gem5/stdlib/simulator/test_event_event.py | 21 ++++++- 3 files changed, 98 insertions(+), 25 deletions(-) diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index 4947b46ebb..e355d200ad 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -85,7 +85,11 @@ class Simulator: on_exit_event: Optional[ Dict[ ExitEvent, - Union[Generator[Optional[bool], None, None], List[Callable]], + Union[ + Generator[Optional[bool], None, None], + List[Callable], + Callable, + ], ] ] = None, expected_execution_order: Optional[List[ExitEvent]] = None, @@ -97,16 +101,21 @@ class Simulator: This is optional and used to override default behavior. If not set, whether or not to run in FS mode will be determined via the board's `is_fullsystem()` function. - :param on_exit_event: An optional map to specify the generator to - execute on each exit event. The generator may yield a boolean which, - if True, will have the Simulator exit the run loop. A List of functions - may also be used. Each function must be callable with no arguments and - return a boolean specifying if the Simulation should exit the run loop. - :param expected_execution_order: May be specified to check the exit - events come in a specified order. If the order specified is not - encountered (e.g., 'Workbegin', 'Workend', then 'Exit'), an Exception - is thrown. If this parameter is not specified, any ordering of exit - events is valid. + :param on_exit_event: An optional map to specify what to execute on + each exit event. There are three possibilities here: a generator, a + list of functions, or a single function.: + 1. Generator: The generator may yield a boolean each time the + associated exit event is encountered. If True the simulator will exit + the simulation loop. + 2. List of functions: Each function must be callable with no mandatory + arguments and return a boolean specifying if the Simulation should exit + the simulation loop. Upon each exit event the list will pop the start + of the list and execute it. If the list is empty the default behavior + for that exit event will be executed. + 3. Single function: The function must be callable with no mandatory + arguments and return a boolean specifying if the Simulation should exit + or not. This function is executed each time the associated exit event + is encountered. :param checkpoint_path: An optional parameter specifying the directory of the checkpoint to instantiate from. When the path is None, no checkpoint will be loaded. By default, the path is None. **This @@ -195,6 +204,29 @@ class Simulator: again before finally, on the forth exit event will call `stop_simulation` which will stop the simulation as it returns False. + With a function + =============== + A single function can be passed. In this case every exit event of that + type will execute that function every time. The function should not + accept any mandatory parameters and return a boolean specifying if the + simulation loop should end after it is executed. + An example: + ``` + def print_hello() -> bool: + print("Hello") + return False + simulator = Simulator( + board=board, + on_exit_event = { + ExitEvent.Exit : print_hello + }, + ) + ``` + The above will print "Hello" on every `Exit` type Exit Event. As the + function returns False, the simulation loop will not end on these + events. + + Exit Event defaults =================== @@ -266,6 +298,15 @@ class Simulator: # In instances where we have a list of functions, we # convert this to a generator. self._on_exit_event[key] = (func() for func in value) + elif isinstance(value, Callable): + # In instances where the user passes a lone function, the + # function is called on every exit event of that type. Here + # we convert the function into an infinite generator. + def function_generator(func: Callable): + while True: + yield func() + + self._on_exit_event[key] = function_generator(func=value) else: raise Exception( f"`on_exit_event` for '{key.value}' event is " diff --git a/tests/gem5/stdlib/configs/simulator_exit_event_run.py b/tests/gem5/stdlib/configs/simulator_exit_event_run.py index c34cfe3ec9..56c99359f2 100644 --- a/tests/gem5/stdlib/configs/simulator_exit_event_run.py +++ b/tests/gem5/stdlib/configs/simulator_exit_event_run.py @@ -41,8 +41,9 @@ About to exit the simulation for the 3 st/nd/rd/th time Handling the final exit event. We'll exit now. ``` -By default a generator is passed to define the evit_event. A list of functions -can also be passed. This is enabled by passing the `--list-format` flag. +By default a generator is passed to define the exit_event behavior. A list of +functions or a lone function can also be passed. This can be specified by the +`--exit-event-type` parameter. """ from gem5.resources.resource import obtain_resource @@ -63,11 +64,12 @@ parser = argparse.ArgumentParser( ) parser.add_argument( - "-l", - "--list-format", - action="store_true", - help="Use a list of functions, instead of a generator, for the exit event " - "handler", + "-e", + "--exit-event-type", + type=str, + choices=("generator", "function-list", "function"), + default="generator", + help="Used to specify what exit event format is to be passed.", ) parser.add_argument( @@ -106,9 +108,9 @@ binary = obtain_resource( ) motherboard.set_se_binary_workload(binary) -# Create the exit event handler. Here there are two kinds: either pass a -# generator or a list of functions. In this script they both do the same things -# for testing purposes. +# Create the exit event handler. Here there are three kinds: either pass a +# generator, a list of functions, or a lone function. In this script they all +# do the same thing for testing purposes. def event_handle() -> bool: @@ -129,11 +131,24 @@ def generator(): func_list = [event_handle, event_handle, event_handle_final] +i = 0 + + +def lone_function() -> bool: + global i + i += 1 + if i < 3: + return event_handle() + return event_handle_final() + + exit_event_handler = None -if args.list_format: +if args.exit_event_type == "function-list": exit_event_handler = func_list -else: +elif args.exit_event_type == "generator": exit_event_handler = generator() +elif args.exit_event_type == "function": + exit_event_handler = lone_function assert exit_event_handler is not None diff --git a/tests/gem5/stdlib/simulator/test_event_event.py b/tests/gem5/stdlib/simulator/test_event_event.py index c71f0b2fb9..ed755c2e36 100644 --- a/tests/gem5/stdlib/simulator/test_event_event.py +++ b/tests/gem5/stdlib/simulator/test_event_event.py @@ -47,7 +47,7 @@ gem5_verify_config( "configs", "simulator_exit_event_run.py", ), - config_args=["-l"], + config_args=["-e", "function-list"], valid_isas=(constants.all_compiled_tag,), length=constants.quick_tag, ) @@ -64,7 +64,24 @@ gem5_verify_config( "configs", "simulator_exit_event_run.py", ), - config_args=[], + config_args=["-e", "generator"], + valid_isas=(constants.all_compiled_tag,), + length=constants.quick_tag, +) + +gem5_verify_config( + name="simulator-exit-event-handler-with-lone-function", + verifiers=verifiers, + fixtures=(), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "stdlib", + "configs", + "simulator_exit_event_run.py", + ), + config_args=["-e", "function"], valid_isas=(constants.all_compiled_tag,), length=constants.quick_tag, ) From ea5951a4675f115cab4f7edd643784527c2643de Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 18 Aug 2023 08:57:31 -0700 Subject: [PATCH 205/693] stdlib, resources: skeleton for workload resouce Change-Id: I5017ac479ad61c767ede36fae195105e0519304f --- .../gem5/components/boards/abstract_board.py | 4 +- src/python/gem5/resources/resource.py | 78 ++++++++++++++++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/python/gem5/components/boards/abstract_board.py b/src/python/gem5/components/boards/abstract_board.py index 4ea8866009..aba080e239 100644 --- a/src/python/gem5/components/boards/abstract_board.py +++ b/src/python/gem5/components/boards/abstract_board.py @@ -28,7 +28,7 @@ from abc import ABCMeta, abstractmethod import inspect from .mem_mode import MemMode, mem_mode_to_string -from ...resources.workload import AbstractWorkload +from ...resources.resource import WorkloadResource from m5.objects import ( AddrRange, @@ -198,7 +198,7 @@ class AbstractBoard: ) return self._is_fs - def set_workload(self, workload: AbstractWorkload) -> None: + def set_workload(self, workload: WorkloadResource) -> None: """ Set the workload for this board to run. diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index bc9f4480ba..2f50f36631 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -35,7 +35,7 @@ from .downloader import get_resource from .looppoint import LooppointCsvLoader, LooppointJsonLoader from ..isas import ISA, get_isa_from_str -from typing import Optional, Dict, Union, Type, Tuple, List +from typing import Optional, Dict, Union, Type, Tuple, List, Any from .client import get_resource_json_obj @@ -554,6 +554,79 @@ class SimpointDirectoryResource(SimpointResource): return simpoint_list, weight_list +class WorkloadResource(AbstractResource): + """A workload resource. This resource is used to specify a workload to run + on a board. It contains the function to call and the parameters to pass to + that function. + """ + + def __init__( + self, + resource_version: Optional[str] = None, + function: str = None, + resoucres: Dict[str, Dict[str, str]] = None, + additional_params: Dict[str, str] = None, + description: Optional[str] = None, + source: Optional[str] = None, + local_path: Optional[str] = None, + ): + """ + :param function: The function to call on the board. + :param parameters: The parameters to pass to the function. + """ + + super().__init__( + local_path=local_path, + description=description, + source=source, + resource_version=resource_version, + ) + + self._func = function + self._params = {} + for key in resoucres.keys(): + assert isinstance(key, str) + value = resoucres[key] + assert isinstance(value, dict) + self._params[key] = obtain_resource( + value["id"], + resource_version=value["resource_version"], + ) + for key in additional_params.keys(): + assert isinstance(key, str) + value = additional_params[key] + assert isinstance(value, str) + self._params[key] = value + + def get_function_str(self) -> str: + """ + Returns the name of the workload function to be run. + + This function is called via the AbstractBoard's `set_workload` + function. The parameters from the `get_parameters` function are passed + to this function. + """ + return self._func + + def get_parameters(self) -> Dict[str, Any]: + """ + Returns a dictionary mapping the workload parameters to their values. + + These parameters are passed to the function specified by + `get_function_str` via the AbstractBoard's `set_workload` function. + """ + return self._params + + def set_parameter(self, parameter: str, value: Any) -> None: + """ + Used to set or override a workload parameter + + :param parameter: The parameter of the function to set. + :param value: The value to set to the parameter. + """ + self._params[parameter] = value + + def obtain_resource( resource_id: str, resource_directory: Optional[str] = None, @@ -640,7 +713,7 @@ def obtain_resource( # Obtain the type from the JSON. From this we will determine what subclass # of `AbstractResource` we are to create and return. resources_category = resource_json["category"] - + print(resource_json) if resources_category == "resource": # This is a stop-gap measure to ensure to work with older versions of # the "resource.json" file. These should be replaced with their @@ -812,4 +885,5 @@ _get_resource_json_type_map = { "resource": Resource, "looppoint-pinpoint-csv": LooppointCsvResource, "looppoint-json": LooppointJsonResource, + "workload": WorkloadResource, } From 9d86a559edf6a107fc20a2430f510f46701884b3 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 18 Aug 2023 09:51:40 -0700 Subject: [PATCH 206/693] tests: removed mips tests and added issue link. - Removed MIPS tests. - Added link to github issue sparc test bug. Change-Id: Ib3c69dca578371ecf0ac2d7694f46f24834a7e5f --- .../configs/sparc-hello-save-checkpoint.py | 3 ++ .../gem5/checkpoint_tests/test-checkpoints.py | 41 +------------------ 2 files changed, 5 insertions(+), 39 deletions(-) diff --git a/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py index 2f995e5a53..ab216588aa 100644 --- a/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py @@ -78,3 +78,6 @@ print( sim.get_current_tick(), sim.get_last_exit_event_cause() ) ) +print("Taking checkpoint at", args.checkpoint_path) +sim.save_checkpoint(args.checkpoint_path) +print("Done taking checkpoint") diff --git a/tests/gem5/checkpoint_tests/test-checkpoints.py b/tests/gem5/checkpoint_tests/test-checkpoints.py index 903a777deb..7a6c18d626 100644 --- a/tests/gem5/checkpoint_tests/test-checkpoints.py +++ b/tests/gem5/checkpoint_tests/test-checkpoints.py @@ -199,45 +199,8 @@ gem5_verify_config( length=constants.quick_tag, ) -# gem5_verify_config( -# name="test-checkpoint-mips-hello-save-checkpoint", -# fixtures=(), -# verifiers=(save_checkpoint_verifier,), -# config=joinpath( -# config.base_dir, -# "tests", -# "gem5", -# "checkpoint_tests", -# "configs", -# "mips-hello-save-checkpoint.py", -# ), -# config_args=[ -# # "--checkpoint-path", -# # joinpath(resource_path, "mips-hello-test-checkpoint"), -# ], -# valid_isas=(constants.all_compiled_tag,), -# valid_hosts=constants.supported_hosts, -# length=constants.quick_tag, -# ) - -# gem5_verify_config( -# name="test-checkpoint-mips-hello-restore-checkpoint", -# fixtures=(), -# verifiers=(hello_verifier,), -# config=joinpath( -# config.base_dir, -# "tests", -# "gem5", -# "checkpoint_tests", -# "configs", -# "mips-hello-restore-checkpoint.py", -# ), -# config_args=[], -# valid_isas=(constants.all_compiled_tag,), -# valid_hosts=constants.supported_hosts, -# length=constants.quick_tag, -# ) - +# There is a bug in sparc isa that causes the checkpoints to fail +# GitHub issue: https://github.com/gem5/gem5/issues/197 # gem5_verify_config( # name="test-checkpoint-sparc-hello-save-checkpoint", # fixtures=(), From a18b4b17ed43c315001c145e8d4fae44e7e1a324 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 18 Aug 2023 13:56:12 -0700 Subject: [PATCH 207/693] stdlib, resources: depricated workload - Added WrokloadResource in resource.py. - depricated Workload and CustomWorkload. - changed iscvmatched-fs.py with obtain resource for workload to test. Change-Id: I2267c44249b96ca37da3890bf630e0d15c7335ed Note: change example files back to original --- .../example/gem5_library/riscvmatched-fs.py | 3 +- src/python/gem5/resources/resource.py | 20 +- src/python/gem5/resources/workload.py | 226 +++++------------- 3 files changed, 76 insertions(+), 173 deletions(-) diff --git a/configs/example/gem5_library/riscvmatched-fs.py b/configs/example/gem5_library/riscvmatched-fs.py index 3e84b8c1ea..5d8bb113dc 100644 --- a/configs/example/gem5_library/riscvmatched-fs.py +++ b/configs/example/gem5_library/riscvmatched-fs.py @@ -43,6 +43,7 @@ from gem5.utils.requires import requires from gem5.isas import ISA from gem5.simulate.simulator import Simulator from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource import argparse @@ -76,7 +77,7 @@ board = RISCVMatchedBoard( # In the case where the `-i` flag is passed, we add the kernel argument # `init=/root/exit.sh`. This means the simulation will exit after the Linux # Kernel has booted. -workload = Workload("riscv-ubuntu-20.04-boot") +workload = obtain_resource("riscv-ubuntu-20.04-boot") kernel_args = board.get_default_kernel_args() if args.to_init: kernel_args.append("init=/root/exit.sh") diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 2f50f36631..9c665e8284 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -562,13 +562,15 @@ class WorkloadResource(AbstractResource): def __init__( self, - resource_version: Optional[str] = None, function: str = None, - resoucres: Dict[str, Dict[str, str]] = None, - additional_params: Dict[str, str] = None, + resources: Optional[Dict[str, str]] = None, + additional_params: Optional[Dict[str, str]] = None, + resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, local_path: Optional[str] = None, + parameters: Optional[Dict[str, Any]] = None, + **kwargs, ): """ :param function: The function to call on the board. @@ -583,14 +585,14 @@ class WorkloadResource(AbstractResource): ) self._func = function - self._params = {} - for key in resoucres.keys(): + self._params = parameters if parameters else {} + print(resources) + for key in resources.keys(): assert isinstance(key, str) - value = resoucres[key] - assert isinstance(value, dict) + value = resources[key] + assert isinstance(value, str) self._params[key] = obtain_resource( - value["id"], - resource_version=value["resource_version"], + value, ) for key in additional_params.keys(): assert isinstance(key, str) diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index 5b25bf879f..26197131dc 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -24,92 +24,14 @@ # (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 .resource import obtain_resource +from .resource import obtain_resource, WorkloadResource from .client import get_resource_json_obj from _m5 import core from typing import Dict, Any, List, Optional - -class AbstractWorkload: - """ - Workloads contain information needed to build a workload. - - A workload specifies a function and its parameters to run on a board to - set a workload. Workload's are passed to board via the `AbstractBoard`'s - `set_workload` function. - - The `AbstractBoard` has a `set_workload` function which accepts an - AbstractWorkload. The `set_workload` function uses the `get_function_str` - to determine which function should be called on the board and the - `get_parameters` function specifies the parameters to be passed. - - Example - ------- - - ```py - workload = CustomWorkload( - function = "set_se_binary_workload", - parameters = { - "binary" : obtain_resource("x86-print-this"), - "arguments" : ["hello", 6] - }, - ) - - board.set_workload(workload) - ``` - - The above is the equivalent of: - - ```py - board.set_se_binary_workload( - binary = obtain_resource("x86-print-this"), - arguments = ["hello", 6], - ) - ``` - - Notes - ----- - This class should not be used directly. Please use `Workload` or - `CustomWorkload`. - """ - - def __init__(self, function: str, parameters: Dict[str, Any]) -> None: - self._func = function - self._params = parameters - - def get_function_str(self) -> str: - """ - Returns the name of the workload function to be run. - - This function is called via the AbstractBoard's `set_workload` - function. The parameters from the `get_parameters` function are passed - to this function. - """ - return self._func - - def get_parameters(self) -> Dict[str, Any]: - """ - Returns a dictionary mapping the workload parameters to their values. - - These parameters are passed to the function specified by - `get_function_str` via the AbstractBoard's `set_workload` function. - """ - return self._params - - def set_parameter(self, parameter: str, value: Any) -> None: - """ - Used to set or override a workload parameter - - :param parameter: The parameter of the function to set. - :param value: The value to set to the parameter. - """ - self._params[parameter] = value - - -class CustomWorkload(AbstractWorkload): - """ +""" A workload specified locally (i.e., not via gem5-resources as with the `Workload` class). Here the user specifies the function and the parameters to be passed. @@ -128,14 +50,14 @@ class CustomWorkload(AbstractWorkload): board.set_workload(workload) ``` - """ - - def __init__(self, function: str, parameters: Dict[str, Any]) -> None: - super().__init__(function=function, parameters=parameters) +""" -class Workload(AbstractWorkload): - """ +def CustomWorkload(function: str, parameters: Dict[str, Any]) -> None: + return WorkloadResource(function=function, parameters=parameters) + + +""" The `Workload` class loads a workload's information from gem5-resources based on a name/id passed via the constructor. @@ -156,87 +78,65 @@ class Workload(AbstractWorkload): board.set_workload(workload) ``` +""" + + +def Workload( + workload_name: str, + resource_directory: Optional[str] = None, + resource_version: Optional[str] = None, + clients: Optional[List] = None, + gem5_version: Optional[str] = core.gem5Version, +): """ + This constructor will load the workload details from the workload with + the given name/id. - def __init__( - self, - workload_name: str, - resource_directory: Optional[str] = None, - resource_version: Optional[str] = None, - clients: Optional[List] = None, - gem5_version: Optional[str] = core.gem5Version, - ) -> None: - """ - This constructor will load the workload details from the workload with - the given name/id. + This function assumes the dictionary returned by the downloader's + `get_workload_json_obj` is a dictionary. An example of the schema is + shown below: - This function assumes the dictionary returned by the downloader's - `get_workload_json_obj` is a dictionary. An example of the schema is - shown below: - - ```json - { - "category" : "workload", - "id" : "x86-ubuntu-18.04-echo-hello", - "description" : "Description of workload here", - "function" : "set_kernel_disk_workload", - "resources" : { - "kernel" : "x86-linux-kernel-5.4.49", - "disk-image" : "x86-ubuntu-18.04-img" - }, - "additional_params" : { - "readfile_contents" : "m5_exit; echo 'hello'; m5_exit" - } + ```json + { + "category" : "workload", + "id" : "x86-ubuntu-18.04-echo-hello", + "description" : "Description of workload here", + "function" : "set_kernel_disk_workload", + "resources" : { + "kernel" : "x86-linux-kernel-5.4.49", + "disk-image" : "x86-ubuntu-18.04-img" + }, + "additional_params" : { + "readfile_contents" : "m5_exit; echo 'hello'; m5_exit" } - ``` + } + ``` - This resource will result in the equivalent of the following action - being taken: + This resource will result in the equivalent of the following action + being taken: - ```python - board.set_kernel_disk_workload( - kernel = obtain_resource("x86-linux-kernel-5.4.49"), - disk-image = obtain_resource("x86-ubuntu-18.04-img"), - readfile_contents = "m5_exit; echo 'hello'; m5_exit", - ) - ``` + ```python + board.set_kernel_disk_workload( + kernel = obtain_resource("x86-linux-kernel-5.4.49"), + disk-image = obtain_resource("x86-ubuntu-18.04-img"), + readfile_contents = "m5_exit; echo 'hello'; m5_exit", + ) + ``` - :param workload_name: The name of the workload in the resources.json - file to be loaded. - :param resource_directory: An optional parameter that specifies where - any resources should be download and accessed from. If None, a default - location will be used. None by default. - :param gem5_version: The gem5 version for the Workload to be loaded. - By default, the current gem5 version is used. This will filter - resources which are incompatible with the current gem5 version. If - None, no filtering will be done. - """ - - workload_json = get_resource_json_obj( - workload_name, - resource_version=resource_version, - clients=clients, - gem5_version=gem5_version, - ) - - func = workload_json["function"] - assert isinstance(func, str) - - params = {} - if "resources" in workload_json: - for key in workload_json["resources"].keys(): - assert isinstance(key, str) - value = workload_json["resources"][key] - assert isinstance(value, str) - params[key] = obtain_resource( - value, - resource_directory=resource_directory, - gem5_version=gem5_version, - ) - - if "additional_params" in workload_json: - for key in workload_json["additional_params"]: - assert isinstance(key, str) - params[key] = workload_json["additional_params"][key] - - super().__init__(function=func, parameters=params) + :param workload_name: The name of the workload in the resources.json + file to be loaded. + :param resource_directory: An optional parameter that specifies where + any resources should be download and accessed from. If None, a default + location will be used. None by default. + :param gem5_version: The gem5 version for the Workload to be loaded. + By default, the current gem5 version is used. This will filter + resources which are incompatible with the current gem5 version. If + None, no filtering will be done. + """ + return obtain_resource( + workload_name, + resource_directory=resource_directory, + gem5_version=gem5_version, + clients=clients, + resource_version=resource_version, + ) From 16752b7ca2a2f7cbfdefa70b88161710c4f8391d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 18 Aug 2023 15:43:14 -0700 Subject: [PATCH 208/693] ext: Update DRAMSys README This fixes: 1. Most importantly: The submodule recursive update was incorrect. This adds the recursive obtaining of submodules as a seperate explicity step. 2. Changes the `git clone` to use https. Change-Id: Iad69e44b927a5aa982b49dffa6929c52fcc7ee72 --- ext/dramsys/README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/dramsys/README b/ext/dramsys/README index 477da52895..7abc5a6bfb 100644 --- a/ext/dramsys/README +++ b/ext/dramsys/README @@ -1,9 +1,10 @@ Follow these steps to get DRAMSys as part of gem5 1. Go to ext/dramsys (this directory) -2. Clone DRAMSys: 'git clone --recursive git@github.com:tukl-msd/DRAMSys.git DRAMSys' +2. Clone DRAMSys: 'git clone https://github.com/tukl-msd/DRAMSys DRAMSys' 3. Change directory to DRAMSys: 'cd DRAMSys' 4. Checkout the correct commit: 'git checkout -b gem5 09f6dcbb91351e6ee7cadfc7bc8b29d97625db8f' +5. Recursively obtain the submodules: 'git submodule update --init --recursive' If you wish to run a simulation using the gem5 processor cores, make sure to enable the storage mode in DRAMSys. This is done by setting the value of the "StoreMode" key to "Store" in the base configuration file. From 98daec7d994514f0af5a0f61b4aee44f09625ff5 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sat, 19 Aug 2023 18:19:41 +0000 Subject: [PATCH 209/693] mem-cache: Allow clflush's uncacheable requests on classic cache When a linux kernel changes a page property, it flushes the related cache lines. The kernel might change the page property before flushing the cache lines. This results in the clflush might occur in an uncacheable region. Currently, an uncacheable request must be a read or a write. However, clflush request is neither of them. This change aims to allow clflush requests to work on uncacheable regions. Since there is no straightforward way to check if a packet is from a clflush instruction, this change permits all Clean Invalidate Requests, which is the type of request produced by clflush, to work on uncacheable regions. Change-Id: Ib3ec01d9281d3dfe565a0ced773ed912edb32b8f Signed-off-by: Hoa Nguyen --- src/mem/cache/cache.cc | 13 ++++++++++--- src/mem/packet.hh | 9 +++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc index 24b3fe7219..214ee3563b 100644 --- a/src/mem/cache/cache.cc +++ b/src/mem/cache/cache.cc @@ -338,15 +338,22 @@ Cache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, if (pkt->isWrite()) { allocateWriteBuffer(pkt, forward_time); - } else { - assert(pkt->isRead()); - + } else if (pkt->isRead() { // uncacheable accesses always allocate a new MSHR // Here we are using forward_time, modelling the latency of // a miss (outbound) just as forwardLatency, neglecting the // lookupLatency component. allocateMissBuffer(pkt, forward_time); + } else { + // When a linux kernel wants to change a page property, + // it flushes the related cache lines. The kernel might change + // the page property before flushing the cache. This results in + // the clflush might occur in an uncacheable region. + // clflush results in a CleanInvalidReq, which is neither read + // nor write. + assert(pkt->req->isCleanInvalidateRequest()); + allocateWriteBuffer(pkt, forward_time); } return; diff --git a/src/mem/packet.hh b/src/mem/packet.hh index ad05b72828..3d146cdd7e 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -1437,6 +1437,15 @@ class Packet : public Printable, public Extensible return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean; } + /** + * Is this packet a clean invalidate request, e.g., clflush/clflushopt? + */ + bool + isCleanInvalidateRequst() const + { + return cmd == MemCmd::CleanInvalidReq; + } + bool isMaskedWrite() const { From 7b897a30fa4abdb7bb81b405a96c93a9d555d86e Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sat, 19 Aug 2023 21:27:53 +0000 Subject: [PATCH 210/693] mem-cache: Fix syntax error Change-Id: I1360879c13d377661e9eeeddf345b785c01efeb6 Signed-off-by: Hoa Nguyen --- src/mem/cache/cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc index 214ee3563b..4fd3535a1c 100644 --- a/src/mem/cache/cache.cc +++ b/src/mem/cache/cache.cc @@ -338,7 +338,7 @@ Cache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, if (pkt->isWrite()) { allocateWriteBuffer(pkt, forward_time); - } else if (pkt->isRead() { + } else if (pkt->isRead()) { // uncacheable accesses always allocate a new MSHR // Here we are using forward_time, modelling the latency of From f442846d9d54c9fdef31b04084d4ebd6fbebe812 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sat, 19 Aug 2023 22:50:53 +0000 Subject: [PATCH 211/693] mem-cache: Fix another typo Change-Id: Ib2051f9bda6e6d9002d3be1dbf0b890299098201 Signed-off-by: Hoa Nguyen --- src/mem/packet.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 3d146cdd7e..df2a8165fc 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -1441,7 +1441,7 @@ class Packet : public Printable, public Extensible * Is this packet a clean invalidate request, e.g., clflush/clflushopt? */ bool - isCleanInvalidateRequst() const + isCleanInvalidateRequest() const { return cmd == MemCmd::CleanInvalidReq; } From 9e007e5bd7180071ef4db5a4984aa996d64b3ea3 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sat, 19 Aug 2023 22:56:55 +0000 Subject: [PATCH 212/693] mem-cache: fix wrong function call Change-Id: I924ede89f373ec21557faf25c96b36f4bc8430dd Signed-off-by: Hoa Nguyen --- src/mem/cache/cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc index 4fd3535a1c..46d7f577d3 100644 --- a/src/mem/cache/cache.cc +++ b/src/mem/cache/cache.cc @@ -352,7 +352,7 @@ Cache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, // the clflush might occur in an uncacheable region. // clflush results in a CleanInvalidReq, which is neither read // nor write. - assert(pkt->req->isCleanInvalidateRequest()); + assert(pkt->isCleanInvalidateRequest()); allocateWriteBuffer(pkt, forward_time); } From 73b6e98f518f52069686e39f79fca2640c929e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thilo=20V=C3=B6rtler?= Date: Fri, 18 Aug 2023 09:56:07 +0200 Subject: [PATCH 213/693] arch-riscv,systemc: Fix cxx_config_cc.py to use is is_source Update the cxx_config_cc.oy port description generation to use the port.is_source attribute. Github Issue: https://github.com/gem5/gem5/issues/181 Change-Id: I3fa12c2fbb06083379118e57aedb8be414c0d929 --- build_tools/cxx_config_cc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_tools/cxx_config_cc.py b/build_tools/cxx_config_cc.py index 33d3bba864..f2b126b463 100644 --- a/build_tools/cxx_config_cc.py +++ b/build_tools/cxx_config_cc.py @@ -3,6 +3,7 @@ # Copyright 2013 Mark D. Hill and David A. Wood # Copyright 2017-2020 ARM Limited # Copyright 2021 Google, Inc. +# Copyright 2023 COSEDA Technologies GmbH # # The license below extends only to copyright in the software and shall # not be construed as granting a license to any other intellectual @@ -104,7 +105,7 @@ for param in sim_object._params.values(): for port in sim_object._ports.values(): is_vector = isinstance(port, m5.params.VectorPort) - is_requestor = port.role == "GEM5 REQUESTOR" + is_requestor = port.is_source code( 'ports["%s"] = new PortDesc("%s", %s, %s);' From e611cc66b1573cdfd1cfb897b81f9a061d1c621c Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 18 Aug 2023 09:49:11 -0700 Subject: [PATCH 214/693] misc: ADD DRAMSys tests to our weekly tests This adds the DRAMSys tests to our weekly-tests.yaml file Change-Id: Ieb7903a3a7ffae6359b3de5f66e1dd65eb51fc80 --- .github/workflows/weekly-tests.yaml | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index ba7038006c..d19110663a 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -77,3 +77,34 @@ jobs: path: output.zip retention-days: 7 - run: echo "This job's status is ${{ job.status }}." + + dramsys-tests: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + timeout-minutes: 4320 # 3 days + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + + - name: Checkout DRAMSys + working-directory: ${{ github.workspace }}/ext/dramsys + run: | + git clone https://github.com/tukl-msd/DRAMSys DRAMSys + cd DRAMSys + git checkout -b gem5 09f6dcbb91351e6ee7cadfc7bc8b29d97625db8f + git submodule update --init --recursive + + # gem5 is built separately because it depends on the DRAMSys library + - name: Build gem5 + working-directory: ${{ github.workspace }} + run: scons build/ALL/gem5.opt -j $(nproc) + + - name: Run DRAMSys Checks + working-directory: ${{ github.workspace }} + run: | + ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/arm-hello-dramsys.py + ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/dramsys-traffic.py + ./build/ALL/gem5.opt configs/example/dramsys.py From 709f632730d66f03977b29c60bfbddc0689e909a Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 18 Aug 2023 16:39:28 -0700 Subject: [PATCH 215/693] base: Make 'findLsbSetFallback' constexpr to fix gcc-8 comp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compilation bug found on: https://github.com/gem5/gem5/actions/runs/5899831222/job/16002984553 In gcc Version 8 and below the following error is received: ``` src/base/bitfield.hh: In function ‘constexpr int gem5::findLsbSet(uint64_t)’: src/base/bitfield.hh:365:34: error: call to non-‘constexpr’ function ‘int gem5::{anonymous}::findLsbSetFallback(uint64_t)’ return findLsbSetFallback(val); ~~~~~~~~~~~~~~~~~~^~~~~ scons: *** [build/ALL/kern/linux/events.o] Error 1 ``` `findLsbSet` cannot be `constexr` as it calls non-constexpr function `findLsbSetFallback`. `findLsbSetFallback`. The problematic function is the `count` on the std::bitset. This patch changes this to a constexpr. Change-Id: I48bd15d03e4615148be6c4d926a3c9c2f777dc3c --- src/base/bitfield.hh | 54 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 29f8929065..bceed60f4e 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -325,33 +325,43 @@ hasBuiltinCtz() { } [[maybe_unused]] -int +constexpr int findLsbSetFallback(uint64_t val) { - // Create a mask with val's trailing zeros flipped to 1, lsb set flipped to - // 0 and the rest unchanged. This effectively is equivalent to doing -1. - // e.g.: 0101000 - 1 = 0100111 - // ^^^^ ^^^^ - auto mask = val - 1; - // This will create a mask of ones from lsb set to last bit - // e.g.: 0101000 ^ 0100111 = 00001111 - // ^^^^ ^^^^ - auto masked = val ^ mask; - // Shift that mask to that there is 1s only where there was 0s after the - // lsb set before - // e.g.: 00001111 >> 1 = 00000111 (val is 0101000 in the example) - auto ones = masked >> 1; - // Number of bit set is the lsb set. This operation should be optimized by - // the compiler without unsing intrinsics. This operation will become - // constexpr starting from C++23. In the meantime, that fallback should not - // be used much in favor of the constexpr intrinsic - return std::bitset(ones).count(); -} + int lsb = 0; + if (!val) { + return sizeof(val) * 8; + } + if (!bits(val, 31, 0)) { + lsb += 32; + val >>= 32; + } + if (!bits(val, 15, 0)) { + lsb += 16; + val >>= 16; + } + if (!bits(val, 7, 0)) { + lsb += 8; + val >>= 8; + } + if (!bits(val, 3, 0)) { + lsb += 4; + val >>= 4; + } + if (!bits(val, 1, 0)) { + lsb += 2; + val >>= 2; + } + if (!bits(val, 0, 0)) { + lsb += 1; + } + return lsb; } +} // anonymous namespace /** * Returns the bit position of the LSB that is set in the input - * That function will either use a builting that exploit a "count trailing - * zeros" instruction or use a bit-fidling algorithm explained bellow. + * That function will either use a builtin that exploit a "count trailing + * zeros" instruction or use fall back method, `findLsbSetFallback`. * * @ingroup api_bitfield */ From 6f7fc51a18f8e4d2e97412fbb10b096e7de4f6c8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 21 Aug 2023 17:19:33 -0700 Subject: [PATCH 216/693] ext: Specialize GDBSignal MACRO to gem5 The goal is to fix this issue which appears to be affects some Apple users: https://github.com/gem5/gem5/issues/94. By specializing the `EXC_*` to gem5 we avoid the name conflicts plagiing some users. Change-Id: I031f7110b4b4ae82677b6586903cd57b22ca2137 --- ext/gdbremote/signals.hh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/gdbremote/signals.hh b/ext/gdbremote/signals.hh index 11835e6f5a..07c0064d39 100644 --- a/ext/gdbremote/signals.hh +++ b/ext/gdbremote/signals.hh @@ -168,12 +168,12 @@ namespace gem5{ INFO = 142, //information request unknown = 143, //unknown signal - EXC_BAD_ACCESS = 145, //could not access memory - EXC_BAD_INSTRUCTION = 146, //illegal instruction/operand - EXC_ARITHMETIC = 147, //arithmetic exception - EXC_EMULATION = 148, //emulation instruction - EXC_SOFTWARE = 149, //software generated exception - EXC_BREAKPOINT = 150, //breakpoint + GEM5_EXC_BAD_ACCESS = 145, //could not access memory + GEM5_EXC_BAD_INSTRUCTION = 146, //illegal instruction/operand + GEM5_EXC_ARITHMETIC = 147, //arithmetic exception + GEM5_EXC_EMULATION = 148, //emulation instruction + GEM5_EXC_SOFTWARE = 149, //software generated exception + GEM5_EXC_BREAKPOINT = 150, //breakpoint LIBRT = 151, //librt internal signal }; From fee1c3fc7aff359a8b62e07c86a0ebb60b33acae Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 15 Aug 2023 16:02:23 +0800 Subject: [PATCH 217/693] tests: Update asmtest script Upload the config script to make it only for riscv asmtest and replace Resource with obtain_resourse Change-Id: I0bab96ea352b7ce1c6838203bfa13eee795f41f9 --- ...{simple_binary_run.py => riscv_asmtest.py} | 95 ++++--------------- tests/gem5/asmtest/tests.py | 3 +- 2 files changed, 17 insertions(+), 81 deletions(-) rename tests/gem5/asmtest/configs/{simple_binary_run.py => riscv_asmtest.py} (58%) diff --git a/tests/gem5/asmtest/configs/simple_binary_run.py b/tests/gem5/asmtest/configs/riscv_asmtest.py similarity index 58% rename from tests/gem5/asmtest/configs/simple_binary_run.py rename to tests/gem5/asmtest/configs/riscv_asmtest.py index 5540e806ba..e98ec1bd49 100644 --- a/tests/gem5/asmtest/configs/simple_binary_run.py +++ b/tests/gem5/asmtest/configs/riscv_asmtest.py @@ -31,7 +31,7 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import Resource +from gem5.resources.resource import obtain_resource from gem5.components.processors.cpu_types import ( get_cpu_types_str_set, get_cpu_type_from_str, @@ -40,29 +40,13 @@ from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.base_cpu_core import BaseCPUCore -from gem5.components.processors.base_cpu_processor import BaseCPUProcessor -from gem5.components.processors.simple_core import SimpleCore -from gem5.components.boards.mem_mode import MemMode -from gem5.components.processors.cpu_types import CPUTypes from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set, ISA - -from m5.util import fatal +from gem5.isas import ISA import argparse -import importlib - -cpu_types_string_map = { - CPUTypes.ATOMIC: "AtomicSimpleCPU", - CPUTypes.O3: "O3CPU", - CPUTypes.TIMING: "TimingSimpleCPU", - CPUTypes.KVM: "KvmCPU", - CPUTypes.MINOR: "MinorCPU", -} parser = argparse.ArgumentParser( - description="A gem5 script for running simple binaries in SE mode." + description="A gem5 script for testing RISC-V instructions" ) parser.add_argument( @@ -73,17 +57,6 @@ parser.add_argument( "cpu", type=str, choices=get_cpu_types_str_set(), help="The CPU type used." ) -parser.add_argument( - "isa", type=str, choices=get_isas_str_set(), help="The ISA used" -) - -parser.add_argument( - "-b", - "--base-cpu-processor", - action="store_true", - help="Use the BaseCPUProcessor instead of the SimpleProcessor.", -) - parser.add_argument( "--riscv-32bits", action="store_true", @@ -98,15 +71,6 @@ parser.add_argument( help="The directory in which resources will be downloaded or exist.", ) -parser.add_argument( - "--arguments", - type=str, - action="append", - default=[], - required=False, - help="The input arguments for the binary.", -) - parser.add_argument( "-n", "--num-cores", @@ -122,45 +86,16 @@ args = parser.parse_args() cache_hierarchy = NoCache() memory = SingleChannelDDR3_1600() -isa_enum = get_isa_from_str(args.isa) -cpu_enum = get_cpu_type_from_str(args.cpu) +processor = SimpleProcessor( + cpu_type=get_cpu_type_from_str(args.cpu), + isa=ISA.RISCV, + num_cores=args.num_cores, +) -if isa_enum == ISA.RISCV and args.riscv_32bits and not args.base_cpu_processor: - fatal("To use Riscv 32 CPU, the base_cpu_processor must be specify!") - -if args.base_cpu_processor: - - if isa_enum == ISA.RISCV and args.riscv_32bits: - m5_objects = importlib.import_module("m5.objects") - cpu_class = getattr( - m5_objects, f"Riscv32{cpu_types_string_map[cpu_enum]}" - ) - cores = [ - BaseCPUCore(core=cpu_class(cpu_id=i), isa=isa_enum) - for i in range(args.num_cores) - ] - else: - cores = [ - BaseCPUCore( - core=SimpleCore.cpu_simobject_factory( - cpu_type=cpu_enum, - isa=isa_enum, - core_id=i, - ), - isa=isa_enum, - ) - for i in range(args.num_cores) - ] - - processor = BaseCPUProcessor( - cores=cores, - ) -else: - processor = SimpleProcessor( - cpu_type=cpu_enum, - isa=isa_enum, - num_cores=args.num_cores, - ) +if args.riscv_32bits: + for simple_core in processor.cores: + for i in range(len(simple_core.core.isa)): + simple_core.core.isa[i].riscv_type = "RV32" motherboard = SimpleBoard( clk_freq="3GHz", @@ -170,8 +105,10 @@ motherboard = SimpleBoard( ) # Set the workload -binary = Resource(args.resource, resource_directory=args.resource_directory) -motherboard.set_se_binary_workload(binary, arguments=args.arguments) +binary = obtain_resource( + args.resource, resource_directory=args.resource_directory +) +motherboard.set_se_binary_workload(binary) # Run the simulation simulator = Simulator(board=motherboard) diff --git a/tests/gem5/asmtest/tests.py b/tests/gem5/asmtest/tests.py index 02283ec213..5822fd519c 100644 --- a/tests/gem5/asmtest/tests.py +++ b/tests/gem5/asmtest/tests.py @@ -182,12 +182,11 @@ for cpu_type in cpu_types: "gem5", "asmtest", "configs", - "simple_binary_run.py", + "riscv_asmtest.py", ), config_args=[ binary, cpu_type, - "riscv", "--num-cores", "4", "--resource-directory", From 61488e1e1719e0374cddfd1112f5728e7e35b4f4 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 22 Aug 2023 11:17:57 +0800 Subject: [PATCH 218/693] tests: Add more tests for RV64 --- tests/gem5/asmtest/tests.py | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/gem5/asmtest/tests.py b/tests/gem5/asmtest/tests.py index 5822fd519c..b1efb73ccf 100644 --- a/tests/gem5/asmtest/tests.py +++ b/tests/gem5/asmtest/tests.py @@ -69,6 +69,50 @@ binaries = ( "rv64uamt-ps-amoswap_d", "rv64uamt-ps-amoxor_d", "rv64uamt-ps-lrsc_d", + "rv64ub-ps-add_uw", + "rv64ub-ps-andn", + "rv64ub-ps-bclr", + "rv64ub-ps-bclri", + "rv64ub-ps-bext", + "rv64ub-ps-bexti", + "rv64ub-ps-binv", + "rv64ub-ps-binvi", + "rv64ub-ps-bset", + "rv64ub-ps-bseti", + "rv64ub-ps-clmul", + "rv64ub-ps-clmulh", + "rv64ub-ps-clmulr", + "rv64ub-ps-clz", + "rv64ub-ps-clzw", + "rv64ub-ps-cpop", + "rv64ub-ps-cpopw", + "rv64ub-ps-ctz", + "rv64ub-ps-ctzw", + "rv64ub-ps-max", + "rv64ub-ps-maxu", + "rv64ub-ps-min", + "rv64ub-ps-minu", + "rv64ub-ps-orc_b", + "rv64ub-ps-orn", + "rv64ub-ps-rev8", + "rv64ub-ps-rol", + "rv64ub-ps-rolw", + "rv64ub-ps-ror", + "rv64ub-ps-rori", + "rv64ub-ps-roriw", + "rv64ub-ps-rorw", + "rv64ub-ps-sext_b", + "rv64ub-ps-sext_h", + "rv64ub-ps-sh1add", + "rv64ub-ps-sh1add_uw", + "rv64ub-ps-sh2add", + "rv64ub-ps-sh2add_uw", + "rv64ub-ps-sh3add", + "rv64ub-ps-sh3add_uw", + "rv64ub-ps-slli_uw", + "rv64ub-ps-xnor", + "rv64ub-ps-zext_h", + "rv64uc-ps-rvc", "rv64ud-ps-fadd", "rv64ud-ps-fclass", "rv64ud-ps-fcmp", From f41172f9e4c10846a2e93e2d75fa745910262aea Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 22 Aug 2023 13:09:06 +0800 Subject: [PATCH 219/693] tests: Add RV32 test binaries --- tests/gem5/asmtest/tests.py | 163 +++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 2 deletions(-) diff --git a/tests/gem5/asmtest/tests.py b/tests/gem5/asmtest/tests.py index b1efb73ccf..62e4ef5859 100644 --- a/tests/gem5/asmtest/tests.py +++ b/tests/gem5/asmtest/tests.py @@ -34,7 +34,7 @@ else: # The following lists the RISCV binaries. Those commented out presently result # in a test failure. This is outlined in the following Jira issue: # https://gem5.atlassian.net/browse/GEM5-496 -binaries = ( +rv64_binaries = ( "rv64samt-ps-sysclone_d", "rv64samt-ps-sysfutex1_d", # 'rv64samt-ps-sysfutex2_d', @@ -213,10 +213,145 @@ binaries = ( "rv64uzfh-ps-recoding", ) +rv32_binaries = ( + "rv32ua-ps-amoadd_w", + "rv32ua-ps-amoand_w", + "rv32ua-ps-amomaxu_w", + "rv32ua-ps-amomax_w", + "rv32ua-ps-amominu_w", + "rv32ua-ps-amomin_w", + "rv32ua-ps-amoor_w", + "rv32ua-ps-amoswap_w", + "rv32ua-ps-amoxor_w", + "rv32ua-ps-lrsc", + "rv32uamt-ps-amoadd_w", + "rv32uamt-ps-amoand_w", + "rv32uamt-ps-amomaxu_w", + "rv32uamt-ps-amomax_w", + "rv32uamt-ps-amominu_w", + "rv32uamt-ps-amomin_w", + "rv32uamt-ps-amoor_w", + "rv32uamt-ps-amoswap_w", + "rv32uamt-ps-amoxor_w", + "rv32uamt-ps-lrsc_w", + "rv32ub-ps-andn", + "rv32ub-ps-bclr", + "rv32ub-ps-bclri", + "rv32ub-ps-bext", + "rv32ub-ps-bexti", + "rv32ub-ps-binv", + "rv32ub-ps-binvi", + "rv32ub-ps-bset", + "rv32ub-ps-bseti", + "rv32ub-ps-clmul", + "rv32ub-ps-clmulh", + "rv32ub-ps-clmulr", + "rv32ub-ps-clz", + "rv32ub-ps-cpop", + "rv32ub-ps-ctz", + "rv32ub-ps-max", + "rv32ub-ps-maxu", + "rv32ub-ps-min", + "rv32ub-ps-minu", + "rv32ub-ps-orc_b", + "rv32ub-ps-orn", + "rv32ub-ps-rev8", + "rv32ub-ps-rol", + "rv32ub-ps-ror", + "rv32ub-ps-rori", + "rv32ub-ps-sext_b", + "rv32ub-ps-sext_h", + "rv32ub-ps-sh1add", + "rv32ub-ps-sh2add", + "rv32ub-ps-sh3add", + "rv32ub-ps-xnor", + "rv32ub-ps-zext_h", + "rv32uc-ps-rvc", + "rv32ud-ps-fadd", + "rv32ud-ps-fclass", + "rv32ud-ps-fcmp", + "rv32ud-ps-fcvt", + "rv32ud-ps-fcvt_w", + "rv32ud-ps-fdiv", + "rv32ud-ps-fmadd", + "rv32ud-ps-fmin", + "rv32ud-ps-ldst", + "rv32ud-ps-recoding", + "rv32uf-ps-fadd", + "rv32uf-ps-fclass", + "rv32uf-ps-fcmp", + "rv32uf-ps-fcvt", + "rv32uf-ps-fcvt_w", + "rv32uf-ps-fdiv", + "rv32uf-ps-fmadd", + "rv32uf-ps-fmin", + "rv32uf-ps-ldst", + "rv32uf-ps-move", + "rv32uf-ps-recoding", + "rv32ui-ps-add", + "rv32ui-ps-addi", + "rv32ui-ps-and", + "rv32ui-ps-andi", + "rv32ui-ps-auipc", + "rv32ui-ps-beq", + "rv32ui-ps-bge", + "rv32ui-ps-bgeu", + "rv32ui-ps-blt", + "rv32ui-ps-bltu", + "rv32ui-ps-bne", + "rv32ui-ps-fence_i", + "rv32ui-ps-jal", + "rv32ui-ps-jalr", + "rv32ui-ps-lb", + "rv32ui-ps-lbu", + "rv32ui-ps-lh", + "rv32ui-ps-lhu", + "rv32ui-ps-lui", + "rv32ui-ps-lw", + "rv32ui-ps-or", + "rv32ui-ps-ori", + "rv32ui-ps-sb", + "rv32ui-ps-sh", + "rv32ui-ps-simple", + "rv32ui-ps-sll", + "rv32ui-ps-slli", + "rv32ui-ps-slt", + "rv32ui-ps-slti", + "rv32ui-ps-sltiu", + "rv32ui-ps-sltu", + "rv32ui-ps-sra", + "rv32ui-ps-srai", + "rv32ui-ps-srl", + "rv32ui-ps-srli", + "rv32ui-ps-sub", + "rv32ui-ps-sw", + "rv32ui-ps-xor", + "rv32ui-ps-xori", + "rv32um-ps-div", + "rv32um-ps-divu", + "rv32um-ps-mul", + "rv32um-ps-mulh", + "rv32um-ps-mulhsu", + "rv32um-ps-mulhu", + "rv32um-ps-rem", + "rv32um-ps-remu", + "rv32uzfh-ps-fadd", + "rv32uzfh-ps-fclass", + "rv32uzfh-ps-fcmp", + "rv32uzfh-ps-fcvt", + "rv32uzfh-ps-fcvt_w", + "rv32uzfh-ps-fdiv", + "rv32uzfh-ps-fmadd", + "rv32uzfh-ps-fmin", + "rv32uzfh-ps-ldst", + "rv32uzfh-ps-move", + "rv32uzfh-ps-recoding", +) + cpu_types = ("atomic", "timing", "minor", "o3") for cpu_type in cpu_types: - for binary in binaries: + for binary in rv64_binaries: gem5_verify_config( name=f"asm-riscv-{binary}-{cpu_type}", verifiers=(), @@ -239,3 +374,27 @@ for cpu_type in cpu_types: valid_isas=(constants.all_compiled_tag,), valid_hosts=constants.supported_hosts, ) + for binary in rv32_binaries: + gem5_verify_config( + name=f"asm-riscv-{binary}-{cpu_type}", + verifiers=(), + config=joinpath( + config.base_dir, + "tests", + "gem5", + "asmtest", + "configs", + "riscv_asmtest.py", + ), + config_args=[ + binary, + cpu_type, + "--num-cores", + "4", + "--riscv-32bits", + "--resource-directory", + resource_path, + ], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + ) From 6acb68797562fbfac983a408d1fc2653658e63d7 Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 17 Aug 2023 13:24:43 +0800 Subject: [PATCH 220/693] sim: provide a signal constructor with an init_state 1. The current SignalSinkPort and SignalSourcePort have no ways to assign the init value of the state. Add a new constructor for them with the param init_state 2. After the source and sink are bound, the state at both side should be the same. Set the the state of sink to the state of source in the bind() function. Change-Id: Idde0a12aa0ddd0c9c599ef47059674fb12aa5d68 --- src/sim/signal.hh | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/sim/signal.hh b/src/sim/signal.hh index 3cb3f62c0d..398da9e711 100644 --- a/src/sim/signal.hh +++ b/src/sim/signal.hh @@ -79,6 +79,7 @@ class SignalSinkPort : public Port _source = dynamic_cast *>(&peer); fatal_if(!_source, "Attempt to bind signal pin %s to " "incompatible pin %s", name(), peer.name()); + _state = _source->state(); Port::bind(peer); } void @@ -94,12 +95,21 @@ class SignalSourcePort : public Port { private: SignalSinkPort *sink = nullptr; - State _state = {}; + State _state; public: - SignalSourcePort(const std::string &_name, PortID _id=InvalidPortID) : - Port(_name, _id) - {} + SignalSourcePort(const std::string &_name, PortID _id = InvalidPortID) + : Port(_name, _id) + { + _state = {}; + } + + SignalSourcePort(const std::string &_name, PortID _id, + const State &init_state) + : SignalSourcePort(_name, _id) + { + _state = init_state; + } void set(const State &new_state) @@ -126,6 +136,6 @@ class SignalSourcePort : public Port } }; -} // namespace gem5 +} // namespace gem5 -#endif //__SIM_SIGNAL_HH__ +#endif //__SIM_SIGNAL_HH__ From 76fe71ebd0d4a56e4d59163393067026dbe6fe2e Mon Sep 17 00:00:00 2001 From: Johnny Date: Wed, 23 Aug 2023 10:13:32 +0800 Subject: [PATCH 221/693] sim: provide a signal constructor with an init_state Add more description to the code Change-Id: Iff8fb20762baa0c9d0b7e5f24fb8769d7e198b5c --- src/sim/signal.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sim/signal.hh b/src/sim/signal.hh index 398da9e711..b94618a9c3 100644 --- a/src/sim/signal.hh +++ b/src/sim/signal.hh @@ -79,6 +79,7 @@ class SignalSinkPort : public Port _source = dynamic_cast *>(&peer); fatal_if(!_source, "Attempt to bind signal pin %s to " "incompatible pin %s", name(), peer.name()); + // The state of sink has to match the state of source. _state = _source->state(); Port::bind(peer); } @@ -104,6 +105,7 @@ class SignalSourcePort : public Port _state = {}; } + // Give an initial value to the _state instead of using a default value. SignalSourcePort(const std::string &_name, PortID _id, const State &init_state) : SignalSourcePort(_name, _id) From f6a453362fbc330bda69d187ac3ffed991bee1ef Mon Sep 17 00:00:00 2001 From: "Ranganath (Bujji) Selagamsetty" Date: Fri, 18 Aug 2023 12:08:01 -0500 Subject: [PATCH 222/693] mem: Atomic ops to same address Augmenting the DataBlock class with a change log structure to record the effects of atomic operations on a data block and service these changes if the atomic operations require return values. Although the operations are atomic, the coalescer need not send unique memory requests for each operation. Atomic operations within a wavefront to the same address are now coalesced into a single memory request. The response of this request carries all the necessary information to provide the requesting lanes unique values as a result of their individual atomic operations. This helps reduce contention for request and response queues in simulation. Previously, only the final value of the datablock after all atomic ops to the same address was visible to the requesting waves. This change corrects this behavior by allowing each wave to see the effect of this individual atomic op is a return value is necessary. Change-Id: I639bea943afd317e45f8fa3bff7689f6b8df9395 --- src/mem/ruby/common/DataBlock.cc | 66 ++++++++++++++++++++-- src/mem/ruby/common/DataBlock.hh | 13 +++++ src/mem/ruby/common/WriteMask.cc | 22 ++++++++ src/mem/ruby/common/WriteMask.hh | 29 +++------- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 1 + src/mem/ruby/protocol/RubySlicc_Exports.sm | 2 + src/mem/ruby/system/GPUCoalescer.cc | 52 ++++++++++++----- 7 files changed, 146 insertions(+), 39 deletions(-) diff --git a/src/mem/ruby/common/DataBlock.cc b/src/mem/ruby/common/DataBlock.cc index f70aa79fd4..70d9bc332a 100644 --- a/src/mem/ruby/common/DataBlock.cc +++ b/src/mem/ruby/common/DataBlock.cc @@ -51,9 +51,19 @@ namespace ruby DataBlock::DataBlock(const DataBlock &cp) { - m_data = new uint8_t[RubySystem::getBlockSizeBytes()]; - memcpy(m_data, cp.m_data, RubySystem::getBlockSizeBytes()); + uint8_t *block_update; + size_t block_bytes = RubySystem::getBlockSizeBytes(); + m_data = new uint8_t[block_bytes]; + memcpy(m_data, cp.m_data, block_bytes); m_alloc = true; + // If this data block is involved in an atomic operation, the effect + // of applying the atomic operations on the data block are recorded in + // m_atomicLog. If so, we must copy over every entry in the change log + for (size_t i = 0; i < cp.m_atomicLog.size(); i++) { + block_update = new uint8_t[block_bytes]; + memcpy(block_update, cp.m_atomicLog[i], block_bytes); + m_atomicLog.push_back(block_update); + } } void @@ -73,7 +83,20 @@ DataBlock::clear() bool DataBlock::equal(const DataBlock& obj) const { - return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes()); + size_t block_bytes = RubySystem::getBlockSizeBytes(); + // Check that the block contents match + if (memcmp(m_data, obj.m_data, block_bytes)) { + return false; + } + if (m_atomicLog.size() != obj.m_atomicLog.size()) { + return false; + } + for (size_t i = 0; i < m_atomicLog.size(); i++) { + if (memcmp(m_atomicLog[i], obj.m_atomicLog[i], block_bytes)) { + return false; + } + } + return true; } void @@ -92,7 +115,7 @@ DataBlock::atomicPartial(const DataBlock &dblk, const WriteMask &mask) for (int i = 0; i < RubySystem::getBlockSizeBytes(); i++) { m_data[i] = dblk.m_data[i]; } - mask.performAtomic(m_data); + mask.performAtomic(m_data, m_atomicLog); } void @@ -107,6 +130,28 @@ DataBlock::print(std::ostream& out) const out << std::dec << "]" << std::flush; } +int +DataBlock::numAtomicLogEntries() const +{ + return m_atomicLog.size(); +} +uint8_t* +DataBlock::popAtomicLogEntryFront() +{ + assert(m_atomicLog.size() > 0); + auto ret = m_atomicLog.front(); + m_atomicLog.pop_front(); + return ret; +} +void +DataBlock::clearAtomicLogEntries() +{ + for (auto log : m_atomicLog) { + delete [] log; + } + m_atomicLog.clear(); +} + const uint8_t* DataBlock::getData(int offset, int len) const { @@ -137,7 +182,18 @@ DataBlock::setData(PacketPtr pkt) DataBlock & DataBlock::operator=(const DataBlock & obj) { - memcpy(m_data, obj.m_data, RubySystem::getBlockSizeBytes()); + uint8_t *block_update; + size_t block_bytes = RubySystem::getBlockSizeBytes(); + // Copy entire block contents from obj to current block + memcpy(m_data, obj.m_data, block_bytes); + // If this data block is involved in an atomic operation, the effect + // of applying the atomic operations on the data block are recorded in + // m_atomicLog. If so, we must copy over every entry in the change log + for (size_t i = 0; i < obj.m_atomicLog.size(); i++) { + block_update = new uint8_t[block_bytes]; + memcpy(block_update, obj.m_atomicLog[i], block_bytes); + m_atomicLog.push_back(block_update); + } return *this; } diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index e147d701c5..aa94f56eb8 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -71,6 +72,12 @@ class DataBlock { if (m_alloc) delete [] m_data; + + // If data block involved in atomic + // operations, free all meta data + for (auto log : m_atomicLog) { + delete [] log; + } } DataBlock& operator=(const DataBlock& obj); @@ -80,6 +87,9 @@ class DataBlock void clear(); uint8_t getByte(int whichByte) const; const uint8_t *getData(int offset, int len) const; + uint8_t* popAtomicLogEntryFront(); + int numAtomicLogEntries() const; + void clearAtomicLogEntries(); uint8_t *getDataMod(int offset); void setByte(int whichByte, uint8_t data); void setData(const uint8_t *data, int offset, int len); @@ -94,6 +104,9 @@ class DataBlock void alloc(); uint8_t *m_data; bool m_alloc; + + // Tracks block changes when atomic ops are applied + std::deque m_atomicLog; }; inline void diff --git a/src/mem/ruby/common/WriteMask.cc b/src/mem/ruby/common/WriteMask.cc index 4c24a64706..911262b4ba 100644 --- a/src/mem/ruby/common/WriteMask.cc +++ b/src/mem/ruby/common/WriteMask.cc @@ -55,5 +55,27 @@ WriteMask::print(std::ostream& out) const << std::flush; } +void +WriteMask::performAtomic(uint8_t * p, + std::deque& log) const +{ + int offset; + uint8_t *block_update; + // Here, operations occur in FIFO order from the mAtomicOp + // vector. This is done to match the ordering of packets + // that was seen when the initial coalesced request was created. + for (int i = 0; i < mAtomicOp.size(); i++) { + // Save the old value of the data block in case a + // return value is needed + block_update = new uint8_t[mSize]; + std::memcpy(block_update, p, mSize); + log.push_back(block_update); + // Perform the atomic operation + offset = mAtomicOp[i].first; + AtomicOpFunctor *fnctr = mAtomicOp[i].second; + (*fnctr)(&p[offset]); + } +} + } // namespace ruby } // namespace gem5 diff --git a/src/mem/ruby/common/WriteMask.hh b/src/mem/ruby/common/WriteMask.hh index 2de21da79b..47ec798500 100644 --- a/src/mem/ruby/common/WriteMask.hh +++ b/src/mem/ruby/common/WriteMask.hh @@ -222,26 +222,15 @@ class WriteMask void print(std::ostream& out) const; - void - performAtomic(uint8_t * p) const - { - for (int i = 0; i < mAtomicOp.size(); i++) { - int offset = mAtomicOp[i].first; - AtomicOpFunctor *fnctr = mAtomicOp[i].second; - (*fnctr)(&p[offset]); - } - } - - void - performAtomic(DataBlock & blk) const - { - for (int i = 0; i < mAtomicOp.size(); i++) { - int offset = mAtomicOp[i].first; - uint8_t *p = blk.getDataMod(offset); - AtomicOpFunctor *fnctr = mAtomicOp[i].second; - (*fnctr)(p); - } - } + /* + * Performs atomic operations on the data block pointed to by p. The + * atomic operations to perform are in the vector mAtomicOp. The + * effect of each atomic operation is pushed to the atomicChangeLog + * so that each individual atomic requestor may see the results of their + * specific atomic operation. + */ + void performAtomic(uint8_t * p, + std::deque& atomicChangeLog) const; const AtomicOpVector& getAtomicOps() const diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index 31fc484973..20a0979af1 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -523,6 +523,7 @@ machine(MachineType:TCC, "TCC Cache") out_msg.isSLCSet := in_msg.isSLCSet; } } + cache_entry.DataBlk.clearAtomicLogEntries(); } action(bar_sendBypassedAtomicResponse, "bar", desc="send bypassed Atomic Ack") { diff --git a/src/mem/ruby/protocol/RubySlicc_Exports.sm b/src/mem/ruby/protocol/RubySlicc_Exports.sm index a32983ada4..2e496a8221 100644 --- a/src/mem/ruby/protocol/RubySlicc_Exports.sm +++ b/src/mem/ruby/protocol/RubySlicc_Exports.sm @@ -77,6 +77,8 @@ structure(DataBlock, external = "yes", desc="..."){ void copyPartial(DataBlock, int, int); void copyPartial(DataBlock, WriteMask); void atomicPartial(DataBlock, WriteMask); + int numAtomicLogEntries(); + void clearAtomicLogEntries(); } bool testAndRead(Addr addr, DataBlock datablk, Packet *pkt); diff --git a/src/mem/ruby/system/GPUCoalescer.cc b/src/mem/ruby/system/GPUCoalescer.cc index 8bde3f7bc8..beb8da3f9c 100644 --- a/src/mem/ruby/system/GPUCoalescer.cc +++ b/src/mem/ruby/system/GPUCoalescer.cc @@ -554,25 +554,48 @@ GPUCoalescer::hitCallback(CoalescedRequest* crequest, success, isRegion); // update the data // - // MUST AD DOING THIS FOR EACH REQUEST IN COALESCER + // MUST ADD DOING THIS FOR EACH REQUEST IN COALESCER std::vector pktList = crequest->getPackets(); + + uint8_t* log = nullptr; DPRINTF(GPUCoalescer, "Responding to %d packets for addr 0x%X\n", pktList.size(), request_line_address); + uint32_t offset; + int pkt_size; for (auto& pkt : pktList) { - request_address = pkt->getAddr(); + offset = getOffset(pkt->getAddr()); + pkt_size = pkt->getSize(); if (pkt->getPtr()) { - if ((type == RubyRequestType_LD) || - (type == RubyRequestType_ATOMIC) || - (type == RubyRequestType_ATOMIC_RETURN) || - (type == RubyRequestType_IFETCH) || - (type == RubyRequestType_RMW_Read) || - (type == RubyRequestType_Locked_RMW_Read) || - (type == RubyRequestType_Load_Linked)) { - pkt->setData( - data.getData(getOffset(request_address), pkt->getSize())); - } else { - data.setData(pkt->getPtr(), - getOffset(request_address), pkt->getSize()); + switch(type) { + // Store and AtomicNoReturns follow the same path, as the + // data response is not needed. + case RubyRequestType_ATOMIC_NO_RETURN: + assert(pkt->isAtomicOp()); + case RubyRequestType_ST: + data.setData(pkt->getPtr(), offset, pkt_size); + break; + case RubyRequestType_LD: + pkt->setData(data.getData(offset, pkt_size)); + break; + case RubyRequestType_ATOMIC_RETURN: + assert(pkt->isAtomicOp()); + // Atomic operations are performed by the WriteMask + // in packet order, set by the crequest. Thus, when + // unpacking the changes from the log, we read from + // the front of the log to correctly map response + // data into the packets. + + // Log entry contains the old value before the current + // atomic operation occurred. + log = data.popAtomicLogEntryFront(); + pkt->setData(&log[offset]); + delete [] log; + log = nullptr; + break; + default: + panic("Unsupported ruby packet type:%s\n", + RubyRequestType_to_string(type)); + break; } } else { DPRINTF(MemoryAccess, @@ -581,6 +604,7 @@ GPUCoalescer::hitCallback(CoalescedRequest* crequest, RubyRequestType_to_string(type)); } } + assert(data.numAtomicLogEntries() == 0); m_outstanding_count--; assert(m_outstanding_count >= 0); From c9ff54677f6cf592ea3bd9e901a5a8dd9514c406 Mon Sep 17 00:00:00 2001 From: Reiley Jeyapaul Date: Thu, 15 Jun 2023 12:36:23 -0500 Subject: [PATCH 223/693] mem-ruby: fix CHI Evict race condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an Evict request is received from upstream for a shared line and the line is no longer cached locally (or on any other upstream cache), we need to also send an Evict downstream. In this case we need to wait until our outgoing Evict completes before completing the Evict from upstream in order be able to resolve race conditions with incoming snoops. E.g.: while our outgoing Evict is pending we may receive a snoop requesting data, but we won't be able to complete this snoop if we have already completed all upstream Evicts and we no longer have the line. Change-Id: I23ac4f0a9c4ddd81e2425376c8d1e1c7fb66d107 Signed-off-by: Tiago Mück --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index d18c600516..94088b020b 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -923,8 +923,8 @@ action(Initiate_Evict, desc="") { tbe.actions.push(Event:WriteBEPipe); tbe.actions.push(Event:SendWBData); } else { - tbe.actions.push(Event:SendCompIResp); tbe.actions.push(Event:SendEvict); + tbe.actions.push(Event:SendCompIResp); } } else { tbe.actions.push(Event:SendCompIResp); From 328d140c703a4253d77e62ff10d80d4c3f10dfb2 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 23 Aug 2023 13:50:08 -0700 Subject: [PATCH 224/693] stdlib, resources: Added warn msgs and commets. - Added deprecated warnings to Workload and Abstract workload. - Added comments to the classes changed. Change-Id: I671daacf5ef455ea65103bd96aa442486142a486 --- .../example/gem5_library/riscvmatched-fs.py | 3 +- src/python/gem5/resources/resource.py | 2 - src/python/gem5/resources/workload.py | 108 ++++-------------- 3 files changed, 23 insertions(+), 90 deletions(-) diff --git a/configs/example/gem5_library/riscvmatched-fs.py b/configs/example/gem5_library/riscvmatched-fs.py index 5d8bb113dc..3e84b8c1ea 100644 --- a/configs/example/gem5_library/riscvmatched-fs.py +++ b/configs/example/gem5_library/riscvmatched-fs.py @@ -43,7 +43,6 @@ from gem5.utils.requires import requires from gem5.isas import ISA from gem5.simulate.simulator import Simulator from gem5.resources.workload import Workload -from gem5.resources.resource import obtain_resource import argparse @@ -77,7 +76,7 @@ board = RISCVMatchedBoard( # In the case where the `-i` flag is passed, we add the kernel argument # `init=/root/exit.sh`. This means the simulation will exit after the Linux # Kernel has booted. -workload = obtain_resource("riscv-ubuntu-20.04-boot") +workload = Workload("riscv-ubuntu-20.04-boot") kernel_args = board.get_default_kernel_args() if args.to_init: kernel_args.append("init=/root/exit.sh") diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 9c665e8284..e71c7646a9 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -586,7 +586,6 @@ class WorkloadResource(AbstractResource): self._func = function self._params = parameters if parameters else {} - print(resources) for key in resources.keys(): assert isinstance(key, str) value = resources[key] @@ -715,7 +714,6 @@ def obtain_resource( # Obtain the type from the JSON. From this we will determine what subclass # of `AbstractResource` we are to create and return. resources_category = resource_json["category"] - print(resource_json) if resources_category == "resource": # This is a stop-gap measure to ensure to work with older versions of # the "resource.json" file. These should be replaced with their diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index 26197131dc..424da2ebc6 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -28,59 +28,27 @@ from .resource import obtain_resource, WorkloadResource from .client import get_resource_json_obj from _m5 import core +from m5.util import warn from typing import Dict, Any, List, Optional -""" - A workload specified locally (i.e., not via gem5-resources as with the - `Workload` class). Here the user specifies the function and the parameters - to be passed. - Usage - ----- +def CustomWorkload(function: str, parameters: Dict[str, Any]): + """ + A custom workload gem5 resource. It can be used to specify a custom, + local workload. - ```py - workload = CustomWorkload( - function = "set_se_binary_workload", - parameters = { - "binary" : obtain_resource("x86-print-this"), - "arguments" : ["hello", 6] - }, + **Warning**: This class is deprecated and changed to a funtion and will be removed in future + releases of gem5. Please use the `WorkloadResource` class instead. This + class is merely a wrapper for it. + """ + warn( + "The `CustomWorkload` class is deprecated. Please use " + "`WorkloadResource` instead." ) - - board.set_workload(workload) - ``` -""" - - -def CustomWorkload(function: str, parameters: Dict[str, Any]) -> None: return WorkloadResource(function=function, parameters=parameters) -""" - The `Workload` class loads a workload's information from gem5-resources - based on a name/id passed via the constructor. - - Usage - ----- - - ```py - # Determine what workload we want to run. - workload = Workload("example-workload-id") - - # Optionally we can override a parameter in the workload. In this example - # we are going to run this workload with a difference kernel. - workload.set_parameter("kernel", - obtain_resource("arm64-linux-kernel-4.14.134") - ) - - # We then set this workload to the board. - board.set_workload(workload) - ``` - -""" - - def Workload( workload_name: str, resource_directory: Optional[str] = None, @@ -89,50 +57,18 @@ def Workload( gem5_version: Optional[str] = core.gem5Version, ): """ - This constructor will load the workload details from the workload with - the given name/id. + This function was created to maintain backwards compability for v23.0.0 + and prior releases of gem5 where `Workload` was a class. - This function assumes the dictionary returned by the downloader's - `get_workload_json_obj` is a dictionary. An example of the schema is - shown below: - - ```json - { - "category" : "workload", - "id" : "x86-ubuntu-18.04-echo-hello", - "description" : "Description of workload here", - "function" : "set_kernel_disk_workload", - "resources" : { - "kernel" : "x86-linux-kernel-5.4.49", - "disk-image" : "x86-ubuntu-18.04-img" - }, - "additional_params" : { - "readfile_contents" : "m5_exit; echo 'hello'; m5_exit" - } - } - ``` - - This resource will result in the equivalent of the following action - being taken: - - ```python - board.set_kernel_disk_workload( - kernel = obtain_resource("x86-linux-kernel-5.4.49"), - disk-image = obtain_resource("x86-ubuntu-18.04-img"), - readfile_contents = "m5_exit; echo 'hello'; m5_exit", - ) - ``` - - :param workload_name: The name of the workload in the resources.json - file to be loaded. - :param resource_directory: An optional parameter that specifies where - any resources should be download and accessed from. If None, a default - location will be used. None by default. - :param gem5_version: The gem5 version for the Workload to be loaded. - By default, the current gem5 version is used. This will filter - resources which are incompatible with the current gem5 version. If - None, no filtering will be done. + In the interests of gem5-resource specialization, the `Workload` class + has been dropped. Instead users are advized to use the `obtain_resource` + function which will return the correct `AbstractResource` implementation. + This function (disguised as a class) wraps this function. """ + warn( + "`Workload` has been deprecated. Please use the `obtain_resource` " + "function instead." + ) return obtain_resource( workload_name, resource_directory=resource_directory, From 49f5ec16d1022fb6890155f55ccbdc6ff33fb333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Wed, 14 Jun 2023 15:32:29 -0500 Subject: [PATCH 225/693] mem-ruby: fix assert on CHI ReadUnique MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DCT must be disabled when handling a ReadUnique where the copy need to be upgraded. Previously we were just asserting as it was assumed DCT is only enabled for HNFs (which can "auto-upgrade"). However DCT may also be enabled for intermediated levels of distributed shared caches above the HNFs. Change-Id: I9e29142a8d2f59ea61c1d90cda6b00c19435d6b7 Signed-off-by: Tiago Mück --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index d18c600516..2ef01ad3de 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -598,10 +598,13 @@ action(Initiate_ReadUnique_AutoUpgrade, desc="") { action(Initiate_ReadUnique_Upgrade, desc="") { // must use the transitions with auto upgrade otherwise assert(is_HN == false); - assert(tbe.use_DCT == false); assert((tbe.dataValid && tbe.dataUnique) == false); assert((tbe.dir_ownerExists && tbe.dir_ownerIsExcl) == false); + // CompData or CompUC will always be send by us after permission is received + // from downstream + tbe.use_DCT := false; + tbe.actions.push(Event:ReadMissPipe); if (tbe.dataMaybeDirtyUpstream) { tbe.actions.push(Event:SendSnpUnique); From a5fd6edea17f3479e6557f9754366d80e1e4a710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Wed, 14 Jun 2023 15:35:42 -0500 Subject: [PATCH 226/693] mem-ruby: fix CHI sending the wrong snoop response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not respond with SnpRespData_I when the line is still present upstream. Change-Id: I2592e5c6637cfc0e83042169a245837648276e61 Signed-off-by: Tiago Mück --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index d18c600516..1af70dbcfb 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -2316,7 +2316,7 @@ action(Send_SnpRespData, desc="") { ((tbe.dataDirty || tbe.dataUnique) && (tbe.reqType == CHIRequestType:SnpShared)) || ((tbe.dataDirty || tbe.dataUnique) && (tbe.reqType == CHIRequestType:SnpUnique))); - if (tbe.dataToBeInvalid) { + if (tbe.dataToBeInvalid && tbe.dir_sharers.isEmpty()) { assert(tbe.dataMaybeDirtyUpstream == false); if (tbe.dataDirty) { tbe.snd_msgType := CHIDataType:SnpRespData_I_PD; From 3360a87d5ac516d7581a75b2b2ee1bc09dd9bc6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Mon, 1 May 2023 18:46:30 -0500 Subject: [PATCH 227/693] mem-ruby: optimize in/outTransLatHist stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generating these stats for all defined Events may generate too many stats that are never used, which unnecessarily increases simulation startup time and memory consumption. This patch limits those stats to events with the "in_trans" and/or "out_trans" properties. SLICC compiler then checks which combinations of event+state are possible when generating the stats. Also the possible level of detail for inTransLatHist was reduced. Only the number of transactions for each event+initial+final state combinations is now accounted. Latency histograms are only defined per event type (similarly to outTransLatHist). This significantly reduces the final file size for generated stats. Change-Id: I29aaeb771436cc3f0ce7547a223d58e71d9cedcc Signed-off-by: Tiago Mück --- .../slicc_interface/AbstractController.hh | 65 +++++++---- src/mem/slicc/symbols/StateMachine.py | 104 +++++++++++++----- 2 files changed, 123 insertions(+), 46 deletions(-) diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 7fdb88b07d..72b679d6cf 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017,2019-2022 ARM Limited + * Copyright (c) 2017,2019-2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -267,7 +267,7 @@ class AbstractController : public ClockedObject, public Consumer assert(m_inTrans.find(addr) == m_inTrans.end()); m_inTrans[addr] = {type, initialState, curTick()}; if (retried) - ++(*stats.inTransLatRetries[type]); + ++(*stats.inTransRetryCnt[type]); } /** @@ -288,11 +288,23 @@ class AbstractController : public ClockedObject, public Consumer isAddressed ? m_inTransAddressed : m_inTransUnaddressed; auto iter = m_inTrans.find(addr); assert(iter != m_inTrans.end()); - stats.inTransLatHist[iter->second.transaction] - [iter->second.state] - [(unsigned)finalState]->sample( - ticksToCycles(curTick() - iter->second.time)); - ++(*stats.inTransLatTotal[iter->second.transaction]); + auto &trans = iter->second; + + auto stat_iter_ev = stats.inTransStateChanges.find(trans.transaction); + gem5_assert(stat_iter_ev != stats.inTransStateChanges.end(), + "%s: event type=%d not marked as in_trans in SLICC", + name(), trans.transaction); + + auto stat_iter_state = stat_iter_ev->second.find(trans.state); + gem5_assert(stat_iter_state != stat_iter_ev->second.end(), + "%s: event type=%d has no transition from state=%d", + name(), trans.transaction, trans.state); + + ++(*stat_iter_state->second[(unsigned)finalState]); + + stats.inTransLatHist[iter->second.transaction]->sample( + ticksToCycles(curTick() - trans.time)); + m_inTrans.erase(iter); } @@ -334,10 +346,17 @@ class AbstractController : public ClockedObject, public Consumer isAddressed ? m_outTransAddressed : m_outTransUnaddressed; auto iter = m_outTrans.find(addr); assert(iter != m_outTrans.end()); - stats.outTransLatHist[iter->second.transaction]->sample( - ticksToCycles(curTick() - iter->second.time)); + auto &trans = iter->second; + + auto stat_iter = stats.outTransLatHist.find(trans.transaction); + gem5_assert(stat_iter != stats.outTransLatHist.end(), + "%s: event type=%d not marked as out_trans in SLICC", + name(), trans.transaction); + + stat_iter->second->sample( + ticksToCycles(curTick() - trans.time)); if (retried) - ++(*stats.outTransLatHistRetries[iter->second.transaction]); + ++(*stats.outTransRetryCnt[trans.transaction]); m_outTrans.erase(iter); } @@ -429,17 +448,25 @@ class AbstractController : public ClockedObject, public Consumer { ControllerStats(statistics::Group *parent); - // Initialized by the SLICC compiler for all combinations of event and - // states. Only histograms with samples will appear in the stats - std::vector>> - inTransLatHist; - std::vector inTransLatRetries; - std::vector inTransLatTotal; + // Initialized by the SLICC compiler for all events with the + // "in_trans" property. + // Only histograms with samples will appear in the stats + std::unordered_map inTransLatHist; + std::unordered_map inTransRetryCnt; + // Initialized by the SLICC compiler for all combinations of events + // with the "in_trans" property, potential initial states, and + // potential final states. Potential initial states are states that + // appear in transitions triggered by that event. Currently all states + // are considered as potential final states. + std::unordered_map>> inTransStateChanges; - // Initialized by the SLICC compiler for all events. + // Initialized by the SLICC compiler for all events with the + // "out_trans" property. // Only histograms with samples will appear in the stats. - std::vector outTransLatHist; - std::vector outTransLatHistRetries; + std::unordered_map outTransLatHist; + std::unordered_map + outTransRetryCnt; //! Counter for the number of cycles when the transitions carried out //! were equal to the maximum allowed diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 4712064089..039202a321 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 ARM Limited +# Copyright (c) 2019-2021,2023 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -111,8 +111,11 @@ class StateMachine(Symbol): self.actions = OrderedDict() self.request_types = OrderedDict() self.transitions = [] + self.transitions_per_ev = {} self.in_ports = [] self.functions = [] + self.event_stats_in_trans = [] + self.event_stats_out_trans = [] # Data members in the State Machine that have been declared inside # the {} machine. Note that these along with the config params @@ -136,6 +139,10 @@ class StateMachine(Symbol): def addEvent(self, event): assert self.table is None self.events[event.ident] = event + if "in_trans" in event.pairs: + self.event_stats_in_trans.append(event) + if "out_trans" in event.pairs: + self.event_stats_out_trans.append(event) def addAction(self, action): assert self.table is None @@ -163,6 +170,9 @@ class StateMachine(Symbol): def addTransition(self, trans): assert self.table is None self.transitions.append(trans) + if trans.event not in self.transitions_per_ev: + self.transitions_per_ev[trans.event] = [] + self.transitions_per_ev[trans.event].append(trans) def addInPort(self, var): self.in_ports.append(var) @@ -957,53 +967,93 @@ $c_ident::regStats() } } - for (${ident}_Event event = ${ident}_Event_FIRST; - event < ${ident}_Event_NUM; ++event) { +""" + ) + # check if Events/States have profiling qualifiers flags for + # inTransLatHist and outTransLatHist stats. + ev_ident_list = [ + "%s_Event_%s" % (ident, ev.ident) + for ev in self.event_stats_out_trans + ] + ev_ident_str = "{" + ",".join(ev_ident_list) + "}" + code( + """ + const std::vector<${ident}_Event> out_trans_evs = ${ev_ident_str}; +""" + ) + ev_ident_list = [ + "%s_Event_%s" % (ident, ev.ident) + for ev in self.event_stats_in_trans + ] + ev_ident_str = "{" + ",".join(ev_ident_list) + "}" + code( + """ + const std::vector<${ident}_Event> in_trans_evs = ${ev_ident_str}; +""" + ) + kv_ident_list = [] + for ev in self.event_stats_in_trans: + key_ident = "%s_Event_%s" % (ident, ev.ident) + val_ident_lst = [ + "%s_State_%s" % (ident, trans.state.ident) + for trans in self.transitions_per_ev[ev] + ] + val_ident_str = "{" + ",".join(val_ident_lst) + "}" + kv_ident_list.append("{%s, %s}" % (key_ident, val_ident_str)) + key_ident_str = "{" + ",".join(kv_ident_list) + "}" + code( + """ + const std::unordered_map<${ident}_Event, std::vector<${ident}_State>> + in_trans_evs_states = ${key_ident_str}; +""" + ) + code( + """ + + for (const auto event : out_trans_evs) { std::string stat_name = "outTransLatHist." + ${ident}_Event_to_string(event); statistics::Histogram* t = new statistics::Histogram(&stats, stat_name.c_str()); - stats.outTransLatHist.push_back(t); + stats.outTransLatHist[event] = t; t->init(5); t->flags(statistics::pdf | statistics::total | statistics::oneline | statistics::nozero); statistics::Scalar* r = new statistics::Scalar(&stats, (stat_name + ".retries").c_str()); - stats.outTransLatHistRetries.push_back(r); + stats.outTransRetryCnt[event] = r; r->flags(statistics::nozero); } - for (${ident}_Event event = ${ident}_Event_FIRST; - event < ${ident}_Event_NUM; ++event) { - std::string stat_name = "inTransLatHist." + - ${ident}_Event_to_string(event); + for (const auto event : in_trans_evs) { + std::string stat_name = + "inTransLatHist." + ${ident}_Event_to_string(event); + statistics::Histogram* t = + new statistics::Histogram(&stats, stat_name.c_str()); + stats.inTransLatHist[event] = t; + t->init(5); + t->flags(statistics::pdf | statistics::total | + statistics::oneline | statistics::nozero); + statistics::Scalar* r = new statistics::Scalar(&stats, - (stat_name + ".total").c_str()); - stats.inTransLatTotal.push_back(r); + (stat_name + ".retries").c_str()); + stats.inTransRetryCnt[event] = r; r->flags(statistics::nozero); - r = new statistics::Scalar(&stats, - (stat_name + ".retries").c_str()); - stats.inTransLatRetries.push_back(r); - r->flags(statistics::nozero); - - stats.inTransLatHist.emplace_back(); - for (${ident}_State initial_state = ${ident}_State_FIRST; - initial_state < ${ident}_State_NUM; ++initial_state) { - stats.inTransLatHist.back().emplace_back(); + auto &src_states = stats.inTransStateChanges[event]; + for (const auto initial_state : in_trans_evs_states.at(event)) { + auto &dst_vector = src_states[initial_state]; for (${ident}_State final_state = ${ident}_State_FIRST; final_state < ${ident}_State_NUM; ++final_state) { std::string stat_name = "inTransLatHist." + ${ident}_Event_to_string(event) + "." + ${ident}_State_to_string(initial_state) + "." + - ${ident}_State_to_string(final_state); - statistics::Histogram* t = - new statistics::Histogram(&stats, stat_name.c_str()); - stats.inTransLatHist.back().back().push_back(t); - t->init(5); - t->flags(statistics::pdf | statistics::total | - statistics::oneline | statistics::nozero); + ${ident}_State_to_string(final_state) + ".total"; + statistics::Scalar* t = + new statistics::Scalar(&stats, stat_name.c_str()); + t->flags(statistics::nozero); + dst_vector.push_back(t); } } } From 9584d2efa96db205c0168838c24defb11749ab1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Mon, 1 May 2023 18:53:44 -0500 Subject: [PATCH 228/693] mem-ruby: add in_trans/out_trans to CHI events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Marks which events signal the beginning of incoming and outgoing transactions for generating inTransLatHist and outTransLatHist stats. Change-Id: I90594a27fa01ef9cfface309971354b281308d22 Signed-off-by: Tiago Mück --- src/mem/ruby/protocol/chi/CHI-cache.sm | 106 +++++++++--------- .../ruby/protocol/chi/CHI-dvm-misc-node.sm | 6 +- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache.sm b/src/mem/ruby/protocol/chi/CHI-cache.sm index 3bd8d3f3c3..568b39c223 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -280,37 +280,37 @@ machine(MachineType:Cache, "Cache coherency protocol") : // Events triggered by sequencer requests or snoops in the rdy queue // See CHIRequestType in CHi-msg.sm for descriptions - Load, desc=""; - Store, desc=""; - Prefetch, desc=""; - ReadShared, desc=""; - ReadNotSharedDirty, desc=""; - ReadUnique, desc=""; - ReadUnique_PoC, desc=""; - ReadOnce, desc=""; - CleanUnique, desc=""; - Evict, desc=""; - WriteBackFull, desc=""; - WriteEvictFull, desc=""; - WriteCleanFull, desc=""; - WriteUnique, desc=""; - WriteUniquePtl_PoC, desc=""; - WriteUniqueFull_PoC, desc=""; - WriteUniqueFull_PoC_Alloc, desc=""; - SnpCleanInvalid, desc=""; - SnpShared, desc=""; - SnpSharedFwd, desc=""; - SnpNotSharedDirtyFwd, desc=""; - SnpUnique, desc=""; - SnpUniqueFwd, desc=""; - SnpOnce, desc=""; - SnpOnceFwd, desc=""; - SnpStalled, desc=""; // A snoop stall triggered from the inport + Load, desc="", in_trans="yes"; + Store, desc="", in_trans="yes"; + Prefetch, desc="", in_trans="yes"; + ReadShared, desc="", in_trans="yes"; + ReadNotSharedDirty, desc="", in_trans="yes"; + ReadUnique, desc="", in_trans="yes"; + ReadUnique_PoC, desc="", in_trans="yes"; + ReadOnce, desc="", in_trans="yes"; + CleanUnique, desc="", in_trans="yes"; + Evict, desc="", in_trans="yes"; + WriteBackFull, desc="", in_trans="yes"; + WriteEvictFull, desc="", in_trans="yes"; + WriteCleanFull, desc="", in_trans="yes"; + WriteUnique, desc="", in_trans="yes"; + WriteUniquePtl_PoC, desc="", in_trans="yes"; + WriteUniqueFull_PoC, desc="", in_trans="yes"; + WriteUniqueFull_PoC_Alloc, desc="", in_trans="yes"; + SnpCleanInvalid, desc="", in_trans="yes"; + SnpShared, desc="", in_trans="yes"; + SnpSharedFwd, desc="", in_trans="yes"; + SnpNotSharedDirtyFwd, desc="", in_trans="yes"; + SnpUnique, desc="", in_trans="yes"; + SnpUniqueFwd, desc="", in_trans="yes"; + SnpOnce, desc="", in_trans="yes"; + SnpOnceFwd, desc="", in_trans="yes"; + SnpStalled, desc="", in_trans="yes"; // A snoop stall triggered from the inport // DVM sequencer requests - DvmTlbi_Initiate, desc=""; // triggered when a CPU core wants to send a TLBI + DvmTlbi_Initiate, desc="", out_trans="yes", in_trans="yes"; // triggered when a CPU core wants to send a TLBI // TLBIs are handled entirely within Ruby, so there's no ExternCompleted message - DvmSync_Initiate, desc=""; // triggered when a CPU core wants to send a sync + DvmSync_Initiate, desc="", out_trans="yes", in_trans="yes"; // triggered when a CPU core wants to send a sync DvmSync_ExternCompleted, desc=""; // triggered when an externally requested Sync is completed // Events triggered by incoming response messages @@ -344,10 +344,10 @@ machine(MachineType:Cache, "Cache coherency protocol") : PCrdGrant_PoC_Hazard, desc=""; // Events triggered by incoming DVM messages - SnpDvmOpSync_P1, desc=""; - SnpDvmOpSync_P2, desc=""; - SnpDvmOpNonSync_P1, desc=""; - SnpDvmOpNonSync_P2, desc=""; + SnpDvmOpSync_P1, desc="", in_trans="yes"; + SnpDvmOpSync_P2, desc="", in_trans="yes"; + SnpDvmOpNonSync_P1, desc="", in_trans="yes"; + SnpDvmOpNonSync_P2, desc="", in_trans="yes"; // Events triggered by incoming data response messages // See CHIDataType in CHi-msg.sm for descriptions @@ -383,20 +383,20 @@ machine(MachineType:Cache, "Cache coherency protocol") : // A Write or Evict becomes stale when the requester receives a snoop that // changes the state of the data while the request was pending. // Actual CHI implementations don't have this check. - Evict_Stale, desc=""; - WriteBackFull_Stale, desc=""; - WriteEvictFull_Stale, desc=""; - WriteCleanFull_Stale, desc=""; - CleanUnique_Stale, desc=""; + Evict_Stale, desc="", in_trans="yes"; + WriteBackFull_Stale, desc="", in_trans="yes"; + WriteEvictFull_Stale, desc="", in_trans="yes"; + WriteCleanFull_Stale, desc="", in_trans="yes"; + CleanUnique_Stale, desc="", in_trans="yes"; // Cache fill handling CheckCacheFill, desc="Check if need to write or update the cache and trigger any necessary allocation and evictions"; // Internal requests generated to evict or writeback a local copy // to free-up cache space - Local_Eviction, desc="Evicts/WB the local copy of the line"; - LocalHN_Eviction, desc="Local_Eviction triggered when is HN"; - Global_Eviction, desc="Local_Eviction + back-invalidate line in all upstream requesters"; + Local_Eviction, in_trans="yes", desc="Evicts/WB the local copy of the line"; + LocalHN_Eviction, in_trans="yes", desc="Local_Eviction triggered when is HN"; + Global_Eviction, in_trans="yes", desc="Local_Eviction + back-invalidate line in all upstream requesters"; // Events triggered from tbe.actions // In general, for each event we define a single transition from @@ -425,11 +425,11 @@ machine(MachineType:Cache, "Cache coherency protocol") : SnpOncePipe, desc="Latency for SnpOnce requests"; // Send a read request downstream. - SendReadShared, desc="Send a ReadShared or ReadNotSharedDirty is allow_SD is false"; - SendReadOnce, desc="Send a ReadOnce"; - SendReadNoSnp, desc="Send a SendReadNoSnp"; - SendReadNoSnpDMT, desc="Send a SendReadNoSnp using DMT"; - SendReadUnique, desc="Send a ReadUnique"; + SendReadShared, out_trans="yes", desc="Send a ReadShared or ReadNotSharedDirty is allow_SD is false"; + SendReadOnce, out_trans="yes", desc="Send a ReadOnce"; + SendReadNoSnp, out_trans="yes", desc="Send a SendReadNoSnp"; + SendReadNoSnpDMT, out_trans="yes", desc="Send a SendReadNoSnp using DMT"; + SendReadUnique, out_trans="yes", desc="Send a ReadUnique"; SendCompAck, desc="Send CompAck"; // Read handling at the completer SendCompData, desc="Send CompData"; @@ -437,11 +437,11 @@ machine(MachineType:Cache, "Cache coherency protocol") : SendRespSepData, desc="Send RespSepData for a DMT request"; // Send a write request downstream. - SendWriteBackOrWriteEvict, desc="Send a WriteBackFull (if line is UD or SD) or WriteEvictFull (if UC)"; - SendWriteClean, desc="Send a WriteCleanFull"; - SendWriteNoSnp, desc="Send a WriteNoSnp for a full line"; - SendWriteNoSnpPartial, desc="Send a WriteNoSnpPtl"; - SendWriteUnique, desc="Send a WriteUniquePtl"; + SendWriteBackOrWriteEvict, out_trans="yes", desc="Send a WriteBackFull (if line is UD or SD) or WriteEvictFull (if UC)"; + SendWriteClean, out_trans="yes", desc="Send a WriteCleanFull"; + SendWriteNoSnp, out_trans="yes", desc="Send a WriteNoSnp for a full line"; + SendWriteNoSnpPartial, out_trans="yes", desc="Send a WriteNoSnpPtl"; + SendWriteUnique, out_trans="yes", desc="Send a WriteUniquePtl"; SendWBData, desc="Send writeback data"; SendWUData, desc="Send write unique data"; SendWUDataCB, desc="Send write unique data from a sequencer callback"; @@ -453,9 +453,9 @@ machine(MachineType:Cache, "Cache coherency protocol") : SendComp_WU, desc="Ack WU completion"; // Dataless requests - SendEvict, desc="Send a Evict"; + SendEvict, out_trans="yes", desc="Send a Evict"; SendCompIResp, desc="Ack Evict with Comp_I"; - SendCleanUnique,desc="Send a CleanUnique"; + SendCleanUnique,out_trans="yes", desc="Send a CleanUnique"; SendCompUCResp, desc="Ack CleanUnique with Comp_UC"; SendCompUCRespStale, desc="Ack stale CleanUnique with Comp_UC"; diff --git a/src/mem/ruby/protocol/chi/CHI-dvm-misc-node.sm b/src/mem/ruby/protocol/chi/CHI-dvm-misc-node.sm index 92a04ed3d2..aa27c40964 100644 --- a/src/mem/ruby/protocol/chi/CHI-dvm-misc-node.sm +++ b/src/mem/ruby/protocol/chi/CHI-dvm-misc-node.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -170,8 +170,8 @@ machine(MachineType:MiscNode, "CHI Misc Node for handling and distrbuting DVM op SendPCrdGrant, desc="Send PCrdGrant"; DoRetry, desc="Resend the current pending request"; - DvmTlbi_Initiate, desc="Initiate a DVM TLBI on the provided TBE"; - DvmSync_Initiate, desc="Initiate a DVM Sync on the provided TBE"; + DvmTlbi_Initiate, out_trans="yes", in_trans="yes", desc="Initiate a DVM TLBI on the provided TBE"; + DvmSync_Initiate, out_trans="yes", in_trans="yes", desc="Initiate a DVM Sync on the provided TBE"; DvmSendNextMessage_P1, desc="Trigger a SnpDvmOp_P1 message based on the TBE type"; DvmSendNextMessage_P2, desc="Trigger a SnpDvmOp_P2 message based on the TBE type"; DvmFinishDistributing, desc="Move the TBE out of the Distributing state into Waiting"; From b2d40edc62d44bdf1b340f1648bba9ec0dd0203a Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 23 Aug 2023 17:06:34 -0700 Subject: [PATCH 229/693] misc: Move compiler tests to run on 'build' runners This is an experiment. The runners were sometimes running out of memory building gem5. The builders have more memory to handle this. The runners have 4-cores so compilation should be faster (note the inclusion of the `-j$(nproc)`. Change-Id: I964c5a778938b449502d92dec3431f8b788397e4 --- .github/workflows/compiler-tests.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 39367ab898..9a567653f5 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -19,7 +19,7 @@ jobs: matrix: image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64, build] timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: @@ -29,7 +29,7 @@ jobs: # therefore need to explicitly checkout the develop branch. ref: develop - name: Compile build/ALL/gem5${{ matrix.opts }} with ${{ matrix.image }} - run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/ALL/gem5${{ matrix.opts }} + run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/ALL/gem5${{ matrix.opts }} -j$(nproc) timeout-minutes: 600 # 10 hours # Tests the two latest gcc and clang supported compilers against all gem5 compilations. @@ -40,7 +40,7 @@ jobs: gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, GCN3_X86] image: [gcc-version-12, clang-version-14] opts: [.opt] - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64, build] timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: @@ -50,5 +50,5 @@ jobs: # therefore need to explicitly checkout the develop branch. ref: develop - name: Compile build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} with ${{ matrix.image }} - run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} + run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} -j$(nproc) timeout-minutes: 600 # 10 hours From 90a518e885dba14f6e6f0101ae5d354caa8e8741 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 23 Aug 2023 19:21:55 -0500 Subject: [PATCH 230/693] gpu-compute,arch-vega: Fix ALU-only LDS counters There are a few LDS instructions that perform local ALU operations and writeback which are marked as loads. These are marked as loads because they fit in the pipeline logic better, according to a several year old comment. In the VEGA ISA these instructions (swizzle, permute, bpermute) are not decrementing the LDS load counter. As a result, the counter will gradually increase over time. Since wavefront slots are persistent, this can cause applications with a few thousand kernels to eventually hang thinking there are not enough resources. This changeset fixes this by decrementing the LDS load counter for these instructions. This fix was already integrated in the GCN3 ISA in the exact same way. This changeset moves it near a similar comment about scheduling register file writes. Change-Id: Ife5237a2cae7213948c32ef266f4f8f22917351c --- src/arch/amdgpu/vega/insts/instructions.cc | 15 +++++++++++++++ src/gpu-compute/compute_unit.cc | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index ab9c1cecf2..b0f8c908ed 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -35971,6 +35971,11 @@ namespace VegaISA */ wf->computeUnit->vrf[wf->simdId]-> scheduleWriteOperandsFromLoad(wf, gpuDynInst); + /** + * Similarly, this counter could build up over time, even across + * multiple wavefronts, and cause a deadlock. + */ + wf->rdLmReqsInPipe--; } // execute // --- Inst_DS__DS_PERMUTE_B32 class methods --- @@ -36054,6 +36059,11 @@ namespace VegaISA */ wf->computeUnit->vrf[wf->simdId]-> scheduleWriteOperandsFromLoad(wf, gpuDynInst); + /** + * Similarly, this counter could build up over time, even across + * multiple wavefronts, and cause a deadlock. + */ + wf->rdLmReqsInPipe--; } // execute // --- Inst_DS__DS_BPERMUTE_B32 class methods --- @@ -36137,6 +36147,11 @@ namespace VegaISA */ wf->computeUnit->vrf[wf->simdId]-> scheduleWriteOperandsFromLoad(wf, gpuDynInst); + /** + * Similarly, this counter could build up over time, even across + * multiple wavefronts, and cause a deadlock. + */ + wf->rdLmReqsInPipe--; } // execute // --- Inst_DS__DS_ADD_U64 class methods --- diff --git a/src/gpu-compute/compute_unit.cc b/src/gpu-compute/compute_unit.cc index 06fe28f5b8..ea903455d5 100644 --- a/src/gpu-compute/compute_unit.cc +++ b/src/gpu-compute/compute_unit.cc @@ -383,6 +383,13 @@ ComputeUnit::startWavefront(Wavefront *w, int waveId, LdsChunk *ldsChunk, stats.waveLevelParallelism.sample(activeWaves); activeWaves++; + + panic_if(w->wrGmReqsInPipe, "GM write counter for wavefront non-zero\n"); + panic_if(w->rdGmReqsInPipe, "GM read counter for wavefront non-zero\n"); + panic_if(w->wrLmReqsInPipe, "LM write counter for wavefront non-zero\n"); + panic_if(w->rdLmReqsInPipe, "GM read counter for wavefront non-zero\n"); + panic_if(w->outstandingReqs, + "Outstanding reqs counter for wavefront non-zero\n"); } /** From 8b4c38302f09a95e0c42a1524bf9c7dede081a83 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 23 Aug 2023 13:20:42 -0500 Subject: [PATCH 231/693] dev: PCI: Fix PCI express capability union The capabilities for PCI express is a struct, instead of a union, like the other capability unions. A union is used here to provide access to the ordinal data values when reading/writing an offset while simultaneously providing human readable field values that can be set when writing the code. This commit changes it to union which is likely should be. Nothing appears to be using this union yet so it is likely an oversight. Change-Id: I85fe7cc62914525c70fd7a5946d725ed308f8775 --- src/dev/pci/pcireg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/pci/pcireg.h b/src/dev/pci/pcireg.h index ab5fea540c..e7794e4dc2 100644 --- a/src/dev/pci/pcireg.h +++ b/src/dev/pci/pcireg.h @@ -326,7 +326,7 @@ struct MSIXPbaEntry * Defines the PCI Express capability register and its associated bitfields * for a PCIe device. */ -struct PXCAP +union PXCAP { uint8_t data[48]; struct From 5c28113a06de5d220e775dfeeef643dd9fb90725 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 16 Aug 2023 18:06:31 +0800 Subject: [PATCH 232/693] cpu-minor: Separate the reg_index of VecClassReg and VecElemReg In the RISC-V system, we need to VecClassReg to run RISC-V vector instruction, and VecElemReg is not applicable because the element length of vector can be resizable via vset*vl* instruction. The change will seperate the reg_index for VecReg and VecElemReg to ensure that have the space for VecReg when VecElemReg is not applicable. Change-Id: I99a82dec273baeee31df89a0ee0f5e87f3ff187c --- src/cpu/minor/scoreboard.cc | 5 ++++- src/cpu/minor/scoreboard.hh | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cpu/minor/scoreboard.cc b/src/cpu/minor/scoreboard.cc index 475d650d3a..25228c1ef5 100644 --- a/src/cpu/minor/scoreboard.cc +++ b/src/cpu/minor/scoreboard.cc @@ -62,10 +62,13 @@ Scoreboard::findIndex(const RegId& reg, Index &scoreboard_index) ret = true; break; case VecRegClass: - case VecElemClass: scoreboard_index = vecRegOffset + reg.index(); ret = true; break; + case VecElemClass: + scoreboard_index = vecRegElemOffset + reg.index(); + ret = true; + break; case VecPredRegClass: scoreboard_index = vecPredRegOffset + reg.index(); ret = true; diff --git a/src/cpu/minor/scoreboard.hh b/src/cpu/minor/scoreboard.hh index d3df324b99..dd42bc6f67 100644 --- a/src/cpu/minor/scoreboard.hh +++ b/src/cpu/minor/scoreboard.hh @@ -71,6 +71,7 @@ class Scoreboard : public Named const unsigned floatRegOffset; const unsigned ccRegOffset; const unsigned vecRegOffset; + const unsigned vecRegElemOffset; const unsigned vecPredRegOffset; const unsigned matRegOffset; @@ -115,7 +116,8 @@ class Scoreboard : public Named floatRegOffset(intRegOffset + reg_classes.at(IntRegClass)->numRegs()), ccRegOffset(floatRegOffset + reg_classes.at(FloatRegClass)->numRegs()), vecRegOffset(ccRegOffset + reg_classes.at(CCRegClass)->numRegs()), - vecPredRegOffset(vecRegOffset + + vecRegElemOffset(vecRegOffset + reg_classes.at(VecRegClass)->numRegs()), + vecPredRegOffset(vecRegElemOffset + reg_classes.at(VecElemClass)->numRegs()), matRegOffset(vecPredRegOffset + reg_classes.at(VecPredRegClass)->numRegs()), From addba01d294a5ea14b9b703ab830e3420db26915 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 23 Aug 2023 13:23:58 -0500 Subject: [PATCH 233/693] configs,dev-amdgpu: Add PCI express capability info The ROCm stack requires PCI express atomics. Currently the first PCI CapabilityPtr does not point to anything, which signals to the OS (Linux) that this is an early generation PCI device. As PCI express atomics were introduced later, the CapabilityPtr needs to point to at least a PCI express capability structure. This capability is defined as 0x10 in Linux. We additionally set the PCI atomic based bits and implement device specific PCI configuration space reads and writes to the amdgpu device. With this commit, the output of simulation when loading the amdgpu driver no longer outputs "PCIE atomics not supported". Further, an application which uses PCIe atomics (PyTorch with a reduce_sum kernel) now makes further progress. Change-Id: I5e3866979659a2657f558941106ef65c2f4d9988 --- configs/example/gpufs/system/amdgpu.py | 23 +++++++++ src/dev/amdgpu/amdgpu_device.cc | 67 +++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/configs/example/gpufs/system/amdgpu.py b/configs/example/gpufs/system/amdgpu.py index 9697e50a04..450a00bf93 100644 --- a/configs/example/gpufs/system/amdgpu.py +++ b/configs/example/gpufs/system/amdgpu.py @@ -185,3 +185,26 @@ def connectGPU(system, args): system.pc.south_bridge.gpu.DeviceID = 0x6863 else: panic("Unknown GPU device: {}".format(args.gpu_device)) + + # Use the gem5 default of 0x280 OR'd with 0x10 which tells Linux there is + # a PCI capabilities list to travse. + system.pc.south_bridge.gpu.Status = 0x0290 + + # The PCI capabilities are like a linked list. The list has a memory + # offset and a capability type ID read by the OS. Make the first + # capability at 0x80 and set the PXCAP (PCI express) capability to + # that address. Mark the type ID as PCI express. + # We leave the next ID of PXCAP blank to end the list. + system.pc.south_bridge.gpu.PXCAPBaseOffset = 0x80 + system.pc.south_bridge.gpu.CapabilityPtr = 0x80 + system.pc.south_bridge.gpu.PXCAPCapId = 0x10 + + # Set bits 7 and 8 in the second PCIe device capabilities register which + # reports support for PCIe atomics for 32 and 64 bits respectively. + # Bit 9 for 128-bit compare and swap is not set because the amdgpu driver + # does not check this. + system.pc.south_bridge.gpu.PXCAPDevCap2 = 0x00000180 + + # Set bit 6 to enable atomic requestor, meaning this device can request + # atomics from other PCI devices. + system.pc.south_bridge.gpu.PXCAPDevCtrl2 = 0x00000040 diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc index 44a1c9d394..5cc8df424f 100644 --- a/src/dev/amdgpu/amdgpu_device.cc +++ b/src/dev/amdgpu/amdgpu_device.cc @@ -216,11 +216,47 @@ AMDGPUDevice::getAddrRanges() const Tick AMDGPUDevice::readConfig(PacketPtr pkt) { - [[maybe_unused]] int offset = pkt->getAddr() & PCI_CONFIG_SIZE; - DPRINTF(AMDGPUDevice, "Read Config: from offset: %#x size: %#x " - "data: %#x\n", offset, pkt->getSize(), config.data[offset]); + int offset = pkt->getAddr() & PCI_CONFIG_SIZE; - Tick delay = PciDevice::readConfig(pkt); + if (offset < PCI_DEVICE_SPECIFIC) { + PciDevice::readConfig(pkt); + } else { + if (offset >= PXCAP_BASE && offset < (PXCAP_BASE + sizeof(PXCAP))) { + int pxcap_offset = offset - PXCAP_BASE; + + switch (pkt->getSize()) { + case sizeof(uint8_t): + pkt->setLE(pxcap.data[pxcap_offset]); + DPRINTF(AMDGPUDevice, + "Read PXCAP: dev %#x func %#x reg %#x 1 bytes: data " + "= %#x\n", _busAddr.dev, _busAddr.func, pxcap_offset, + (uint32_t)pkt->getLE()); + break; + case sizeof(uint16_t): + pkt->setLE( + *(uint16_t*)&pxcap.data[pxcap_offset]); + DPRINTF(AMDGPUDevice, + "Read PXCAP: dev %#x func %#x reg %#x 2 bytes: data " + "= %#x\n", _busAddr.dev, _busAddr.func, pxcap_offset, + (uint32_t)pkt->getLE()); + break; + case sizeof(uint32_t): + pkt->setLE( + *(uint32_t*)&pxcap.data[pxcap_offset]); + DPRINTF(AMDGPUDevice, + "Read PXCAP: dev %#x func %#x reg %#x 4 bytes: data " + "= %#x\n",_busAddr.dev, _busAddr.func, pxcap_offset, + (uint32_t)pkt->getLE()); + break; + default: + panic("Invalid access size (%d) for amdgpu PXCAP %#x\n", + pkt->getSize(), pxcap_offset); + } + pkt->makeAtomicResponse(); + } else { + warn("Device specific offset %d not implemented!\n", offset); + } + } // Before sending MMIOs the driver sends three interrupts in a row. // Use this to trigger creating a checkpoint to restore in timing mode. @@ -231,14 +267,14 @@ AMDGPUDevice::readConfig(PacketPtr pkt) if (offset == PCI0_INTERRUPT_PIN) { if (++init_interrupt_count == 3) { DPRINTF(AMDGPUDevice, "Checkpointing before first MMIO\n"); - exitSimLoop("checkpoint", 0, curTick() + delay + 1); + exitSimLoop("checkpoint", 0, curTick() + configDelay + 1); } } else { init_interrupt_count = 0; } } - return delay; + return configDelay; } Tick @@ -249,7 +285,24 @@ AMDGPUDevice::writeConfig(PacketPtr pkt) "data: %#x\n", offset, pkt->getSize(), pkt->getUintX(ByteOrder::little)); - return PciDevice::writeConfig(pkt); + if (offset < PCI_DEVICE_SPECIFIC) + return PciDevice::writeConfig(pkt); + + + if (offset >= PXCAP_BASE && offset < (PXCAP_BASE + sizeof(PXCAP))) { + uint8_t *pxcap_data = &(pxcap.data[0]); + int pxcap_offset = offset - PXCAP_BASE; + + DPRINTF(AMDGPUDevice, "Writing PXCAP offset %d size %d\n", + pxcap_offset, pkt->getSize()); + + memcpy(pxcap_data + pxcap_offset, pkt->getConstPtr(), + pkt->getSize()); + } + + pkt->makeAtomicResponse(); + + return configDelay; } void From d640c17f758b8f5221c7dff822e1e90820c9914c Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 25 Aug 2023 10:27:08 -0700 Subject: [PATCH 234/693] misc: Update CI tests to not run on draft PRs This updates all the jobs for our CI tests to make sure they don't run tests on draft pull request, and only trigger when ready for review Change-Id: I3fe7ae373c39fc6ef594c0c71c6f10e7319553d8 --- .github/workflows/ci-tests.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 2fb5910d44..8def494668 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -11,6 +11,7 @@ jobs: pre-commit: # runs on github hosted runner runs-on: ubuntu-22.04 + if: github.event.pull_request.draft == false steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v3 @@ -20,6 +21,7 @@ jobs: check-for-change-id: # runs on github hosted runner runs-on: ubuntu-22.04 + if: github.event.pull_request.draft == false steps: - uses: actions/checkout@v3 with: @@ -43,6 +45,7 @@ jobs: build-gem5: runs-on: [self-hosted, linux, x64, build] + if: github.event.pull_request.draft == false container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes outputs: @@ -63,6 +66,7 @@ jobs: unittests-all-opt: runs-on: [self-hosted, linux, x64, run] + if: github.event.pull_request.draft == false container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes timeout-minutes: 60 @@ -75,6 +79,7 @@ jobs: testlib-quick: runs-on: [self-hosted, linux, x64, run] + if: github.event.pull_request.draft == false container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, build-gem5, check-for-change-id] timeout-minutes: 360 # 6 hours From 57b3d2897c77d0907016ee972655c7bbcdfe23e7 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 25 Aug 2023 09:35:55 -0500 Subject: [PATCH 235/693] gpu-compute: Use timing DMAs for GPUFS HSA signals The functional HSA signal read was a hack left in the gpu-compute code. In full system, this functional read is causing problems occasionally with the translation not yet being in the page table. The error message output by gem5 was a fatal message on the readBlob method in port proxy. Changing this to a timing DMA fixes this problem. This commit adds the various timing DMA functions to send and receive response and clean up. A helper method "sendCompletionSignal" is added to the GPUCommandProcessor because the indentation level was getting too deep. This change applies only to FS mode. Code for SE mode is equivalent to what it was before this commit. Change-Id: I1bfcaa0a52731cdf9532a7fd0eb06ab2f0e09d48 --- src/dev/hsa/hsa_packet_processor.cc | 16 ++-- src/gpu-compute/dispatcher.cc | 12 +-- src/gpu-compute/gpu_command_processor.cc | 104 +++++++++++++++++++++++ src/gpu-compute/gpu_command_processor.hh | 7 ++ 4 files changed, 118 insertions(+), 21 deletions(-) diff --git a/src/dev/hsa/hsa_packet_processor.cc b/src/dev/hsa/hsa_packet_processor.cc index d0afcf816f..2064de41ce 100644 --- a/src/dev/hsa/hsa_packet_processor.cc +++ b/src/dev/hsa/hsa_packet_processor.cc @@ -389,20 +389,16 @@ HSAPacketProcessor::processPkt(void* pkt, uint32_t rl_idx, Addr host_pkt_addr) dep_sgnl_rd_st->resetSigVals(); // The completion signal is connected if (bar_and_pkt->completion_signal != 0) { - // HACK: The semantics of the HSA signal is to - // decrement the current signal value - // I'm going to cheat here and read out - // the value from main memory using functional - // access, and then just DMA the decremented value. - uint64_t signal_value = gpu_device->functionalReadHsaSignal(\ - bar_and_pkt->completion_signal); - + // The semantics of the HSA signal is to decrement the current + // signal value by one. Do this asynchronously via DMAs and + // callbacks as we can safely continue with this function + // while waiting for the next packet from the host. DPRINTF(HSAPacketProcessor, "Triggering barrier packet" \ " completion signal! Addr: %x\n", bar_and_pkt->completion_signal); - gpu_device->updateHsaSignal(bar_and_pkt->completion_signal, - signal_value - 1); + gpu_device->sendCompletionSignal( + bar_and_pkt->completion_signal); } } if (dep_sgnl_rd_st->pendingReads > 0) { diff --git a/src/gpu-compute/dispatcher.cc b/src/gpu-compute/dispatcher.cc index babc938489..8a72fd73f4 100644 --- a/src/gpu-compute/dispatcher.cc +++ b/src/gpu-compute/dispatcher.cc @@ -310,20 +310,10 @@ GPUDispatcher::notifyWgCompl(Wavefront *wf) gpuCmdProc->hsaPacketProc() .finishPkt(task->dispPktPtr(), task->queueId()); if (task->completionSignal()) { - /** - * HACK: The semantics of the HSA signal is to decrement - * the current signal value. We cheat here and read out - * he value from main memory using functional access and - * then just DMA the decremented value. - */ - uint64_t signal_value = - gpuCmdProc->functionalReadHsaSignal(task->completionSignal()); - DPRINTF(GPUDisp, "HSA AQL Kernel Complete with completion " "signal! Addr: %d\n", task->completionSignal()); - gpuCmdProc->updateHsaSignal(task->completionSignal(), - signal_value - 1); + gpuCmdProc->sendCompletionSignal(task->completionSignal()); } else { DPRINTF(GPUDisp, "HSA AQL Kernel Complete! No completion " "signal\n"); diff --git a/src/gpu-compute/gpu_command_processor.cc b/src/gpu-compute/gpu_command_processor.cc index 8f748bdc31..db69ad5cbd 100644 --- a/src/gpu-compute/gpu_command_processor.cc +++ b/src/gpu-compute/gpu_command_processor.cc @@ -250,6 +250,110 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, ++dynamic_task_id; } +void +GPUCommandProcessor::sendCompletionSignal(Addr signal_handle) +{ + // Originally the completion signal was read functionally and written + // with a timing DMA. This can cause issues in FullSystem mode and + // cause translation failures. Therefore, in FullSystem mode everything + // is done in timing mode. + + if (!FullSystem) { + /** + * HACK: The semantics of the HSA signal is to decrement + * the current signal value. We cheat here and read out + * he value from main memory using functional access and + * then just DMA the decremented value. + */ + uint64_t signal_value = functionalReadHsaSignal(signal_handle); + + updateHsaSignal(signal_handle, signal_value - 1); + } else { + // The semantics of the HSA signal is to decrement the current + // signal value by one. Do this asynchronously via DMAs and + // callbacks as we can safely continue with this function + // while waiting for the next packet from the host. + updateHsaSignalAsync(signal_handle, -1); + } +} + +void +GPUCommandProcessor::updateHsaSignalAsync(Addr signal_handle, int64_t diff) +{ + Addr value_addr = getHsaSignalValueAddr(signal_handle); + + uint64_t *signalValue = new uint64_t; + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaSignalData(value_addr, diff, signalValue); }); + dmaReadVirt(value_addr, sizeof(uint64_t), cb, (void *)signalValue); + DPRINTF(GPUCommandProc, "updateHsaSignalAsync reading value addr %lx\n", + value_addr); + + Addr mailbox_addr = getHsaSignalMailboxAddr(signal_handle); + uint64_t *mailboxValue = new uint64_t; + auto cb2 = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaMailboxData(signal_handle, mailboxValue); }); + dmaReadVirt(mailbox_addr, sizeof(uint64_t), cb2, (void *)mailboxValue); + DPRINTF(GPUCommandProc, "updateHsaSignalAsync reading mailbox addr %lx\n", + mailbox_addr); +} + +void +GPUCommandProcessor::updateHsaSignalData(Addr value_addr, int64_t diff, + uint64_t *prev_value) +{ + // Reuse the value allocated for the read + DPRINTF(GPUCommandProc, "updateHsaSignalData read %ld, writing %ld\n", + *prev_value, *prev_value + diff); + *prev_value += diff; + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaSignalDone(prev_value); }); + dmaWriteVirt(value_addr, sizeof(uint64_t), cb, (void *)prev_value); +} + +void +GPUCommandProcessor::updateHsaMailboxData(Addr signal_handle, + uint64_t *mailbox_value) +{ + Addr event_addr = getHsaSignalEventAddr(signal_handle); + + DPRINTF(GPUCommandProc, "updateHsaMailboxData read %ld\n", *mailbox_value); + if (*mailbox_value != 0) { + // This is an interruptible signal. Now, read the + // event ID and directly communicate with the driver + // about that event notification. + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaEventData(signal_handle, mailbox_value); }); + dmaReadVirt(event_addr, sizeof(uint64_t), cb, (void *)mailbox_value); + } else { + delete mailbox_value; + } +} + +void +GPUCommandProcessor::updateHsaEventData(Addr signal_handle, + uint64_t *event_value) +{ + Addr mailbox_addr = getHsaSignalMailboxAddr(signal_handle); + + DPRINTF(GPUCommandProc, "updateHsaEventData read %ld\n", *event_value); + // Write *event_value to the mailbox to clear the event + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaSignalDone(event_value); }, *event_value); + dmaWriteVirt(mailbox_addr, sizeof(uint64_t), cb, &cb->dmaBuffer, 0); +} + +void +GPUCommandProcessor::updateHsaSignalDone(uint64_t *signal_value) +{ + delete signal_value; +} + uint64_t GPUCommandProcessor::functionalReadHsaSignal(Addr signal_handle) { diff --git a/src/gpu-compute/gpu_command_processor.hh b/src/gpu-compute/gpu_command_processor.hh index bafe733ee1..d2ddf5c78f 100644 --- a/src/gpu-compute/gpu_command_processor.hh +++ b/src/gpu-compute/gpu_command_processor.hh @@ -106,9 +106,16 @@ class GPUCommandProcessor : public DmaVirtDevice AddrRangeList getAddrRanges() const override; System *system(); + void sendCompletionSignal(Addr signal_handle); void updateHsaSignal(Addr signal_handle, uint64_t signal_value, HsaSignalCallbackFunction function = [] (const uint64_t &) { }); + void updateHsaSignalAsync(Addr signal_handle, int64_t diff); + void updateHsaSignalData(Addr value_addr, int64_t diff, + uint64_t *prev_value); + void updateHsaSignalDone(uint64_t *signal_value); + void updateHsaMailboxData(Addr signal_handle, uint64_t *mailbox_value); + void updateHsaEventData(Addr signal_handle, uint64_t *event_value); uint64_t functionalReadHsaSignal(Addr signal_handle); From e0379f45262fc582793ed29e88bd6d69a8241196 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sat, 26 Aug 2023 13:06:54 -0500 Subject: [PATCH 236/693] gpu-compute: Fix flat scratch resource counters Flat instructions may access memory locations in LDS (scratchpad) and global (VRAM/framebuffer) and therefore increment both counters when dispatched. Once the aperture is known, we decrement the counters of the aperture that was *not* used. This is done incorrectly for scratch / private flat instruction. Private memory is global and therefore local memory counters should be decremented. This commit fixes the counters by changing the global decrements to local decrements. Change-Id: I25890446908df72e5469e9dbaba6c984955196cf --- src/gpu-compute/gpu_dyn_inst.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gpu-compute/gpu_dyn_inst.cc b/src/gpu-compute/gpu_dyn_inst.cc index 3cbb6f1ff8..991ba2c07a 100644 --- a/src/gpu-compute/gpu_dyn_inst.cc +++ b/src/gpu-compute/gpu_dyn_inst.cc @@ -919,12 +919,12 @@ GPUDynInst::resolveFlatSegment(const VectorMask &mask) wavefront()->execUnitId = wavefront()->flatLmUnitId; wavefront()->decLGKMInstsIssued(); if (isLoad()) { - wavefront()->rdGmReqsInPipe--; + wavefront()->rdLmReqsInPipe--; } else if (isStore()) { - wavefront()->wrGmReqsInPipe--; + wavefront()->wrLmReqsInPipe--; } else if (isAtomic() || isMemSync()) { - wavefront()->rdGmReqsInPipe--; - wavefront()->wrGmReqsInPipe--; + wavefront()->wrLmReqsInPipe--; + wavefront()->rdLmReqsInPipe--; } else { panic("Invalid memory operation!\n"); } From 4506188e003c7f67e1323f1330da239f22441da7 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sat, 26 Aug 2023 13:09:28 -0500 Subject: [PATCH 237/693] gpu-compute: Fix private offset/size register indexes According to the ABI documentation from LLVM, the *low* register of flat scratch (maxSGPR - 4) is the offset and the high register (maxSGPR - 3) is size. These are currently backwards, resulting in some gnarly addresses being generated leading to page fault and/or incorrect data. This commit fixes this by setting the order correctly. Change-Id: I0b1d077c49c0ee2a4e59b0f6d85cdb8f17f9be61 --- src/gpu-compute/gpu_dyn_inst.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gpu-compute/gpu_dyn_inst.cc b/src/gpu-compute/gpu_dyn_inst.cc index 991ba2c07a..8dfae1dc90 100644 --- a/src/gpu-compute/gpu_dyn_inst.cc +++ b/src/gpu-compute/gpu_dyn_inst.cc @@ -901,12 +901,12 @@ GPUDynInst::resolveFlatSegment(const VectorMask &mask) uint32_t numSgprs = wavefront()->maxSgprs; uint32_t physSgprIdx = wavefront()->computeUnit->registerManager->mapSgpr(wavefront(), - numSgprs - 3); + numSgprs - 4); uint32_t offset = wavefront()->computeUnit->srf[simdId]->read(physSgprIdx); physSgprIdx = wavefront()->computeUnit->registerManager->mapSgpr(wavefront(), - numSgprs - 4); + numSgprs - 3); uint32_t size = wavefront()->computeUnit->srf[simdId]->read(physSgprIdx); for (int lane = 0; lane < wavefront()->computeUnit->wfSize(); ++lane) { From 60f071d09a03ced31c2f1c7496222b3007a33bae Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sat, 26 Aug 2023 13:14:13 -0500 Subject: [PATCH 238/693] gpu-compute,arch-vega: Implement flat scratch insts Flat scratch instructions (aka private) are the 3rd and final segment of flat instructions in gfx9 (Vega) and beyond. These are used for things like spills/fills and thread local storage. This commit enables two forms of flat scratch instructions: (1) flat_load/flat_store instructions where the memory address resolves to private memory and (2) the new scratch_load/scratch_store instructions in Vega. The first are similar to older generation ISAs where the aperture is unknown until address translation. The second are instructions guaranteed to go to private memory. Since these are very similar to flat global instructions there are minimal changes needed: - Ensure a flat instruction is either regular flat, global, XOR scratch - Rename the global op_encoding methods to GlobalScratch to indicate they are for both and are intentionally used. - Flat instructions in segment 1 output scratch_ in the disassembly - Flat instruction executed as private use similar mem helpers as global - Flat scratch cannot be an atomic This was tested using a modified version of the 'square' application: template __global__ void scratch_square(T *C_d, T *A_d, size_t N) { size_t offset = (blockIdx.x * blockDim.x + threadIdx.x); size_t stride = blockDim.x * gridDim.x ; volatile int foo; // Volatile ensures scratch / unoptimized code for (size_t i=offset; iSEG == 0) { setFlag(Flat); + } else if (iFmt->SEG == 1) { + setFlag(FlatScratch); } else if (iFmt->SEG == 2) { setFlag(FlatGlobal); } else { @@ -1573,12 +1575,12 @@ namespace VegaISA Inst_FLAT::initOperandInfo() { // One of the flat subtypes should be specified via flags - assert(isFlat() ^ isFlatGlobal()); + assert(isFlat() ^ isFlatGlobal() ^ isFlatScratch()); if (isFlat()) { initFlatOperandInfo(); - } else if (isFlatGlobal()) { - initGlobalOperandInfo(); + } else if (isFlatGlobal() || isFlatScratch()) { + initGlobalScratchOperandInfo(); } else { panic("Unknown flat subtype!\n"); } @@ -1622,7 +1624,7 @@ namespace VegaISA } void - Inst_FLAT::initGlobalOperandInfo() + Inst_FLAT::initGlobalScratchOperandInfo() { //3 formats: // 1 dst + 2 src (load) @@ -1691,12 +1693,12 @@ namespace VegaISA Inst_FLAT::generateDisassembly() { // One of the flat subtypes should be specified via flags - assert(isFlat() ^ isFlatGlobal()); + assert(isFlat() ^ isFlatGlobal() ^ isFlatScratch()); if (isFlat()) { generateFlatDisassembly(); - } else if (isFlatGlobal()) { - generateGlobalDisassembly(); + } else if (isFlatGlobal() || isFlatScratch()) { + generateGlobalScratchDisassembly(); } else { panic("Unknown flat subtype!\n"); } @@ -1720,11 +1722,16 @@ namespace VegaISA } void - Inst_FLAT::generateGlobalDisassembly() + Inst_FLAT::generateGlobalScratchDisassembly() { // Replace flat_ with global_ in assembly string std::string global_opcode = _opcode; - global_opcode.replace(0, 4, "global"); + if (isFlatGlobal()) { + global_opcode.replace(0, 4, "global"); + } else { + assert(isFlatScratch()); + global_opcode.replace(0, 4, "scratch"); + } std::stringstream dis_stream; dis_stream << global_opcode << " "; diff --git a/src/arch/amdgpu/vega/insts/op_encodings.hh b/src/arch/amdgpu/vega/insts/op_encodings.hh index 0f5f502add..613d78b25e 100644 --- a/src/arch/amdgpu/vega/insts/op_encodings.hh +++ b/src/arch/amdgpu/vega/insts/op_encodings.hh @@ -926,7 +926,8 @@ namespace VegaISA void initMemRead(GPUDynInstPtr gpuDynInst) { - if (gpuDynInst->executedAs() == enums::SC_GLOBAL) { + if (gpuDynInst->executedAs() == enums::SC_GLOBAL || + gpuDynInst->executedAs() == enums::SC_PRIVATE) { initMemReqHelper(gpuDynInst, MemCmd::ReadReq); } else if (gpuDynInst->executedAs() == enums::SC_GROUP) { Wavefront *wf = gpuDynInst->wavefront(); @@ -944,7 +945,8 @@ namespace VegaISA void initMemRead(GPUDynInstPtr gpuDynInst) { - if (gpuDynInst->executedAs() == enums::SC_GLOBAL) { + if (gpuDynInst->executedAs() == enums::SC_GLOBAL || + gpuDynInst->executedAs() == enums::SC_PRIVATE) { initMemReqHelper(gpuDynInst, MemCmd::ReadReq); } else if (gpuDynInst->executedAs() == enums::SC_GROUP) { Wavefront *wf = gpuDynInst->wavefront(); @@ -966,7 +968,8 @@ namespace VegaISA void initMemWrite(GPUDynInstPtr gpuDynInst) { - if (gpuDynInst->executedAs() == enums::SC_GLOBAL) { + if (gpuDynInst->executedAs() == enums::SC_GLOBAL || + gpuDynInst->executedAs() == enums::SC_PRIVATE) { initMemReqHelper(gpuDynInst, MemCmd::WriteReq); } else if (gpuDynInst->executedAs() == enums::SC_GROUP) { Wavefront *wf = gpuDynInst->wavefront(); @@ -984,7 +987,8 @@ namespace VegaISA void initMemWrite(GPUDynInstPtr gpuDynInst) { - if (gpuDynInst->executedAs() == enums::SC_GLOBAL) { + if (gpuDynInst->executedAs() == enums::SC_GLOBAL || + gpuDynInst->executedAs() == enums::SC_PRIVATE) { initMemReqHelper(gpuDynInst, MemCmd::WriteReq); } else if (gpuDynInst->executedAs() == enums::SC_GROUP) { Wavefront *wf = gpuDynInst->wavefront(); @@ -1006,6 +1010,10 @@ namespace VegaISA void initAtomicAccess(GPUDynInstPtr gpuDynInst) { + // Flat scratch requests may not be atomic according to ISA manual + // up to MI200. See MI200 manual Table 45. + assert(gpuDynInst->executedAs() != enums::SC_PRIVATE); + if (gpuDynInst->executedAs() == enums::SC_GLOBAL) { initMemReqHelper(gpuDynInst, MemCmd::SwapReq, true); } else if (gpuDynInst->executedAs() == enums::SC_GROUP) { @@ -1044,7 +1052,8 @@ namespace VegaISA // If saddr = 0x7f there is no scalar reg to read and address will // be a 64-bit address. Otherwise, saddr is the reg index for a // scalar reg used as the base address for a 32-bit address. - if ((saddr == 0x7f && isFlatGlobal()) || isFlat()) { + if ((saddr == 0x7f && (isFlatGlobal() || isFlatScratch())) + || isFlat()) { ConstVecOperandU64 vbase(gpuDynInst, vaddr); vbase.read(); @@ -1063,9 +1072,13 @@ namespace VegaISA if (isFlat()) { gpuDynInst->resolveFlatSegment(gpuDynInst->exec_mask); - } else { + } else if (isFlatGlobal()) { gpuDynInst->staticInstruction()->executed_as = enums::SC_GLOBAL; + } else { + assert(isFlatScratch()); + gpuDynInst->staticInstruction()->executed_as = + enums::SC_PRIVATE; } } @@ -1081,7 +1094,9 @@ namespace VegaISA gpuDynInst->computeUnit()->localMemoryPipe .issueRequest(gpuDynInst); } else { - fatal("Unsupported scope for flat instruction.\n"); + assert(gpuDynInst->executedAs() == enums::SC_PRIVATE); + gpuDynInst->computeUnit()->globalMemoryPipe + .issueRequest(gpuDynInst); } } @@ -1098,10 +1113,10 @@ namespace VegaISA private: void initFlatOperandInfo(); - void initGlobalOperandInfo(); + void initGlobalScratchOperandInfo(); void generateFlatDisassembly(); - void generateGlobalDisassembly(); + void generateGlobalScratchDisassembly(); void calcAddrSgpr(GPUDynInstPtr gpuDynInst, ConstVecOperandU32 &vaddr, diff --git a/src/gpu-compute/GPUStaticInstFlags.py b/src/gpu-compute/GPUStaticInstFlags.py index b75e2c6c92..3a44d402be 100644 --- a/src/gpu-compute/GPUStaticInstFlags.py +++ b/src/gpu-compute/GPUStaticInstFlags.py @@ -54,6 +54,7 @@ class GPUStaticInstFlags(Enum): "MemoryRef", # References memory (load, store, or atomic) "Flat", # Flat memory op "FlatGlobal", # Global memory op + "FlatScratch", # Scratch memory op "Load", # Reads from memory "Store", # Writes to memory # Atomic ops diff --git a/src/gpu-compute/compute_unit.cc b/src/gpu-compute/compute_unit.cc index ea903455d5..8d6deeb85a 100644 --- a/src/gpu-compute/compute_unit.cc +++ b/src/gpu-compute/compute_unit.cc @@ -1917,6 +1917,8 @@ ComputeUnit::updateInstStats(GPUDynInstPtr gpuDynInst) } } else if (gpuDynInst->isFlatGlobal()) { stats.flatVMemInsts++; + } else if (gpuDynInst->isFlatScratch()) { + stats.flatVMemInsts++; } else if (gpuDynInst->isLocalMem()) { stats.ldsNoFlatInsts++; } else if (gpuDynInst->isLoad()) { diff --git a/src/gpu-compute/gpu_dyn_inst.cc b/src/gpu-compute/gpu_dyn_inst.cc index 8dfae1dc90..0b394e7e36 100644 --- a/src/gpu-compute/gpu_dyn_inst.cc +++ b/src/gpu-compute/gpu_dyn_inst.cc @@ -432,6 +432,12 @@ GPUDynInst::isFlatGlobal() const return _staticInst->isFlatGlobal(); } +bool +GPUDynInst::isFlatScratch() const +{ + return _staticInst->isFlatScratch(); +} + bool GPUDynInst::isLoad() const { diff --git a/src/gpu-compute/gpu_dyn_inst.hh b/src/gpu-compute/gpu_dyn_inst.hh index e2884a012a..558cce8431 100644 --- a/src/gpu-compute/gpu_dyn_inst.hh +++ b/src/gpu-compute/gpu_dyn_inst.hh @@ -234,6 +234,7 @@ class GPUDynInst : public GPUExecContext bool isMemRef() const; bool isFlat() const; bool isFlatGlobal() const; + bool isFlatScratch() const; bool isLoad() const; bool isStore() const; diff --git a/src/gpu-compute/gpu_static_inst.hh b/src/gpu-compute/gpu_static_inst.hh index b86a507dce..156f0e529d 100644 --- a/src/gpu-compute/gpu_static_inst.hh +++ b/src/gpu-compute/gpu_static_inst.hh @@ -130,6 +130,7 @@ class GPUStaticInst : public GPUStaticInstFlags bool isMemRef() const { return _flags[MemoryRef]; } bool isFlat() const { return _flags[Flat]; } bool isFlatGlobal() const { return _flags[FlatGlobal]; } + bool isFlatScratch() const { return _flags[FlatScratch]; } bool isLoad() const { return _flags[Load]; } bool isStore() const { return _flags[Store]; } diff --git a/src/gpu-compute/scoreboard_check_stage.cc b/src/gpu-compute/scoreboard_check_stage.cc index 3d18260822..b618cab278 100644 --- a/src/gpu-compute/scoreboard_check_stage.cc +++ b/src/gpu-compute/scoreboard_check_stage.cc @@ -154,7 +154,8 @@ ScoreboardCheckStage::ready(Wavefront *w, nonrdytype_e *rdyStatus, if (!(ii->isBarrier() || ii->isNop() || ii->isReturn() || ii->isBranch() || ii->isALU() || ii->isLoad() || ii->isStore() || ii->isAtomic() || ii->isEndOfKernel() || ii->isMemSync() || ii->isFlat() || - ii->isFlatGlobal() || ii->isSleep() || ii->isLocalMem())) { + ii->isFlatGlobal() || ii->isFlatScratch() || ii->isSleep() || + ii->isLocalMem())) { panic("next instruction: %s is of unknown type\n", ii->disassemble()); } From fab458daa24c486f16fc18390db26442b0c7da87 Mon Sep 17 00:00:00 2001 From: atrah22 Date: Tue, 22 Aug 2023 01:06:50 -0700 Subject: [PATCH 239/693] util: Update & fix bug in m5stats2streamline.py 1) writeBinary function binary_list can have either string or ints and it needs to be properly converted to bytes 2) packed32(x) function can have x as int or float. Incase of float it needs to be converted to int Change-Id: I6a52aa59e1582dd6bb06b2d1c49ddaf8fe61c997 --- util/streamline/m5stats2streamline.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/util/streamline/m5stats2streamline.py b/util/streamline/m5stats2streamline.py index 8dc72bf0f9..85b263f304 100755 --- a/util/streamline/m5stats2streamline.py +++ b/util/streamline/m5stats2streamline.py @@ -221,6 +221,7 @@ def packed32(x): ret = [] more = True while more: + x = int(x) b = x & 0x7F x = x >> 7 if ((x == 0) and ((b & 0x40) == 0)) or ( @@ -383,7 +384,13 @@ def timestampList(x): def writeBinary(outfile, binary_list): for i in binary_list: - outfile.write(f"{i:c}") + if isinstance(i, str): + byteVal = bytes(i, "utf-8") + elif isinstance(i, int): + byteVal = bytes([i]) + else: + byteVal = i + outfile.write(byteVal) ############################################################ @@ -661,7 +668,7 @@ def parseProcessInfo(task_file): task_name_failure_warned = False for line in process_file: - match = re.match(process_re, line) + match = re.match(process_re, line.decode("ISO-8859-1")) if match: tick = int(match.group(1)) if start_tick < 0: From 99fc5de3fb33c1e67849db8dc9bd7555b5129665 Mon Sep 17 00:00:00 2001 From: atrah22 Date: Tue, 22 Aug 2023 03:48:51 -0700 Subject: [PATCH 240/693] util: Update & fix bug in m5stats2streamline.py 1) writeBinary function binary_list can have either string or ints and it needs to be properly converted to bytes 2) packed32(x) function can have x as int or float. Incase of float it needs to be converted to int 3) encode lines to string using .decode() or else TypeError will be invoked during run Change-Id: I678169f191901f02a80187418a17adbc1240c7d3 --- util/streamline/m5stats2streamline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/streamline/m5stats2streamline.py b/util/streamline/m5stats2streamline.py index 85b263f304..7e82744d0b 100755 --- a/util/streamline/m5stats2streamline.py +++ b/util/streamline/m5stats2streamline.py @@ -668,7 +668,7 @@ def parseProcessInfo(task_file): task_name_failure_warned = False for line in process_file: - match = re.match(process_re, line.decode("ISO-8859-1")) + match = re.match(process_re, line.decode()) if match: tick = int(match.group(1)) if start_tick < 0: From fee465c97c462bb460eff0fcb18ec417f1e3cca8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 28 Aug 2023 22:58:14 -0700 Subject: [PATCH 241/693] misc: Add test status badges to README.md These allow visitors to the repository to quickly see the status of our tests run on the develop branch. Change-Id: I3658c0e0d9dea66feebd69588c8a29d369a0b43d --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index bd6db2fbd7..c7c0d14463 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,15 @@ system software changes, and compile-time and run-time system optimizations. The main website can be found at . +## Testing status + +**Note**: These regard tests run on the develop branch of gem5: +. + +[![Daily Tests](https://github.com/gem5/gem5/actions/workflows/daily-tests.yaml/badge.svg)](https://github.com/gem5/gem5/actions/workflows/daily-tests.yaml) +[![Weekly Tests](https://github.com/gem5/gem5/actions/workflows/weekly-tests.yaml/badge.svg)](https://github.com/gem5/gem5/actions/workflows/weekly-tests.yaml) +[![Compiler Tests](https://github.com/gem5/gem5/actions/workflows/compiler-tests.yaml/badge.svg)](https://github.com/gem5/gem5/actions/workflows/compiler-tests.yaml) + ## Getting started A good starting point is , and for From 7cdce3a975390d3d2217852317f1a05180ae1efe Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 29 Aug 2023 00:08:40 -0700 Subject: [PATCH 242/693] util-docker: Add GitHub Action to create Docker Images This is built to test the following assumptions: 1. We can trigger a GitHub action event on the changing of a file/directory. 2. We can use GitHub actions to build a docker image. 3. We can use GitHub actions to push a docker image to a container registry. 4. We can use GitHub's container registry. Right now this will only build and push ubuntu-20.04_all-depenencies, as a test. Change-Id: Ie1a55c97c6eef26281456c908e1200b27da4d961 --- .github/workflows/docker-build.yaml | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/docker-build.yaml diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml new file mode 100644 index 0000000000..cbacaad9aa --- /dev/null +++ b/.github/workflows/docker-build.yaml @@ -0,0 +1,42 @@ +# +name: Docker images build and push + +on: + push: + branches: + - develop + paths: + - 'util/docker/ubuntu-20.04_all-depenencies' + workflow_dispatch: + +env: + IMAGE_NAME: ubuntu-20.04_all-depenencies +# +jobs: + # This builds and pushes the docker image. + push: + runs-on: [self-hosted, linux, x64, run] + permissions: + packages: write + contents: read + + steps: + - uses: actions/checkout@v3 + + - name: Build image + run: | + cd util/docker/ubuntu-20.04_all-depenencies + docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}" + + - name: Log in to registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + + - name: Push image + run: | + IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME + + # This changes all uppercase characters to lowercase. + IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + + docker tag $IMAGE_NAME $IMAGE_ID:latest + docker push $IMAGE_ID::latest From 7da0aeee7d6330c69da6f6142d1df00fe90d147c Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 29 Aug 2023 09:08:44 -0700 Subject: [PATCH 243/693] stdlib, resources: Updated warn messages - Updated warn messages to be more clear. Change-Id: I2a8922e96b5b544f2f229b01b3c51fc5e79995b4 --- src/python/gem5/resources/resource.py | 1 + src/python/gem5/resources/workload.py | 34 ++++++++++++++++++--------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index e71c7646a9..8db1d4bdd4 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -714,6 +714,7 @@ def obtain_resource( # Obtain the type from the JSON. From this we will determine what subclass # of `AbstractResource` we are to create and return. resources_category = resource_json["category"] + if resources_category == "resource": # This is a stop-gap measure to ensure to work with older versions of # the "resource.json" file. These should be replaced with their diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index 424da2ebc6..bdb596921f 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -38,13 +38,16 @@ def CustomWorkload(function: str, parameters: Dict[str, Any]): A custom workload gem5 resource. It can be used to specify a custom, local workload. - **Warning**: This class is deprecated and changed to a funtion and will be removed in future - releases of gem5. Please use the `WorkloadResource` class instead. This - class is merely a wrapper for it. + **Warning**: This `CustomWorkload` class is deprecated. It will be removed in a + future release of gem5. Please use the `gem5.resources.resource.WorkloadResource` + class instead. + + The class has been stealthily converted to a function which wraps the + `WorkloadResource` class. """ warn( "The `CustomWorkload` class is deprecated. Please use " - "`WorkloadResource` instead." + "the `gem5.resources.resource.WorkloadResource` class instead." ) return WorkloadResource(function=function, parameters=parameters) @@ -57,17 +60,26 @@ def Workload( gem5_version: Optional[str] = core.gem5Version, ): """ - This function was created to maintain backwards compability for v23.0.0 - and prior releases of gem5 where `Workload` was a class. + **Warning**: The `Workload` class is deprecated. It will be removed in a + future release of gem5. Please use the `gem5.resources.resource.WorkloadResource` + class instead. - In the interests of gem5-resource specialization, the `Workload` class - has been dropped. Instead users are advized to use the `obtain_resource` - function which will return the correct `AbstractResource` implementation. - This function (disguised as a class) wraps this function. + The class has been stealthily converted to a function which wraps the + `WorkloadResource` class. """ warn( "`Workload` has been deprecated. Please use the `obtain_resource` " - "function instead." + "function instead:\n\n" + "```\n" + "from gem5.resources.resource import obtain_resource\n" + "workload = obtain_resource(\n" + f' resource_id="{workload_name}",\n' + f' resource_directory="{resource_directory}",\n' + f' gem5_version="{gem5_version}",\n' + f" clients={clients},\n" + f" resource_version={resource_version},\n" + ")\n" + "```" ) return obtain_resource( workload_name, From d52c7ce87fb555375952d551de897ed452e50228 Mon Sep 17 00:00:00 2001 From: KUNAL PAI Date: Fri, 18 Aug 2023 22:37:21 -0700 Subject: [PATCH 244/693] resources, stdlib: Add support for local files in obtain_resource This patch allows a local JSON file to specify a local path in the JSON object of a Resource, through the "url" field. Local paths can be entered with the prefix "file:" in "url". All File URI scheme formats are supported. This behavior is the same as using specific Resource classes (ex. BinaryResource) and passing a local_path into the function. But, the above infrastructure does not allow simultaneous creation of Resources and Workloads of those Resources. With this patch, someone can use a local JSON, specify the location of local Resources and create a Workload from those Resources and test both together. Also, this patch adds pyunit tests to check the functionality of the function used to convert the "url" field into a path. Change-Id: I1fa3ce33a9870528efd7751d7ca24c27baf36ad4 --- src/python/gem5/resources/downloader.py | 60 +++++++++++++--- .../resources/pyunit_local_file_path_check.py | 72 +++++++++++++++++++ 2 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index b4f7a2f016..5bca67f677 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -34,6 +34,7 @@ import random from pathlib import Path import tarfile from urllib.error import HTTPError +from urllib.parse import urlparse from typing import List, Optional, Dict from _m5 import core @@ -310,19 +311,34 @@ def get_resource( if run_unzip: download_dest += zip_extension - # TODO: Might be nice to have some kind of download status bar here. - # TODO: There might be a case where this should be silenced. - print( - "Resource '{}' was not found locally. Downloading to '{}'...".format( - resource_name, download_dest + file_uri_path = _file_uri_to_path(resource_json["url"]) + if file_uri_path: + if not file_uri_path.exists(): + raise Exception( + f"Could not find file at path '{file_uri_path}'" + ) + print( + "Resource '{}' is being copied from '{}' to '{}'...".format( + resource_name, + urlparse(resource_json["url"]).path, + download_dest, + ) + ) + shutil.copy(file_uri_path, download_dest) + else: + # TODO: Might be nice to have some kind of download status bar here. + # TODO: There might be a case where this should be silenced. + print( + "Resource '{}' was not found locally. Downloading to '{}'...".format( + resource_name, download_dest + ) ) - ) - # Get the URL. - url = resource_json["url"] + # Get the URL. + url = resource_json["url"] - _download(url=url, download_to=download_dest) - print(f"Finished downloading resource '{resource_name}'.") + _download(url=url, download_to=download_dest) + print(f"Finished downloading resource '{resource_name}'.") if run_unzip: print( @@ -368,3 +384,27 @@ def get_resource( safe_extract(f, unpack_to) os.remove(download_dest) + + +def _file_uri_to_path(uri: str) -> Optional[Path]: + """ + If the URI uses the File scheme (e.g, `file://host/path`) then + a Path object for the local path is returned, otherwise None. + + **Note:** Only files from localhost are permitted. An exception + is thrown otherwise. + + :param uri: The file URI to convert. + + :returns: The path to the file. + """ + + if urlparse(uri).scheme == "file": + if urlparse(uri).netloc == "" or urlparse(uri).netloc == "localhost": + local_path = urlparse(uri).path + return Path(local_path) + raise Exception( + f"File URI '{uri}' specifies host '{urlparse(uri).netloc}'. " + "Only localhost is permitted." + ) + return None diff --git a/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py b/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py new file mode 100644 index 0000000000..b1d0ea1bc3 --- /dev/null +++ b/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py @@ -0,0 +1,72 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from gem5.resources.downloader import _file_uri_to_path +from pathlib import Path +import unittest + + +class LocalPathTestSuite(unittest.TestCase): + def test_local_path_exists_single_slash(self): + # Test that a local path is returned as-is + path = "file:/test/test/file" + expected_path = Path("/test/test/file") + self.assertEqual(_file_uri_to_path(path), expected_path) + + def test_non_localhost_exception(self): + # Test that a local path with different netloc throws an exception + path = "file://test/test/file" + # should raise Exception because netloc is not '' or 'localhost' + with self.assertRaises(Exception) as exception: + _file_uri_to_path(path) + self.assertEqual( + str(exception.exception), + f"File URI '{path}' specifies host 'test'. " + "Only localhost is permitted.", + ) + + def test_localhost_accepted(self): + path = "file://localhost/test/test/file" + # should work as expected because netloc is 'localhost' + expected_path = Path("/test/test/file") + self.assertEqual(_file_uri_to_path(path), expected_path) + + def test_local_path_exists_triple_slash(self): + # Test that a local path is returned as-is + path = "file:///test/test/file" + expected_path = Path("/test/test/file") + self.assertEqual(_file_uri_to_path(path), expected_path) + + def test_local_path_exists_quadruple_slash(self): + # Test that a local path is returned as-is + path = "file:////test/test/file" + expected_path = Path("//test/test/file") + self.assertEqual(_file_uri_to_path(path), expected_path) + + def test_uri_not_file(self): + # Test that a URL returns None + path = "http://test/test/file" + self.assertIsNone(_file_uri_to_path(path)) From 7db2aac943757789276ca4b1de1c4f0061937b39 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 31 Aug 2023 02:12:20 -0700 Subject: [PATCH 245/693] misc: Remove 'run-name' from compiler-tests.yaml This isn't necessary. Without 'run-name' the action's default name is 'run-name'. Displaying the actor who launched the action is pointless for scheduled tests. Change-Id: I15d52959389881381ef7685efb57152c5162c89d --- .github/workflows/compiler-tests.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 9a567653f5..7c9493cbba 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -1,8 +1,6 @@ # This workflow runs all of the compiler tests name: Compiler Tests -run-name: ${{ github.actor }} is running compiler tests - on: # Runs every Friday from 7AM UTC From cfa833a97d1fcd3e53238718797e98ef4acdde3f Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 31 Aug 2023 11:01:32 -0500 Subject: [PATCH 246/693] gpu-compute: Set LDS/scratch aperture base register Starting with gfx900 (Vega) the LDS and scratch apertures can be queried using a new s_getreg_b32 instruction. If the instruction is called with the SH_MEM_BASES argument it returns the upper 16 bits of a 64 bit address for the LDS and scratch apertures. The current addresses cannot be encoded in this register, so that addresses are changed to have the lower 48 bits be all zeros in addition to writing the bases register. Change-Id: If20f262b2685d248afe31aa3ebb274e4f0fc0772 --- src/gpu-compute/shader.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gpu-compute/shader.cc b/src/gpu-compute/shader.cc index 620d0152c1..e13e7c9cf4 100644 --- a/src/gpu-compute/shader.cc +++ b/src/gpu-compute/shader.cc @@ -41,6 +41,7 @@ #include "debug/GPUMem.hh" #include "debug/GPUShader.hh" #include "debug/GPUWgLatency.hh" +#include "dev/amdgpu/hwreg_defines.hh" #include "gpu-compute/dispatcher.hh" #include "gpu-compute/gpu_command_processor.hh" #include "gpu-compute/gpu_static_inst.hh" @@ -72,15 +73,25 @@ Shader::Shader(const Params &p) : ClockedObject(p), gpuCmdProc.setShader(this); _dispatcher.setShader(this); + // These apertures are set by the driver. In full system mode that is done + // using a PM4 packet but the emulated SE mode driver does not set them + // explicitly, so we need to define some reasonable defaults here. _gpuVmApe.base = ((Addr)1 << 61) + 0x1000000000000L; _gpuVmApe.limit = (_gpuVmApe.base & 0xFFFFFF0000000000UL) | 0xFFFFFFFFFFL; - _ldsApe.base = ((Addr)1 << 61) + 0x0; + _ldsApe.base = 0x1000000000000; _ldsApe.limit = (_ldsApe.base & 0xFFFFFFFF00000000UL) | 0xFFFFFFFF; - _scratchApe.base = ((Addr)1 << 61) + 0x100000000L; + _scratchApe.base = 0x2000000000000; _scratchApe.limit = (_scratchApe.base & 0xFFFFFFFF00000000UL) | 0xFFFFFFFF; + // The scratch and LDS address can be queried starting in gfx900. The + // base addresses are in the SH_MEM_BASES 32-bit register. The upper 16 + // bits are for the LDS address and the lower 16 bits are for scratch + // address. In both cases the 16 bits represent bits 63:48 of the address. + // This means bits 47:0 of the base address is always zero. + setHwReg(HW_REG_SH_MEM_BASES, 0x00010002); + shHiddenPrivateBaseVmid = 0; cuList.resize(n_cu); From 3520c83673e789b929a559cd8fe0b558c8f99517 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Thu, 31 Aug 2023 11:08:20 -0500 Subject: [PATCH 247/693] util: Add gdb to gcn-gpu Dockerfile gdb was originally part of the ROCm 1.6 Dockerfile a few years ago. It got removed when updating to ROCm 4.0. This adds it back as being able to debug things is quite useful. Change-Id: I3f8148cde79e6cc5233fa3c8c830b64817f01d3a --- util/dockerfiles/gcn-gpu/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/dockerfiles/gcn-gpu/Dockerfile b/util/dockerfiles/gcn-gpu/Dockerfile index c5db8963a8..618495c5a9 100644 --- a/util/dockerfiles/gcn-gpu/Dockerfile +++ b/util/dockerfiles/gcn-gpu/Dockerfile @@ -29,7 +29,7 @@ RUN apt -y update && apt -y upgrade && \ apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev python-is-python3 doxygen libboost-all-dev \ - libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config + libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config gdb # Requirements for ROCm RUN apt -y install cmake mesa-common-dev libgflags-dev libgoogle-glog-dev From 7042d74ac2efa16b8ff6b2b7e1251f238cc4aff0 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Thu, 31 Aug 2023 09:19:24 -0700 Subject: [PATCH 248/693] stdlib, resources: Moved parsing params. - moved parsing from WorkloadResource __init__ to obtain_resource Change-Id: I9ed2aebb23af7f359bc1e5fff8ebe616a0da1374 --- src/python/gem5/resources/resource.py | 38 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 8db1d4bdd4..9e6c79ab01 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -563,13 +563,11 @@ class WorkloadResource(AbstractResource): def __init__( self, function: str = None, - resources: Optional[Dict[str, str]] = None, - additional_params: Optional[Dict[str, str]] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, local_path: Optional[str] = None, - parameters: Optional[Dict[str, Any]] = None, + parameters: Optional[Dict[str, Any]] = {}, **kwargs, ): """ @@ -585,19 +583,7 @@ class WorkloadResource(AbstractResource): ) self._func = function - self._params = parameters if parameters else {} - for key in resources.keys(): - assert isinstance(key, str) - value = resources[key] - assert isinstance(value, str) - self._params[key] = obtain_resource( - value, - ) - for key in additional_params.keys(): - assert isinstance(key, str) - value = additional_params[key] - assert isinstance(value, str) - self._params[key] = value + self._params = parameters def get_function_str(self) -> str: """ @@ -732,6 +718,26 @@ def obtain_resource( assert resources_category in _get_resource_json_type_map resource_class = _get_resource_json_type_map[resources_category] + if resources_category == "workload": + # This parses the "resources" and "additional_params" fields of the + # workload resource into a dictionary of AbstractResource objects and + # strings respectively. + params = {} + if "resources" in resource_json: + for key in resource_json["resources"].keys(): + assert isinstance(key, str) + value = resource_json["resources"][key] + assert isinstance(value, str) + params[key] = obtain_resource( + value, + ) + if "additional_params" in resource_json: + for key in resource_json["additional_params"].keys(): + assert isinstance(key, str) + value = resource_json["additional_params"][key] + assert isinstance(value, str) + params[key] = value + resource_json["parameters"] = params # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the # subclass contructor, so we can pass the resource_json map directly. From 4ff1f160ece82387d90df71b8da11e30a1444f7a Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Fri, 1 Sep 2023 00:26:51 +0000 Subject: [PATCH 249/693] arch-x86: Fix wrong x86 assembly The RM field of ModRM was printed as Reg field for several instructions. For reference, this change fixes typos introduced by [1]. [1] https://gem5-review.googlesource.com/c/public/gem5/+/40339 Change-Id: I41eb58e6a70845c4ddd6774ccba81b8069888be5 Signed-off-by: Hoa Nguyen --- src/arch/x86/isa/specialize.isa | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index a86d5126b6..236465dc1b 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -240,7 +240,7 @@ let {{ regFormat = \ "printReg(out, intRegClass[%s], regSize);\n" regSuffix = "_R" - env.addToDisassembly(regFormat % ModRMRegIndex) + env.addToDisassembly(regFormat % ModRMRMIndex) return doSplitDecode("MODRM_MOD", {"3" : (specializeInst, Name + regSuffix, copy.copy(opTypes), regEnv)}, @@ -268,7 +268,7 @@ let {{ regFormat = \ "printReg(out, intRegClass[%s], regSize);\n" Name += "_R" - env.addToDisassembly(regFormat % ModRMRegIndex) + env.addToDisassembly(regFormat % ModRMRMIndex) elif opType.tag in ("X", "Y"): # This type of memory addressing is for string instructions. # They'll use the right index and segment internally. From 73b0e88d6e77af50a8718b03c9a5688f676e60c3 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 30 Aug 2023 23:29:25 -0700 Subject: [PATCH 250/693] scons: Add an option specifying the path to mold linker binary To use mold linker with gcc of version older than 12.1.0, the user has to pass the -B option to specify where the linker is. [1] Currently in gem5, scons only looks for the mold binary at conventional places, such as /usr/libexec/mold and /usr/local/libexec/mold. There's no option to manually specify the path to the linker. gcc-12 and mold are not widely available on older systems. Having an option to manually input the mold linker path allows users to use built mold instances anywhere on the system, not just the default locations in /usr where they may not have permission to install mold (i.e., no sudo permissions). [1] https://github.com/rui314/mold#how-to-use Change-Id: Ifb2366a0c2342bf4e7207df8db6196e14184a9d4 Signed-off-by: Hoa Nguyen --- SConstruct | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/SConstruct b/SConstruct index 32e0c36e09..ca0496a238 100755 --- a/SConstruct +++ b/SConstruct @@ -84,6 +84,7 @@ from os import mkdir, remove, environ from os.path import abspath, dirname, expanduser from os.path import isdir, isfile from os.path import join, split +from pathlib import Path import logging logging.basicConfig() @@ -121,6 +122,8 @@ AddOption('--ignore-style', action='store_true', help='Disable style checking hooks') AddOption('--linker', action='store', default=None, choices=linker_options, help=f'Select which linker to use ({", ".join(linker_options)})') +AddOption('--mold-path', action='store', default='/usr/libexec/mold/', + help='Path to the binary of mold linker.') AddOption('--gold-linker', action='store_const', const='gold', dest='linker', help='Use the gold linker. Deprecated: Use --linker=gold') AddOption('--no-compress-debug', action='store_true', @@ -425,19 +428,36 @@ for variant_path in variant_paths: conf.CheckLinkFlag('-Wl,--as-needed') linker = GetOption('linker') + # check for mold linker when -fuse-ld=mold fails + # this checks whether mold_dir has ld or ld.mold and + # whether -B{mold_dir} works + mold_check = lambda mold_dir: \ + isdir(mold_dir) and \ + (isfile(mold_dir/'ld') or isfile(mold_dir/'ld.mold')) and \ + conf.CheckLinkFlag('-B' + str(mold_dir)) + mold_check_message = \ + "You are seeing this error because -fuse-ld=mold failed.\n" \ + "If you did not add the folder containing mold to $PATH, you " \ + "should do so and recompiling gem5.\n" \ + "If that does not work, you can manually specify the path to " \ + "the binary of mold using the --mold-path option. This will " \ + "cause scons to look for ld or ld.mold in the same folder as " \ + "the binary of mold." if linker: with gem5_scons.Configure(env) as conf: if not conf.CheckLinkFlag(f'-fuse-ld={linker}'): - # check mold support for gcc older than 12.1.0 - if linker == 'mold' and \ - (env['GCC'] and \ - compareVersions(env['CXXVERSION'], - "12.1.0") < 0) and \ - ((isdir('/usr/libexec/mold') and \ - conf.CheckLinkFlag('-B/usr/libexec/mold')) or \ - (isdir('/usr/local/libexec/mold') and \ - conf.CheckLinkFlag('-B/usr/local/libexec/mold'))): - pass # support mold + # If -fuse-ld=mold fails, we use "-B$mold_path" instead. + mold_path = Path(GetOption('mold_path')).parent + if linker == 'mold': + if any(map(mold_check, [mold_path, + Path("/usr/libexec/mold"), + Path("/usr/libexec/mold")])): + pass # support mold + else: + error( + f'Linker "{linker}" is not supported. ' + f'{mold_check_message}' + ) else: error(f'Linker "{linker}" is not supported') if linker == 'gold' and not GetOption('with_lto'): From 2da54d5a4f600eccd9332839c5b5e6d238c7e7ea Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 1 Sep 2023 09:50:33 -0500 Subject: [PATCH 251/693] mem-ruby: Reorder SLC atomic and response actions Currently the MOESI_AMD_Base-directory transition for system level atomics sends the response message before the atomic is performed. This was likely done because atomics are supposed to return the value of the data *before* the atomic is performed and by simply ordering the actions this way that was taken care of. With the new atomic log feature, the atomic values are pulled from the log by the coalescer on the return path. Therefore, these actions can be reordered. However, it is now necessary that the atomics be performed before sending the response so that the log is populated and copied by the response action. This should fix #253 . Change-Id: Ie7e178f93990975367de2cc3e89e5ef9c9069241 --- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index fd0cca5782..774b54a432 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -1411,8 +1411,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(BDW_M, MemData, U) { mt_writeMemDataToTBE; - da_sendResponseDmaAck; wd_writeBackData; + da_sendResponseDmaAck; wada_wakeUpAllDependentsAddr; dt_deallocateTBE; pm_popMemQueue; @@ -1420,8 +1420,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(BS_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} { mt_writeMemDataToTBE; - s_sendResponseS; wd_writeBackData; + s_sendResponseS; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pm_popMemQueue; @@ -1429,8 +1429,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(BM_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} { mt_writeMemDataToTBE; - m_sendResponseM; wd_writeBackData; + m_sendResponseM; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pm_popMemQueue; @@ -1438,32 +1438,32 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(B_M, MemData, B){L3TagArrayWrite, L3DataArrayWrite} { mt_writeMemDataToTBE; - es_sendResponseES; wd_writeBackData; + es_sendResponseES; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pm_popMemQueue; } transition(BS_M, L3Hit, B) {L3TagArrayWrite, L3DataArrayWrite} { - s_sendResponseS; wd_writeBackData; + s_sendResponseS; alwt_allocateL3BlockOnWT; dt_deallocateTBE; ptl_popTriggerQueue; } transition(BM_M, L3Hit, B) {L3DataArrayWrite, L3TagArrayWrite} { - m_sendResponseM; wd_writeBackData; + m_sendResponseM; alwt_allocateL3BlockOnWT; dt_deallocateTBE; ptl_popTriggerQueue; } transition(B_M, L3Hit, B) {L3DataArrayWrite, L3TagArrayWrite} { - es_sendResponseES; wd_writeBackData; + es_sendResponseES; alwt_allocateL3BlockOnWT; dt_deallocateTBE; ptl_popTriggerQueue; @@ -1509,8 +1509,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") } transition(BDW_Pm, ProbeAcksComplete, U) { - da_sendResponseDmaAck; wd_writeBackData; + da_sendResponseDmaAck; // Check for pending requests from the core we put to sleep while waiting // for a response wada_wakeUpAllDependentsAddr; @@ -1520,8 +1520,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(BS_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} { sf_setForwardReqTime; - s_sendResponseS; wd_writeBackData; + s_sendResponseS; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pt_popTriggerQueue; @@ -1529,8 +1529,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(BM_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} { sf_setForwardReqTime; - m_sendResponseM; wd_writeBackData; + m_sendResponseM; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pt_popTriggerQueue; @@ -1538,8 +1538,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(B_Pm, ProbeAcksComplete, B){L3DataArrayWrite, L3TagArrayWrite} { sf_setForwardReqTime; - es_sendResponseES; wd_writeBackData; + es_sendResponseES; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pt_popTriggerQueue; @@ -1547,8 +1547,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") transition(BP, ProbeAcksComplete, B){L3TagArrayWrite, L3TagArrayWrite} { sf_setForwardReqTime; - c_sendResponseCtoD; wd_writeBackData; + c_sendResponseCtoD; alwt_allocateL3BlockOnWT; dt_deallocateTBE; pt_popTriggerQueue; From 0ac2f67437702ee47e65b6d51a793301791b277e Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sat, 2 Sep 2023 04:41:08 -0700 Subject: [PATCH 252/693] misc: Remove escape characters from bug_report.md The bug_report.md is rendered as plain text, not markdown, when creating a bug report. As such the escape characters are removed in this commit. Change-Id: I524c66ae61d00b7ed59153ba9f4b2297ff50ee18 --- .github/ISSUE_TEMPLATE/bug_report.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 179a37ac0b..8cbf4c6db2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -21,10 +21,10 @@ Steps to reproduce the behavior. Please assume starting from a clean repository: 1. Compile gem5 with command ... 2. Execute the simulation with... -If writing code, or a terminal command, use code blocks. Either an inline code block, \`scons build/ALL/gem5.opt\` (enclosed in two \`) or a multi-line codeblock: +If writing code, or a terminal command, use code blocks. Either an inline code block, `scons build/ALL/gem5.opt` (enclosed in two '`') or a multi-line codeblock: -\`\`\` +``` int x=2; @@ -32,7 +32,7 @@ int y=3' print(x+y); -\`\`\` +``` If possible, please include the Python configuration script used and state clearly any parameters passed. @@ -40,11 +40,11 @@ If possible, please include the Python configuration script used and state clear If applicable, add the terminal output here. If long, only include the relevant lines. Please put the terminal output in code blocks. I.e.: -\`\`\` +``` #Terminal output here# -\`\`\` +``` **Expected behavior** A clear and concise description of what you expected to happen. From fcb586cfedeaebe146ae270886dcf6c8f77f3070 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sat, 2 Sep 2023 04:42:53 -0700 Subject: [PATCH 253/693] misc: Add/Remove new lines from bug_report.md There were some weird newline characters in this file, or lack of lines. This patch adds/removes them. Change-Id: I6cc918788c07bbc4be5c68401ad3987be00fffc4 --- .github/ISSUE_TEMPLATE/bug_report.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8cbf4c6db2..9600934675 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,7 +4,6 @@ about: Create a report to help us find and fix the bug title: '' labels: bug assignees: '' - --- **Describe the bug** @@ -18,6 +17,7 @@ If you have modified gem5 in some way please state, to the best of your ability, **To Reproduce** Steps to reproduce the behavior. Please assume starting from a clean repository: + 1. Compile gem5 with command ... 2. Execute the simulation with... @@ -25,13 +25,9 @@ If writing code, or a terminal command, use code blocks. Either an inline code b ``` - int x=2; - int y=3' - print(x+y); - ``` If possible, please include the Python configuration script used and state clearly any parameters passed. @@ -41,9 +37,7 @@ If applicable, add the terminal output here. If long, only include the relevant Please put the terminal output in code blocks. I.e.: ``` - #Terminal output here# - ``` **Expected behavior** From 188d29fe057947522d6159284b3669b132cd781b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sat, 2 Sep 2023 04:44:07 -0700 Subject: [PATCH 254/693] misc: Add language specification to code-blocks Change-Id: I875aeee7eb0f9970711a97448d3bcb7acddbe7b1 --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9600934675..c7d10c1724 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -24,7 +24,7 @@ Steps to reproduce the behavior. Please assume starting from a clean repository: If writing code, or a terminal command, use code blocks. Either an inline code block, `scons build/ALL/gem5.opt` (enclosed in two '`') or a multi-line codeblock: -``` +```python int x=2; int y=3' print(x+y); @@ -36,7 +36,7 @@ If possible, please include the Python configuration script used and state clear If applicable, add the terminal output here. If long, only include the relevant lines. Please put the terminal output in code blocks. I.e.: -``` +```shell #Terminal output here# ``` From 1ec58d589a3dfe76c144b2257dba2205fc9eada1 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sat, 2 Sep 2023 04:46:04 -0700 Subject: [PATCH 255/693] misc: Fix broken code example in bug_report.md Change-Id: I9bc1b42d488a415d2ea165385d83fea3d4ac288d --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c7d10c1724..6f89a7eb33 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,9 +25,9 @@ If writing code, or a terminal command, use code blocks. Either an inline code b ```python -int x=2; -int y=3' -print(x+y); +int x=2 +int y=3 +print(x+y) ``` If possible, please include the Python configuration script used and state clearly any parameters passed. From ff75e5b30eb1e7197b1bda97353891cad6da1adc Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 23:48:40 -0700 Subject: [PATCH 256/693] misc,ext: Update pre-commit hook to run on ext/testlib Though in ext, we regularly modify these files to add features and extend our testlib testing infrastructure. Ergo, the pre-commit checks should be run. Change-Id: I921a263f25f850b03e5535a8a1f509921c124763 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8cbc6afdb7..37b1acbbea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ default_language_version: exclude: | (?x)^( - ext/.*| + ext/(?!testlib/).*| build/.*| src/systemc/ext/.*| src/systemc/tests/.*/.*| From 9e1afdecefaf910fa6e266f29dc480a32b0fa83e Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 23:51:14 -0700 Subject: [PATCH 257/693] ext: Run `pre-commit run --files ext/testlib` Change-Id: Ic581132f6136dddb127e2a1c5a1ecc19876488c3 --- ext/testlib/__init__.py | 6 +- ext/testlib/configuration.py | 484 +++++++++++++++++++---------------- ext/testlib/fixture.py | 9 +- ext/testlib/handlers.py | 204 ++++++++------- ext/testlib/helper.py | 188 ++++++++------ ext/testlib/loader.py | 109 ++++---- ext/testlib/log.py | 81 ++++-- ext/testlib/main.py | 120 +++++---- ext/testlib/query.py | 8 +- ext/testlib/result.py | 152 +++++------ ext/testlib/runner.py | 59 +++-- ext/testlib/state.py | 10 +- ext/testlib/suite.py | 18 +- ext/testlib/terminal.py | 87 ++++--- ext/testlib/test_util.py | 12 +- ext/testlib/uid.py | 18 +- ext/testlib/wrappers.py | 96 ++++--- 17 files changed, 952 insertions(+), 709 deletions(-) diff --git a/ext/testlib/__init__.py b/ext/testlib/__init__.py index 898205d9ab..2fad890b65 100644 --- a/ext/testlib/__init__.py +++ b/ext/testlib/__init__.py @@ -36,9 +36,9 @@ from .fixture import * from .configuration import * from .main import main -#TODO Remove this awkward bootstrap -#FIXME +# TODO Remove this awkward bootstrap +# FIXME from gem5 import * -#TODO Remove this as an export, users should getcwd from os +# TODO Remove this as an export, users should getcwd from os from os import getcwd diff --git a/ext/testlib/configuration.py b/ext/testlib/configuration.py index fd47e3b33a..600f0e13cc 100644 --- a/ext/testlib/configuration.py +++ b/ext/testlib/configuration.py @@ -38,7 +38,7 @@ # # Authors: Sean Wilson -''' +""" Global configuration module which exposes two types of configuration variables: @@ -76,7 +76,7 @@ found an AttributeError will be raised. common string names used across the test framework. :code:`_defaults.build_dir = None` Once this module has been imported constants should not be modified and their base attributes are frozen. -''' +""" import abc import argparse import copy @@ -87,27 +87,33 @@ from pickle import HIGHEST_PROTOCOL as highest_pickle_protocol from testlib.helper import absdirpath, AttrDict, FrozenAttrDict + class UninitialzedAttributeException(Exception): - ''' + """ Signals that an attribute in the config file was not initialized. - ''' + """ + pass + class UninitializedConfigException(Exception): - ''' + """ Signals that the config was not initialized before trying to access an attribute. - ''' + """ + pass + class TagRegex(object): def __init__(self, include, regex): self.include = include self.regex = re.compile(regex) def __str__(self): - type_ = 'Include' if self.include else 'Remove' - return '%10s: %s' % (type_, self.regex.pattern) + type_ = "Include" if self.include else "Remove" + return "%10s: %s" % (type_, self.regex.pattern) + class _Config(object): _initialized = False @@ -131,14 +137,14 @@ class _Config(object): self._initialized = True def _add_post_processor(self, attr, post_processor): - ''' + """ :param attr: Attribute to pass to and recieve from the :func:`post_processor`. :param post_processor: A callback functions called in a chain to perform additional setup for a config argument. Should return a tuple containing the new value for the config attr. - ''' + """ if attr not in self._post_processors: self._post_processors[attr] = [] self._post_processors[attr].append(post_processor) @@ -153,7 +159,7 @@ class _Config(object): for attr in dir(args): # Ignore non-argument attributes. - if not attr.startswith('_'): + if not attr.startswith("_"): self._config_file_args[attr] = getattr(args, attr) self._config.update(self._config_file_args) @@ -166,14 +172,13 @@ class _Config(object): newval = newval[0] self._set(attr, newval) - def _lookup_val(self, attr): - ''' + """ Get the attribute from the config or fallback to defaults. :returns: If the value is not stored return None. Otherwise a tuple containing the value. - ''' + """ if attr in self._config: return (self._config[attr],) elif hasattr(self._defaults, attr): @@ -184,82 +189,87 @@ class _Config(object): return getattr(super(_Config, self), attr) elif not self._initialized: raise UninitializedConfigException( - 'Cannot directly access elements from the config before it is' - ' initialized') + "Cannot directly access elements from the config before it is" + " initialized" + ) else: val = self._lookup_val(attr) if val is not None: return val[0] else: raise UninitialzedAttributeException( - '%s was not initialzed in the config.' % attr) + "%s was not initialzed in the config." % attr + ) def get_tags(self): - d = {typ: set(self.__getattr__(typ)) - for typ in self.constants.supported_tags} + d = { + typ: set(self.__getattr__(typ)) + for typ in self.constants.supported_tags + } if any(map(lambda vals: bool(vals), d.values())): return d else: return {} + def define_defaults(defaults): - ''' + """ Defaults are provided by the config if the attribute is not found in the config or commandline. For instance, if we are using the list command fixtures might not be able to count on the build_dir being provided since we aren't going to build anything. - ''' - defaults.base_dir = os.path.abspath(os.path.join(absdirpath(__file__), - os.pardir, - os.pardir)) - defaults.result_path = os.path.join(os.getcwd(), 'testing-results') - defaults.resource_url = 'http://dist.gem5.org/dist/develop' - defaults.resource_path = os.path.abspath(os.path.join(defaults.base_dir, - 'tests', - 'gem5', - 'resources')) + """ + defaults.base_dir = os.path.abspath( + os.path.join(absdirpath(__file__), os.pardir, os.pardir) + ) + defaults.result_path = os.path.join(os.getcwd(), "testing-results") + defaults.resource_url = "http://dist.gem5.org/dist/develop" + defaults.resource_path = os.path.abspath( + os.path.join(defaults.base_dir, "tests", "gem5", "resources") + ) + def define_constants(constants): - ''' + """ 'constants' are values not directly exposed by the config, but are attached to the object for centralized access. These should be used for setting common string names used across the test framework. A simple typo in a string can take a lot of debugging to uncover the issue, attribute errors are easier to notice and most autocompletion systems detect them. - ''' - constants.system_out_name = 'system-out' - constants.system_err_name = 'system-err' + """ + constants.system_out_name = "system-out" + constants.system_err_name = "system-err" - constants.isa_tag_type = 'isa' - constants.x86_tag = 'X86' - constants.gcn3_x86_tag = 'GCN3_X86' - constants.vega_x86_tag = 'VEGA_X86' - constants.sparc_tag = 'SPARC' - constants.riscv_tag = 'RISCV' - constants.arm_tag = 'ARM' - constants.mips_tag = 'MIPS' - constants.power_tag = 'POWER' - constants.null_tag = 'NULL' - constants.all_compiled_tag = 'ALL' + constants.isa_tag_type = "isa" + constants.x86_tag = "X86" + constants.gcn3_x86_tag = "GCN3_X86" + constants.vega_x86_tag = "VEGA_X86" + constants.sparc_tag = "SPARC" + constants.riscv_tag = "RISCV" + constants.arm_tag = "ARM" + constants.mips_tag = "MIPS" + constants.power_tag = "POWER" + constants.null_tag = "NULL" + constants.all_compiled_tag = "ALL" - constants.variant_tag_type = 'variant' - constants.opt_tag = 'opt' - constants.debug_tag = 'debug' - constants.fast_tag = 'fast' + constants.variant_tag_type = "variant" + constants.opt_tag = "opt" + constants.debug_tag = "debug" + constants.fast_tag = "fast" - constants.length_tag_type = 'length' - constants.quick_tag = 'quick' - constants.long_tag = 'long' - constants.very_long_tag = 'very-long' + constants.length_tag_type = "length" + constants.quick_tag = "quick" + constants.long_tag = "long" + constants.very_long_tag = "very-long" - constants.host_isa_tag_type = 'host' - constants.host_x86_64_tag = 'x86_64' - constants.host_arm_tag = 'aarch64' + constants.host_isa_tag_type = "host" + constants.host_x86_64_tag = "x86_64" + constants.host_arm_tag = "aarch64" - constants.kvm_tag = 'kvm' + constants.kvm_tag = "kvm" constants.supported_tags = { - constants.isa_tag_type : ( + constants.isa_tag_type: ( constants.x86_tag, constants.gcn3_x86_tag, constants.vega_x86_tag, @@ -270,7 +280,7 @@ def define_constants(constants): constants.power_tag, constants.null_tag, constants.all_compiled_tag, - ), + ), constants.variant_tag_type: ( constants.opt_tag, constants.debug_tag, @@ -290,41 +300,43 @@ def define_constants(constants): # Binding target ISA with host ISA. This is useful for the # case where host ISA and target ISA need to coincide constants.target_host = { - constants.arm_tag : (constants.host_arm_tag,), - constants.x86_tag : (constants.host_x86_64_tag,), - constants.gcn3_x86_tag : (constants.host_x86_64_tag,), - constants.vega_x86_tag : (constants.host_x86_64_tag,), - constants.sparc_tag : (constants.host_x86_64_tag,), - constants.riscv_tag : (constants.host_x86_64_tag,), - constants.mips_tag : (constants.host_x86_64_tag,), - constants.power_tag : (constants.host_x86_64_tag,), - constants.null_tag : (None,), + constants.arm_tag: (constants.host_arm_tag,), + constants.x86_tag: (constants.host_x86_64_tag,), + constants.gcn3_x86_tag: (constants.host_x86_64_tag,), + constants.vega_x86_tag: (constants.host_x86_64_tag,), + constants.sparc_tag: (constants.host_x86_64_tag,), + constants.riscv_tag: (constants.host_x86_64_tag,), + constants.mips_tag: (constants.host_x86_64_tag,), + constants.power_tag: (constants.host_x86_64_tag,), + constants.null_tag: (None,), constants.all_compiled_tag: (None,), } - constants.supported_isas = constants.supported_tags['isa'] - constants.supported_variants = constants.supported_tags['variant'] - constants.supported_lengths = constants.supported_tags['length'] - constants.supported_hosts = constants.supported_tags['host'] + constants.supported_isas = constants.supported_tags["isa"] + constants.supported_variants = constants.supported_tags["variant"] + constants.supported_lengths = constants.supported_tags["length"] + constants.supported_hosts = constants.supported_tags["host"] - constants.tempdir_fixture_name = 'tempdir' - constants.gem5_simulation_stderr = 'simerr' - constants.gem5_simulation_stdout = 'simout' - constants.gem5_simulation_stats = 'stats.txt' - constants.gem5_simulation_config_ini = 'config.ini' - constants.gem5_simulation_config_json = 'config.json' - constants.gem5_returncode_fixture_name = 'gem5-returncode' - constants.gem5_binary_fixture_name = 'gem5' - constants.xml_filename = 'results.xml' - constants.pickle_filename = 'results.pickle' + constants.tempdir_fixture_name = "tempdir" + constants.gem5_simulation_stderr = "simerr" + constants.gem5_simulation_stdout = "simout" + constants.gem5_simulation_stats = "stats.txt" + constants.gem5_simulation_config_ini = "config.ini" + constants.gem5_simulation_config_json = "config.json" + constants.gem5_returncode_fixture_name = "gem5-returncode" + constants.gem5_binary_fixture_name = "gem5" + constants.xml_filename = "results.xml" + constants.pickle_filename = "results.pickle" constants.pickle_protocol = highest_pickle_protocol # The root directory which all test names will be based off of. - constants.testing_base = absdirpath(os.path.join(absdirpath(__file__), - os.pardir)) + constants.testing_base = absdirpath( + os.path.join(absdirpath(__file__), os.pardir) + ) + def define_post_processors(config): - ''' + """ post_processors are used to do final configuration of variables. This is useful if there is a dynamically set default, or some function that needs to be applied after parsing in order to set a configration value. @@ -333,17 +345,17 @@ def define_post_processors(config): containing the already set config value or ``None`` if the config value has not been set to anything. They must return the modified value in the same format. - ''' + """ def set_default_build_dir(build_dir): - ''' + """ Post-processor to set the default build_dir based on the base_dir. .. seealso :func:`~_Config._add_post_processor` - ''' + """ if not build_dir or build_dir[0] is None: - base_dir = config._lookup_val('base_dir')[0] - build_dir = (os.path.join(base_dir, 'build'),) + base_dir = config._lookup_val("base_dir")[0] + build_dir = (os.path.join(base_dir, "build"),) return build_dir def fix_verbosity_hack(verbose): @@ -381,6 +393,7 @@ def define_post_processors(config): if not host[0]: try: import platform + host_machine = platform.machine() if host_machine not in constants.supported_hosts: raise ValueError("Invalid host machine") @@ -398,87 +411,98 @@ def define_post_processors(config): positional_tags = positional_tags[0] for flag, regex in positional_tags: - if flag == 'exclude_tags': + if flag == "exclude_tags": tag_regex = TagRegex(False, regex) - elif flag == 'include_tags': + elif flag == "include_tags": tag_regex = TagRegex(True, regex) else: - raise ValueError('Unsupported flag.') + raise ValueError("Unsupported flag.") new_positional_tags_list.append(tag_regex) return (new_positional_tags_list,) - config._add_post_processor('build_dir', set_default_build_dir) - config._add_post_processor('verbose', fix_verbosity_hack) - config._add_post_processor('isa', default_isa) - config._add_post_processor('variant', default_variant) - config._add_post_processor('length', default_length) - config._add_post_processor('host', default_host) - config._add_post_processor('threads', threads_as_int) - config._add_post_processor('test_threads', test_threads_as_int) - config._add_post_processor(StorePositionalTagsAction.position_kword, - compile_tag_regex) + config._add_post_processor("build_dir", set_default_build_dir) + config._add_post_processor("verbose", fix_verbosity_hack) + config._add_post_processor("isa", default_isa) + config._add_post_processor("variant", default_variant) + config._add_post_processor("length", default_length) + config._add_post_processor("host", default_host) + config._add_post_processor("threads", threads_as_int) + config._add_post_processor("test_threads", test_threads_as_int) + config._add_post_processor( + StorePositionalTagsAction.position_kword, compile_tag_regex + ) + + class Argument(object): - ''' + """ Class represents a cli argument/flag for a argparse parser. :attr name: The long name of this object that will be stored in the arg output by the final parser. - ''' + """ + def __init__(self, *flags, **kwargs): self.flags = flags self.kwargs = kwargs if len(flags) == 0: raise ValueError("Need at least one argument.") - elif 'dest' in kwargs: - self.name = kwargs['dest'] - elif len(flags) > 1 or flags[0].startswith('-'): + elif "dest" in kwargs: + self.name = kwargs["dest"] + elif len(flags) > 1 or flags[0].startswith("-"): for flag in flags: - if not flag.startswith('-'): - raise ValueError("invalid option string %s: must start" - "with a character '-'" % flag) + if not flag.startswith("-"): + raise ValueError( + "invalid option string %s: must start" + "with a character '-'" % flag + ) - if flag.startswith('--'): - if not hasattr(self, 'name'): - self.name = flag.lstrip('-') + if flag.startswith("--"): + if not hasattr(self, "name"): + self.name = flag.lstrip("-") - if not hasattr(self, 'name'): - self.name = flags[0].lstrip('-') - self.name = self.name.replace('-', '_') + if not hasattr(self, "name"): + self.name = flags[0].lstrip("-") + self.name = self.name.replace("-", "_") def add_to(self, parser): - '''Add this argument to the given parser.''' + """Add this argument to the given parser.""" parser.add_argument(*self.flags, **self.kwargs) def copy(self): - '''Copy this argument so you might modify any of its kwargs.''' + """Copy this argument so you might modify any of its kwargs.""" return copy.deepcopy(self) class _StickyInt: - ''' + """ A class that is used to cheat the verbosity count incrementer by pretending to be an int. This makes the int stay on the heap and eat other real numbers when they are added to it. We use this so we can allow the verbose flag to be provided before or after the subcommand. This likely has no utility outside of this use case. - ''' + """ + def __init__(self, val=0): self.val = val self.type = int + def __add__(self, other): self.val += other return self + common_args = NotImplemented + class StorePositionAction(argparse.Action): - '''Base class for classes wishing to create namespaces where + """Base class for classes wishing to create namespaces where arguments are stored in the order provided via the command line. - ''' - position_kword = 'positional' + """ + + position_kword = "positional" def __call__(self, parser, namespace, values, option_string=None): if not self.position_kword in namespace: @@ -487,120 +511,134 @@ class StorePositionAction(argparse.Action): previous.append((self.dest, values)) setattr(namespace, self.position_kword, previous) + class StorePositionalTagsAction(StorePositionAction): - position_kword = 'tag_filters' + position_kword = "tag_filters" + def define_common_args(config): - ''' + """ Common args are arguments which are likely to be simular between different subcommands, so they are available to all by placing their definitions here. - ''' + """ global common_args - parse_comma_separated_string = lambda st: st.split(',') + parse_comma_separated_string = lambda st: st.split(",") # A list of common arguments/flags used across cli parsers. common_args = [ Argument( - 'directories', - nargs='*', + "directories", + nargs="*", default=[os.getcwd()], - help='Space separated list of directories to start searching ' - 'for tests in'), + help="Space separated list of directories to start searching " + "for tests in", + ), Argument( - '--exclude-tags', + "--exclude-tags", action=StorePositionalTagsAction, - help='A tag comparison used to select tests.'), + help="A tag comparison used to select tests.", + ), Argument( - '--include-tags', + "--include-tags", action=StorePositionalTagsAction, - help='A tag comparison used to select tests.'), + help="A tag comparison used to select tests.", + ), Argument( - '--isa', - action='extend', + "--isa", + action="extend", default=[], type=parse_comma_separated_string, help="Only tests that are valid with one of these ISAs. " - "Comma separated."), + "Comma separated.", + ), Argument( - '--variant', - action='extend', + "--variant", + action="extend", default=[], type=parse_comma_separated_string, help="Only tests that are valid with one of these binary variants" - "(e.g., opt, debug). Comma separated."), + "(e.g., opt, debug). Comma separated.", + ), Argument( - '--length', - action='extend', + "--length", + action="extend", default=[], type=parse_comma_separated_string, - help="Only tests that are one of these lengths. Comma separated."), + help="Only tests that are one of these lengths. Comma separated.", + ), Argument( - '--host', - action='append', + "--host", + action="append", default=[], - help="Only tests that are meant to runnable on the selected host"), + help="Only tests that are meant to runnable on the selected host", + ), Argument( - '--uid', - action='store', + "--uid", + action="store", default=None, - help='UID of a specific test item to run.'), + help="UID of a specific test item to run.", + ), Argument( - '--build-dir', - action='store', - help='Build directory for SCons'), + "--build-dir", action="store", help="Build directory for SCons" + ), Argument( - '--base-dir', - action='store', + "--base-dir", + action="store", default=config._defaults.base_dir, - help='Directory to change to in order to exec scons.'), + help="Directory to change to in order to exec scons.", + ), Argument( - '-j', '--threads', - action='store', + "-j", + "--threads", + action="store", default=1, - help='Number of threads to run SCons with.'), + help="Number of threads to run SCons with.", + ), Argument( - '-t', '--test-threads', - action='store', + "-t", + "--test-threads", + action="store", default=1, - help='Number of threads to spawn to run concurrent tests with.'), + help="Number of threads to spawn to run concurrent tests with.", + ), Argument( - '-v', - action='count', - dest='verbose', + "-v", + action="count", + dest="verbose", default=_StickyInt(), - help='Increase verbosity'), + help="Increase verbosity", + ), Argument( - '--config-path', - action='store', + "--config-path", + action="store", default=os.getcwd(), - help='Path to read a testing.ini config in' + help="Path to read a testing.ini config in", ), Argument( - '--skip-build', - action='store_true', + "--skip-build", + action="store_true", default=False, - help='Skip the building component of SCons targets.' + help="Skip the building component of SCons targets.", ), Argument( - '--result-path', - action='store', - help='The path to store results in.' + "--result-path", + action="store", + help="The path to store results in.", ), Argument( - '--bin-path', - action='store', + "--bin-path", + action="store", default=config._defaults.resource_path, - help='Path where resources are stored (downloaded if not present)' + help="Path where resources are stored (downloaded if not present)", ), Argument( - '--resource-url', - action='store', + "--resource-url", + action="store", default=config._defaults.resource_url, - help='The URL where the resources reside.' + help="The URL where the resources reside.", ), - ] # NOTE: There is a limitation which arises due to this format. If you have @@ -610,7 +648,8 @@ def define_common_args(config): # e.g. if you have a -v argument which increments verbosity level and # a separate --verbose flag which 'store's verbosity level. the final # one in the list will be saved. - common_args = AttrDict({arg.name:arg for arg in common_args}) + common_args = AttrDict({arg.name: arg for arg in common_args}) + class ArgParser(object, metaclass=abc.ABCMeta): class ExtendAction(argparse.Action): @@ -622,10 +661,10 @@ class ArgParser(object, metaclass=abc.ABCMeta): def __init__(self, parser): # Copy public methods of the parser. for attr in dir(parser): - if not attr.startswith('_'): + if not attr.startswith("_"): setattr(self, attr, getattr(parser, attr)) self.parser = parser - self.parser.register('action', 'extend', ArgParser.ExtendAction) + self.parser.register("action", "extend", ArgParser.ExtendAction) self.add_argument = self.parser.add_argument # Argument will be added to all parsers and subparsers. @@ -633,25 +672,24 @@ class ArgParser(object, metaclass=abc.ABCMeta): class CommandParser(ArgParser): - ''' + """ Main parser which parses command strings and uses those to direct to a subparser. - ''' + """ + def __init__(self): parser = argparse.ArgumentParser() super(CommandParser, self).__init__(parser) - self.subparser = self.add_subparsers(dest='command') + self.subparser = self.add_subparsers(dest="command") class RunParser(ArgParser): - ''' + """ Parser for the \'run\' command. - ''' + """ + def __init__(self, subparser): - parser = subparser.add_parser( - 'run', - help='''Run Tests.''' - ) + parser = subparser.add_parser("run", help="""Run Tests.""") super(RunParser, self).__init__(parser) @@ -672,46 +710,46 @@ class RunParser(ArgParser): class ListParser(ArgParser): - ''' + """ Parser for the \'list\' command. - ''' + """ + def __init__(self, subparser): parser = subparser.add_parser( - 'list', - help='''List and query test metadata.''' + "list", help="""List and query test metadata.""" ) super(ListParser, self).__init__(parser) Argument( - '--suites', - action='store_true', + "--suites", + action="store_true", default=False, - help='List all test suites.' + help="List all test suites.", ).add_to(parser) Argument( - '--tests', - action='store_true', + "--tests", + action="store_true", default=False, - help='List all test cases.' + help="List all test cases.", ).add_to(parser) Argument( - '--fixtures', - action='store_true', + "--fixtures", + action="store_true", default=False, - help='List all fixtures.' + help="List all fixtures.", ).add_to(parser) Argument( - '--all-tags', - action='store_true', + "--all-tags", + action="store_true", default=False, - help='List all tags.' + help="List all tags.", ).add_to(parser) Argument( - '-q', - dest='quiet', - action='store_true', + "-q", + dest="quiet", + action="store_true", default=False, - help='Quiet output (machine readable).' + help="Quiet output (machine readable).", ).add_to(parser) common_args.directories.add_to(parser) @@ -726,10 +764,7 @@ class ListParser(ArgParser): class RerunParser(ArgParser): def __init__(self, subparser): - parser = subparser.add_parser( - 'rerun', - help='''Rerun failed tests.''' - ) + parser = subparser.add_parser("rerun", help="""Rerun failed tests.""") super(RerunParser, self).__init__(parser) common_args.skip_build.add_to(parser) @@ -744,6 +779,7 @@ class RerunParser(ArgParser): common_args.length.add_to(parser) common_args.host.add_to(parser) + config = _Config() define_constants(config.constants) @@ -752,14 +788,16 @@ define_constants(config.constants) config.constants = FrozenAttrDict(config.constants.__dict__) constants = config.constants -''' +""" This config object is the singleton config object available throughout the framework. -''' +""" + + def initialize_config(): - ''' + """ Parse the commandline arguments and setup the config varibles. - ''' + """ global config # Setup constants and defaults diff --git a/ext/testlib/fixture.py b/ext/testlib/fixture.py index bcd22d9220..148229a597 100644 --- a/ext/testlib/fixture.py +++ b/ext/testlib/fixture.py @@ -28,16 +28,18 @@ import testlib.helper as helper + class SkipException(Exception): def __init__(self, fixture, testitem): self.msg = 'Fixture "%s" raised SkipException for "%s".' % ( - fixture.name, testitem.name + fixture.name, + testitem.name, ) super(SkipException, self).__init__(self.msg) class Fixture(object): - ''' + """ Base Class for a test Fixture. Fixtures are items which possibly require setup and/or tearing down after @@ -50,7 +52,8 @@ class Fixture(object): .. note:: In order for Fixtures to be enumerated by the test system this class' :code:`__new__` method must be called. - ''' + """ + collector = helper.InstanceCollector() def __new__(klass, *args, **kwargs): diff --git a/ext/testlib/handlers.py b/ext/testlib/handlers.py index fa7aea9c89..029ac8baa4 100644 --- a/ext/testlib/handlers.py +++ b/ext/testlib/handlers.py @@ -26,11 +26,11 @@ # # Authors: Sean Wilson -''' +""" Handlers for the testlib Log. -''' +""" import multiprocessing import os import sys @@ -54,9 +54,10 @@ class _TestStreamManager(object): def open_writer(self, test_result): if test_result in self._writers: - raise ValueError('Cannot have multiple writters on a single test.') - self._writers[test_result] = _TestStreams(test_result.stdout, - test_result.stderr) + raise ValueError("Cannot have multiple writters on a single test.") + self._writers[test_result] = _TestStreams( + test_result.stdout, test_result.stderr + ) def get_writer(self, test_result): if test_result not in self._writers: @@ -73,89 +74,94 @@ class _TestStreamManager(object): writer.close() self._writers.clear() + class _TestStreams(object): def __init__(self, stdout, stderr): helper.mkdir_p(os.path.dirname(stdout)) helper.mkdir_p(os.path.dirname(stderr)) - self.stdout = open(stdout, 'w') - self.stderr = open(stderr, 'w') + self.stdout = open(stdout, "w") + self.stderr = open(stderr, "w") def close(self): self.stdout.close() self.stderr.close() + class ResultHandler(object): - ''' + """ Log handler which listens for test results and output saving data as it is reported. When the handler is closed it writes out test results in the python pickle format. - ''' + """ + def __init__(self, schedule, directory): - ''' + """ :param schedule: The entire schedule as a :class:`LoadedLibrary` object. :param directory: Directory to save test stdout/stderr and aggregate results to. - ''' + """ self.directory = directory - self.internal_results = result.InternalLibraryResults(schedule, - directory) + self.internal_results = result.InternalLibraryResults( + schedule, directory + ) self.test_stream_manager = _TestStreamManager() self._closed = False self.mapping = { log.LibraryStatus.type_id: self.handle_library_status, - log.SuiteResult.type_id: self.handle_suite_result, log.TestResult.type_id: self.handle_test_result, - log.TestStderr.type_id: self.handle_stderr, log.TestStdout.type_id: self.handle_stdout, } def handle(self, record): if not self._closed: - self.mapping.get(record.type_id, lambda _:None)(record) + self.mapping.get(record.type_id, lambda _: None)(record) def handle_library_status(self, record): - if record['status'] in (state.Status.Complete, state.Status.Avoided): + if record["status"] in (state.Status.Complete, state.Status.Avoided): self.test_stream_manager.close() def handle_suite_result(self, record): suite_result = self.internal_results.get_suite_result( - record['metadata'].uid) - suite_result.result = record['result'] + record["metadata"].uid + ) + suite_result.result = record["result"] def handle_test_result(self, record): test_result = self._get_test_result(record) - test_result.result = record['result'] + test_result.result = record["result"] def handle_stderr(self, record): self.test_stream_manager.get_writer( self._get_test_result(record) - ).stderr.write(record['buffer']) + ).stderr.write(record["buffer"]) def handle_stdout(self, record): self.test_stream_manager.get_writer( self._get_test_result(record) - ).stdout.write(record['buffer']) + ).stdout.write(record["buffer"]) def _get_test_result(self, test_record): return self.internal_results.get_test_result( - test_record['metadata'].uid, - test_record['metadata'].suite_uid) + test_record["metadata"].uid, test_record["metadata"].suite_uid + ) def _save(self): - #FIXME Hardcoded path name + # FIXME Hardcoded path name result.InternalSavedResults.save( self.internal_results, - os.path.join(self.directory, constants.pickle_filename)) + os.path.join(self.directory, constants.pickle_filename), + ) result.JUnitSavedResults.save( self.internal_results, - os.path.join(self.directory, constants.xml_filename)) + os.path.join(self.directory, constants.xml_filename), + ) def close(self): if self._closed: @@ -164,11 +170,11 @@ class ResultHandler(object): self._save() def unsuccessful(self): - ''' + """ Performs an or reduce on all of the results. Returns true if at least one test is unsuccessful, false when all tests pass - ''' + """ for suite_result in self.internal_results: if suite_result.unsuccessful: return True @@ -176,20 +182,21 @@ class ResultHandler(object): return False -#TODO Change from a handler to an internal post processor so it can be used +# TODO Change from a handler to an internal post processor so it can be used # to reprint results class SummaryHandler(object): - ''' + """ A log handler which listens to the log for test results and reports the aggregate results when closed. - ''' + """ + color = terminal.get_termcap() reset = color.Normal colormap = { - state.Result.Errored: color.Red, - state.Result.Failed: color.Red, - state.Result.Passed: color.Green, - state.Result.Skipped: color.Cyan, + state.Result.Errored: color.Red, + state.Result.Failed: color.Red, + state.Result.Passed: color.Green, + state.Result.Skipped: color.Cyan, } def __init__(self): @@ -201,24 +208,28 @@ class SummaryHandler(object): self.results = [] def handle_library_status(self, record): - if record['status'] == state.Status.Building: + if record["status"] == state.Status.Building: self._timer.restart() def handle_testresult(self, record): - result = record['result'].value - if result in (state.Result.Skipped, state.Result.Failed, - state.Result.Passed, state.Result.Errored): + result = record["result"].value + if result in ( + state.Result.Skipped, + state.Result.Failed, + state.Result.Passed, + state.Result.Errored, + ): self.results.append(result) def handle(self, record): - self.mapping.get(record.type_id, lambda _:None)(record) + self.mapping.get(record.type_id, lambda _: None)(record) def close(self): print(self._display_summary()) def _display_summary(self): most_severe_outcome = None - outcome_fmt = ' {count} {outcome}' + outcome_fmt = " {count} {outcome}" strings = [] outcome_count = [0] * len(state.Result.enums) @@ -228,22 +239,29 @@ class SummaryHandler(object): # Iterate over enums so they are in order of severity for outcome in state.Result.enums: outcome = getattr(state.Result, outcome) - count = outcome_count[outcome] + count = outcome_count[outcome] if count: - strings.append(outcome_fmt.format(count=count, - outcome=state.Result.enums[outcome])) + strings.append( + outcome_fmt.format( + count=count, outcome=state.Result.enums[outcome] + ) + ) most_severe_outcome = outcome - string = ','.join(strings) + string = ",".join(strings) if most_severe_outcome is None: - string = ' No testing done' + string = " No testing done" most_severe_outcome = state.Result.Passed else: - string = ' Results:' + string + ' in {:.2} seconds '.format( - self._timer.active_time()) - string += ' ' + string = ( + " Results:" + + string + + " in {:.2} seconds ".format(self._timer.active_time()) + ) + string += " " return terminal.insert_separator( - string, - color=self.colormap[most_severe_outcome] + self.color.Bold) + string, color=self.colormap[most_severe_outcome] + self.color.Bold + ) + class TerminalHandler(object): color = terminal.get_termcap() @@ -268,75 +286,85 @@ class TerminalHandler(object): } def _display_outcome(self, name, outcome, reason=None): - print(self.color.Bold - + SummaryHandler.colormap[outcome] - + name - + ' ' - + state.Result.enums[outcome] - + SummaryHandler.reset) + print( + self.color.Bold + + SummaryHandler.colormap[outcome] + + name + + " " + + state.Result.enums[outcome] + + SummaryHandler.reset + ) if reason is not None: - log.test_log.info('') - log.test_log.info('Reason:') + log.test_log.info("") + log.test_log.info("Reason:") log.test_log.info(reason) - log.test_log.info(terminal.separator('-')) + log.test_log.info(terminal.separator("-")) def handle_teststatus(self, record): - if record['status'] == state.Status.Running: - log.test_log.debug('Starting Test Case: %s' %\ - record['metadata'].name) + if record["status"] == state.Status.Running: + log.test_log.debug( + "Starting Test Case: %s" % record["metadata"].name + ) def handle_testresult(self, record): self._display_outcome( - 'Test: %s' % record['metadata'].name, - record['result'].value) + "Test: %s" % record["metadata"].name, record["result"].value + ) def handle_suitestatus(self, record): - if record['status'] == state.Status.Running: - log.test_log.debug('Starting Test Suite: %s ' %\ - record['metadata'].name) + if record["status"] == state.Status.Running: + log.test_log.debug( + "Starting Test Suite: %s " % record["metadata"].name + ) def handle_stderr(self, record): if self.stream: - print(record.data['buffer'], file=sys.stderr, end='') + print(record.data["buffer"], file=sys.stderr, end="") def handle_stdout(self, record): if self.stream: - print(record.data['buffer'], file=sys.stdout, end='') + print(record.data["buffer"], file=sys.stdout, end="") def handle_testmessage(self, record): if self.stream: - print(self._colorize(record['message'], record['level'])) + print(self._colorize(record["message"], record["level"])) def handle_librarymessage(self, record): - if not self.machine_only or record.data.get('machine_readable', False): - print(self._colorize(record['message'], record['level'], - record['bold'])) + if not self.machine_only or record.data.get("machine_readable", False): + print( + self._colorize( + record["message"], record["level"], record["bold"] + ) + ) def _colorize(self, message, level, bold=False): - return '%s%s%s%s' % ( - self.color.Bold if bold else '', - self.verbosity_mapping.get(level, ''), - message, - self.default) + return "%s%s%s%s" % ( + self.color.Bold if bold else "", + self.verbosity_mapping.get(level, ""), + message, + self.default, + ) def handle(self, record): - if record.data.get('level', self.verbosity) > self.verbosity: + if record.data.get("level", self.verbosity) > self.verbosity: return - self.mapping.get(record.type_id, lambda _:None)(record) + self.mapping.get(record.type_id, lambda _: None)(record) def close(self): pass + class MultiprocessingHandlerWrapper(object): - ''' + """ A handler class which forwards log records to subhandlers, enabling logging across multiprocessing python processes. The 'parent' side of the handler should execute either :func:`async_process` or :func:`process` to forward log records to subhandlers. - ''' + """ + def __init__(self, *subhandlers): # Create thread to spin handing recipt of messages # Create queue to push onto @@ -350,7 +378,7 @@ class MultiprocessingHandlerWrapper(object): def add_handler(self, handler): self._handler_lock.acquire() - self._subhandlers = (handler, ) + self._subhandlers + self._subhandlers = (handler,) + self._subhandlers self._handler_lock.release() def _with_handlers(self, callback): @@ -405,7 +433,7 @@ class MultiprocessingHandlerWrapper(object): self.queue.put(record) def _close(self): - if hasattr(self, 'thread'): + if hasattr(self, "thread"): self.thread.join() _wrap(self._drain) self._with_handlers(lambda handler: _wrap(handler.close)) @@ -415,9 +443,9 @@ class MultiprocessingHandlerWrapper(object): # This sleep adds some time for the sender threads on this process to # finish pickling the object and complete shutdown after the queue is # closed. - time.sleep(.2) + time.sleep(0.2) self.queue.close() - time.sleep(.2) + time.sleep(0.2) def close(self): if not self._shutdown.is_set(): diff --git a/ext/testlib/helper.py b/ext/testlib/helper.py index ea102f262b..6b5194bd97 100644 --- a/ext/testlib/helper.py +++ b/ext/testlib/helper.py @@ -38,9 +38,9 @@ # # Authors: Sean Wilson -''' +""" Helper classes for writing tests with this test library. -''' +""" from collections import namedtuple from collections.abc import MutableSet @@ -55,6 +55,7 @@ import tempfile import threading import time + class TimedWaitPID(object): """Utility to monkey-patch os.waitpid() with os.wait4(). @@ -69,7 +70,8 @@ class TimedWaitPID(object): it is read. """ - TimeRecord = namedtuple( "_TimeRecord", "user_time system_time" ) + + TimeRecord = namedtuple("_TimeRecord", "user_time system_time") class Wrapper(object): def __init__(self): @@ -79,11 +81,8 @@ class TimedWaitPID(object): def __call__(self, pid, options): pid, status, resource_usage = os.wait4(pid, options) with self._access_lock: - self._time_for_pid[pid] = ( - TimedWaitPID.TimeRecord( - resource_usage.ru_utime, - resource_usage.ru_stime - ) + self._time_for_pid[pid] = TimedWaitPID.TimeRecord( + resource_usage.ru_utime, resource_usage.ru_stime ) return (pid, status) @@ -108,14 +107,14 @@ class TimedWaitPID(object): with TimedWaitPID._wrapper_lock: if TimedWaitPID._wrapper is None: TimedWaitPID._wrapper = TimedWaitPID.Wrapper() - if TimedWaitPID._original_os_waitpid is None : + if TimedWaitPID._original_os_waitpid is None: TimedWaitPID._original_os_waitpid = os.waitpid os.waitpid = TimedWaitPID._wrapper @staticmethod def restore(): with TimedWaitPID._wrapper_lock: - if TimedWaitPID._original_os_waitpid is not None : + if TimedWaitPID._original_os_waitpid is not None: os.waitpid = TimedWaitPID._original_os_waitpid TimedWaitPID._original_os_waitpid = None @@ -129,12 +128,13 @@ class TimedWaitPID(object): with TimedWaitPID._wrapper_lock: return TimedWaitPID._wrapper.get_time_for_pid(pid) + # Patch os.waitpid() TimedWaitPID.install() -#TODO Tear out duplicate logic from the sandbox IOManager +# TODO Tear out duplicate logic from the sandbox IOManager def log_call(logger, command, time, *popenargs, **kwargs): - ''' + """ Calls the given process and automatically logs the command and output. If stdout or stderr are provided output will also be piped into those @@ -145,7 +145,7 @@ def log_call(logger, command, time, *popenargs, **kwargs): :params stderr: Iterable of items to write to as we read from the subprocess. - ''' + """ if isinstance(command, str): cmdstr = command else: @@ -159,33 +159,35 @@ def log_call(logger, command, time, *popenargs, **kwargs): raise e logger_callback = logger.trace - logger.trace('Logging call to command: %s' % cmdstr) + logger.trace("Logging call to command: %s" % cmdstr) - stdout_redirect = kwargs.get('stdout', tuple()) - stderr_redirect = kwargs.get('stderr', tuple()) + stdout_redirect = kwargs.get("stdout", tuple()) + stderr_redirect = kwargs.get("stderr", tuple()) - if hasattr(stdout_redirect, 'write'): + if hasattr(stdout_redirect, "write"): stdout_redirect = (stdout_redirect,) - if hasattr(stderr_redirect, 'write'): + if hasattr(stderr_redirect, "write"): stderr_redirect = (stderr_redirect,) - kwargs['stdout'] = subprocess.PIPE - kwargs['stderr'] = subprocess.PIPE + kwargs["stdout"] = subprocess.PIPE + kwargs["stderr"] = subprocess.PIPE p = subprocess.Popen(command, *popenargs, **kwargs) def log_output(log_callback, pipe, redirects=tuple()): # Read iteractively, don't allow input to fill the pipe. - for line in iter(pipe.readline, b''): + for line in iter(pipe.readline, b""): line = line.decode("utf-8") for r in redirects: r.write(line) log_callback(line.rstrip()) - stdout_thread = threading.Thread(target=log_output, - args=(logger_callback, p.stdout, stdout_redirect)) + stdout_thread = threading.Thread( + target=log_output, args=(logger_callback, p.stdout, stdout_redirect) + ) stdout_thread.setDaemon(True) - stderr_thread = threading.Thread(target=log_output, - args=(logger_callback, p.stderr, stderr_redirect)) + stderr_thread = threading.Thread( + target=log_output, args=(logger_callback, p.stderr, stderr_redirect) + ) stderr_thread.setDaemon(True) stdout_thread.start() @@ -197,25 +199,26 @@ def log_call(logger, command, time, *popenargs, **kwargs): if time is not None and TimedWaitPID.has_time_for_pid(p.pid): resource_usage = TimedWaitPID.get_time_for_pid(p.pid) - time['user_time'] = resource_usage.user_time - time['system_time'] = resource_usage.system_time + time["user_time"] = resource_usage.user_time + time["system_time"] = resource_usage.system_time # Return the return exit code of the process. if retval != 0: raise subprocess.CalledProcessError(retval, cmdstr) + # lru_cache stuff (Introduced in python 3.2+) # Renamed and modified to cacheresult class _HashedSeq(list): - ''' + """ This class guarantees that hash() will be called no more than once per element. This is important because the cacheresult() will hash the key multiple times on a cache miss. .. note:: From cpython 3.7 - ''' + """ - __slots__ = 'hashvalue' + __slots__ = "hashvalue" def __init__(self, tup, hash=hash): self[:] = tup @@ -224,11 +227,18 @@ class _HashedSeq(list): def __hash__(self): return self.hashvalue -def _make_key(args, kwds, typed, - kwd_mark = (object(),), - fasttypes = {int, str, frozenset, type(None)}, - tuple=tuple, type=type, len=len): - ''' + +def _make_key( + args, + kwds, + typed, + kwd_mark=(object(),), + fasttypes={int, str, frozenset, type(None)}, + tuple=tuple, + type=type, + len=len, +): + """ Make a cache key from optionally typed positional and keyword arguments. The key is constructed in a way that is flat as possible rather than as a nested structure that would take more memory. If there is only a single @@ -237,7 +247,7 @@ def _make_key(args, kwds, typed, lookup speed. .. note:: From cpython 3.7 - ''' + """ key = args if kwds: key += kwd_mark @@ -253,15 +263,16 @@ def _make_key(args, kwds, typed, def cacheresult(function, typed=False): - ''' + """ :param typed: If typed is True, arguments of different types will be cached separately. I.e. f(3.0) and f(3) will be treated as distinct calls with distinct results. .. note:: From cpython 3.7 - ''' - sentinel = object() # unique object used to signal cache misses + """ + sentinel = object() # unique object used to signal cache misses cache = {} + def wrapper(*args, **kwds): # Simple caching without ordering or size limit key = _make_key(args, kwds, typed) @@ -271,19 +282,21 @@ def cacheresult(function, typed=False): result = function(*args, **kwds) cache[key] = result return result + return wrapper + class OrderedSet(MutableSet): - ''' + """ Maintain ordering of insertion in items to the set with quick iteration. http://code.activestate.com/recipes/576694/ - ''' + """ def __init__(self, iterable=None): self.end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.map = {} # key --> [key, prev, next] + end += [None, end, end] # sentinel node for doubly linked list + self.map = {} # key --> [key, prev, next] if iterable is not None: self |= iterable @@ -325,35 +338,38 @@ class OrderedSet(MutableSet): def pop(self, last=True): if not self: - raise KeyError('set is empty') + raise KeyError("set is empty") key = self.end[1][0] if last else self.end[2][0] self.discard(key) return key def __repr__(self): if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, list(self)) + return "%s()" % (self.__class__.__name__,) + return "%s(%r)" % (self.__class__.__name__, list(self)) def __eq__(self, other): if isinstance(other, OrderedSet): return len(self) == len(other) and list(self) == list(other) return set(self) == set(other) + def absdirpath(path): - ''' + """ Return the directory component of the absolute path of the given path. - ''' + """ return os.path.dirname(os.path.abspath(path)) + joinpath = os.path.join + def mkdir_p(path): - ''' + """ Same thing as mkdir -p https://stackoverflow.com/a/600612 - ''' + """ try: os.makedirs(path) except OSError as exc: # Python >2.5 @@ -364,12 +380,14 @@ def mkdir_p(path): class FrozenSetException(Exception): - '''Signals one tried to set a value in a 'frozen' object.''' + """Signals one tried to set a value in a 'frozen' object.""" + pass class AttrDict(object): - '''Object which exposes its own internal dictionary through attributes.''' + """Object which exposes its own internal dictionary through attributes.""" + def __init__(self, dict_={}): self.update(dict_) @@ -377,7 +395,7 @@ class AttrDict(object): dict_ = self.__dict__ if attr in dict_: return dict_[attr] - raise AttributeError('Could not find %s attribute' % attr) + raise AttributeError("Could not find %s attribute" % attr) def __setattr__(self, attr, val): self.__dict__[attr] = val @@ -393,8 +411,10 @@ class AttrDict(object): class FrozenAttrDict(AttrDict): - '''An AttrDict whose attributes cannot be modified directly.''' + """An AttrDict whose attributes cannot be modified directly.""" + __initialized = False + def __init__(self, dict_={}): super(FrozenAttrDict, self).__init__(dict_) self.__initialized = True @@ -402,20 +422,22 @@ class FrozenAttrDict(AttrDict): def __setattr__(self, attr, val): if self.__initialized: raise FrozenSetException( - 'Cannot modify an attribute in a FozenAttrDict') + "Cannot modify an attribute in a FozenAttrDict" + ) else: super(FrozenAttrDict, self).__setattr__(attr, val) def update(self, items): if self.__initialized: raise FrozenSetException( - 'Cannot modify an attribute in a FozenAttrDict') + "Cannot modify an attribute in a FozenAttrDict" + ) else: super(FrozenAttrDict, self).update(items) class InstanceCollector(object): - ''' + """ A class used to simplify collecting of Classes. >> instance_list = collector.create() @@ -423,7 +445,8 @@ class InstanceCollector(object): >> # instance_list contains all instances created since >> # collector.create was called >> collector.remove(instance_list) - ''' + """ + def __init__(self): self.collectors = [] @@ -441,14 +464,15 @@ class InstanceCollector(object): def append_dictlist(dict_, key, value): - ''' + """ Append the `value` to a list associated with `key` in `dict_`. If `key` doesn't exist, create a new list in the `dict_` with value in it. - ''' + """ list_ = dict_.get(key, []) list_.append(value) dict_[key] = list_ + def _filter_file(fname, filters): with open(fname, "r") as file_: for line in file_: @@ -460,19 +484,19 @@ def _filter_file(fname, filters): def _copy_file_keep_perms(source, target): - '''Copy a file keeping the original permisions of the target.''' + """Copy a file keeping the original permisions of the target.""" st = os.stat(target) shutil.copy2(source, target) os.chown(target, st[stat.ST_UID], st[stat.ST_GID]) def _filter_file_inplace(fname, dir, filters): - ''' + """ Filter the given file writing filtered lines out to a temporary file, then copy that tempfile back into the original file. - ''' + """ (_, tfname) = tempfile.mkstemp(dir=dir, text=True) - with open(tfname, 'w') as tempfile_: + with open(tfname, "w") as tempfile_: for line in _filter_file(fname, filters): tempfile_.write(line) @@ -481,39 +505,45 @@ def _filter_file_inplace(fname, dir, filters): def diff_out_file(ref_file, out_file, logger, ignore_regexes=tuple()): - '''Diff two files returning the diff as a string.''' + """Diff two files returning the diff as a string.""" if not os.path.exists(ref_file): - raise OSError("%s doesn't exist in reference directory"\ - % ref_file) + raise OSError("%s doesn't exist in reference directory" % ref_file) if not os.path.exists(out_file): raise OSError("%s doesn't exist in output directory" % out_file) _filter_file_inplace(out_file, os.path.dirname(out_file), ignore_regexes) _filter_file_inplace(ref_file, os.path.dirname(out_file), ignore_regexes) - #try : + # try : (_, tfname) = tempfile.mkstemp(dir=os.path.dirname(out_file), text=True) - with open(tfname, 'r+') as tempfile_: + with open(tfname, "r+") as tempfile_: try: - log_call(logger, ['diff', out_file, ref_file], - time=None, stdout=tempfile_) + log_call( + logger, + ["diff", out_file, ref_file], + time=None, + stdout=tempfile_, + ) except OSError: # Likely signals that diff does not exist on this system. fallback # to difflib - with open(out_file, 'r') as outf, open(ref_file, 'r') as reff: - diff = difflib.unified_diff(iter(reff.readline, ''), - iter(outf.readline, ''), - fromfile=ref_file, - tofile=out_file) - return ''.join(diff) + with open(out_file, "r") as outf, open(ref_file, "r") as reff: + diff = difflib.unified_diff( + iter(reff.readline, ""), + iter(outf.readline, ""), + fromfile=ref_file, + tofile=out_file, + ) + return "".join(diff) except subprocess.CalledProcessError: tempfile_.seek(0) - return ''.join(tempfile_.readlines()) + return "".join(tempfile_.readlines()) else: return None -class Timer(): + +class Timer: def __init__(self): self.restart() diff --git a/ext/testlib/loader.py b/ext/testlib/loader.py index 58b1b2e777..f5eacfc2ce 100644 --- a/ext/testlib/loader.py +++ b/ext/testlib/loader.py @@ -26,7 +26,7 @@ # # Authors: Sean Wilson -''' +""" Contains the :class:`Loader` which is responsible for discovering and loading tests. @@ -63,7 +63,7 @@ a :class:`TestSuite` by the test writer will be placed into a :class:`TestSuite` named after the module. .. seealso:: :func:`load_file` -''' +""" import os import re @@ -77,44 +77,52 @@ import testlib.fixture as fixture_mod import testlib.wrappers as wrappers import testlib.uid as uid + class DuplicateTestItemException(Exception): - ''' + """ Exception indicates multiple test items with the same UID were discovered. - ''' + """ + pass # Match filenames that either begin or end with 'test' or tests and use # - or _ to separate additional name components. default_filepath_regex = re.compile( - r'(((.+[_])?tests?)|(tests?([-_].+)?))\.py$') + r"(((.+[_])?tests?)|(tests?([-_].+)?))\.py$" +) + def default_filepath_filter(filepath): - '''The default filter applied to filepaths to marks as test sources.''' + """The default filter applied to filepaths to marks as test sources.""" filepath = os.path.basename(filepath) if default_filepath_regex.match(filepath): # Make sure doesn't start with . - return not filepath.startswith('.') + return not filepath.startswith(".") return False + def path_as_modulename(filepath): - '''Return the given filepath as a module name.''' + """Return the given filepath as a module name.""" # Remove the file extention (.py) return os.path.splitext(os.path.basename(filepath))[0] + def path_as_suitename(filepath): return os.path.split(os.path.dirname(os.path.abspath((filepath))))[-1] + def _assert_files_in_same_dir(files): if __debug__: if files: directory = os.path.dirname(files[0]) for f in files: - assert(os.path.dirname(f) == directory) + assert os.path.dirname(f) == directory + class Loader(object): - ''' + """ Class for discovering tests. Discovered :class:`TestCase` and :class:`TestSuite` objects are wrapped by @@ -135,7 +143,8 @@ class Loader(object): .. warn:: This class is extremely thread-unsafe. It modifies the sys path and global config. Use with care. - ''' + """ + def __init__(self): self.suites = [] self.suite_uids = {} @@ -153,16 +162,15 @@ class Loader(object): for file_ in files: self.load_file(file_) - return wrappers.LoadedLibrary( - [self.suite_uids[id_] for id_ in uids]) + return wrappers.LoadedLibrary([self.suite_uids[id_] for id_ in uids]) def _verify_no_duplicate_suites(self, new_suites): new_suite_uids = self.suite_uids.copy() for suite in new_suites: if suite.uid in new_suite_uids: raise DuplicateTestItemException( - "More than one suite with UID '%s' was defined" %\ - suite.uid) + "More than one suite with UID '%s' was defined" % suite.uid + ) new_suite_uids[suite.uid] = suite def _verify_no_duplicate_tests_in_suites(self, new_suites): @@ -170,17 +178,17 @@ class Loader(object): test_uids = set() for test in suite: if test.uid in test_uids: - raise DuplicateTestItemException( - "More than one test with UID '%s' was defined" - " in suite '%s'" - % (test.uid, suite.uid)) + raise DuplicateTestItemException( + "More than one test with UID '%s' was defined" + " in suite '%s'" % (test.uid, suite.uid) + ) test_uids.add(test.uid) def load_root(self, root): - ''' + """ Load files from the given root directory which match `self.filepath_filter`. - ''' + """ for directory in self._discover_files(root): directory = list(directory) if directory: @@ -193,17 +201,18 @@ class Loader(object): if path in self._files: if not self._files[path]: - raise Exception('Attempted to load a file which already' - ' failed to load') + raise Exception( + "Attempted to load a file which already" " failed to load" + ) else: - log.test_log.debug('Tried to reload: %s' % path) + log.test_log.debug("Tried to reload: %s" % path) return # Create a custom dictionary for the loaded module. newdict = { - '__builtins__':__builtins__, - '__name__': path_as_modulename(path), - '__file__': path, + "__builtins__": __builtins__, + "__name__": path_as_modulename(path), + "__file__": path, } # Add the file's containing directory to the system path. So it can do @@ -222,9 +231,9 @@ class Loader(object): except Exception as e: log.test_log.debug(traceback.format_exc()) log.test_log.warn( - 'Exception thrown while loading "%s"\n' - 'Ignoring all tests in this file.' - % (path)) + 'Exception thrown while loading "%s"\n' + "Ignoring all tests in this file." % (path) + ) # Clean up sys.path[:] = old_path os.chdir(cwd) @@ -247,27 +256,34 @@ class Loader(object): # tests. # NOTE: This is automatically collected (we still have the # collector active.) - suite_mod.TestSuite(tests=orphan_tests, - name=path_as_suitename(path)) + suite_mod.TestSuite( + tests=orphan_tests, name=path_as_suitename(path) + ) try: - loaded_suites = [wrappers.LoadedSuite(suite, path) - for suite in new_suites] + loaded_suites = [ + wrappers.LoadedSuite(suite, path) for suite in new_suites + ] self._verify_no_duplicate_suites(loaded_suites) self._verify_no_duplicate_tests_in_suites(loaded_suites) except Exception as e: - log.test_log.warn('%s\n' - 'Exception thrown while loading "%s"\n' - 'Ignoring all tests in this file.' - % (traceback.format_exc(), path)) + log.test_log.warn( + "%s\n" + 'Exception thrown while loading "%s"\n' + "Ignoring all tests in this file." + % (traceback.format_exc(), path) + ) else: - log.test_log.info('Discovered %d tests and %d suites in %s' - '' % (len(new_tests), len(loaded_suites), path)) + log.test_log.info( + "Discovered %d tests and %d suites in %s" + "" % (len(new_tests), len(loaded_suites), path) + ) self.suites.extend(loaded_suites) - self.suite_uids.update({suite.uid: suite - for suite in loaded_suites}) + self.suite_uids.update( + {suite.uid: suite for suite in loaded_suites} + ) # Clean up sys.path[:] = old_path os.chdir(cwd) @@ -276,18 +292,19 @@ class Loader(object): fixture_mod.Fixture.collector.remove(new_fixtures) def _discover_files(self, root): - ''' + """ Recurse down from the given root directory returning a list of directories which contain a list of files matching `self.filepath_filter`. - ''' + """ # Will probably want to order this traversal. for root, dirnames, filenames in os.walk(root): dirnames.sort() if filenames: filenames.sort() - filepaths = [os.path.join(root, filename) \ - for filename in filenames] + filepaths = [ + os.path.join(root, filename) for filename in filenames + ] filepaths = filter(self.filepath_filter, filepaths) if filepaths: yield filepaths diff --git a/ext/testlib/log.py b/ext/testlib/log.py index fb5907cd5c..346fea747d 100644 --- a/ext/testlib/log.py +++ b/ext/testlib/log.py @@ -26,49 +26,53 @@ # # Authors: Sean Wilson -''' +""" This module supplies the global `test_log` object which all testing results and messages are reported through. -''' +""" import testlib.wrappers as wrappers -class LogLevel(): + +class LogLevel: Fatal = 0 Error = 1 - Warn = 2 - Info = 3 + Warn = 2 + Info = 3 Debug = 4 Trace = 5 class RecordTypeCounterMetaclass(type): - ''' + """ Record type metaclass. Adds a static integer value in addition to typeinfo so identifiers are common across processes, networks and module reloads. - ''' + """ + counter = 0 + def __init__(cls, name, bases, dct): cls.type_id = RecordTypeCounterMetaclass.counter RecordTypeCounterMetaclass.counter += 1 class Record(object, metaclass=RecordTypeCounterMetaclass): - ''' + """ A generic object that is passed to the :class:`Log` and its handlers. ..note: Although not statically enforced, all items in the record should be be pickleable. This enables logging accross multiple processes. - ''' + """ def __init__(self, **data): self.data = data def __getitem__(self, item): if item not in self.data: - raise KeyError('%s not in record %s' %\ - (item, self.__class__.__name__)) + raise KeyError( + "%s not in record %s" % (item, self.__class__.__name__) + ) return self.data[item] def __str__(self): @@ -78,30 +82,52 @@ class Record(object, metaclass=RecordTypeCounterMetaclass): class StatusRecord(Record): def __init__(self, obj, status): Record.__init__(self, metadata=obj.metadata, status=status) + + class ResultRecord(Record): def __init__(self, obj, result): Record.__init__(self, metadata=obj.metadata, result=result) -#TODO Refactor this shit... Not ideal. Should just specify attributes. + + +# TODO Refactor this shit... Not ideal. Should just specify attributes. class TestStatus(StatusRecord): pass + + class SuiteStatus(StatusRecord): pass + + class LibraryStatus(StatusRecord): pass + + class TestResult(ResultRecord): pass + + class SuiteResult(ResultRecord): pass + + class LibraryResult(ResultRecord): pass + + # Test Output Types class TestStderr(Record): pass + + class TestStdout(Record): pass + + # Message (Raw String) Types class TestMessage(Record): pass + + class LibraryMessage(Record): pass @@ -121,8 +147,8 @@ class Log(object): def __init__(self, test=None): self.test = test self.handlers = [] - self._opened = False # TODO Guards to methods - self._closed = False # TODO Guards to methods + self._opened = False # TODO Guards to methods + self._closed = False # TODO Guards to methods def finish_init(self): self._opened = True @@ -136,19 +162,25 @@ class Log(object): if not self._opened: self.finish_init() if self._closed: - raise Exception('The log has been closed' - ' and is no longer available.') + raise Exception( + "The log has been closed" " and is no longer available." + ) for handler in self.handlers: handler.handle(record) def message(self, message, level=LogLevel.Info, bold=False, **metadata): if self.test: - record = TestMessage(message=message, level=level, - test_uid=self.test.uid, suite_uid=self.test.parent_suite.uid) + record = TestMessage( + message=message, + level=level, + test_uid=self.test.uid, + suite_uid=self.test.parent_suite.uid, + ) else: - record = LibraryMessage(message=message, level=level, - bold=bold, **metadata) + record = LibraryMessage( + message=message, level=level, bold=bold, **metadata + ) self.log(record) @@ -168,20 +200,19 @@ class Log(object): self.message(message, LogLevel.Trace) def status_update(self, obj, status): - self.log( - self._status_typemap[obj.__class__.__name__](obj, status)) + self.log(self._status_typemap[obj.__class__.__name__](obj, status)) def result_update(self, obj, result): - self.log( - self._result_typemap[obj.__class__.__name__](obj, result)) + self.log(self._result_typemap[obj.__class__.__name__](obj, result)) def add_handler(self, handler): if self._opened: - raise Exception('Unable to add a handler once the log is open.') + raise Exception("Unable to add a handler once the log is open.") self.handlers.append(handler) def close_handler(self, handler): handler.close() self.handlers.remove(handler) + test_log = Log() diff --git a/ext/testlib/main.py b/ext/testlib/main.py index b9d8e93e66..3888a1ec6b 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -39,21 +39,26 @@ import testlib.runner as runner import testlib.terminal as terminal import testlib.uid as uid + def entry_message(): log.test_log.message("Running the new gem5 testing script.") log.test_log.message("For more information see TESTING.md.") - log.test_log.message("To see details as the testing scripts are" - " running, use the option" - " -v, -vv, or -vvv") + log.test_log.message( + "To see details as the testing scripts are" + " running, use the option" + " -v, -vv, or -vvv" + ) -class RunLogHandler(): + +class RunLogHandler: def __init__(self): term_handler = handlers.TerminalHandler( - verbosity=configuration.config.verbose+log.LogLevel.Info + verbosity=configuration.config.verbose + log.LogLevel.Info ) summary_handler = handlers.SummaryHandler() self.mp_handler = handlers.MultiprocessingHandlerWrapper( - summary_handler, term_handler) + summary_handler, term_handler + ) self.mp_handler.async_process() log.test_log.add_handler(self.mp_handler) entry_message() @@ -61,7 +66,8 @@ class RunLogHandler(): def schedule_finalized(self, test_schedule): # Create the result handler object. self.result_handler = handlers.ResultHandler( - test_schedule, configuration.config.result_path) + test_schedule, configuration.config.result_path + ) self.mp_handler.add_handler(self.result_handler) def finish_testing(self): @@ -78,35 +84,43 @@ class RunLogHandler(): self.mp_handler.close() def unsuccessful(self): - ''' + """ Performs an or reduce on all of the results. Returns true if at least one test is unsuccessful, false when all tests pass - ''' + """ return self.result_handler.unsuccessful() + def get_config_tags(): - return getattr(configuration.config, - configuration.StorePositionalTagsAction.position_kword) + return getattr( + configuration.config, + configuration.StorePositionalTagsAction.position_kword, + ) + def filter_with_config_tags(loaded_library): tags = get_config_tags() final_tags = [] - regex_fmt = '^%s$' + regex_fmt = "^%s$" cfg = configuration.config def _append_inc_tag_filter(name): if hasattr(cfg, name): tag_opts = getattr(cfg, name) for tag in tag_opts: - final_tags.append(configuration.TagRegex(True, regex_fmt % tag)) + final_tags.append( + configuration.TagRegex(True, regex_fmt % tag) + ) def _append_rem_tag_filter(name): if hasattr(cfg, name): tag_opts = getattr(cfg, name) for tag in cfg.constants.supported_tags[name]: if tag not in tag_opts: - final_tags.append(configuration.TagRegex(False, regex_fmt % tag)) + final_tags.append( + configuration.TagRegex(False, regex_fmt % tag) + ) # Append additional tags for the isa, length, and variant options. # They apply last (they take priority) @@ -114,7 +128,7 @@ def filter_with_config_tags(loaded_library): cfg.constants.isa_tag_type, cfg.constants.length_tag_type, cfg.constants.host_isa_tag_type, - cfg.constants.variant_tag_type + cfg.constants.variant_tag_type, ) for tagname in special_tags: @@ -126,15 +140,15 @@ def filter_with_config_tags(loaded_library): tags = tuple() filters = list(itertools.chain(final_tags, tags)) - string = 'Filtering suites with tags as follows:\n' - filter_string = '\t\n'.join((str(f) for f in filters)) + string = "Filtering suites with tags as follows:\n" + filter_string = "\t\n".join((str(f) for f in filters)) log.test_log.trace(string + filter_string) return filter_with_tags(loaded_library, filters) def filter_with_tags(loaded_library, filters): - ''' + """ Filter logic supports two filter types: --include-tags --exclude-tags @@ -168,7 +182,7 @@ def filter_with_tags(loaded_library, filters): set() # Removed all suites which have tags # Process --include-tags "X86" set(suite_X86) - ''' + """ if not filters: return @@ -182,6 +196,7 @@ def filter_with_tags(loaded_library, filters): def exclude(excludes): return suites - excludes + def include(includes): return suites | includes @@ -189,32 +204,39 @@ def filter_with_tags(loaded_library, filters): matched_tags = (tag for tag in tags if tag_regex.regex.search(tag)) for tag in matched_tags: matched_suites = set(query_runner.suites_with_tag(tag)) - suites = include(matched_suites) if tag_regex.include \ - else exclude(matched_suites) + suites = ( + include(matched_suites) + if tag_regex.include + else exclude(matched_suites) + ) # Set the library's suites to only those which where accepted by our filter - loaded_library.suites = [suite for suite in loaded_library.suites - if suite in suites] + loaded_library.suites = [ + suite for suite in loaded_library.suites if suite in suites + ] + # TODO Add results command for listing previous results. + def load_tests(): - ''' + """ Create a TestLoader and load tests for the directory given by the config. - ''' + """ testloader = loader_mod.Loader() log.test_log.message(terminal.separator()) - log.test_log.message('Loading Tests', bold=True) + log.test_log.message("Loading Tests", bold=True) for root in configuration.config.directories: testloader.load_root(root) return testloader + def do_list(): term_handler = handlers.TerminalHandler( - verbosity=configuration.config.verbose+log.LogLevel.Info, - machine_only=configuration.config.quiet + verbosity=configuration.config.verbose + log.LogLevel.Info, + machine_only=configuration.config.quiet, ) log.test_log.add_handler(term_handler) @@ -238,8 +260,9 @@ def do_list(): return 0 + def run_schedule(test_schedule, log_handler): - ''' + """ Test Phases ----------- * Test Collection @@ -253,15 +276,18 @@ def run_schedule(test_schedule, log_handler): * Test Fixture Teardown * Suite Fixture Teardown * Global Fixture Teardown - ''' + """ log_handler.schedule_finalized(test_schedule) log.test_log.message(terminal.separator()) - log.test_log.message('Running Tests from {} suites' - .format(len(test_schedule.suites)), bold=True) - log.test_log.message("Results will be stored in {}".format( - configuration.config.result_path)) + log.test_log.message( + "Running Tests from {} suites".format(len(test_schedule.suites)), + bold=True, + ) + log.test_log.message( + "Results will be stored in {}".format(configuration.config.result_path) + ) log.test_log.message(terminal.separator()) # Build global fixtures and exectute scheduled test suites. @@ -278,16 +304,19 @@ def run_schedule(test_schedule, log_handler): return 1 if failed else 0 + def do_run(): # Initialize early parts of the log. with RunLogHandler() as log_handler: if configuration.config.uid: uid_ = uid.UID.from_uid(configuration.config.uid) if isinstance(uid_, uid.TestUID): - log.test_log.error('Unable to run a standalone test.\n' - 'Gem5 expects test suites to be the smallest unit ' - ' of test.\n\n' - 'Pass a SuiteUID instead.') + log.test_log.error( + "Unable to run a standalone test.\n" + "Gem5 expects test suites to be the smallest unit " + " of test.\n\n" + "Pass a SuiteUID instead." + ) return test_schedule = loader_mod.Loader().load_schedule_for_suites(uid_) if get_config_tags(): @@ -302,13 +331,17 @@ def do_run(): # Execute the tests return run_schedule(test_schedule, log_handler) + def do_rerun(): # Init early parts of log with RunLogHandler() as log_handler: # Load previous results results = result.InternalSavedResults.load( - os.path.join(configuration.config.result_path, - configuration.constants.pickle_filename)) + os.path.join( + configuration.config.result_path, + configuration.constants.pickle_filename, + ) + ) rerun_suites = (suite.uid for suite in results if suite.unsuccessful) @@ -319,16 +352,17 @@ def do_rerun(): # Execute the tests return run_schedule(test_schedule, log_handler) + def main(): - ''' + """ Main entrypoint for the testlib test library. Returns 0 on success and 1 otherwise so it can be used as a return code for scripts. - ''' + """ configuration.initialize_config() # 'do' the given command. - result = globals()['do_'+configuration.config.command]() + result = globals()["do_" + configuration.config.command]() log.test_log.close() return result diff --git a/ext/testlib/query.py b/ext/testlib/query.py index 174af626fe..7b69d7d76b 100644 --- a/ext/testlib/query.py +++ b/ext/testlib/query.py @@ -49,7 +49,7 @@ class QueryRunner(object): def list_tests(self): log.test_log.message(terminal.separator()) - log.test_log.message('Listing all Test Cases.', bold=True) + log.test_log.message("Listing all Test Cases.", bold=True) log.test_log.message(terminal.separator()) for suite in self.schedule: for test in suite: @@ -57,15 +57,15 @@ class QueryRunner(object): def list_suites(self): log.test_log.message(terminal.separator()) - log.test_log.message('Listing all Test Suites.', bold=True) + log.test_log.message("Listing all Test Suites.", bold=True) log.test_log.message(terminal.separator()) for suite in self.suites(): log.test_log.message(suite.uid, machine_readable=True) def list_tags(self): log.test_log.message(terminal.separator()) - log.test_log.message('Listing all Test Tags.', bold=True) + log.test_log.message("Listing all Test Tags.", bold=True) log.test_log.message(terminal.separator()) for tag in self.tags(): - log.test_log.message(tag, machine_readable=True) \ No newline at end of file + log.test_log.message(tag, machine_readable=True) diff --git a/ext/testlib/result.py b/ext/testlib/result.py index 786febde2a..38295f3a04 100644 --- a/ext/testlib/result.py +++ b/ext/testlib/result.py @@ -46,6 +46,7 @@ from testlib.configuration import config import testlib.helper as helper import testlib.state as state + def _create_uid_index(iterable): index = {} for item in iterable: @@ -58,12 +59,15 @@ class _CommonMetadataMixin: @property def name(self): return self._metadata.name + @property def uid(self): return self._metadata.uid + @property def result(self): return self._metadata.result + @result.setter def result(self, result): self._metadata.result = result @@ -83,12 +87,10 @@ class InternalTestResult(_CommonMetadataMixin): self.suite = suite self.stderr = os.path.join( - InternalSavedResults.output_path(self.uid, suite.uid), - 'stderr' + InternalSavedResults.output_path(self.uid, suite.uid), "stderr" ) self.stdout = os.path.join( - InternalSavedResults.output_path(self.uid, suite.uid), - 'stdout' + InternalSavedResults.output_path(self.uid, suite.uid), "stdout" ) @@ -99,8 +101,9 @@ class InternalSuiteResult(_CommonMetadataMixin): self._wrap_tests(obj) def _wrap_tests(self, obj): - self._tests = [InternalTestResult(test, self, self.directory) - for test in obj] + self._tests = [ + InternalTestResult(test, self, self.directory) for test in obj + ] self._tests_index = _create_uid_index(self._tests) def get_test(self, uid): @@ -129,13 +132,14 @@ class InternalLibraryResults(_CommonMetadataMixin): return iter(self._suites) def _wrap_suites(self, obj): - self._suites = [InternalSuiteResult(suite, self.directory) - for suite in obj] + self._suites = [ + InternalSuiteResult(suite, self.directory) for suite in obj + ] self._suites_index = _create_uid_index(self._suites) def add_suite(self, suite): if suite.uid in self._suites: - raise ValueError('Cannot have duplicate suite UIDs.') + raise ValueError("Cannot have duplicate suite UIDs.") self._suites[suite.uid] = suite def get_suite_result(self, suite_uid): @@ -151,35 +155,37 @@ class InternalLibraryResults(_CommonMetadataMixin): helper.append_dictlist(results, test.result.value, test) return results + class InternalSavedResults: @staticmethod def output_path(test_uid, suite_uid, base=None): - ''' + """ Return the path which results for a specific test case should be stored. - ''' + """ if base is None: base = config.result_path return os.path.join( - base, - str(suite_uid).replace(os.path.sep, '-'), - str(test_uid).replace(os.path.sep, '-')) + base, + str(suite_uid).replace(os.path.sep, "-"), + str(test_uid).replace(os.path.sep, "-"), + ) @staticmethod def save(results, path, protocol=pickle.HIGHEST_PROTOCOL): if not os.path.exists(os.path.dirname(path)): - try: - os.makedirs(os.path.dirname(path)) - except OSError as exc: # Guard against race condition - if exc.errno != errno.EEXIST: - raise + try: + os.makedirs(os.path.dirname(path)) + except OSError as exc: # Guard against race condition + if exc.errno != errno.EEXIST: + raise - with open(path, 'wb') as f: + with open(path, "wb") as f: pickle.dump(results, f, protocol) @staticmethod def load(path): - with open(path, 'rb') as f: + with open(path, "rb") as f: return pickle.load(f) @@ -189,29 +195,29 @@ class XMLElement(object): self.end(file_) def begin(self, file_): - file_.write('<') + file_.write("<") file_.write(self.name) - if hasattr(self, 'attributes'): + if hasattr(self, "attributes"): for attr in self.attributes: - file_.write(' ') + file_.write(" ") attr.write(file_) - file_.write('>') + file_.write(">") self.body(file_) def body(self, file_): - if hasattr(self, 'elements'): + if hasattr(self, "elements"): for elem in self.elements: - file_.write('\n') + file_.write("\n") elem.write(file_) - if hasattr(self, 'content'): - file_.write('\n') - file_.write( - xml.sax.saxutils.escape(self.content)) - file_.write('\n') + if hasattr(self, "content"): + file_.write("\n") + file_.write(xml.sax.saxutils.escape(self.content)) + file_.write("\n") def end(self, file_): - file_.write('' % self.name) + file_.write("" % self.name) + class XMLAttribute(object): def __init__(self, name, value): @@ -219,16 +225,17 @@ class XMLAttribute(object): self.value = value def write(self, file_): - file_.write('%s=%s' % (self.name, - xml.sax.saxutils.quoteattr(self.value))) + file_.write( + "%s=%s" % (self.name, xml.sax.saxutils.quoteattr(self.value)) + ) class JUnitTestSuites(XMLElement): - name = 'testsuites' + name = "testsuites" result_map = { - state.Result.Errored: 'errors', - state.Result.Failed: 'failures', - state.Result.Passed: 'tests' + state.Result.Errored: "errors", + state.Result.Failed: "failures", + state.Result.Passed: "tests", } def __init__(self, internal_results): @@ -236,8 +243,9 @@ class JUnitTestSuites(XMLElement): self.attributes = [] for result, tests in results.items(): - self.attributes.append(self.result_attribute(result, - str(len(tests)))) + self.attributes.append( + self.result_attribute(result, str(len(tests))) + ) self.elements = [] for suite in internal_results: @@ -246,24 +254,24 @@ class JUnitTestSuites(XMLElement): def result_attribute(self, result, count): return XMLAttribute(self.result_map[result], count) + class JUnitTestSuite(JUnitTestSuites): - name = 'testsuite' + name = "testsuite" result_map = { - state.Result.Errored: 'errors', - state.Result.Failed: 'failures', - state.Result.Passed: 'tests', - state.Result.Skipped: 'skipped' + state.Result.Errored: "errors", + state.Result.Failed: "failures", + state.Result.Passed: "tests", + state.Result.Skipped: "skipped", } def __init__(self, suite_result): results = suite_result.aggregate_test_results() - self.attributes = [ - XMLAttribute('name', suite_result.name) - ] + self.attributes = [XMLAttribute("name", suite_result.name)] for result, tests in results.items(): - self.attributes.append(self.result_attribute(result, - str(len(tests)))) + self.attributes.append( + self.result_attribute(result, str(len(tests))) + ) self.elements = [] for test in suite_result: @@ -272,40 +280,42 @@ class JUnitTestSuite(JUnitTestSuites): def result_attribute(self, result, count): return XMLAttribute(self.result_map[result], count) + class JUnitTestCase(XMLElement): - name = 'testcase' + name = "testcase" + def __init__(self, test_result): self.attributes = [ - XMLAttribute('name', test_result.name), - # TODO JUnit expects class of test.. add as test metadata. - XMLAttribute('classname', str(test_result.uid)), - XMLAttribute('status', str(test_result.result)), - XMLAttribute('time', str(test_result.time["user_time"])), + XMLAttribute("name", test_result.name), + # TODO JUnit expects class of test.. add as test metadata. + XMLAttribute("classname", str(test_result.uid)), + XMLAttribute("status", str(test_result.result)), + XMLAttribute("time", str(test_result.time["user_time"])), ] # TODO JUnit expects a message for the reason a test was # skipped or errored, save this with the test metadata. # http://llg.cubic.org/docs/junit/ self.elements = [ - LargeFileElement('system-err', test_result.stderr), - LargeFileElement('system-out', test_result.stdout), + LargeFileElement("system-err", test_result.stderr), + LargeFileElement("system-out", test_result.stdout), ] - if str(test_result.result) == 'Failed': - self.elements.append(JUnitFailure( - 'Test failed', - str(test_result.result.reason)) + if str(test_result.result) == "Failed": + self.elements.append( + JUnitFailure("Test failed", str(test_result.result.reason)) ) class JUnitFailure(XMLElement): - name = 'failure' + name = "failure" + def __init__(self, message, cause): self.attributes = [ - XMLAttribute('message', message), + XMLAttribute("message", message), ] cause_element = XMLElement() - cause_element.name = 'cause' + cause_element.name = "cause" cause_element.content = cause self.elements = [cause_element] @@ -318,7 +328,7 @@ class LargeFileElement(XMLElement): def body(self, file_): try: - with open(self.filename, 'r') as f: + with open(self.filename, "r") as f: for line in f: file_.write(xml.sax.saxutils.escape(line)) except IOError: @@ -330,15 +340,13 @@ class LargeFileElement(XMLElement): pass - class JUnitSavedResults: @staticmethod def save(results, path): - ''' + """ Compile the internal results into JUnit format writting it to the given file. - ''' + """ results = JUnitTestSuites(results) - with open(path, 'w') as f: + with open(path, "w") as f: results.write(f) - diff --git a/ext/testlib/runner.py b/ext/testlib/runner.py index 16ff952985..bfae7ce308 100644 --- a/ext/testlib/runner.py +++ b/ext/testlib/runner.py @@ -47,14 +47,15 @@ import testlib.log as log from testlib.state import Status, Result from testlib.fixture import SkipException + def compute_aggregate_result(iterable): - ''' + """ Status of the test suite by default is: * Passed if all contained tests passed * Errored if any contained tests errored * Failed if no tests errored, but one or more failed. * Skipped if all contained tests were skipped - ''' + """ failed = [] skipped = [] for testitem in iterable: @@ -73,18 +74,18 @@ def compute_aggregate_result(iterable): else: return Result(Result.Passed) + class TestParameters(object): def __init__(self, test, suite): self.test = test self.suite = suite self.log = log.test_log self.log.test = test - self.time = { - "user_time" : 0, "system_time" : 0} + self.time = {"user_time": 0, "system_time": 0} @helper.cacheresult def _fixtures(self): - fixtures = {fixture.name:fixture for fixture in self.suite.fixtures} + fixtures = {fixture.name: fixture for fixture in self.suite.fixtures} for fixture in self.test.fixtures: fixtures[fixture.name] = fixture return fixtures @@ -139,18 +140,18 @@ class RunnerPattern: else: self.testable.status = Status.Complete + class TestRunner(RunnerPattern): def test(self): - test_params = TestParameters( - self.testable, - self.testable.parent_suite) + test_params = TestParameters(self.testable, self.testable.parent_suite) try: # Running the test test_params.test.test(test_params) except Exception: - self.testable.result = Result(Result.Failed, - traceback.format_exc()) + self.testable.result = Result( + Result.Failed, traceback.format_exc() + ) else: self.testable.result = Result(Result.Passed) @@ -161,8 +162,7 @@ class SuiteRunner(RunnerPattern): def test(self): for test in self.testable: test.runner(test).run() - self.testable.result = compute_aggregate_result( - iter(self.testable)) + self.testable.result = compute_aggregate_result(iter(self.testable)) class LibraryRunner(SuiteRunner): @@ -175,22 +175,22 @@ class LibraryParallelRunner(RunnerPattern): def test(self): pool = multiprocessing.dummy.Pool(self.threads) - pool.map(lambda suite : suite.runner(suite).run(), self.testable) - self.testable.result = compute_aggregate_result( - iter(self.testable)) + pool.map(lambda suite: suite.runner(suite).run(), self.testable) + self.testable.result = compute_aggregate_result(iter(self.testable)) class BrokenFixtureException(Exception): def __init__(self, fixture, testitem, trace): self.trace = trace - self.msg = ('%s\n' - 'Exception raised building "%s" raised SkipException' - ' for "%s".' % - (trace, fixture.name, testitem.name) + self.msg = ( + "%s\n" + 'Exception raised building "%s" raised SkipException' + ' for "%s".' % (trace, fixture.name, testitem.name) ) super(BrokenFixtureException, self).__init__(self.msg) + class FixtureBuilder(object): def __init__(self, fixtures): self.fixtures = fixtures @@ -207,12 +207,15 @@ class FixtureBuilder(object): raise except Exception as e: exc = traceback.format_exc() - msg = 'Exception raised while setting up fixture for %s' %\ - testitem.uid - log.test_log.warn('%s\n%s' % (exc, msg)) + msg = ( + "Exception raised while setting up fixture for %s" + % testitem.uid + ) + log.test_log.warn("%s\n%s" % (exc, msg)) - raise BrokenFixtureException(fixture, testitem, - traceback.format_exc()) + raise BrokenFixtureException( + fixture, testitem, traceback.format_exc() + ) def post_test_procedure(self, testitem): for fixture in self.built_fixtures: @@ -225,6 +228,8 @@ class FixtureBuilder(object): except Exception: # Log exception but keep cleaning up. exc = traceback.format_exc() - msg = 'Exception raised while tearing down fixture for %s' %\ - testitem.uid - log.test_log.warn('%s\n%s' % (exc, msg)) + msg = ( + "Exception raised while tearing down fixture for %s" + % testitem.uid + ) + log.test_log.warn("%s\n%s" % (exc, msg)) diff --git a/ext/testlib/state.py b/ext/testlib/state.py index d220bb1019..21a23628bc 100644 --- a/ext/testlib/state.py +++ b/ext/testlib/state.py @@ -24,14 +24,15 @@ # # Authors: Sean Wilson + class Result: - enums = ''' + enums = """ NotRun Skipped Passed Failed Errored - '''.split() + """.split() for idx, enum in enumerate(enums): locals()[enum] = idx @@ -46,15 +47,16 @@ class Result: def __str__(self): return self.name(self.value) + class Status: - enums = ''' + enums = """ Unscheduled Building Running TearingDown Complete Avoided - '''.split() + """.split() for idx, enum in enumerate(enums): locals()[enum] = idx diff --git a/ext/testlib/suite.py b/ext/testlib/suite.py index eae52fd922..cf9f0e646a 100644 --- a/ext/testlib/suite.py +++ b/ext/testlib/suite.py @@ -30,8 +30,9 @@ import testlib.helper as helper import testlib.runner as runner_mod + class TestSuite(object): - ''' + """ An object grouping a collection of tests. It provides tags which enable filtering during list and run selection. All tests held in the suite must have a unique name. @@ -44,7 +45,8 @@ class TestSuite(object): To reduce test definition boilerplate, the :func:`init` method is forwarded all `*args` and `**kwargs`. This means derived classes can define init without boilerplate super().__init__(*args, **kwargs). - ''' + """ + runner = runner_mod.SuiteRunner collector = helper.InstanceCollector() fixtures = [] @@ -56,8 +58,14 @@ class TestSuite(object): TestSuite.collector.collect(obj) return obj - def __init__(self, name=None, fixtures=tuple(), tests=tuple(), - tags=tuple(), **kwargs): + def __init__( + self, + name=None, + fixtures=tuple(), + tests=tuple(), + tags=tuple(), + **kwargs + ): self.fixtures = self.fixtures + list(fixtures) self.tags = self.tags | set(tags) self.tests = self.tests + list(tests) @@ -66,4 +74,4 @@ class TestSuite(object): self.name = name def __iter__(self): - return iter(self.tests) \ No newline at end of file + return iter(self.tests) diff --git a/ext/testlib/terminal.py b/ext/testlib/terminal.py index be489f5296..ef4f780ff3 100644 --- a/ext/testlib/terminal.py +++ b/ext/testlib/terminal.py @@ -41,7 +41,7 @@ import struct # ANSI color names in index order color_names = "Black Red Green Yellow Blue Magenta Cyan White".split() -default_separator = '=' +default_separator = "=" # Character attribute capabilities. Note that not all terminals # support all of these capabilities, or support them @@ -54,39 +54,46 @@ default_separator = '=' # Please feel free to add information about other terminals here. # capability_map = { - 'Bold': 'bold', - 'Dim': 'dim', - 'Blink': 'blink', - 'Underline': 'smul', - 'Reverse': 'rev', - 'Standout': 'smso', - 'Normal': 'sgr0' + "Bold": "bold", + "Dim": "dim", + "Blink": "blink", + "Underline": "smul", + "Reverse": "rev", + "Standout": "smso", + "Normal": "sgr0", } capability_names = capability_map.keys() + def null_cap_string(s, *args): - return '' + return "" + try: import curses + curses.setupterm() + def cap_string(s, *args): cap = curses.tigetstr(s) if cap: return curses.tparm(cap, *args).decode("utf-8") else: - return '' + return "" + except: cap_string = null_cap_string + class ColorStrings(object): def __init__(self, cap_string): for i, c in enumerate(color_names): - setattr(self, c, cap_string('setaf', i)) + setattr(self, c, cap_string("setaf", i)) for name, cap in capability_map.items(): setattr(self, name, cap_string(cap)) + termcap = ColorStrings(cap_string) no_termcap = ColorStrings(null_cap_string) @@ -95,7 +102,8 @@ if sys.stdout.isatty(): else: tty_termcap = no_termcap -def get_termcap(use_colors = None): + +def get_termcap(use_colors=None): if use_colors: return termcap elif use_colors is None: @@ -104,12 +112,16 @@ def get_termcap(use_colors = None): else: return no_termcap + def terminal_size(): - '''Return the (width, heigth) of the terminal screen.''' + """Return the (width, heigth) of the terminal screen.""" try: - h, w, hp, wp = struct.unpack('HHHH', - fcntl.ioctl(0, termios.TIOCGWINSZ, - struct.pack('HHHH', 0, 0, 0, 0))) + h, w, hp, wp = struct.unpack( + "HHHH", + fcntl.ioctl( + 0, termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0) + ), + ) return w, h except IOError: # It's possible that in sandboxed environments the above ioctl is not @@ -118,51 +130,60 @@ def terminal_size(): def separator(char=default_separator, color=None): - ''' + """ Return a separator of the given character that is the length of the full width of the terminal screen. - ''' + """ (w, h) = terminal_size() if color: - return color + char*w + termcap.Normal + return color + char * w + termcap.Normal else: - return char*w + return char * w -def insert_separator(inside, char=default_separator, - min_barrier=3, color=None): - ''' + +def insert_separator( + inside, char=default_separator, min_barrier=3, color=None +): + """ Place the given string inside of the separator. If it does not fit inside, expand the separator to fit it with at least min_barrier. .. seealso:: :func:`separator` - ''' + """ # Use a bytearray so it's efficient to manipulate - string = bytearray(separator(char, color=color), 'utf-8') + string = bytearray(separator(char, color=color), "utf-8") # Check if we can fit inside with at least min_barrier. gap = (len(string) - len(inside)) - min_barrier * 2 if gap > 0: # We'll need to expand the string to fit us. - string.extend([ char for _ in range(-gap)]) + string.extend([char for _ in range(-gap)]) # Emplace inside - middle = (len(string)-1)//2 - start_idx = middle - len(inside)//2 - string[start_idx:len(inside)+start_idx] = str.encode(inside) + middle = (len(string) - 1) // 2 + start_idx = middle - len(inside) // 2 + string[start_idx : len(inside) + start_idx] = str.encode(inside) return str(string.decode("utf-8")) -if __name__ == '__main__': +if __name__ == "__main__": + def test_termcap(obj): for c_name in color_names: c_str = getattr(obj, c_name) print(c_str + c_name + obj.Normal) for attr_name in capability_names: - if attr_name == 'Normal': + if attr_name == "Normal": continue attr_str = getattr(obj, attr_name) print(attr_str + c_str + attr_name + " " + c_name + obj.Normal) - print(obj.Bold + obj.Underline + \ - c_name + "Bold Underline " + c_str + obj.Normal) + print( + obj.Bold + + obj.Underline + + c_name + + "Bold Underline " + + c_str + + obj.Normal + ) print("=== termcap enabled ===") test_termcap(termcap) diff --git a/ext/testlib/test_util.py b/ext/testlib/test_util.py index 22e2c973f6..5a995c7810 100644 --- a/ext/testlib/test_util.py +++ b/ext/testlib/test_util.py @@ -29,14 +29,16 @@ import testlib.helper as helper import testlib.runner as runner_mod + class TestCase(object): - ''' + """ Base class for all tests. ..note:: The :func:`__new__` method enables collection of test cases, it must be called in order for test cases to be collected. - ''' + """ + fixtures = [] # TODO, remove explicit dependency. Use the loader to set the @@ -55,10 +57,12 @@ class TestCase(object): name = self.__class__.__name__ self.name = name + class TestFunction(TestCase): - ''' + """ TestCase implementation which uses a callable object as a test. - ''' + """ + def __init__(self, function, name=None, **kwargs): self.test_function = function if name is None: diff --git a/ext/testlib/uid.py b/ext/testlib/uid.py index f8951a28da..62f477134a 100644 --- a/ext/testlib/uid.py +++ b/ext/testlib/uid.py @@ -31,8 +31,9 @@ import itertools import testlib.configuration as configuration + class UID(object): - sep = ':' + sep = ":" type_idx, path_idx = range(2) def __init__(self, path, *args): @@ -41,9 +42,10 @@ class UID(object): @staticmethod def _shorten_path(path): - return os.path.relpath(path, - os.path.commonprefix((configuration.constants.testing_base, - path))) + return os.path.relpath( + path, + os.path.commonprefix((configuration.constants.testing_base, path)), + ) @staticmethod def _full_path(short_path): @@ -75,11 +77,11 @@ class UID(object): def __str__(self): common_opts = { self.path_idx: self.path, - self.type_idx: self.__class__.__name__ + self.type_idx: self.__class__.__name__, } - return self.sep.join(itertools.chain( - [common_opts[0], common_opts[1]], - self.attributes)) + return self.sep.join( + itertools.chain([common_opts[0], common_opts[1]], self.attributes) + ) def __hash__(self): return hash(str(self)) diff --git a/ext/testlib/wrappers.py b/ext/testlib/wrappers.py index b2b887b0f9..930713e36f 100644 --- a/ext/testlib/wrappers.py +++ b/ext/testlib/wrappers.py @@ -38,16 +38,17 @@ # # Authors: Sean Wilson -''' +""" Module contains wrappers for test items that have been loaded by the testlib :class:`testlib.loader.Loader`. -''' +""" import itertools import testlib.uid as uid from testlib.state import Status, Result -class TestCaseMetadata(): + +class TestCaseMetadata: def __init__(self, name, uid, path, result, status, suite_uid): self.name = name self.uid = uid @@ -57,7 +58,7 @@ class TestCaseMetadata(): self.suite_uid = suite_uid -class TestSuiteMetadata(): +class TestSuiteMetadata: def __init__(self, name, uid, tags, path, status, result): self.name = name self.uid = uid @@ -67,7 +68,7 @@ class TestSuiteMetadata(): self.result = result -class LibraryMetadata(): +class LibraryMetadata: def __init__(self, name, result, status): self.name = name self.result = result @@ -75,13 +76,14 @@ class LibraryMetadata(): class LoadedTestable(object): - ''' + """ Base class for loaded test items. :property:`result` and :property:`status` setters notify testlib via the :func:`log_result` and :func:`log_status` of the updated status. - ''' + """ + def __init__(self, obj): self.obj = obj self.metadata = self._generate_metadata() @@ -135,10 +137,12 @@ class LoadedTestable(object): # TODO Change log to provide status_update, result_update for all types. def log_status(self, status): import testlib.log as log + log.test_log.status_update(self, status) def log_result(self, result): import testlib.log as log + log.test_log.result_update(self, result) def __iter__(self): @@ -155,16 +159,18 @@ class LoadedTest(LoadedTestable): self.obj.test(*args, **kwargs) def _generate_metadata(self): - return TestCaseMetadata( **{ - 'name':self.obj.name, - 'path': self._path, - 'uid': uid.TestUID(self._path, - self.obj.name, - self.parent_suite.name), - 'status': Status.Unscheduled, - 'result': Result(Result.NotRun), - 'suite_uid': self.parent_suite.metadata.uid - }) + return TestCaseMetadata( + **{ + "name": self.obj.name, + "path": self._path, + "uid": uid.TestUID( + self._path, self.obj.name, self.parent_suite.name + ), + "status": Status.Unscheduled, + "result": Result(Result.NotRun), + "suite_uid": self.parent_suite.metadata.uid, + } + ) class LoadedSuite(LoadedTestable): @@ -174,18 +180,21 @@ class LoadedSuite(LoadedTestable): self.tests = self._wrap_children(suite_obj) def _wrap_children(self, suite_obj): - return [LoadedTest(test, self, self.metadata.path) - for test in suite_obj] + return [ + LoadedTest(test, self, self.metadata.path) for test in suite_obj + ] def _generate_metadata(self): - return TestSuiteMetadata( **{ - 'name': self.obj.name, - 'tags':self.obj.tags, - 'path': self._path, - 'uid': uid.SuiteUID(self._path, self.obj.name), - 'status': Status.Unscheduled, - 'result': Result(Result.NotRun) - }) + return TestSuiteMetadata( + **{ + "name": self.obj.name, + "tags": self.obj.tags, + "path": self._path, + "uid": uid.SuiteUID(self._path, self.obj.name), + "status": Status.Unscheduled, + "result": Result(Result.NotRun), + } + ) def __iter__(self): return iter(self.tests) @@ -196,41 +205,44 @@ class LoadedSuite(LoadedTestable): class LoadedLibrary(LoadedTestable): - ''' + """ Wraps a collection of all loaded test suites and provides utility functions for accessing fixtures. - ''' + """ + def __init__(self, suites): LoadedTestable.__init__(self, suites) def _generate_metadata(self): - return LibraryMetadata( **{ - 'name': 'Test Library', - 'status': Status.Unscheduled, - 'result': Result(Result.NotRun) - }) + return LibraryMetadata( + **{ + "name": "Test Library", + "status": Status.Unscheduled, + "result": Result(Result.NotRun), + } + ) def __iter__(self): - ''' + """ :returns: an iterator over contained :class:`TestSuite` objects. - ''' + """ return iter(self.obj) def all_fixtures(self): - ''' + """ :returns: an interator overall all global, suite, and test fixtures - ''' - return itertools.chain(itertools.chain( - *(suite.fixtures for suite in self.obj)), + """ + return itertools.chain( + itertools.chain(*(suite.fixtures for suite in self.obj)), *(self.test_fixtures(suite) for suite in self.obj) ) def test_fixtures(self, suite): - ''' + """ :returns: an interator over all fixtures of each test contained in the given suite - ''' + """ return itertools.chain(*(test.fixtures for test in suite)) @property From 96144f90ed882e1788ede0e6c0e4638c1cff2025 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 23:57:49 -0700 Subject: [PATCH 258/693] misc: Add pre-commit run to .git-blame-ignore-revs Change-Id: Iaae9d735e2972e41f1f9225ea5bed9acf22ff991 --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 799591c5ce..da2f5c07bc 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -29,3 +29,6 @@ c3bd8eb1214cbebbc92c7958b80aa06913bce3ba # A commit which ran flynt all Python files. e73655d038cdfa68964109044e33c9a6e7d85ac9 + +# A commit which ran pre-commit on ext/testlib +9e1afdecefaf910fa6e266f29dc480a32b0fa83e From bf06d61c3572e7a6d41737a30e2f941a5f81b7a6 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 5 Sep 2023 12:39:38 -0700 Subject: [PATCH 259/693] stdlib, tests, resources: Updated tests - Updated workload tests to use WrokloadResource and obtain_resource Change-Id: I39194e7fe764566a528e5141c29f30efa14e0cde --- tests/pyunit/stdlib/resources/pyunit_workload_checks.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index ef7c3caba1..a9fa5e28e2 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -32,6 +32,7 @@ from gem5.resources.resource import ( BinaryResource, DiskImageResource, obtain_resource, + WorkloadResource, ) from typing import Dict @@ -61,7 +62,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): new=ClientWrapper(mock_config_json), ) def setUpClass(cls) -> None: - cls.custom_workload = CustomWorkload( + cls.custom_workload = WorkloadResource( function="set_se_binary_workload", parameters={ "binary": obtain_resource( @@ -135,7 +136,7 @@ class WorkloadTestSuite(unittest.TestCase): ClientWrapper(mock_config_json), ) def setUpClass(cls): - cls.workload = Workload("simple-boot", gem5_version="develop") + cls.workload = obtain_resource("simple-boot", gem5_version="develop") def test_get_function_str(self) -> None: # Tests `Resource.get_function_str` From 3dfdd48211e1b4a043cafcbeb87dd7df4735c5e9 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Tue, 5 Sep 2023 13:40:34 -0700 Subject: [PATCH 260/693] misc: Fix buggy special path comparisons This patch fixes the buggy special path comparisons in src/kern/linux/linux.cc Linux::openSpecialFile(), which only checked for equality of path prefixes, but not equality of the paths themselves. This patch replaces those buggy comparisons with regular std::string::operator== string equality comparisons. GitHub issue: https://github.com/gem5/gem5/issues/269 Change-Id: I216ff8019b9a6a3e87e364c2e197d9b991959ec1 --- src/kern/linux/linux.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/kern/linux/linux.cc b/src/kern/linux/linux.cc index 1a54c9c53e..11b9fe0ee4 100644 --- a/src/kern/linux/linux.cc +++ b/src/kern/linux/linux.cc @@ -58,19 +58,19 @@ Linux::openSpecialFile(std::string path, Process *process, bool matched = false; std::string data; - if (path.compare(0, 13, "/proc/meminfo") == 0) { + if (path == "/proc/meminfo") { data = Linux::procMeminfo(process, tc); matched = true; - } else if (path.compare(0, 11, "/etc/passwd") == 0) { + } else if (path == "/etc/passwd") { data = Linux::etcPasswd(process, tc); matched = true; - } else if (path.compare(0, 15, "/proc/self/maps") == 0) { + } else if (path == "/proc/self/maps") { data = Linux::procSelfMaps(process, tc); matched = true; - } else if (path.compare(0, 30, "/sys/devices/system/cpu/online") == 0) { + } else if (path == "/sys/devices/system/cpu/online") { data = Linux::cpuOnline(process, tc); matched = true; - } else if (path.compare(0, 12 ,"/dev/urandom") == 0) { + } else if (path == "/dev/urandom") { data = Linux::devRandom(process, tc); matched = true; } From 1b0bb678ab8d6609776ecadad09d38c247464af9 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 31 Aug 2023 02:16:35 -0700 Subject: [PATCH 261/693] util-docker: Proof-of-concept using Docker buildx Introduced in https://github.com/gem5/gem5/pull/236 the "docker-build.yaml" file will allow us to build and push docker images to the GitHub Container Registry. This allows for both automation of docker image building and allows us to utilize Github's zero-cost pulling policy for downloads to GitHub Actions runners. In this PR https://github.com/gem5/gem5/pull/236 has been altered to use Docker `buildx` which allows for multi-platform Docker Image builds. A multi-platform Docker image pull automatically pull the correct image for your platform from a single URL. In this prototype the images are build to both `linux/arm64` and `linux/amd64` have been set. Docker `buildx` has it's own file format for specifying image builds called `bake`. "util/dockerfiles/docker-bake.hcl" has been added with the goal of replacing "util/dockerfiles/docker-compose.yaml". In this proof-of-concept doesn't build all our docker images, just enough to ensure it works inside our actions as intended. Change-Id: Id0debed216c91ec514aa4fce3bc2ff4fc2ea669b --- .github/workflows/docker-build.yaml | 47 +++++------ util/dockerfiles/docker-bake.hcl | 83 +++++++++++++++++++ .../ubuntu-20.04_all-dependencies/Dockerfile | 2 +- .../ubuntu-20.04_clang-version/Dockerfile | 2 +- .../ubuntu-22.04_all-dependencies/Dockerfile | 2 +- 5 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 util/dockerfiles/docker-bake.hcl diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index cbacaad9aa..c46c7f7fb8 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -1,42 +1,39 @@ -# name: Docker images build and push on: - push: - branches: - - develop - paths: - - 'util/docker/ubuntu-20.04_all-depenencies' workflow_dispatch: - -env: - IMAGE_NAME: ubuntu-20.04_all-depenencies -# jobs: # This builds and pushes the docker image. - push: + build-and-push: runs-on: [self-hosted, linux, x64, run] permissions: packages: write contents: read + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest steps: - uses: actions/checkout@v3 + name: Checkout the develop branch + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop - - name: Build image - run: | - cd util/docker/ubuntu-20.04_all-depenencies - docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}" + - uses: docker/setup-qemu-action@v2 + name: Setup QEMU - - name: Log in to registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + - uses: docker/setup-buildx-action@v2 + name: Set up Docker Buildx - - name: Push image - run: | - IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME + - uses: docker/login-action@v2 + name: Login to the GitHub Container Registry + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - # This changes all uppercase characters to lowercase. - IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') - - docker tag $IMAGE_NAME $IMAGE_ID:latest - docker push $IMAGE_ID::latest + - name: Build and push with bake + uses: docker/bake-action@v3 + with: + files: util/dockerfiles/docker-bake.hcl + push: true diff --git a/util/dockerfiles/docker-bake.hcl b/util/dockerfiles/docker-bake.hcl new file mode 100644 index 0000000000..d508ecd45e --- /dev/null +++ b/util/dockerfiles/docker-bake.hcl @@ -0,0 +1,83 @@ +# Copyright (c) 2023 The Regents of the University of California +# All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# docker buildx bake --push +# https://docs.docker.com/build/bake/reference + +variable "IMAGE_URI" { + default = "ghcr.io/gem5" # The gem5 GitHub container registry. +} + +variable "TAG" { + default = "latest" +} + +# A group of targets to be built. Note: groups can contain other groups. +# Any target or group can be build individually. I.e.: +# `docker buildx bake --push ubuntu-20-04_all-dependencies` or +# `docker buildx bake --push ubuntu-releases`. +group "default" { + targets=["clang-compilers", "ubuntu-releases"] +} + +group "ubuntu-releases" { + targets=["ubuntu-22-04_all-dependencies", "ubuntu-20-04_all-dependencies"] +} + +# Common attributes across all targets. Note: these can be overwritten. +target "common" { + # Here we are enabling multi-platform builds. We are compiling to both ARM + # amd X86. + platforms = ["linux/amd64", "linux/arm64"] +} + +target "clang-compilers" { + name="clang-compilers-${replace(ver, ".", "-")}" + inherits = ["common"] + context = "ubuntu-20.04_clang-version" + dockerfile = "Dockerfile" + matrix = { + ver = ["6.0","7","8","9","10","11"] + } + args = { + version=ver + } + tags = ["${IMAGE_URI}/clang-version-${ver}:${TAG}"] +} + +target "ubuntu-22-04_all-dependencies" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "ubuntu-22.04_all-dependencies" + tags = ["${IMAGE_URI}/ubuntu-22.04_all-dependencies:${TAG}"] +} + +target "ubuntu-20-04_all-dependencies" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "ubuntu-20.04_all-dependencies" + tags = ["${IMAGE_URI}/ubuntu-20.04_all-dependencies:${TAG}"] +} diff --git a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile index c838a06dda..449f8b1b06 100644 --- a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile @@ -24,7 +24,7 @@ # (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 ubuntu:20.04 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ diff --git a/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile b/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile index f1ecf89105..2ea9413c7d 100644 --- a/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_clang-version/Dockerfile @@ -23,7 +23,7 @@ # 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 ubuntu:20.04 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 # Valid version values: # 6.0 diff --git a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile index e5afc63be6..9e2580e642 100644 --- a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile @@ -24,7 +24,7 @@ # (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 ubuntu:22.04 +FROM --platform=${BUILDPLATFORM} ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ From 12c67426077d2653751fe04cbfb3480cf88c0caa Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 5 Sep 2023 20:46:55 -0700 Subject: [PATCH 262/693] misc: Fix CI GitHub Action to stop if Workflow re-triggered This ensures that if the CI tests are running for a PR, and a new workflow is triggered (typically by pushing/rebasing the PR) then the older workflow is cancelled. Change-Id: Ifa172bdbdac09c5a91abb41a0162c597445e4e2e --- .github/workflows/ci-tests.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 8def494668..9987083731 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -6,6 +6,9 @@ on: pull_request: types: [opened, edited, synchronize, ready_for_review] +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: pre-commit: From bbe96d6485e830c42311a53c7ee1c3f99b156851 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 6 Sep 2023 10:06:16 -0700 Subject: [PATCH 263/693] stdlib: Changed use of Workload to obtain_resource - Changed files calling Workload class to call obtain_resoucre instead. Change-Id: I41f5f0c3ccc7c08b39e7049eabef9609d6d68788 --- configs/example/gem5_library/arm-ubuntu-run.py | 4 ++-- configs/example/gem5_library/caches/octopi-cache-example.py | 4 ++-- .../gem5_library/looppoints/create-looppoint-checkpoints.py | 6 ++++-- .../gem5_library/looppoints/restore-looppoint-checkpoint.py | 3 +-- configs/example/gem5_library/riscv-ubuntu-run.py | 4 ++-- configs/example/gem5_library/riscvmatched-fs.py | 4 ++-- .../example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py | 4 ++-- configs/example/gem5_library/x86-ubuntu-run-with-kvm.py | 4 ++-- configs/example/gem5_library/x86-ubuntu-run.py | 4 ++-- tests/gem5/riscv_boot_tests/configs/riscv_boot_exit_run.py | 4 ++-- tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py | 4 ++-- 11 files changed, 23 insertions(+), 22 deletions(-) diff --git a/configs/example/gem5_library/arm-ubuntu-run.py b/configs/example/gem5_library/arm-ubuntu-run.py index 7f976f06db..78160c9976 100644 --- a/configs/example/gem5_library/arm-ubuntu-run.py +++ b/configs/example/gem5_library/arm-ubuntu-run.py @@ -43,7 +43,7 @@ scons build/ARM/gem5.opt -j from gem5.isas import ISA from m5.objects import ArmDefaultRelease from gem5.utils.requires import requires -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator from m5.objects import VExpress_GEM5_Foundation from gem5.coherence_protocol import CoherenceProtocol @@ -100,7 +100,7 @@ board = ArmBoard( # Here we set a full system workload. The "arm64-ubuntu-20.04-boot" boots # Ubuntu 20.04. -board.set_workload(Workload("arm64-ubuntu-20.04-boot")) +board.set_workload(obtain_resource("arm64-ubuntu-20.04-boot")) # We define the system with the aforementioned system defined. diff --git a/configs/example/gem5_library/caches/octopi-cache-example.py b/configs/example/gem5_library/caches/octopi-cache-example.py index 1b39a8bee5..4a4926a174 100644 --- a/configs/example/gem5_library/caches/octopi-cache-example.py +++ b/configs/example/gem5_library/caches/octopi-cache-example.py @@ -51,7 +51,7 @@ from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.octopi import from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol from gem5.simulate.simulator import Simulator -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource num_ccds = 1 # CCDs num_cores_per_ccd = 8 # 8 cores/CCD @@ -94,7 +94,7 @@ board = ArmBoard( platform=platform, ) -board.set_workload(Workload("arm64-ubuntu-20.04-boot")) +board.set_workload(obtain_resource("arm64-ubuntu-20.04-boot")) simulator = Simulator(board=board) simulator.run() diff --git a/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py b/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py index abb15fb7f8..4a15da55ff 100644 --- a/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py +++ b/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py @@ -56,7 +56,7 @@ from gem5.components.memory.single_channel import SingleChannelDDR3_1600 from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource from pathlib import Path from gem5.simulate.exit_event_generators import ( looppoint_save_checkpoint_generator, @@ -110,7 +110,9 @@ board = SimpleBoard( cache_hierarchy=cache_hierarchy, ) -board.set_workload(Workload("x86-matrix-multiply-omp-100-8-looppoint-csv")) +board.set_workload( + obtain_resource("x86-matrix-multiply-omp-100-8-looppoint-csv") +) dir = Path(args.checkpoint_path) dir.mkdir(exist_ok=True) diff --git a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py index 21353a34a1..5224c6e6ea 100644 --- a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py +++ b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py @@ -54,7 +54,6 @@ from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.resources.resource import obtain_resource -from gem5.resources.workload import Workload from m5.stats import reset, dump requires(isa_required=ISA.X86) @@ -113,7 +112,7 @@ board = SimpleBoard( ) board.set_workload( - Workload( + obtain_resource( f"x86-matrix-multiply-omp-100-8-looppoint-region-{args.checkpoint_region}" ) ) diff --git a/configs/example/gem5_library/riscv-ubuntu-run.py b/configs/example/gem5_library/riscv-ubuntu-run.py index 87b98cc5ba..9b172fd501 100644 --- a/configs/example/gem5_library/riscv-ubuntu-run.py +++ b/configs/example/gem5_library/riscv-ubuntu-run.py @@ -50,7 +50,7 @@ from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.simulate.simulator import Simulator -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource # This runs a check to ensure the gem5 binary is compiled for RISCV. @@ -88,7 +88,7 @@ board = RiscvBoard( # Ubuntu 20.04. Once the system successfully boots it encounters an `m5_exit` # instruction which stops the simulation. When the simulation has ended you may # inspect `m5out/system.pc.com_1.device` to see the stdout. -board.set_workload(Workload("riscv-ubuntu-20.04-boot")) +board.set_workload(obtain_resource("riscv-ubuntu-20.04-boot")) simulator = Simulator(board=board) simulator.run() diff --git a/configs/example/gem5_library/riscvmatched-fs.py b/configs/example/gem5_library/riscvmatched-fs.py index 3e84b8c1ea..29ec76e16b 100644 --- a/configs/example/gem5_library/riscvmatched-fs.py +++ b/configs/example/gem5_library/riscvmatched-fs.py @@ -42,7 +42,7 @@ from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard from gem5.utils.requires import requires from gem5.isas import ISA from gem5.simulate.simulator import Simulator -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource import argparse @@ -76,7 +76,7 @@ board = RISCVMatchedBoard( # In the case where the `-i` flag is passed, we add the kernel argument # `init=/root/exit.sh`. This means the simulation will exit after the Linux # Kernel has booted. -workload = Workload("riscv-ubuntu-20.04-boot") +workload = obtain_resource("riscv-ubuntu-20.04-boot") kernel_args = board.get_default_kernel_args() if args.to_init: kernel_args.append("init=/root/exit.sh") diff --git a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py index 1c65357921..f25ffb62f8 100644 --- a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py +++ b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py @@ -52,7 +52,7 @@ from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent -from gem5.resources.workload import Workload +from gem5.resources.resoruce import obtain_resource # This simulation requires using KVM with gem5 compiled for X86 simulation # and with MESI_Two_Level cache coherence protocol. @@ -121,7 +121,7 @@ command = ( + "m5 exit;" ) -workload = Workload("x86-ubuntu-18.04-boot") +workload = obtain_resource("x86-ubuntu-18.04-boot") workload.set_parameter("readfile_contents", command) board.set_workload(workload) diff --git a/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py b/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py index f55ec60f21..00c00d1459 100644 --- a/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py +++ b/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py @@ -51,7 +51,7 @@ from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource # This runs a check to ensure the gem5 binary is compiled to X86 and to the # MESI Two Level coherence protocol. @@ -117,7 +117,7 @@ command = ( + "m5 exit;" ) -workload = Workload("x86-ubuntu-18.04-boot") +workload = obtain_resource("x86-ubuntu-18.04-boot") workload.set_parameter("readfile_contents", command) board.set_workload(workload) diff --git a/configs/example/gem5_library/x86-ubuntu-run.py b/configs/example/gem5_library/x86-ubuntu-run.py index 50b52e6e3c..fe72d653f5 100644 --- a/configs/example/gem5_library/x86-ubuntu-run.py +++ b/configs/example/gem5_library/x86-ubuntu-run.py @@ -45,7 +45,7 @@ scons build/X86/gem5.opt """ from gem5.prebuilt.demo.x86_demo_board import X86DemoBoard -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator @@ -56,7 +56,7 @@ board = X86DemoBoard() # We then set the workload. Here we use the "x86-ubuntu-18.04-boot" workload. # This boots Ubuntu 18.04 with Linux 5.4.49. If the required resources are not # found locally, they will be downloaded. -board.set_workload(Workload("x86-ubuntu-18.04-boot")) +board.set_workload(obtain_resource("x86-ubuntu-18.04-boot")) simulator = Simulator(board=board) simulator.run() 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 e9fc06b27b..3726d7de46 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 @@ -40,7 +40,7 @@ from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.riscv_board import RiscvBoard from gem5.components.processors.simple_processor import SimpleProcessor from gem5.simulate.simulator import Simulator -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource import argparse import importlib @@ -160,7 +160,7 @@ board = RiscvBoard( ) # Set the workload. -workload = Workload( +workload = obtain_resource( "riscv-ubuntu-20.04-boot", resource_directory=args.resource_directory ) board.set_workload(workload) diff --git a/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py b/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py index e9eeacefd8..63b6625479 100644 --- a/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py +++ b/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py @@ -41,7 +41,7 @@ from gem5.components.processors.cpu_types import ( ) from gem5.components.processors.simple_processor import SimpleProcessor from gem5.simulate.simulator import Simulator -from gem5.resources.workload import Workload +from gem5.resources.resource import obtain_resource import argparse import importlib @@ -184,7 +184,7 @@ if args.boot_type == "init": kernal_args.append("init=/root/exit.sh") # Set the workload. -workload = Workload( +workload = obtain_resource( "x86-ubuntu-18.04-boot", resource_directory=args.resource_directory ) workload.set_parameter("kernel_args", kernal_args) From 0249d47acc3a87a82c9d7417dba4804cda4a3f4b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 5 Sep 2023 15:04:57 -0700 Subject: [PATCH 264/693] util: Add docker prune cron to GitHub runners Change-Id: Ic90ebc650b6a89606eaf9e8feafddfe15c44e578 Issue-on: https://github.com/gem5/gem5/issues/254 --- util/github-runners-vagrant/provision_nonroot.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/github-runners-vagrant/provision_nonroot.sh b/util/github-runners-vagrant/provision_nonroot.sh index 4465b5a192..2b1e51504e 100644 --- a/util/github-runners-vagrant/provision_nonroot.sh +++ b/util/github-runners-vagrant/provision_nonroot.sh @@ -13,3 +13,7 @@ DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/rel mkdir -p "${HOME}/.docker/cli-plugins" curl -sL "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o "${HOME}/.docker/cli-plugins/docker-compose" chmod +x "${HOME}/.docker/cli-plugins/docker-compose" + +# Setup crontab to run docker prune every 3 hours +echo "0 */3 * * * docker system prune -af --volumes"> /tmp/cron +crontab /tmp/cron From 6cdaa2c16add86a749df75199ac2a4a556e49ef9 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Thu, 7 Sep 2023 03:18:58 +0000 Subject: [PATCH 265/693] sim-se: Fix crash in chdirFunc() on nonexistent directory This commit fixes a crash in the syscall emulation of the chdir(2) syscall, implemented by chdirFunc() in src/sim/syscall_emul.cc, when passed a nonexistent directory. The buggy code did not check the return value of realpath(). This patch adds code to check the return value of realpath(), and if it is NULL (i.e., there was an error with the requested directory to change to), propagates the error in `errno` to the application. GitHub issue: https://github.com/gem5/gem5/issues/276 Change-Id: I8a576f60fe3687f320d0cfc28e9d3a6b477d7054 --- src/sim/syscall_emul.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index c212d242fb..9794a4835e 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -959,7 +959,9 @@ chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname) tgt_cwd = path; } else { char buf[PATH_MAX]; - tgt_cwd = realpath((p->tgtCwd + "/" + path).c_str(), buf); + if (!realpath((p->tgtCwd + "/" + path).c_str(), buf)) + return -errno; + tgt_cwd = buf; } std::string host_cwd = p->checkPathRedirect(tgt_cwd); From 105839ae2bb6795eca6bf35f42f6df61501e37b6 Mon Sep 17 00:00:00 2001 From: Johnny Date: Wed, 6 Sep 2023 10:42:30 +0800 Subject: [PATCH 266/693] sim: add bypass_on_change to the set() of a signal When reset a port, we don't want to trigger a onChange(). Offer an option to bypass it and update state only. Change-Id: Ia53b7a76d2a320ea67101096cdbfe2eafaf440d2 --- src/sim/signal.hh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sim/signal.hh b/src/sim/signal.hh index b94618a9c3..233de07658 100644 --- a/src/sim/signal.hh +++ b/src/sim/signal.hh @@ -54,14 +54,16 @@ class SignalSinkPort : public Port OnChangeFunc _onChange; protected: + // if bypass_on_change is specified true, it will not call the _onChange + // function. Only _state will be updated if needed. void - set(const State &new_state) + set(const State &new_state, const bool bypass_on_change = false) { if (new_state == _state) return; _state = new_state; - if (_onChange) + if (!bypass_on_change && _onChange) _onChange(_state); } @@ -113,11 +115,13 @@ class SignalSourcePort : public Port _state = init_state; } + // if bypass_on_change is specified true, it will not call the _onChange + // function. Only _state will be updated if needed. void - set(const State &new_state) + set(const State &new_state, const bool bypass_on_change = false) { _state = new_state; - sink->set(new_state); + sink->set(new_state, bypass_on_change); } const State &state() const { return _state; } From 0dab27f24a9476a91aa57fc07ef78a318cbf6ded Mon Sep 17 00:00:00 2001 From: studyztp Date: Wed, 23 Aug 2023 14:47:01 -0700 Subject: [PATCH 267/693] sim: check redirect path when unserialize for cpt Change-Id: I55b8ce1770b0580d52b8dfa782572d492c1bf727 --- src/sim/fd_array.cc | 19 +++++++++++++++++-- src/sim/fd_array.hh | 8 ++++++-- src/sim/process.cc | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/sim/fd_array.cc b/src/sim/fd_array.cc index 5ca9370054..d8cb981a93 100644 --- a/src/sim/fd_array.cc +++ b/src/sim/fd_array.cc @@ -42,6 +42,7 @@ #include "base/output.hh" #include "params/Process.hh" #include "sim/fd_entry.hh" +#include "sim/process.hh" namespace gem5 { @@ -367,7 +368,7 @@ FDArray::serialize(CheckpointOut &cp) const { } void -FDArray::unserialize(CheckpointIn &cp) { +FDArray::unserialize(CheckpointIn &cp, SimObject* process_ptr) { ScopedCheckpointSection sec(cp, "fdarray"); uint64_t size; paramIn(cp, "size", size); @@ -418,11 +419,25 @@ FDArray::unserialize(CheckpointIn &cp) { setFDEntry(tgt_fd, fdep); mode_t mode = this_ffd->getFileMode(); + std::string const& path = this_ffd->getFileName(); + int flags = this_ffd->getFlags(); // Re-open the file and assign a new sim_fd - int sim_fd = openFile(path, flags, mode); + int sim_fd; + if (process_ptr) + { + Process* ptr = static_cast(process_ptr); + std::string const& host_path = + ptr->checkPathRedirect(this_ffd->getFileName()); + sim_fd = openFile(host_path, flags, mode); + } + else + { + sim_fd = openFile(path, flags, mode); + } + this_ffd->setSimFD(sim_fd); // Restore the file offset to the proper value diff --git a/src/sim/fd_array.hh b/src/sim/fd_array.hh index d6d1b3cfbe..79e5a4b92e 100644 --- a/src/sim/fd_array.hh +++ b/src/sim/fd_array.hh @@ -36,9 +36,9 @@ #include #include #include - #include "sim/fd_entry.hh" #include "sim/serialize.hh" +#include "sim/sim_object.hh" namespace gem5 { @@ -117,7 +117,11 @@ class FDArray : public Serializable * Serialization methods for file descriptors */ void serialize(CheckpointOut &cp) const override; - void unserialize(CheckpointIn &cp) override; + void unserialize(CheckpointIn &cp, SimObject* process_ptr ); + void unserialize(CheckpointIn &cp) override { + unserialize(cp, nullptr); + }; + private: /** diff --git a/src/sim/process.cc b/src/sim/process.cc index a348b450b0..f47dbd59c6 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -387,7 +387,7 @@ Process::unserialize(CheckpointIn &cp) { memState->unserialize(cp); pTable->unserialize(cp); - fds->unserialize(cp); + fds->unserialize(cp, this); /** * Checkpoints for pipes, device drivers or sockets currently From 2a4f3f206bf3e86f139b4cd2b7a379da25647e38 Mon Sep 17 00:00:00 2001 From: studyztp Date: Wed, 23 Aug 2023 16:27:45 -0700 Subject: [PATCH 268/693] sim: modifed the type of path Change-Id: I56be3b62b1804371b9b9e0f84ee1ec49cbedf553 --- src/sim/fd_array.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sim/fd_array.cc b/src/sim/fd_array.cc index d8cb981a93..f3605a5b7d 100644 --- a/src/sim/fd_array.cc +++ b/src/sim/fd_array.cc @@ -420,23 +420,23 @@ FDArray::unserialize(CheckpointIn &cp, SimObject* process_ptr) { mode_t mode = this_ffd->getFileMode(); - std::string const& path = this_ffd->getFileName(); + std::string path; + + if (process_ptr) + { + Process* ptr = static_cast(process_ptr); + path = ptr->checkPathRedirect(this_ffd->getFileName()); + } + else + { + path = this_ffd->getFileName(); + } int flags = this_ffd->getFlags(); // Re-open the file and assign a new sim_fd int sim_fd; - if (process_ptr) - { - Process* ptr = static_cast(process_ptr); - std::string const& host_path = - ptr->checkPathRedirect(this_ffd->getFileName()); - sim_fd = openFile(host_path, flags, mode); - } - else - { - sim_fd = openFile(path, flags, mode); - } + sim_fd = openFile(path, flags, mode); this_ffd->setSimFD(sim_fd); From 377c875733b38865ca22ef5232f2ad25c6d054c9 Mon Sep 17 00:00:00 2001 From: studyztp Date: Thu, 31 Aug 2023 11:33:45 -0700 Subject: [PATCH 269/693] sim: check redirect path when unserialize for cpt sim/fd_array.hh: Add "class Process;" to forward declare Process for unserialize function to pass in a Process object pointer. Fix the styling issue with include files. sim/fd_array.cc" Add comments. Change-Id: Ifb21eb1c7bad119028b8fd8e610a125100fde696 --- src/sim/fd_array.cc | 7 ++++--- src/sim/fd_array.hh | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sim/fd_array.cc b/src/sim/fd_array.cc index f3605a5b7d..1ce46a1e33 100644 --- a/src/sim/fd_array.cc +++ b/src/sim/fd_array.cc @@ -368,7 +368,7 @@ FDArray::serialize(CheckpointOut &cp) const { } void -FDArray::unserialize(CheckpointIn &cp, SimObject* process_ptr) { +FDArray::unserialize(CheckpointIn &cp, Process* process_ptr) { ScopedCheckpointSection sec(cp, "fdarray"); uint64_t size; paramIn(cp, "size", size); @@ -424,8 +424,9 @@ FDArray::unserialize(CheckpointIn &cp, SimObject* process_ptr) { if (process_ptr) { - Process* ptr = static_cast(process_ptr); - path = ptr->checkPathRedirect(this_ffd->getFileName()); + // Check if it is needed to redirect the app path to another host + // path + path = process_ptr->checkPathRedirect(this_ffd->getFileName()); } else { diff --git a/src/sim/fd_array.hh b/src/sim/fd_array.hh index 79e5a4b92e..c2a6b64dea 100644 --- a/src/sim/fd_array.hh +++ b/src/sim/fd_array.hh @@ -36,13 +36,15 @@ #include #include #include + #include "sim/fd_entry.hh" #include "sim/serialize.hh" -#include "sim/sim_object.hh" namespace gem5 { +class Process; + class FDArray : public Serializable { public: @@ -117,7 +119,7 @@ class FDArray : public Serializable * Serialization methods for file descriptors */ void serialize(CheckpointOut &cp) const override; - void unserialize(CheckpointIn &cp, SimObject* process_ptr ); + void unserialize(CheckpointIn &cp, Process* process_ptr ); void unserialize(CheckpointIn &cp) override { unserialize(cp, nullptr); }; From e206b16f734630fae3c047adba82c34444ad660b Mon Sep 17 00:00:00 2001 From: studyztp Date: Tue, 5 Sep 2023 18:25:33 -0700 Subject: [PATCH 270/693] sim:fixed some style issues Change-Id: I0832a8b68e802e9671b755d3a71fd9c8f17e1648 --- src/sim/fd_array.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/sim/fd_array.cc b/src/sim/fd_array.cc index 1ce46a1e33..ea58299587 100644 --- a/src/sim/fd_array.cc +++ b/src/sim/fd_array.cc @@ -422,14 +422,12 @@ FDArray::unserialize(CheckpointIn &cp, Process* process_ptr) { std::string path; - if (process_ptr) - { + if (process_ptr) { // Check if it is needed to redirect the app path to another host // path path = process_ptr->checkPathRedirect(this_ffd->getFileName()); } - else - { + else { path = this_ffd->getFileName(); } From ce54ff061ac041e1101bc21dc88af16b58fe1d10 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 7 Sep 2023 12:52:31 -0700 Subject: [PATCH 271/693] scons: Fix 'recompiling' -> 'recompile' Change-Id: Ifb2366a0c2342bf4e7207df8db6196e14184a9d5 --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index ca0496a238..ee913bf782 100755 --- a/SConstruct +++ b/SConstruct @@ -438,7 +438,7 @@ for variant_path in variant_paths: mold_check_message = \ "You are seeing this error because -fuse-ld=mold failed.\n" \ "If you did not add the folder containing mold to $PATH, you " \ - "should do so and recompiling gem5.\n" \ + "should do so and recompile gem5.\n" \ "If that does not work, you can manually specify the path to " \ "the binary of mold using the --mold-path option. This will " \ "cause scons to look for ld or ld.mold in the same folder as " \ From 75a33ec377ac22c501eaa8c6f624f69b1d52f394 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 7 Sep 2023 14:02:28 -0700 Subject: [PATCH 272/693] misc,util-docker: Fix docker-build.yaml https://github.com/gem5/gem5/actions/runs/6114221855 failure was due to to running the actions inside our 22.04-all-dependencies container. This container does not contain docker. We must therefore run this action outside of the container. However, due to our policy of checking out the code within this container, we must split this into two jobs and use the artifact upload and download to get the resources we want. Change-Id: I6a5f9c3a4c287a56a3d5abe3b84dd560fa2e9ff1 --- .github/workflows/docker-build.yaml | 33 ++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index c46c7f7fb8..73ea3c93c6 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -3,21 +3,34 @@ name: Docker images build and push on: workflow_dispatch: jobs: - # This builds and pushes the docker image. - build-and-push: + obtain-dockerfiles: runs-on: [self-hosted, linux, x64, run] - permissions: - packages: write - contents: read container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest steps: - uses: actions/checkout@v3 - name: Checkout the develop branch with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/upload-artifact@v2 + with: + name: dockerfiles + path: util/dockerfiles + + # This builds and pushes the docker image. + build-and-push: + runs-on: [self-hosted, linux, x64, run] + needs: obtain-dockerfiles + permissions: + packages: write + contents: read + + steps: + - uses: actions/download-artifact@v2 + with: + name: dockerfiles + path: dockerfiles - uses: docker/setup-qemu-action@v2 name: Setup QEMU @@ -35,5 +48,5 @@ jobs: - name: Build and push with bake uses: docker/bake-action@v3 with: - files: util/dockerfiles/docker-bake.hcl + files: dockerfiles/docker-bake.hcl push: true From ddb6749b62fbb0fe035d84c7a7a86df0446b7f50 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 28 Jun 2023 17:02:28 +0100 Subject: [PATCH 273/693] mem-ruby: Add static_cast by value in SLICC At the moment it is possible to static_cast by pointer/reference only: static_cast(type, "pointer", val) -> static_cast(val); static_cast(type, "reference", val) -> static_cast(val); With this patch it will also be possible to do something like static_cast(type, "value", val) -> static_cast(val); Which is important when wishing to convert integer types into custom onces and viceversa. This patch is also deferring static_cast type check to C++ At the moment it is difficult to use the static_cast utility in slicc as it tries to handle type checking in the language itself. This would force us to explicitly define compatible types (like an Addr and an int as an example). Rather than pushing the burden on us, we should always allow a developer to use a static_cast in slicc and let the C++ compiler complain if the generated code is not compatible Change-Id: I0586b9224b1e41751a07d15e2d48a435061c2582 Signed-off-by: Giacomo Travaglini --- src/mem/slicc/ast/StaticCastAST.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/mem/slicc/ast/StaticCastAST.py b/src/mem/slicc/ast/StaticCastAST.py index 178285202b..b6b70efcb5 100644 --- a/src/mem/slicc/ast/StaticCastAST.py +++ b/src/mem/slicc/ast/StaticCastAST.py @@ -1,3 +1,15 @@ +# Copyright (c) 2023 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) 2009 Advanced Micro Devices, Inc. # All rights reserved. # @@ -42,22 +54,9 @@ class StaticCastAST(ExprAST): actual_type, ecode = self.expr_ast.inline(True) if self.type_modifier == "pointer": code("static_cast<${{self.type_ast.type.c_ident}} *>($ecode)") + elif self.type_modifier == "value": + code("static_cast<${{self.type_ast.type.c_ident}} >($ecode)") else: code("static_cast<${{self.type_ast.type.c_ident}} &>($ecode)") - if not "interface" in self.type_ast.type: - self.expr_ast.error( - "static cast only premitted for those types " - "that implement inherit an interface" - ) - - # The interface type should match - if str(actual_type) != str(self.type_ast.type["interface"]): - self.expr_ast.error( - "static cast miss-match, type is '%s'," - "but inherited type is '%s'", - actual_type, - self.type_ast.type["interface"], - ) - return self.type_ast.type From f7d6dadc108340dd884dba32425eb84895d6648d Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 29 Jun 2023 09:48:21 +0100 Subject: [PATCH 274/693] mem-ruby: Allow trivial integer operations with Addr type At the moment an address value can only be used in the slicc code to do TBE lookups but there is no way to add/subtract/divide/multiply two addresses nor an address and an integer value. This hinders the development of protocol specific code and forces developers to place such code in shared C++ structures Change-Id: Ia184e793b6cd38f951f475a7cdf284f529972ccb Signed-off-by: Giacomo Travaglini --- src/mem/slicc/ast/OperatorExprAST.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/mem/slicc/ast/OperatorExprAST.py b/src/mem/slicc/ast/OperatorExprAST.py index 714b553101..cc1e7a2fb4 100644 --- a/src/mem/slicc/ast/OperatorExprAST.py +++ b/src/mem/slicc/ast/OperatorExprAST.py @@ -1,3 +1,15 @@ +# Copyright (c) 2023 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) 1999-2008 Mark D. Hill and David A. Wood # Copyright (c) 2009 The Hewlett-Packard Development Company # All rights reserved. @@ -76,11 +88,14 @@ class InfixOperatorExprAST(ExprAST): ("int", "int", "int"), ("Cycles", "Cycles", "Cycles"), ("Tick", "Tick", "Tick"), + ("Addr", "Addr", "Addr"), ("Cycles", "int", "Cycles"), ("Scalar", "int", "Scalar"), ("int", "bool", "int"), ("bool", "int", "int"), ("int", "Cycles", "Cycles"), + ("Addr", "int", "Addr"), + ("int", "Addr", "Addr"), ] else: self.error(f"No operator matched with {self.op}!") From 5dbc48432f121f6849e7cb079295fe4dc815205f Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 29 Jun 2023 09:55:12 +0100 Subject: [PATCH 275/693] mem-ruby: Allow Addr as a controller member type Change-Id: I63127ed06b4f871b74faad6c2c6436aebd118334 Signed-off-by: Giacomo Travaglini --- src/mem/slicc/symbols/StateMachine.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 039202a321..20ab096a63 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -64,6 +64,7 @@ python_class_map = { "DMASequencer": "DMASequencer", "RubyPrefetcher": "RubyPrefetcher", "Cycles": "Cycles", + "Addr": "Addr", } From f032eeae9369564369428e8507eb8767e2ca098e Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 30 Aug 2023 09:49:46 +0100 Subject: [PATCH 276/693] mem-ruby: Provide a fromSequencer helper function Based on the CHIRequestType, it automatically tells if the request has been originated from the sequencer (CPU load/fetch/store) Change-Id: I50fd116c8b1a995b1c37e948cd96db60c027fe66 Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 4 +--- src/mem/ruby/protocol/chi/CHI-cache-funcs.sm | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index e52bb01e83..39ae2d6dcc 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -3155,9 +3155,7 @@ action(Profile_OutgoingEnd_DatalessResp, desc="") { action(TagArrayRead, desc="") { assert(is_valid(tbe)); tbe.delayNextAction := curTick() + cyclesToTicks( - tagLatency((tbe.reqType == CHIRequestType:Load) || - (tbe.reqType == CHIRequestType:Store) || - (tbe.reqType == CHIRequestType:StoreLine))); + tagLatency(fromSequencer(tbe.reqType))); } action(TagArrayWrite, desc="") { diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index f990c0b3b5..22de205eb0 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -299,6 +299,12 @@ Cycles dataLatency() { return cache.getDataLatency(); } +bool fromSequencer(CHIRequestType reqType) { + return reqType == CHIRequestType:Load || + reqType == CHIRequestType:Store || + reqType == CHIRequestType:StoreLine; +} + bool inCache(Addr addr) { CacheEntry entry := getCacheEntry(makeLineAddress(addr)); // NOTE: we consider data for the addr to be in cache if it exists in local, From 4359567180918887d0247b5f57d4a3023e448c6b Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 28 Jun 2023 17:01:04 +0100 Subject: [PATCH 277/693] mem-ruby: Generate TxnId field for an incoming CHI request The TxnId field of a CHI request has so far been unused (other than for DVM transactions). With this patch we always initialize the field when we extract a ruby request from the sequencer port. According to specs (IHI0050F): A 12-bit field is defined for the TxnID with the number of outstanding transactions being limited to 1024. A Requester is permitted to reuse a TxnID value after it has received either: * All responses associated with a previous transaction that have used the same value. * A RetryAck response for a previous transaction that used the same value Change-Id: Ie48f0fee99966339799ac50932d36b2a927b1c7d Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 8 ++++++++ src/mem/ruby/protocol/chi/CHI-cache-funcs.sm | 18 +++++++++++++++--- src/mem/ruby/protocol/chi/CHI-cache.sm | 5 +++++ src/mem/ruby/protocol/chi/CHI-mem.sm | 5 ++++- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 39ae2d6dcc..37d782a29b 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -63,6 +63,7 @@ action(AllocateTBE_Request, desc="") { out_msg.usesTxnId := false; out_msg.event := Event:SendRetryAck; out_msg.retryDest := in_msg.requestor; + out_msg.txnId := in_msg.txnId; retryQueue.emplace(in_msg.addr,false,in_msg.requestor); } } @@ -145,6 +146,7 @@ action(AllocateTBE_SeqRequest, desc="") { assert(in_msg.Prefetch == PrefetchBit:No); out_msg.is_local_pf := false; out_msg.is_remote_pf := false; + out_msg.txnId := max_outstanding_transactions; if ((in_msg.Type == RubyRequestType:LD) || (in_msg.Type == RubyRequestType:IFETCH)) { @@ -2508,6 +2510,7 @@ action(Send_Data, desc="") { enqueue(datOutPort, CHIDataMsg, data_latency) { out_msg.addr := tbe.addr; out_msg.type := tbe.snd_msgType; + out_msg.txnId := tbe.txnId; int offset := tbe.snd_pendBytes.firstBitSet(true); assert(offset < blockSize); @@ -2564,6 +2567,7 @@ action(Send_CompUC, desc="") { out_msg.type := CHIResponseType:Comp_UC; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.txnId := tbe.txnId; } } @@ -2574,6 +2578,7 @@ action(Send_CompUC_Stale, desc="") { out_msg.type := CHIResponseType:Comp_UC; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.txnId := tbe.txnId; // We don't know if this is a stale clean unique or a bug, so flag the // reponse so the requestor can make further checks out_msg.stale := true; @@ -2587,6 +2592,7 @@ action(Send_CompAck, desc="") { out_msg.type := CHIResponseType:CompAck; out_msg.responder := machineID; out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr)); + out_msg.txnId := tbe.txnId; } } @@ -2610,6 +2616,7 @@ action(Send_CompDBIDResp, desc="") { out_msg.type := CHIResponseType:CompDBIDResp; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.txnId := tbe.txnId; } } @@ -2667,6 +2674,7 @@ action(Send_RetryAck, desc="") { out_msg.type := CHIResponseType:RetryAck; out_msg.responder := machineID; out_msg.Destination.add(in_msg.retryDest); + out_msg.txnId := in_msg.txnId; } } } diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index 22de205eb0..4d8c35053c 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -411,6 +411,12 @@ TBE allocateRequestTBE(Addr addr, CHIRequestMsg in_msg), return_by_pointer="yes" TBE tbe := TBEs[addr]; initializeTBE(tbe, addr, storTBEs.addEntryToNewSlot()); + if (fromSequencer(in_msg.type)) { + assert(in_msg.txnId == max_outstanding_transactions); + tbe.txnId := static_cast(Addr, "value", tbe.storSlot); + } else { + tbe.txnId := in_msg.txnId; + } assert(tbe.is_snp_tbe == false); assert(tbe.is_repl_tbe == false); @@ -492,6 +498,7 @@ TBE allocateSnoopTBE(Addr addr, CHIRequestMsg in_msg), return_by_pointer="yes" { tbe.requestor := in_msg.requestor; tbe.fwdRequestor := in_msg.fwdRequestor; tbe.reqType := in_msg.type; + tbe.txnId := in_msg.txnId; tbe.snpNeedsData := in_msg.retToSrc; @@ -544,6 +551,8 @@ TBE _allocateReplacementTBE(Addr addr, int storSlot), return_by_pointer="yes" { tbe.accSize := blockSize; tbe.requestor := machineID; tbe.reqType := CHIRequestType:null; + // This is an internal event and should generate a new TxnId + tbe.txnId := static_cast(Addr, "value", storSlot); tbe.use_DMT := false; tbe.use_DCT := false; @@ -630,6 +639,9 @@ void prepareRequest(TBE tbe, CHIRequestType type, CHIRequestMsg & out_msg) { out_msg.seqReq := tbe.seqReq; out_msg.is_local_pf := false; out_msg.is_remote_pf := tbe.is_local_pf || tbe.is_remote_pf; + out_msg.txnId := tbe.txnId; + + assert(tbe.txnId != static_cast(Addr, "value", -1)); } void allowRequestRetry(TBE tbe, CHIRequestMsg & out_msg) { @@ -786,12 +798,12 @@ bool upstreamHasShared(State state) { } void printTBEState(TBE tbe) { - DPRINTF(RubySlicc, "STATE: addr: %#x data present=%d valid=%d unique=%d dirty=%d mu_dirty=%d dir ownerV=%d ownerE=%d sharers=%d tobe_I=%d tobe_SC=%d doFill=%d pendAction=%s\n", + DPRINTF(RubySlicc, "STATE: addr: %#x data present=%d valid=%d unique=%d dirty=%d mu_dirty=%d dir ownerV=%d ownerE=%d sharers=%d tobe_I=%d tobe_SC=%d doFill=%d pendAction=%s txnId=%d\n", tbe.addr, tbe.dataBlkValid.isFull(), tbe.dataValid, tbe.dataUnique, tbe.dataDirty, tbe.dataMaybeDirtyUpstream, tbe.dir_ownerExists, tbe.dir_ownerIsExcl,tbe.dir_sharers.count(), tbe.dataToBeInvalid, tbe.dataToBeSharedClean, - tbe.doCacheFill, tbe.pendAction); + tbe.doCacheFill, tbe.pendAction, tbe.txnId); DPRINTF(RubySlicc, "dataBlkValid = %s\n", tbe.dataBlkValid); } diff --git a/src/mem/ruby/protocol/chi/CHI-cache.sm b/src/mem/ruby/protocol/chi/CHI-cache.sm index 568b39c223..e40989df47 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache.sm @@ -81,6 +81,9 @@ machine(MachineType:Cache, "Cache coherency protocol") : int sc_lock_multiplier_max := 256; bool sc_lock_enabled; + // Maximum number of outstanding transactions from a single requester + Addr max_outstanding_transactions := 1024; + // Recycle latency on resource stalls Cycles stall_recycle_lat := 1; @@ -599,6 +602,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : Addr accAddr, desc="Access address for Load/Store/WriteUniquePtl; otherwisse == addr"; int accSize, desc="Access size for Load/Store/WriteUniquePtl; otherwisse == blockSize"; CHIRequestType reqType, desc="Request type that initiated this transaction"; + Addr txnId, desc="Transaction ID. We default to -1 for debug purposes", default="-1"; MachineID requestor, desc="Requestor ID"; MachineID fwdRequestor, desc="Requestor to receive data on fwding snoops"; bool use_DMT, desc="Use DMT for this transaction"; @@ -785,6 +789,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : Event event; MachineID retryDest; bool usesTxnId; + Addr txnId; bool functionalRead(Packet *pkt) { return false; } bool functionalRead(Packet *pkt, WriteMask &mask) { return false; } diff --git a/src/mem/ruby/protocol/chi/CHI-mem.sm b/src/mem/ruby/protocol/chi/CHI-mem.sm index 1e34d234c2..46f57456a5 100644 --- a/src/mem/ruby/protocol/chi/CHI-mem.sm +++ b/src/mem/ruby/protocol/chi/CHI-mem.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021,2022 ARM Limited + * Copyright (c) 2021-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -164,6 +164,7 @@ machine(MachineType:Memory, "Memory controller interface") : int storSlot, desc="Slot in the storage tracker occupied by this entry"; Addr addr, desc="Line address for this TBE"; Addr accAddr, desc="Original access address. Set only for Write*Ptl"; + Addr txnId, desc="Transaction ID"; int accSize, desc="Access size. Set only for Write*Ptl"; State state, desc="Current line state"; DataBlock dataBlk, desc="Transaction data"; @@ -503,6 +504,7 @@ machine(MachineType:Memory, "Memory controller interface") : } tbe.accAddr := in_msg.accAddr; tbe.accSize := in_msg.accSize; + tbe.txnId := in_msg.txnId; } } @@ -608,6 +610,7 @@ machine(MachineType:Memory, "Memory controller interface") : assert(tbe.rxtxBytes < blockSize); enqueue(datOutPort, CHIDataMsg, data_latency) { out_msg.addr := tbe.addr; + out_msg.txnId := tbe.txnId; if (tbe.useDataSepResp) { out_msg.type := CHIDataType:DataSepResp_UC; } else { From da740b1cdd9e213fb740f3401a5d61bf7be10b10 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 29 Jun 2023 10:46:20 +0100 Subject: [PATCH 278/693] mem-ruby: Add a DBID field to the CHIResponseMsg data type This will hold the CHI Data Buffer Identifier (DBID) field. The DBID allows a Completer of a transaction to provide its own identifier for a transaction ID. This new ID will be used as a TxnId field by a following WriteData/CompData/CompAck response. For now we only set it to the original txnId (identity mapping) Change-Id: If30c5e1cafbe5a30073c7cd01d60bf41eb586cee Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 17 +++++++++++++++++ .../ruby/protocol/chi/CHI-cache-transitions.sm | 15 ++++++++++++--- src/mem/ruby/protocol/chi/CHI-msg.sm | 3 ++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 37d782a29b..ad1935a119 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -2135,6 +2135,16 @@ action(Receive_ReqResp_WUComp, desc="") { } } +action(Receive_ReqResp_CopyDBID, desc="Copy the rsp DBID into the TBE") { + if (tbe.expected_req_resp.receivedRespType(CHIResponseType:DBIDResp) == false && + tbe.expected_req_resp.receivedRespType(CHIResponseType:CompDBIDResp) == false) { + error("Received unexpected message"); + } + peek(rspInPort, CHIResponseMsg) { + tbe.txnId := in_msg.dbid; + } +} + action(Receive_SnpResp, desc="") { assert(tbe.expected_snp_resp.hasExpected()); peek(rspInPort, CHIResponseMsg) { @@ -2557,6 +2567,7 @@ action(Send_CompI, desc="") { out_msg.type := CHIResponseType:Comp_I; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.dbid := tbe.txnId; } } @@ -2568,6 +2579,7 @@ action(Send_CompUC, desc="") { out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); out_msg.txnId := tbe.txnId; + out_msg.dbid := tbe.txnId; } } @@ -2579,6 +2591,7 @@ action(Send_CompUC_Stale, desc="") { out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); out_msg.txnId := tbe.txnId; + out_msg.dbid := tbe.txnId; // We don't know if this is a stale clean unique or a bug, so flag the // reponse so the requestor can make further checks out_msg.stale := true; @@ -2603,6 +2616,7 @@ action(Send_CompI_Stale, desc="") { out_msg.type := CHIResponseType:Comp_I; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.dbid := tbe.txnId; // We don't know if this is a stale writeback or a bug, so flag the // reponse so the requestor can make further checks out_msg.stale := true; @@ -2617,6 +2631,7 @@ action(Send_CompDBIDResp, desc="") { out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); out_msg.txnId := tbe.txnId; + out_msg.dbid := tbe.txnId; } } @@ -2627,6 +2642,7 @@ action(Send_CompDBIDResp_Stale, desc="") { out_msg.type := CHIResponseType:CompDBIDResp; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.dbid := tbe.txnId; // We don't know if this is a stale writeback or a bug, so flag the // reponse so the requestor can make further checks out_msg.stale := true; @@ -2640,6 +2656,7 @@ action(Send_DBIDResp, desc="") { out_msg.type := CHIResponseType:DBIDResp; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.dbid := tbe.txnId; } } diff --git a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm index 4c93988afd..cb9ffa567a 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 ARM Limited + * Copyright (c) 2021-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -1212,8 +1212,7 @@ transition(BUSY_BLKD, } // waiting for WB or evict ack -transition(BUSY_INTR, - {CompDBIDResp,Comp_I}, BUSY_BLKD) { +transition(BUSY_INTR, Comp_I, BUSY_BLKD) { Receive_ReqResp; Profile_OutgoingEnd_DatalessResp; Pop_RespInQueue; @@ -1229,9 +1228,19 @@ transition(BUSY_INTR, Comp_UC, BUSY_BLKD) { ProcessNextState; } +// waiting for WB or evict ack +transition(BUSY_INTR, CompDBIDResp, BUSY_BLKD) { + Receive_ReqResp; + Receive_ReqResp_CopyDBID; + Profile_OutgoingEnd_DatalessResp; + Pop_RespInQueue; + ProcessNextState; +} + // alternative flow for WU with separate Comp transition(BUSY_INTR, DBIDResp, BUSY_BLKD) { Receive_ReqResp; + Receive_ReqResp_CopyDBID; Receive_ReqResp_WUNeedComp; Pop_RespInQueue; ProcessNextState; diff --git a/src/mem/ruby/protocol/chi/CHI-msg.sm b/src/mem/ruby/protocol/chi/CHI-msg.sm index 63648a5920..f3c2d66363 100644 --- a/src/mem/ruby/protocol/chi/CHI-msg.sm +++ b/src/mem/ruby/protocol/chi/CHI-msg.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 ARM Limited + * Copyright (c) 2021, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -156,6 +156,7 @@ structure(CHIResponseMsg, desc="", interface="Message") { bool stale, desc="Response to a stale request"; bool usesTxnId, desc="True if using a Transaction ID", default="false"; Addr txnId, desc="Transaction ID", default="0"; + Addr dbid, desc="Data Buffer ID", default="0"; //NOTE: not in CHI and for debuging only MessageSizeType MessageSize, default="MessageSizeType_Control"; From 16e8c95091e6107f411a8c3762797d05dcf7cd6b Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 8 Sep 2023 10:25:09 -0700 Subject: [PATCH 279/693] util: Update gcn-gpu Dockerfile This adds the setting up of environment variables to the gcn-gpu Dockerfile from the halofinder Dockerfile in gem5-resources so that we don't need to use a seperate Docker image in the gpu tests. Change-Id: Ifcc7a4c6bbcd5289ce9561923366e9ed193f170c --- util/dockerfiles/gcn-gpu/Dockerfile | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/util/dockerfiles/gcn-gpu/Dockerfile b/util/dockerfiles/gcn-gpu/Dockerfile index 618495c5a9..85ec6d7c0d 100644 --- a/util/dockerfiles/gcn-gpu/Dockerfile +++ b/util/dockerfiles/gcn-gpu/Dockerfile @@ -121,3 +121,41 @@ RUN git clone -b rocm-4.0.1 https://github.com/ROCmSoftwarePlatform/MIOpen.git # when linking in the database file RUN mkdir -p /root/.cache/miopen/2.9.0.8252-rocm-rel-4.0-26-64506314 && \ ln -s /root/.cache/miopen/2.9.0.8252-rocm-rel-4.0-26-64506314 /root/.cache/miopen/2.9.0 + +# Add commands from halofinder Dockerfile +RUN apt-get update && apt-get -y install libopenmpi-dev libomp-dev + +ENV HCC_AMDGPU_TARGET="gfx801,gfx803,gfx900" + +ENV HIPCC_BIN=/opt/rocm/bin +ENV MPI_INCLUDE=/usr/lib/x86_64-linux-gnu/openmpi/include + +ENV OPT="-O3 -g -DRCB_UNTHREADED_BUILD -DUSE_SERIAL_COSMO" +ENV OMP="-I/usr/lib/llvm-10/include/openmp -L/usr/lib/llvm-10/lib -fopenmp" + +ENV HIPCC_FLAGS="-v -ffast_math -DINLINE_FORCE -I${MPI_INCLUDE}" +ENV HIPCC_FLAGS="-v -I${MPI_INCLUDE} -I/opt/rocm/hip/include" + +ENV HACC_PLATFORM="hip" +ENV HACC_OBJDIR="${HACC_PLATFORM}" + +ENV HACC_CFLAGS="$OPT $OMP $HIPCC_FLAGS" +ENV HACC_CC="${HIPCC_BIN}/hipcc -x c -Xclang -std=c99" + +ENV HACC_CXXFLAGS="$OPT $OMP $HIPCC_FLAGS" +ENV HACC_CXX="${HIPCC_BIN}/hipcc -Xclang" + +ENV HACC_LDFLAGS="-lm -lrt" + +# USE_SERIAL_COSMO must be set to avoid building the code with MPI, which isn't +# supported on the GPU model in gem5. +ENV USE_SERIAL_COSMO="1" +ENV HACC_NUM_CUDA_DEV="1" +ENV HACC_MPI_CFLAGS="$OPT $OMP $HIPCC_FLAGS" +ENV HACC_MPI_CC="${HIPCC_BIN}/hipcc -x c -Xclang -std=c99 -Xclang -pthread" + +ENV HACC_MPI_CXXFLAGS="$OPT $OMP $HIPCC_FLAGS" +ENV HACC_MPI_CXX="${HIPCC_BIN}/hipcc -Xclang -pthread" +ENV HACC_MPI_LD="${HIPCC_BIN}/hipcc -Xclang -pthread" + +ENV HACC_MPI_LDFLAGS="-lm -lrt" From 91d1a5deb532f34188249db94aa996ecbbfead7b Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 6 Sep 2023 03:08:19 +0000 Subject: [PATCH 280/693] mem-cache: Fix bug in classic cache while clflush This change, https://github.com/gem5/gem5/pull/205, mistakenly allocates write buffer for clflush instruction when there's a cache miss. However, clflush in gem5 is not a write instruction. Thus, the cache should allocate miss buffer in this case. Change-Id: I9c1c9b841159c4420567e9c929e71e4aa27d5c28 Signed-off-by: Hoa Nguyen --- src/mem/cache/cache.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc index 46d7f577d3..3357d5e1b2 100644 --- a/src/mem/cache/cache.cc +++ b/src/mem/cache/cache.cc @@ -338,22 +338,27 @@ Cache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, if (pkt->isWrite()) { allocateWriteBuffer(pkt, forward_time); - } else if (pkt->isRead()) { + } else { // uncacheable accesses always allocate a new MSHR // Here we are using forward_time, modelling the latency of // a miss (outbound) just as forwardLatency, neglecting the // lookupLatency component. + + // Here we allow allocating miss buffer for read requests + // and x86's clflush requests. A clflush request should be + // propagate through all levels of the cache system. + + // Doing clflush in uncacheable regions might sound contradictory; + // however, it is entirely possible due to how the Linux kernel + // handle page property changes. When a linux kernel wants to + // change a page property, it flushes the related cache lines. The + // kernel might change the page property before flushing the cache + // lines. This results in the clflush might occur in an uncacheable + // region, where the kernel marks a region uncacheable before + // flushing. clflush results in a CleanInvalidReq. + assert(pkt->isRead() || pkt->isCleanInvalidateRequest()); allocateMissBuffer(pkt, forward_time); - } else { - // When a linux kernel wants to change a page property, - // it flushes the related cache lines. The kernel might change - // the page property before flushing the cache. This results in - // the clflush might occur in an uncacheable region. - // clflush results in a CleanInvalidReq, which is neither read - // nor write. - assert(pkt->isCleanInvalidateRequest()); - allocateWriteBuffer(pkt, forward_time); } return; From 259a5d62724fd59519b73ca4f9f86199685db666 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Thu, 7 Sep 2023 10:52:47 -0700 Subject: [PATCH 281/693] sim-se: Use tgt_stat64 instead of tgt_stat in newfstatatFunc The syscall emulation of newfstatat incorrectly treated the output stat buffer to be of type `OS::tgt_stat`, not `OS::tgt_stat64`, causing the invalid output stat buffer in the application to hold invalid data. This patch fixes the bug by simply substituting the type `OS::tgt_stat` with `OS::tgt_stat64` in `newstatatFunc()`. GitHub issue: https://github.com/gem5/gem5/issues/281 Change-Id: Ice97c1fc4cccbfb6824e313ebecde00f134ebf9c --- src/sim/syscall_emul.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index b4550dd86b..1ae1603d77 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1375,7 +1375,7 @@ statFunc(SyscallDesc *desc, ThreadContext *tc, template SyscallReturn newfstatatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, - VPtr<> pathname, VPtr tgt_stat, + VPtr<> pathname, VPtr tgt_stat, int flags) { std::string path; @@ -1405,7 +1405,7 @@ newfstatatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, if (result < 0) return -errno; - copyOutStatBuf(tgt_stat, &host_buf); + copyOutStat64Buf(tgt_stat, &host_buf); return 0; } From 8740385f9ed2c5953e204b124ce6099c45d6d76f Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Thu, 7 Sep 2023 14:17:32 -0700 Subject: [PATCH 282/693] sim-se: Fix tgkill logic bug in handling signal argument The syscall emulation of tgkill contained a simple logic bug (a `||` instead of a `&&`), causing the signal argument to always be considered invalid. This patch fixes the bug by simply changing the `||` to a `&&`. GitHub issue: https://github.com/gem5/gem5/issues/284 Change-Id: I3b02c618c369ef56d32a0b04e0b13eacc9fb4977 --- src/sim/syscall_emul.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index b4550dd86b..8e6fde3714 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -2409,7 +2409,7 @@ tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig) } } - if (sig != 0 || sig != OS::TGT_SIGABRT) + if (sig != 0 && sig != OS::TGT_SIGABRT) return -EINVAL; if (tgt_proc == nullptr) From 2b9d558ceff0e183c7bf6eae7399fd57e3438757 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Sun, 10 Sep 2023 15:16:50 +0000 Subject: [PATCH 283/693] cpu-kvm: properly set x86 xsave header on gem5->KVM transition If the XSAVE KVM capability is available (KVM_CAP_XSAVE), the X86KvmCPU will try to set the x87 FPU + SSE state using KVM_SET_XSAVE, which expects a buffer (struct kvm_xsave) in XSAVE area format (Vol. 1, Sec. 13.4 of Intel x86 SDM). The original implementation of `X86KvmCPU::updateKvmStateFPUXSave()`, however, improperly sets the xsave header, which contains a bitmap of state components present in the xsave area. This patch defines `XSaveHeader` structure to model the xsave header, which is expected directly following the legacy FPU region (defined in the `FXSave` structure) in the xsave area. It then sets two bist in the xsave header to indicate the presence of x86 FPU and SSE state components. GitHub issue: https://github.com/gem5/gem5/issues/296 Change-Id: I5c5c7925fa7f78a7b5e2adc209187deff53ac039 --- src/arch/x86/kvm/x86_cpu.cc | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/arch/x86/kvm/x86_cpu.cc b/src/arch/x86/kvm/x86_cpu.cc index b88a96a2b9..da6e1bb9e1 100644 --- a/src/arch/x86/kvm/x86_cpu.cc +++ b/src/arch/x86/kvm/x86_cpu.cc @@ -42,6 +42,7 @@ #include "arch/x86/regs/int.hh" #include "arch/x86/regs/msr.hh" #include "arch/x86/utility.hh" +#include "base/bitunion.hh" #include "base/compiler.hh" #include "cpu/kvm/base.hh" #include "debug/Drain.hh" @@ -117,6 +118,32 @@ struct GEM5_PACKED FXSave static_assert(sizeof(FXSave) == 512, "Unexpected size of FXSave"); +BitUnion64(XStateBV) + Bitfield<0> fpu; + Bitfield<1> sse; + Bitfield<2> avx; + Bitfield<4, 3> mpx; + Bitfield<7, 5> avx512; + Bitfield<8> pt; + Bitfield<9> pkru; + Bitfield<10> pasid; + Bitfield<12, 11> cet; + Bitfield<13> hdc; + Bitfield<14> uintr; + Bitfield<15> lbr; + Bitfield<16> hwp; + Bitfield<18, 17> amx; + Bitfield<63, 19> reserved; +EndBitUnion(XStateBV) + +struct XSaveHeader +{ + XStateBV xstate_bv; + uint64_t reserved[7]; +}; + +static_assert(sizeof(XSaveHeader) == 64, "Unexpected size of XSaveHeader"); + #define FOREACH_IREG() \ do { \ APPLY_IREG(rax, int_reg::Rax); \ @@ -912,6 +939,19 @@ X86KvmCPU::updateKvmStateFPUXSave() updateKvmStateFPUCommon(tc, xsave); + /** + * The xsave header (Vol. 1, Section 13.4.2 of the Intel Software + * Development Manual) directly follows the legacy xsave region + * (i.e., the FPU/SSE state). The first 8 bytes of the xsave header + * hold a state-component bitmap called xstate_bv. We need to set + * the state component bits corresponding to the FPU and SSE + * states. + */ + XSaveHeader& xsave_hdr = + * (XSaveHeader *) ((char *) &kxsave + sizeof(FXSave)); + xsave_hdr.xstate_bv.fpu = 1; + xsave_hdr.xstate_bv.sse = 1; + if (tc->readMiscRegNoEffect(misc_reg::Fiseg)) warn_once("misc_reg::Fiseg is non-zero.\n"); From 7091a8b7a0b1644f7565ff492cd289eb1f50959f Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sun, 10 Sep 2023 20:25:20 -0700 Subject: [PATCH 284/693] util: Revert "Add docker prune cron to GitHub..." This reverts commit 0249d47acc3a87a82c9d7417dba4804cda4a3f4b, https://github.com/gem5/gem5/pull/271. This solution doesn't work. GitHub runners pull the images they need at the start of job (i.e., all the images they may need for each step). They then create the containers later, at the step they are needed. This solution therefore breaks in the case a cleanup happens during the running of a job. I.e., a `docker system prune` happens after setup, therefore deleting all the images, then the job tries to use one of the images during a step. This crontab solution may work if we can only do it when the runner is in an idle state. Whether this is possible is unknown. Change-Id: I7cb5b2d98d596e9380ae1525c7d66ad97af1b59b --- util/github-runners-vagrant/provision_nonroot.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/util/github-runners-vagrant/provision_nonroot.sh b/util/github-runners-vagrant/provision_nonroot.sh index 2b1e51504e..4465b5a192 100644 --- a/util/github-runners-vagrant/provision_nonroot.sh +++ b/util/github-runners-vagrant/provision_nonroot.sh @@ -13,7 +13,3 @@ DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/rel mkdir -p "${HOME}/.docker/cli-plugins" curl -sL "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o "${HOME}/.docker/cli-plugins/docker-compose" chmod +x "${HOME}/.docker/cli-plugins/docker-compose" - -# Setup crontab to run docker prune every 3 hours -echo "0 */3 * * * docker system prune -af --volumes"> /tmp/cron -crontab /tmp/cron From dfc725838ee17f64e6601b5a4e64a9366a1a5681 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 31 Aug 2023 13:27:41 +0800 Subject: [PATCH 285/693] arch-riscv: Refactor PCState class Change-Id: I1d25350ba2a3c7c366f42340c20b4488c33cde6f --- src/arch/riscv/pcstate.hh | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh index 1c04cb5109..c790305504 100644 --- a/src/arch/riscv/pcstate.hh +++ b/src/arch/riscv/pcstate.hh @@ -56,15 +56,22 @@ constexpr enums::RiscvType RV64 = enums::RV64; class PCState : public GenericISA::UPCState<4> { - private: + protected: + typedef GenericISA::UPCState<4> Base; + bool _compressed = false; RiscvType _rvType = RV64; public: + PCState(const PCState &other) : Base(other), _rvType(other._rvType) + {} + PCState &operator=(const PCState &other) = default; PCState() = default; - PCState(const PCState &other) = default; - PCState(Addr addr, RiscvType rvType) : UPCState(addr), _rvType(rvType) + explicit PCState(Addr addr) { set(addr); } + explicit PCState(Addr addr, RiscvType rvType) { + set(addr); + _rvType = rvType; } PCStateBase *clone() const override { return new PCState(*this); } @@ -84,14 +91,28 @@ class PCState : public GenericISA::UPCState<4> void rvType(RiscvType rvType) { _rvType = rvType; } RiscvType rvType() const { return _rvType; } + uint64_t size() const { return _compressed ? 2 : 4; } + bool branching() const override { - if (_compressed) { - return npc() != pc() + 2 || nupc() != upc() + 1; - } else { - return npc() != pc() + 4 || nupc() != upc() + 1; - } + return npc() != pc() + size() || nupc() != upc() + 1; + } + + void + serialize(CheckpointOut &cp) const override + { + Base::serialize(cp); + SERIALIZE_SCALAR(_rvType); + SERIALIZE_SCALAR(_compressed); + } + + void + unserialize(CheckpointIn &cp) override + { + Base::unserialize(cp); + UNSERIALIZE_SCALAR(_rvType); + UNSERIALIZE_SCALAR(_compressed); } }; From 3f0475321a071b016ba92dc4401183032d1c08f0 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 5 Sep 2023 10:39:02 +0800 Subject: [PATCH 286/693] arch-riscv: Change VTYPE to BitUnion64 Change-Id: I7620ad1ef3ee0cc045bcd02b3c9a2d83f93bf3fe --- src/arch/riscv/regs/vector.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/regs/vector.hh b/src/arch/riscv/regs/vector.hh index d722c2d03a..388e1cb78d 100644 --- a/src/arch/riscv/regs/vector.hh +++ b/src/arch/riscv/regs/vector.hh @@ -75,8 +75,8 @@ inline constexpr RegClass vecRegClass = ops(vecRegClassOps). regType(); -BitUnion32(VTYPE) - Bitfield<31> vill; +BitUnion64(VTYPE) + Bitfield<63> vill; Bitfield<7, 0> vtype8; Bitfield<7> vma; Bitfield<6> vta; From f94658098d666a96ce342f78c59528c3746ce7d4 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 14 Aug 2023 11:03:31 +0800 Subject: [PATCH 287/693] arch-riscv: Remove checked_type in StaticInst Constructor We should not try to check vtype when decoding the instruction. It should be checked in vset{i}vl{i} since the register can be modified via vset{i}vl{i} Change-Id: I403e5c4579bc5b8e6af10f93eac20c14662e4d2d --- src/arch/riscv/insts/vector.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index cae0dcac0a..8098c98b78 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -100,7 +100,7 @@ class VectorNonSplitInst : public RiscvStaticInst OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass), vl(_machInst.vl), - vtype(checked_vtype(_machInst.vill, _machInst.vtype8)) + vtype(_machInst.vtype8) { this->flags[IsVector] = true; } @@ -118,7 +118,7 @@ class VectorMacroInst : public RiscvMacroInst OpClass __opClass) : RiscvMacroInst(mnem, _machInst, __opClass), vl(_machInst.vl), - vtype(checked_vtype(_machInst.vill, _machInst.vtype8)) + vtype(_machInst.vtype8) { this->flags[IsVector] = true; } From 7b5d8b4e5bc913d35f3be5f5242650140a92df78 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 31 Aug 2023 14:22:46 +0800 Subject: [PATCH 288/693] arch-riscv: Add vlenb, vtype and vl in PCState Change-Id: I7c2aed7dda34a1a449253671d7b86aa615c28464 --- src/arch/riscv/faults.cc | 4 ++++ src/arch/riscv/isa.hh | 2 +- src/arch/riscv/pcstate.hh | 39 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 89bb838f88..502b748087 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -183,6 +183,10 @@ Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst) std::unique_ptr new_pc(dynamic_cast( tc->getIsaPtr()->newPCState(workload->getEntry()))); panic_if(!new_pc, "Failed create new PCState from ISA pointer"); + VTYPE vtype = 0; + vtype.vill = 1; + new_pc->vtype(vtype); + new_pc->vl(0); tc->pcState(*new_pc); // Reset PMP Cfg diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index f7726160c9..13366ef4c3 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -92,7 +92,7 @@ class ISA : public BaseISA PCStateBase* newPCState(Addr new_inst_addr=0) const override { - return new PCState(new_inst_addr, _rvType); + return new PCState(new_inst_addr, _rvType, VLENB); } public: diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh index c790305504..918e85708b 100644 --- a/src/arch/riscv/pcstate.hh +++ b/src/arch/riscv/pcstate.hh @@ -43,6 +43,7 @@ #define __ARCH_RISCV_PCSTATE_HH__ #include "arch/generic/pcstate.hh" +#include "arch/riscv/regs/vector.hh" #include "enums/RiscvType.hh" namespace gem5 @@ -61,17 +62,23 @@ class PCState : public GenericISA::UPCState<4> bool _compressed = false; RiscvType _rvType = RV64; + uint64_t _vlenb = VLENB; + VTYPE _vtype = (1ULL << 63); // vtype.vill = 1 at initial; + uint32_t _vl = 0; public: - PCState(const PCState &other) : Base(other), _rvType(other._rvType) + PCState(const PCState &other) : Base(other), + _rvType(other._rvType), _vlenb(other._vlenb), + _vtype(other._vtype), _vl(other._vl) {} PCState &operator=(const PCState &other) = default; PCState() = default; explicit PCState(Addr addr) { set(addr); } - explicit PCState(Addr addr, RiscvType rvType) + explicit PCState(Addr addr, RiscvType rvType, uint64_t vlenb = VLENB) { set(addr); _rvType = rvType; + _vlenb = vlenb; } PCStateBase *clone() const override { return new PCState(*this); } @@ -83,6 +90,9 @@ class PCState : public GenericISA::UPCState<4> auto &pcstate = other.as(); _compressed = pcstate._compressed; _rvType = pcstate._rvType; + _vlenb = pcstate._vlenb; + _vtype = pcstate._vtype; + _vl = pcstate._vl; } void compressed(bool c) { _compressed = c; } @@ -91,6 +101,15 @@ class PCState : public GenericISA::UPCState<4> void rvType(RiscvType rvType) { _rvType = rvType; } RiscvType rvType() const { return _rvType; } + void vlenb(uint64_t v) { _vlenb = v; } + uint64_t vlenb() const { return _vlenb; } + + void vtype(VTYPE v) { _vtype = v; } + VTYPE vtype() const { return _vtype; } + + void vl(uint32_t v) { _vl = v; } + uint32_t vl() const { return _vl; } + uint64_t size() const { return _compressed ? 2 : 4; } bool @@ -99,11 +118,24 @@ class PCState : public GenericISA::UPCState<4> return npc() != pc() + size() || nupc() != upc() + 1; } + bool + equals(const PCStateBase &other) const override + { + auto &opc = other.as(); + return Base::equals(other) && + _vlenb == opc._vlenb && + _vtype == opc._vtype && + _vl == opc._vl; + } + void serialize(CheckpointOut &cp) const override { Base::serialize(cp); SERIALIZE_SCALAR(_rvType); + SERIALIZE_SCALAR(_vlenb); + SERIALIZE_SCALAR(_vtype); + SERIALIZE_SCALAR(_vl); SERIALIZE_SCALAR(_compressed); } @@ -112,6 +144,9 @@ class PCState : public GenericISA::UPCState<4> { Base::unserialize(cp); UNSERIALIZE_SCALAR(_rvType); + UNSERIALIZE_SCALAR(_vlenb); + UNSERIALIZE_SCALAR(_vtype); + UNSERIALIZE_SCALAR(_vl); UNSERIALIZE_SCALAR(_compressed); } }; From 8918302239576de56807e1b2c4269610a7d269de Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Fri, 1 Sep 2023 16:20:51 +0800 Subject: [PATCH 289/693] arch-riscv: Change the implementation of vset*vl* The changes includes: 1. Add VL, Vtype and VlenbBits operands 2. Change R/W methods of VL, Vtype and VlenbBits from PCState Change-Id: I0531ddc14344f2cca94d0e750a3b4291e0227d54 --- src/arch/riscv/decoder.cc | 7 ++--- src/arch/riscv/isa/decoder.isa | 27 ++++++++++++++----- src/arch/riscv/isa/formats/vector_conf.isa | 31 +++++++++++----------- src/arch/riscv/isa/operands.isa | 6 +++++ 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index 702d84fd91..2070b149dd 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -101,9 +101,7 @@ Decoder::moreBytes(const PCStateBase &pc, Addr fetchPC) } } if (instDone) { - emi.vl = this->machVl; - emi.vtype8 = this->machVtype & 0xff; - emi.vill = this->machVtype.vill; + if (vconf(emi)) { this->vConfigDone = false; // set true when vconfig inst execute } @@ -142,6 +140,9 @@ Decoder::decode(PCStateBase &_next_pc) next_pc.compressed(false); } + emi.vl = next_pc.vl(); + emi.vtype8 = next_pc.vtype() & 0xff; + emi.vill = next_pc.vtype().vill; emi.rv_type = static_cast(next_pc.rvType()); return decode(emi, next_pc.instAddr()); } diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 71efac5958..4f573598e9 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -4359,8 +4359,13 @@ decode QUADRANT default Unknown::unknown() { uint64_t rs1_bits = RS1; uint64_t requested_vl = Rs1_ud; uint64_t requested_vtype = zimm11; - - Rd_ud = 0; + uint32_t vlen = VlenbBits * 8; + uint32_t vlmax = getVlmax(Vtype, vlen); + uint32_t current_vl = VL; + }}, {{ + Rd_ud = new_vl; + VL = new_vl; + Vtype = new_vtype; }}, VectorConfigOp, IsSerializeAfter, IsNonSpeculative); 0x1: decode BIT30 { 0x0: vsetvl({{ @@ -4368,8 +4373,13 @@ decode QUADRANT default Unknown::unknown() { uint64_t rs1_bits = RS1; uint64_t requested_vl = Rs1_ud; uint64_t requested_vtype = Rs2_ud; - - Rd_ud = 0; + uint32_t vlen = VlenbBits * 8; + uint32_t vlmax = getVlmax(Vtype, vlen); + uint32_t current_vl = VL; + }}, {{ + Rd_ud = new_vl; + VL = new_vl; + Vtype = new_vtype; }}, VectorConfigOp, IsSerializeAfter, IsNonSpeculative); 0x1: vsetivli({{ @@ -4377,8 +4387,13 @@ decode QUADRANT default Unknown::unknown() { uint64_t rs1_bits = -1; uint64_t requested_vl = uimm; uint64_t requested_vtype = zimm10; - - Rd_ud = 0; + uint32_t vlen = VlenbBits * 8; + uint32_t vlmax = getVlmax(Vtype, vlen); + uint32_t current_vl = VL; + }}, {{ + Rd_ud = new_vl; + VL = new_vl; + Vtype = new_vtype; }}, VectorConfigOp, IsSerializeAfter, IsNonSpeculative); } diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa index 84e2f26783..93361ecb94 100644 --- a/src/arch/riscv/isa/formats/vector_conf.isa +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -27,8 +27,17 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -def format VConfOp(code, *flags) {{ - iop = InstObjParams(name, Name, 'VConfOp', code, flags) +def format VConfOp(code, write_code, *flags) {{ + iop = InstObjParams( + name, + Name, + 'VConfOp', + { + 'code': code, + 'write_code': write_code, + }, + flags + ) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) @@ -54,11 +63,8 @@ def template VConfExecute {{ tc->setMiscReg(MISCREG_VSTART, 0); - uint32_t vlen = xc->readMiscReg(MISCREG_VLENB) * 8; - uint32_t vlmax = getVlmax(xc->readMiscReg(MISCREG_VTYPE), vlen); - VTYPE new_vtype = requested_vtype; - if (xc->readMiscReg(MISCREG_VTYPE) != new_vtype) { + if (Vtype != new_vtype) { vlmax = getVlmax(new_vtype, vlen); float vflmul = getVflmul(new_vtype.vlmul); @@ -68,17 +74,16 @@ def template VConfExecute {{ uint32_t new_vill = !(vflmul >= 0.125 && vflmul <= 8) || sew > std::min(vflmul, 1.0f) * ELEN || - bits(requested_vtype, 30, 8) != 0; + bits(requested_vtype, 62, 8) != 0; if (new_vill) { vlmax = 0; new_vtype = 0; new_vtype.vill = 1; } - - xc->setMiscReg(MISCREG_VTYPE, new_vtype); + } else { + new_vtype = Vtype; } - uint32_t current_vl = xc->readMiscReg(MISCREG_VL); uint32_t new_vl = 0; if (vlmax == 0) { new_vl = 0; @@ -90,11 +95,7 @@ def template VConfExecute {{ new_vl = requested_vl > vlmax ? vlmax : requested_vl; } - xc->setMiscReg(MISCREG_VL, new_vl); - - tc->getDecoderPtr()->as().setVlAndVtype(new_vl, new_vtype); - - Rd = new_vl; + %(write_code)s; %(op_wb)s; return NoFault; diff --git a/src/arch/riscv/isa/operands.isa b/src/arch/riscv/isa/operands.isa index a81b28df57..3a16e0994c 100644 --- a/src/arch/riscv/isa/operands.isa +++ b/src/arch/riscv/isa/operands.isa @@ -98,4 +98,10 @@ def operands {{ #Program Counter Operands 'PC': PCStateOp('ud', 'pc', (None, None, 'IsControl'), 7), 'NPC': PCStateOp('ud', 'npc', (None, None, 'IsControl'), 8), + +# VL and VTYPE + 'Vtype': PCStateOp('ud', 'vtype', (None, None, 'IsControl'), 10), + 'VL': PCStateOp('uw', 'vl', (None, None, 'IsControl'), 11), +#VLENB, actually the CSR is read only. + 'VlenbBits': PCStateOp('ud', 'vlenb', (None, None, 'IsControl'), 12), }}; From 1bde42760f51e4fb6b54107ad3ac65be8427968c Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 4 Sep 2023 15:15:23 +0800 Subject: [PATCH 290/693] arch-riscv: Get vl, vtype and vlenb from PCState Change-Id: I0ded57a3dc2db6fcc7121f147bcaf6d8a8873f6a --- src/arch/riscv/isa.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 14d741e9e4..4cb5082cad 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -40,6 +40,7 @@ #include "arch/riscv/mmu.hh" #include "arch/riscv/pagetable.hh" #include "arch/riscv/pmp.hh" +#include "arch/riscv/pcstate.hh" #include "arch/riscv/regs/float.hh" #include "arch/riscv/regs/int.hh" #include "arch/riscv/regs/misc.hh" @@ -503,9 +504,19 @@ ISA::readMiscReg(RegIndex idx) } case MISCREG_VLENB: { - return VLENB; + auto rpc = tc->pcState().as(); + return rpc.vlenb(); + } + case MISCREG_VTYPE: + { + auto rpc = tc->pcState().as(); + return rpc.vtype(); + } + case MISCREG_VL: + { + auto rpc = tc->pcState().as(); + return (RegVal)rpc.vl(); } - break; case MISCREG_VCSR: { return readMiscRegNoEffect(MISCREG_VXSAT) & From a3aaad2ecd252c591053500c5f2347550b320267 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 5 Sep 2023 11:18:57 +0800 Subject: [PATCH 291/693] arch-riscv: Refactor the execution part of vset*vl* Change-Id: Ie0d9671242481a85bb0fe5728748b16c3ef62592 --- src/arch/riscv/isa/formats/vector_conf.isa | 97 +++++++++++++++------- 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa index 93361ecb94..104d0ab2cd 100644 --- a/src/arch/riscv/isa/formats/vector_conf.isa +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -38,13 +38,75 @@ def format VConfOp(code, write_code, *flags) {{ }, flags ) - header_output = BasicDeclare.subst(iop) + header_output = VSetVlDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = VConfExecute.subst(iop) }}; +def template VSetVlDeclare {{ + // + // Static instruction class for "%(mnemonic)s". + // + class %(class_name)s : public %(base_class)s + { + private: + %(reg_idx_arr_decl)s; + VTYPE getNewVtype(VTYPE, VTYPE, uint32_t) const; + uint32_t getNewVL( + uint32_t, uint32_t, uint32_t, uint64_t, uint64_t) const; + + public: + /// Constructor. + %(class_name)s(ExtMachInst machInst); + Fault execute(ExecContext *, trace::InstRecord *) const override; + using %(base_class)s::generateDisassembly; + + }; +}}; + def template VConfExecute {{ + VTYPE + %(class_name)s::getNewVtype( + VTYPE oldVtype, VTYPE reqVtype, uint32_t vlen) const + { + VTYPE newVtype = oldVtype; + if (oldVtype != reqVtype) { + newVtype = reqVtype; + + float vflmul = getVflmul(newVtype.vlmul); + + uint32_t sew = getSew(newVtype.vsew); + + uint32_t newVill = + !(vflmul >= 0.125 && vflmul <= 8) || + sew > std::min(vflmul, 1.0f) * ELEN || + bits(reqVtype, 62, 8) != 0; + if (newVill) { + newVtype = 0; + newVtype.vill = 1; + } + } + return newVtype; + } + + uint32_t + %(class_name)s::getNewVL(uint32_t currentVl, uint32_t reqVl, + uint32_t vlmax, uint64_t rdBits, uint64_t rs1Bits) const + { + uint32_t newVl = 0; + if (vlmax == 0) { + newVl = 0; + } else if (rdBits == 0 && rs1Bits == 0) { + newVl = currentVl > vlmax ? vlmax : currentVl; + } else if (rdBits != 0 && rs1Bits == 0) { + newVl = vlmax; + } else if (rs1Bits != 0) { + newVl = reqVl > vlmax ? vlmax : reqVl; + } + return newVl; + } + Fault %(class_name)s::execute(ExecContext *xc, trace::InstRecord *traceData) const @@ -63,37 +125,12 @@ def template VConfExecute {{ tc->setMiscReg(MISCREG_VSTART, 0); - VTYPE new_vtype = requested_vtype; - if (Vtype != new_vtype) { - vlmax = getVlmax(new_vtype, vlen); + VTYPE new_vtype = getNewVtype(Vtype, requested_vtype, vlen); + vlmax = new_vtype.vill ? 0 : getVlmax(new_vtype, vlen); + uint32_t new_vl = getNewVL( + current_vl, requested_vl, vlmax, rd_bits, rs1_bits); - float vflmul = getVflmul(new_vtype.vlmul); - uint32_t sew = getSew(new_vtype.vsew); - - uint32_t new_vill = - !(vflmul >= 0.125 && vflmul <= 8) || - sew > std::min(vflmul, 1.0f) * ELEN || - bits(requested_vtype, 62, 8) != 0; - if (new_vill) { - vlmax = 0; - new_vtype = 0; - new_vtype.vill = 1; - } - } else { - new_vtype = Vtype; - } - - uint32_t new_vl = 0; - if (vlmax == 0) { - new_vl = 0; - } else if (rd_bits == 0 && rs1_bits == 0) { - new_vl = current_vl > vlmax ? vlmax : current_vl; - } else if (rd_bits != 0 && rs1_bits == 0) { - new_vl = vlmax; - } else if (rs1_bits != 0) { - new_vl = requested_vl > vlmax ? vlmax : requested_vl; - } %(write_code)s; From 282765234b58538dd3b48060c90ed5ad388eeef8 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 4 Sep 2023 15:24:45 +0800 Subject: [PATCH 292/693] arch-riscv: Implement the branchTarget for vset*vl* Change-Id: I10bf6be736ce2b99323ace410bff1d8e1e2a4123 --- src/arch/riscv/isa/decoder.isa | 9 +- src/arch/riscv/isa/formats/vector_conf.isa | 113 ++++++++++++++++++++- 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 4f573598e9..5e792e7dde 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -4366,7 +4366,8 @@ decode QUADRANT default Unknown::unknown() { Rd_ud = new_vl; VL = new_vl; Vtype = new_vtype; - }}, VectorConfigOp, IsSerializeAfter, IsNonSpeculative); + }}, VSetVlDeclare, VSetVliBranchTarget + , VectorConfigOp, IsSerializeAfter, IsNonSpeculative); 0x1: decode BIT30 { 0x0: vsetvl({{ uint64_t rd_bits = RD; @@ -4380,7 +4381,8 @@ decode QUADRANT default Unknown::unknown() { Rd_ud = new_vl; VL = new_vl; Vtype = new_vtype; - }}, VectorConfigOp, IsSerializeAfter, + }}, VSetVlDeclare, VSetVlBranchTarget + , VectorConfigOp, IsSerializeAfter, IsNonSpeculative); 0x1: vsetivli({{ uint64_t rd_bits = RD; @@ -4394,7 +4396,8 @@ decode QUADRANT default Unknown::unknown() { Rd_ud = new_vl; VL = new_vl; Vtype = new_vtype; - }}, VectorConfigOp, IsSerializeAfter, + }}, VSetiVliDeclare, VSetiVliBranchTarget + , VectorConfigOp, IsSerializeAfter, IsNonSpeculative); } } diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa index 104d0ab2cd..457c5ce40d 100644 --- a/src/arch/riscv/isa/formats/vector_conf.isa +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -27,7 +27,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -def format VConfOp(code, write_code, *flags) {{ +def format VConfOp(code, write_code, declare_class, branch_class, *flags) {{ iop = InstObjParams( name, Name, @@ -38,10 +38,13 @@ def format VConfOp(code, write_code, *flags) {{ }, flags ) - header_output = VSetVlDeclare.subst(iop) + declareTemplate = eval(declare_class) + branchTargetTemplate = eval(branch_class) + + header_output = declareTemplate.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) - exec_output = VConfExecute.subst(iop) + exec_output = VConfExecute.subst(iop) + branchTargetTemplate.subst(iop) }}; def template VSetVlDeclare {{ @@ -60,6 +63,35 @@ def template VSetVlDeclare {{ /// Constructor. %(class_name)s(ExtMachInst machInst); Fault execute(ExecContext *, trace::InstRecord *) const override; + std::unique_ptr branchTarget( + ThreadContext *tc) const override; + + using StaticInst::branchTarget; + using %(base_class)s::generateDisassembly; + + }; +}}; + +def template VSetiVliDeclare {{ + // + // Static instruction class for "%(mnemonic)s". + // + class %(class_name)s : public %(base_class)s + { + private: + %(reg_idx_arr_decl)s; + VTYPE getNewVtype(VTYPE, VTYPE, uint32_t) const; + uint32_t getNewVL( + uint32_t, uint32_t, uint32_t, uint64_t, uint64_t) const; + + public: + /// Constructor. + %(class_name)s(ExtMachInst machInst); + Fault execute(ExecContext *, trace::InstRecord *) const override; + std::unique_ptr branchTarget( + const PCStateBase &branch_pc) const override; + + using StaticInst::branchTarget; using %(base_class)s::generateDisassembly; }; @@ -138,3 +170,78 @@ def template VConfExecute {{ return NoFault; } }}; + +def template VSetiVliBranchTarget {{ + std::unique_ptr + %(class_name)s::branchTarget(const PCStateBase &branch_pc) const + { + auto &rpc = branch_pc.as(); + + uint64_t rd_bits = machInst.rd; + uint64_t rs1_bits = -1; + uint64_t requested_vl = uimm; + uint64_t requested_vtype = zimm10; + + uint32_t vlen = rpc.vlenb() * 8; + + VTYPE new_vtype = getNewVtype(rpc.vtype(), requested_vtype, vlen); + uint32_t vlmax = new_vtype.vill ? 0 : getVlmax(new_vtype, vlen); + uint32_t new_vl = getNewVL( + rpc.vl(), requested_vl, vlmax, rd_bits, rs1_bits); + + std::unique_ptr npc(dynamic_cast(rpc.clone())); + npc->vtype(new_vtype); + npc->vl(new_vl); + return npc; + } +}}; + +def template VSetVliBranchTarget {{ + std::unique_ptr + %(class_name)s::branchTarget(ThreadContext *tc) const + { + PCStateBase *pc_ptr = tc->pcState().clone(); + + uint64_t rd_bits = machInst.rd; + uint64_t rs1_bits = machInst.rs1; + uint64_t requested_vl = tc->getReg(srcRegIdx(0)); + uint64_t requested_vtype = zimm11; + + uint32_t vlen = pc_ptr->as().vlenb() * 8; + + VTYPE new_vtype = getNewVtype( + pc_ptr->as().vtype(), requested_vtype, vlen); + uint32_t vlmax = new_vtype.vill ? 0 : getVlmax(new_vtype, vlen); + uint32_t new_vl = getNewVL( + pc_ptr->as().vl(), requested_vl, vlmax, rd_bits, rs1_bits); + + pc_ptr->as().vtype(new_vtype); + pc_ptr->as().vl(new_vl); + return std::unique_ptr{pc_ptr}; + } +}}; + +def template VSetVlBranchTarget {{ + std::unique_ptr + %(class_name)s::branchTarget(ThreadContext *tc) const + { + PCStateBase *pc_ptr = tc->pcState().clone(); + + uint64_t rd_bits = machInst.rd; + uint64_t rs1_bits = machInst.rs1; + uint64_t requested_vl = tc->getReg(srcRegIdx(0)); + uint64_t requested_vtype = tc->getReg(srcRegIdx(1)); + + uint32_t vlen = pc_ptr->as().vlenb() * 8; + + VTYPE new_vtype = getNewVtype( + pc_ptr->as().vtype(), requested_vtype, vlen); + uint32_t vlmax = new_vtype.vill ? 0 : getVlmax(new_vtype, vlen); + uint32_t new_vl = getNewVL( + pc_ptr->as().vl(), requested_vl, vlmax, rd_bits, rs1_bits); + + pc_ptr->as().vtype(new_vtype); + pc_ptr->as().vl(new_vl); + return std::unique_ptr{pc_ptr}; + } +}}; From 31b95987da9aa9dab225108c6fb9a5e4b4d20789 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Fri, 1 Sep 2023 15:53:15 +0800 Subject: [PATCH 293/693] arch-riscv: Change the instruction family to jump like The method that get the vl, vtype from PCState in the next changes Change-Id: I022b47b7a96572f6434eed30dd9f7caa79854c31 --- src/arch/riscv/isa/decoder.isa | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 5e792e7dde..aeebfd6bf5 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -4367,7 +4367,8 @@ decode QUADRANT default Unknown::unknown() { VL = new_vl; Vtype = new_vtype; }}, VSetVlDeclare, VSetVliBranchTarget - , VectorConfigOp, IsSerializeAfter, IsNonSpeculative); + , VectorConfigOp, IsUncondControl + , IsIndirectControl); 0x1: decode BIT30 { 0x0: vsetvl({{ uint64_t rd_bits = RD; @@ -4382,8 +4383,8 @@ decode QUADRANT default Unknown::unknown() { VL = new_vl; Vtype = new_vtype; }}, VSetVlDeclare, VSetVlBranchTarget - , VectorConfigOp, IsSerializeAfter, - IsNonSpeculative); + , VectorConfigOp, IsUncondControl + , IsIndirectControl); 0x1: vsetivli({{ uint64_t rd_bits = RD; uint64_t rs1_bits = -1; @@ -4397,8 +4398,8 @@ decode QUADRANT default Unknown::unknown() { VL = new_vl; Vtype = new_vtype; }}, VSetiVliDeclare, VSetiVliBranchTarget - , VectorConfigOp, IsSerializeAfter, - IsNonSpeculative); + , VectorConfigOp, IsUncondControl + , IsDirectControl); } } } From 0f54cb05936ac97d447343c58c52ac0b0b89bb39 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 4 Sep 2023 16:13:51 +0800 Subject: [PATCH 294/693] arch-riscv: Remove check vconf done implementation Change-Id: If633cef209390d0500c4c2c5741d56158ef26c00 --- src/arch/riscv/decoder.cc | 31 ------------------------------- src/arch/riscv/decoder.hh | 10 ---------- 2 files changed, 41 deletions(-) diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index 2070b149dd..d225871241 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -41,8 +41,6 @@ namespace RiscvISA Decoder::Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst) { - ISA *isa = dynamic_cast(p.isa); - enableRvv = isa->getEnableRvv(); reset(); } @@ -50,7 +48,6 @@ void Decoder::reset() { aligned = true; mid = false; - vConfigDone = true; machInst = 0; emi = 0; } @@ -58,19 +55,6 @@ void Decoder::reset() void Decoder::moreBytes(const PCStateBase &pc, Addr fetchPC) { - // TODO: Current vsetvl instructions stall decode. Future fixes should - // enable speculation, and this code will be removed. - if (GEM5_UNLIKELY(!this->vConfigDone)) { - fatal_if(!enableRvv, - "Vector extension is not enabled for this CPU type\n" - "You can manually enable vector extensions by setting rvv_enabled " - "to true for each ISA object after `createThreads()`\n"); - DPRINTF(Decode, "Waiting for vset*vl* to be executed\n"); - instDone = false; - outOfBytes = false; - return; - } - // The MSB of the upper and lower halves of a machine instruction. constexpr size_t max_bit = sizeof(machInst) * 8 - 1; constexpr size_t mid_bit = sizeof(machInst) * 4 - 1; @@ -100,12 +84,6 @@ Decoder::moreBytes(const PCStateBase &pc, Addr fetchPC) instDone = compressed(emi); } } - if (instDone) { - - if (vconf(emi)) { - this->vConfigDone = false; // set true when vconfig inst execute - } - } } StaticInstPtr @@ -147,14 +125,5 @@ Decoder::decode(PCStateBase &_next_pc) return decode(emi, next_pc.instAddr()); } -void -Decoder::setVlAndVtype(uint32_t vl, VTYPE vtype) -{ - this->machVtype = vtype; - this->machVl = vl; - - this->vConfigDone = true; -} - } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh index 1f510e8280..6ce72ee35a 100644 --- a/src/arch/riscv/decoder.hh +++ b/src/arch/riscv/decoder.hh @@ -54,17 +54,12 @@ class Decoder : public InstDecoder decode_cache::InstMap instMap; bool aligned; bool mid; - bool vConfigDone; protected: //The extended machine instruction being generated ExtMachInst emi; uint32_t machInst; - bool enableRvv = false; - VTYPE machVtype; - uint32_t machVl; - StaticInstPtr decodeInst(ExtMachInst mach_inst); /// Decode a machine instruction. @@ -78,17 +73,12 @@ class Decoder : public InstDecoder void reset() override; inline bool compressed(ExtMachInst inst) { return inst.quadRant < 0x3; } - inline bool vconf(ExtMachInst inst) { - return inst.opcode == 0b1010111u && inst.funct3 == 0b111u; - } //Use this to give data to the decoder. This should be used //when there is control flow. void moreBytes(const PCStateBase &pc, Addr fetchPC) override; StaticInstPtr decode(PCStateBase &nextPC) override; - - void setVlAndVtype(uint32_t vl, VTYPE vtype); }; } // namespace RiscvISA From def89745bc054622dd17ae9d34d1fae06fbd1cfd Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 14 Aug 2023 15:06:11 +0800 Subject: [PATCH 295/693] arch-riscv: Allow Minor and O3 CPU execute RVV Change-Id: I4780b42c25d349806254b5053fb0da3b6993ca2f --- src/arch/riscv/RiscvCPU.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/arch/riscv/RiscvCPU.py b/src/arch/riscv/RiscvCPU.py index 449bf5e7af..1c77045c67 100644 --- a/src/arch/riscv/RiscvCPU.py +++ b/src/arch/riscv/RiscvCPU.py @@ -41,17 +41,6 @@ class RiscvCPU: ArchISA = RiscvISA -class RiscvISANoRVV(RiscvISA): - enable_rvv = False - - -class RiscvCPUNoRVV: - ArchDecoder = RiscvDecoder - ArchMMU = RiscvMMU - ArchInterrupts = RiscvInterrupts - ArchISA = RiscvISANoRVV - - class RiscvAtomicSimpleCPU(BaseAtomicSimpleCPU, RiscvCPU): mmu = RiscvMMU() @@ -64,9 +53,9 @@ class RiscvTimingSimpleCPU(BaseTimingSimpleCPU, RiscvCPU): mmu = RiscvMMU() -class RiscvO3CPU(BaseO3CPU, RiscvCPUNoRVV): +class RiscvO3CPU(BaseO3CPU, RiscvCPU): mmu = RiscvMMU() -class RiscvMinorCPU(BaseMinorCPU, RiscvCPUNoRVV): +class RiscvMinorCPU(BaseMinorCPU, RiscvCPU): mmu = RiscvMMU() From e41184fafc693c5e8405c347c451b5bd98b96666 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 6 Sep 2023 10:09:19 +0800 Subject: [PATCH 296/693] util: Update the RISC-V PCState checkpoint Change-Id: I64b6a3e1706173a001f5f8fb06756bd50d65f5bd --- util/cpt_upgraders/riscv-pcstate.py | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 util/cpt_upgraders/riscv-pcstate.py diff --git a/util/cpt_upgraders/riscv-pcstate.py b/util/cpt_upgraders/riscv-pcstate.py new file mode 100644 index 0000000000..b8c6baf729 --- /dev/null +++ b/util/cpt_upgraders/riscv-pcstate.py @@ -0,0 +1,51 @@ +# Copyright (c) 2023 Google LLC +# 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. + + +def upgrader(cpt): + + # Update the RISC-V pcstate to match the new version of + # PCState + + for sec in cpt.sections(): + import re + + if re.search(".*processor.*\.core.*\.xc.*", sec): + + if cpt.get(sec, "_rvType", fallback="") == "": + cpt.set(sec, "_rvType", "1") + + if cpt.get(sec, "_vlenb", fallback="") == "": + cpt.set(sec, "_vlenb", "32") + + if cpt.get(sec, "_vtype", fallback="") == "": + cpt.set(sec, "_vtype", str(1 << 63)) + + if cpt.get(sec, "_vl", fallback="") == "": + cpt.set(sec, "_vl", "0") + + if cpt.get(sec, "_compressed", fallback="") == "": + cpt.set(sec, "_compressed", "false") From 9a5d900770b8af540a9edac6694030d28a36f671 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 12 Sep 2023 08:10:34 +0100 Subject: [PATCH 297/693] cpu: Stop treating TraceCPU as a BaseCPU This is fixing a recently reported issue [1] where it is not possible to use the TraceCPU to replay elastic traces It requires some architectural data structures (like ArchMMU, ArchDecoder...) which are no longer defined in the BaseCPU class at compilation time. Which Arch version should be used for a class (TraceCPU) that is supposed to be ISA agnostic ? Does it really make sense to define them for the TraceCPU? Those classes are not used anyway during trace replay and their sole purpose would just be to comply to the BaseCPU interface. As there is no elegant way to make things work, this patch stops treating the TraceCPU as a BaseCPU. While it philosophically makes sense to treat the TraceCPU as a common CPU (it sort of replays pre-executed instructions), a case can be made for considering it more like a traffic generator. [1]: https://github.com/gem5/gem5/issues/301 Change-Id: I7438169e8cc7fb6272731efb336ed2cf271c0844 Signed-off-by: Giacomo Travaglini --- src/cpu/trace/TraceCPU.py | 14 ++++++++------ src/cpu/trace/trace_cpu.cc | 27 ++++++++++++++++++++------ src/cpu/trace/trace_cpu.hh | 39 ++++++++++++++++++++++---------------- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/cpu/trace/TraceCPU.py b/src/cpu/trace/TraceCPU.py index 1be16518d7..586e77caed 100644 --- a/src/cpu/trace/TraceCPU.py +++ b/src/cpu/trace/TraceCPU.py @@ -1,4 +1,4 @@ -# Copyright (c) 2013 - 2016 ARM Limited +# Copyright (c) 2013 - 2016, 2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -34,10 +34,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.params import * -from m5.objects.BaseCPU import BaseCPU +from m5.proxy import * +from m5.objects.ClockedObject import ClockedObject -class TraceCPU(BaseCPU): +class TraceCPU(ClockedObject): """Trace CPU model which replays traces generated in a prior simulation using DerivO3CPU or its derived classes. It interfaces with L1 caches. """ @@ -54,13 +55,14 @@ class TraceCPU(BaseCPU): def require_caches(cls): return True - def addPMU(self, pmu=None): - pass - @classmethod def support_take_over(cls): return True + system = Param.System(Parent.any, "system object") + + icache_port = RequestPort("Instruction Port") + dcache_port = RequestPort("Data Port") instTraceFile = Param.String("", "Instruction trace file") dataTraceFile = Param.String("", "Data dependency trace file") sizeStoreBuffer = Param.Unsigned( diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc index 7399cf6199..ab14c8784a 100644 --- a/src/cpu/trace/trace_cpu.cc +++ b/src/cpu/trace/trace_cpu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 - 2016 ARM Limited + * Copyright (c) 2013 - 2016, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -47,7 +47,8 @@ namespace gem5 int TraceCPU::numTraceCPUs = 0; TraceCPU::TraceCPU(const TraceCPUParams ¶ms) - : BaseCPU(params), + : ClockedObject(params), + cacheLineSize(params.system->cacheLineSize()), icachePort(this), dcachePort(this), instRequestorID(params.system->getRequestorId(this, "inst")), @@ -109,7 +110,7 @@ TraceCPU::init() DPRINTF(TraceCPUData, "Data memory request trace file is \"%s\".\n", dataTraceFile); - BaseCPU::init(); + ClockedObject::init(); // Get the send tick of the first instruction read request Tick first_icache_tick = icacheGen.init(); @@ -176,7 +177,7 @@ TraceCPU::schedDcacheNext() DPRINTF(TraceCPUData, "DcacheGen event.\n"); // Update stat for numCycles - baseStats.numCycles = clockEdge() / clockPeriod(); + traceStats.numCycles = clockEdge() / clockPeriod(); dcacheGen.execute(); if (dcacheGen.isExecComplete()) { @@ -216,7 +217,7 @@ TraceCPU::checkAndSchedExitEvent() ADD_STAT(cpi, statistics::units::Rate< statistics::units::Cycle, statistics::units::Count>::get(), "Cycles per micro-op used as a proxy for CPI", - trace->baseStats.numCycles / numOps) + trace->traceStats.numCycles / numOps) { cpi.precision(6); } @@ -591,7 +592,7 @@ TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr) // stat counting this is useful to keep a check on how frequently this // happens. If required the code could be revised to mimick splitting such // a request into two. - unsigned blk_size = owner.cacheLineSize(); + unsigned blk_size = owner.cacheLineSize; Addr blk_offset = (node_ptr->physAddr & (Addr)(blk_size - 1)); if (!(blk_offset + node_ptr->size <= blk_size)) { node_ptr->size = blk_size - blk_offset; @@ -1152,6 +1153,20 @@ TraceCPU::schedDcacheNextEvent(Tick when) } +Port & +TraceCPU::getPort(const std::string &if_name, PortID idx) +{ + // Get the right port based on name. This applies to all the + // subclasses of the base CPU and relies on their implementation + // of getDataPort and getInstPort. + if (if_name == "dcache_port") + return getDataPort(); + else if (if_name == "icache_port") + return getInstPort(); + else + return ClockedObject::getPort(if_name, idx); +} + bool TraceCPU::IcachePort::recvTimingResp(PacketPtr pkt) { diff --git a/src/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh index 87f820fe6d..f3f5c38786 100644 --- a/src/cpu/trace/trace_cpu.hh +++ b/src/cpu/trace/trace_cpu.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 - 2016 ARM Limited + * Copyright (c) 2013 - 2016, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -48,10 +48,13 @@ #include "cpu/base.hh" #include "debug/TraceCPUData.hh" #include "debug/TraceCPUInst.hh" +#include "mem/packet.hh" +#include "mem/request.hh" #include "params/TraceCPU.hh" #include "proto/inst_dep_record.pb.h" #include "proto/packet.pb.h" #include "proto/protoio.hh" +#include "sim/clocked_object.hh" #include "sim/sim_events.hh" namespace gem5 @@ -66,8 +69,7 @@ namespace gem5 * simulation compared to the detailed cpu model and good correlation when the * same trace is used for playback on different memory sub-systems. * - * The TraceCPU inherits from BaseCPU so some virtual methods need to be - * defined. It has two port subclasses inherited from RequestPort for + * The TraceCPU has two port subclasses inherited from RequestPort for * instruction and data ports. It issues the memory requests deducing the * timing from the trace and without performing real execution of micro-ops. As * soon as the last dependency for an instruction is complete, its @@ -139,7 +141,7 @@ namespace gem5 * exit. */ -class TraceCPU : public BaseCPU +class TraceCPU : public ClockedObject { public: @@ -147,15 +149,6 @@ class TraceCPU : public BaseCPU void init(); - /** - * This is a pure virtual function in BaseCPU. As we don't know how many - * insts are in the trace but only know how how many micro-ops are we - * cannot count this stat. - * - * @return 0 - */ - Counter totalInsts() const { return 0; } - /** * Return totalOps as the number of committed micro-ops plus the * speculatively issued loads that are modelled in the TraceCPU replay. @@ -170,9 +163,6 @@ class TraceCPU : public BaseCPU */ void updateNumOps(uint64_t rob_num); - /* Pure virtual function in BaseCPU. Do nothing. */ - void wakeup(ThreadID tid=0) { return; } - /* * When resuming from checkpoint in FS mode, the TraceCPU takes over from * the old cpu. This function overrides the takeOverFrom() function in the @@ -303,6 +293,9 @@ class TraceCPU : public BaseCPU TraceCPU* owner; }; + /** Cache the cache line size that we get from the system */ + const unsigned int cacheLineSize; + /** Port to connect to L1 instruction cache. */ IcachePort icachePort; @@ -1112,6 +1105,8 @@ class TraceCPU : public BaseCPU /** Stat for number of simulated micro-ops. */ statistics::Scalar numOps; + /** Number of CPU cycles simulated */ + statistics::Scalar numCycles; /** Stat for the CPI. This is really cycles per * micro-op and not inst. */ statistics::Formula cpi; @@ -1125,6 +1120,18 @@ class TraceCPU : public BaseCPU /** Used to get a reference to the dcache port. */ Port &getDataPort() { return dcachePort; } + /** + * Get a port on this CPU. All CPUs have a data and + * instruction port, and this method uses getDataPort and + * getInstPort of the subclasses to resolve the two ports. + * + * @param if_name the port name + * @param idx ignored index + * + * @return a reference to the port with the given name + */ + Port &getPort(const std::string &if_name, + PortID idx=InvalidPortID) override; }; } // namespace gem5 From 785eba6ce120cbeee371ab39ce5e4079cb4bf91d Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 12 Sep 2023 10:32:31 +0100 Subject: [PATCH 298/693] configs: Reflect TraceCPU changes in the etrace_replay script As we no longer inherit from the BaseCPU, we can't really use CPU generation methods (like Simulation.setCPUClass) and cache generation ones (like CacheConfig.config_cache). This is good news as it allows us to simplify the etrace script and to remove a dependency with the deprecated-to-be common library. Change-Id: Ic89ce2b9d713ee6f6e11bf20c5065426298b3da2 Signed-off-by: Giacomo Travaglini --- configs/example/etrace_replay.py | 67 ++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/configs/example/etrace_replay.py b/configs/example/etrace_replay.py index ddbf01acf5..184934fab9 100644 --- a/configs/example/etrace_replay.py +++ b/configs/example/etrace_replay.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015 ARM Limited +# Copyright (c) 2015, 2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -43,10 +43,42 @@ addToPath("../") from common import Options from common import Simulation -from common import CacheConfig from common import MemConfig from common.Caches import * + +def config_cache(args, system): + """ + Configure the cache hierarchy. Only two configurations are natively + supported as an example: L1(I/D) only or L1 + L2. + """ + from common.CacheConfig import _get_cache_opts + + system.l1i = L1_ICache(**_get_cache_opts("l1i", args)) + system.l1d = L1_DCache(**_get_cache_opts("l1d", args)) + + system.cpu.dcache_port = system.l1d.cpu_side + system.cpu.icache_port = system.l1i.cpu_side + + if args.l2cache: + # Provide a clock for the L2 and the L1-to-L2 bus here as they + # are not connected using addTwoLevelCacheHierarchy. Use the + # same clock as the CPUs. + system.l2 = L2Cache( + clk_domain=system.cpu_clk_domain, **_get_cache_opts("l2", args) + ) + + system.tol2bus = L2XBar(clk_domain=system.cpu_clk_domain) + system.l2.cpu_side = system.tol2bus.mem_side_ports + system.l2.mem_side = system.membus.cpu_side_ports + + system.l1i.mem_side = system.tol2bus.cpu_side_ports + system.l1d.mem_side = system.tol2bus.cpu_side_ports + else: + system.l1i.mem_side = system.membus.cpu_side_ports + system.l1d.mem_side = system.membus.cpu_side_ports + + parser = argparse.ArgumentParser() Options.addCommonOptions(parser) @@ -59,29 +91,18 @@ if "--ruby" in sys.argv: args = parser.parse_args() -numThreads = 1 - -if args.cpu_type != "TraceCPU": - fatal( - "This is a script for elastic trace replay simulation, use " - "--cpu-type=TraceCPU\n" - ) - if args.num_cpus > 1: fatal("This script does not support multi-processor trace replay.\n") -# In this case FutureClass will be None as there is not fast forwarding or -# switching -(CPUClass, test_mem_mode, FutureClass) = Simulation.setCPUClass(args) -CPUClass.numThreads = numThreads - system = System( - cpu=CPUClass(cpu_id=0), - mem_mode=test_mem_mode, + mem_mode=TraceCPU.memory_mode(), mem_ranges=[AddrRange(args.mem_size)], cache_line_size=args.cacheline_size, ) +# Generate the TraceCPU +system.cpu = TraceCPU() + # Create a top-level voltage domain system.voltage_domain = VoltageDomain(voltage=args.sys_voltage) @@ -105,11 +126,6 @@ system.cpu_clk_domain = SrcClockDomain( for cpu in system.cpu: cpu.clk_domain = system.cpu_clk_domain -# BaseCPU no longer has default values for the BaseCPU.isa -# createThreads() is needed to fill in the cpu.isa -for cpu in system.cpu: - cpu.createThreads() - # Assign input trace files to the Trace CPU system.cpu.instTraceFile = args.inst_trace_file system.cpu.dataTraceFile = args.data_trace_file @@ -118,8 +134,11 @@ system.cpu.dataTraceFile = args.data_trace_file MemClass = Simulation.setMemClass(args) system.membus = SystemXBar() system.system_port = system.membus.cpu_side_ports -CacheConfig.config_cache(args, system) + +# Configure the classic cache hierarchy +config_cache(args, system) + MemConfig.config_mem(args, system) root = Root(full_system=False, system=system) -Simulation.run(args, root, system, FutureClass) +Simulation.run(args, root, system, None) From a0a799f4743a007706406bd5114e897343b9b020 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 12 Sep 2023 13:39:22 +0100 Subject: [PATCH 299/693] cpu: Disable CPU switching functionality with TraceCPU Now that the TraceCPU is no longer a BaseCPU we disable CPU switching functionality. AFAICS from the code, it seems like using m5.switchCpus was never really working. The takeOverFrom was described as being used when checkpointing (which is not really the case). Moreover the icache/dcache event loops were not checking if the CPU was switched out so the trace was always been consumed regardless of the BaseCPU state. Note: IMHO the only case where you might want to switch between an execution-driven CPU to the TraceCPU is when you want to warm your caches before the ROI. All other cases don't really make sense as with the TraceCPU there is no architectural state being maintained/updated. Change-Id: I0611359d2b833e1bc0762be72642df24a7c92b1e Signed-off-by: Giacomo Travaglini --- src/cpu/trace/TraceCPU.py | 4 ---- src/cpu/trace/trace_cpu.cc | 9 +-------- src/cpu/trace/trace_cpu.hh | 10 +--------- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/cpu/trace/TraceCPU.py b/src/cpu/trace/TraceCPU.py index 586e77caed..5e82fd9f9f 100644 --- a/src/cpu/trace/TraceCPU.py +++ b/src/cpu/trace/TraceCPU.py @@ -55,10 +55,6 @@ class TraceCPU(ClockedObject): def require_caches(cls): return True - @classmethod - def support_take_over(cls): - return True - system = Param.System(Parent.any, "system object") icache_port = RequestPort("Instruction Port") diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc index ab14c8784a..d5c6b4fb3c 100644 --- a/src/cpu/trace/trace_cpu.cc +++ b/src/cpu/trace/trace_cpu.cc @@ -39,6 +39,7 @@ #include "base/compiler.hh" #include "sim/sim_exit.hh" +#include "sim/system.hh" namespace gem5 { @@ -94,14 +95,6 @@ TraceCPU::updateNumOps(uint64_t rob_num) } } -void -TraceCPU::takeOverFrom(BaseCPU *oldCPU) -{ - // Unbind the ports of the old CPU and bind the ports of the TraceCPU. - getInstPort().takeOverFrom(&oldCPU->getInstPort()); - getDataPort().takeOverFrom(&oldCPU->getDataPort()); -} - void TraceCPU::init() { diff --git a/src/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh index f3f5c38786..d54b3c4227 100644 --- a/src/cpu/trace/trace_cpu.hh +++ b/src/cpu/trace/trace_cpu.hh @@ -45,10 +45,10 @@ #include #include "base/statistics.hh" -#include "cpu/base.hh" #include "debug/TraceCPUData.hh" #include "debug/TraceCPUInst.hh" #include "mem/packet.hh" +#include "mem/port.hh" #include "mem/request.hh" #include "params/TraceCPU.hh" #include "proto/inst_dep_record.pb.h" @@ -163,14 +163,6 @@ class TraceCPU : public ClockedObject */ void updateNumOps(uint64_t rob_num); - /* - * When resuming from checkpoint in FS mode, the TraceCPU takes over from - * the old cpu. This function overrides the takeOverFrom() function in the - * BaseCPU. It unbinds the ports of the old CPU and binds the ports of the - * TraceCPU. - */ - void takeOverFrom(BaseCPU *oldCPU); - /** * When instruction cache port receives a retry, schedule event * icacheNextEvent. From 2178e26bf2c926d4202cf851dc057f2d1ff20f4a Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Tue, 12 Sep 2023 15:24:45 +0000 Subject: [PATCH 300/693] arch-x86: initialize and correct bitwidth for FPU tag word The x87 FPU tag word (FTW) was not explicitly initialized in {X86_64,i386}Process::initState(), resulting in holding an initial value of zero, resulting in an invalid x87 FPU state. This commit initializes FTW to 0xFFFF, indicating the FPU is empty at program start during syscall emulation. The 16-bit FTW register was also incorrectly masked down to 8-bits in X86ISA::ISA::setMiscRegNoEffect(), leading to an invalid X87 FPU state that later caused crashes in the X86KvmCPU. This commit corrects the bitwidth of the mask to 16. GitHub issue: https://github.com/gem5/gem5/issues/303 Change-Id: I97892d707998a87c1ff8546e08c15fede7eed66f --- src/arch/x86/isa.cc | 2 +- src/arch/x86/process.cc | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/isa.cc b/src/arch/x86/isa.cc index 9e6082a268..7d401a6c59 100644 --- a/src/arch/x86/isa.cc +++ b/src/arch/x86/isa.cc @@ -262,7 +262,7 @@ ISA::setMiscRegNoEffect(RegIndex idx, RegVal val) reg_width = 3; break; case misc_reg::Ftw: - reg_width = 8; + reg_width = 16; break; case misc_reg::Fsw: case misc_reg::Fcw: diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index a195fdf888..6589ee821d 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -397,6 +397,7 @@ X86_64Process::initState() tc->setMiscReg(misc_reg::Cr8, cr8); tc->setMiscReg(misc_reg::Mxcsr, 0x1f80); + tc->setMiscReg(misc_reg::Ftw, 0xffff); tc->setMiscReg(misc_reg::ApicBase, 0xfee00900); @@ -593,6 +594,7 @@ X86_64Process::initState() tc->setMiscReg(misc_reg::Cr0, cr0); tc->setMiscReg(misc_reg::Mxcsr, 0x1f80); + tc->setMiscReg(misc_reg::Ftw, 0xffff); // Setting CR3 to the process pid so that concatinated // page addr with lower 12 bits of CR3 can be used in SE @@ -727,6 +729,7 @@ I386Process::initState() tc->setMiscReg(misc_reg::Cr0, cr0); tc->setMiscReg(misc_reg::Mxcsr, 0x1f80); + tc->setMiscReg(misc_reg::Ftw, 0xffff); } } From 39f0bcd9aff4851f91d851bd07f2078dc1891857 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 12 Sep 2023 14:51:59 -0700 Subject: [PATCH 301/693] python: Mimic Python 3's `-P` flag in gem5 Python 3's `-P` flag, when set, means `sys.path` is not prepended with potentially unsafe paths: https://docs.python.org/3/using/cmdline.html#cmdoption-P This patch allows gem5 to mimic this. This is necesssary when using `mypy.stubgen` as it expects the Python Interpreter to have the `-P` flag. Change-Id: I456c8001d3ee1e806190dc37142566d50d54cc90 --- src/python/m5/main.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/python/m5/main.py b/src/python/m5/main.py index e07e9562ab..3c418ba29b 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -193,6 +193,14 @@ def parse_options(): callback=collect_args, ) + option( + "-P", + action="store_true", + default=False, + help="Don't prepend the script directory to the system path. " + "Mimics Python 3's `-P` option.", + ) + option( "-s", action="store_true", @@ -601,7 +609,11 @@ def main(): sys.argv = ["-c"] + options.c[1] scope = {"__name__": "__m5_main__"} else: - sys.path = [os.path.dirname(sys.argv[0])] + sys.path + # If `-P` was used (`options.P == true`), don't prepend the script + # directory to the `sys.path`. This mimics Python 3's `-P` option + # (https://docs.python.org/3/using/cmdline.html#cmdoption-P). + if not options.P: + sys.path = [os.path.dirname(sys.argv[0])] + sys.path filename = sys.argv[0] filedata = open(filename, "r").read() filecode = compile(filedata, filename, "exec") From bceac5d951438a43e097be5ea26ab416130e8161 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 12 Sep 2023 15:17:50 -0700 Subject: [PATCH 302/693] util: Allow MyPy stubgen to aid Pylance IntelliSense Change-Id: I42fe177e5ae428afd0f23ea482b6af5b7d3ecaf9 --- requirements.txt | 1 + util/gem5-stubgen.py | 63 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 util/gem5-stubgen.py diff --git a/requirements.txt b/requirements.txt index 561cab79cf..c057a43b97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ pre-commit==2.20.0 +mypy==1.5.1 diff --git a/util/gem5-stubgen.py b/util/gem5-stubgen.py new file mode 100644 index 0000000000..d003e2212e --- /dev/null +++ b/util/gem5-stubgen.py @@ -0,0 +1,63 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from mypy.stubgen import generate_stubs, parse_options + +""" +This allows us to generate stubs for the modules in gem5. The output will be +a "typings" directory which can be used by Pylance (Python IntelliSense) to +infer typings in Visual Studio Code. + +Note: A "typings" directory in the root of the workspace is the default +location for Pylance to look for typings. This can be changed via +`python.analysis.stubPath` in "settings.json". + +Usage +===== + +```sh +pip3 install -r requirements.txt +scons build/ALL/gem5.opt -j$(nproc) +./build/ALL/gem5.opt util/gem5-stubgen.py +``` + +""" + +if __name__ == "__m5_main__": + import m5 + + # get a list of all modules exported by gem5 + modules = m5.__spec__.loader_state + + options = parse_options( + ("--module " + " --module ".join(modules)).split(" ") + + ["--output", "typings"] + ) + generate_stubs(options) + +if __name__ == "__main__": + print("Error: This script is meant to be run with the gem5 binary") + exit(1) From 133e4ed6369dd5f5069238777e82312c6b91ae0c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 12 Sep 2023 15:20:06 -0700 Subject: [PATCH 303/693] misc: Add "typings" directory to .gitignore This is used by Pylance IntelliSense to infer gem5 typing. See "util/gem5-stubgen.py" for generating this directory. Change-Id: Ie39762c718e5392f6194ff7c8238bd0cd677f486 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 229a0d5ae9..8aaf08f076 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ configs/example/memcheck.cfg configs/dram/lowp_sweep.cfg .pyenv .vscode +typings From f95e1505b839a95489bf3cfa6cec9833781bf788 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 13 Sep 2023 13:36:33 +0100 Subject: [PATCH 304/693] util: Fix TLM configs making use of TraceCPU replayer A recent PR [1] moved the TraceCPU away from the BaseCPU hierarchy. While the common etrace_replayer.py has been amended, I missed these hybrid TLM + TraceCPU example scripts. [1]: https://github.com/gem5/gem5/pull/302 Change-Id: I7e9bc9a612d2721d72f5881ddb2fb4d9ee011587 Signed-off-by: Giacomo Travaglini --- util/tlm/conf/tlm_elastic_slave.py | 13 ++++++------- util/tlm/examples/tlm_elastic_slave_with_l2.py | 17 ++++++++--------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/util/tlm/conf/tlm_elastic_slave.py b/util/tlm/conf/tlm_elastic_slave.py index 30a412b2f8..1007c5244b 100644 --- a/util/tlm/conf/tlm_elastic_slave.py +++ b/util/tlm/conf/tlm_elastic_slave.py @@ -65,7 +65,7 @@ from Caches import * # Setup System: system = System( - cpu=TraceCPU(cpu_id=0), + cpu=TraceCPU(), mem_mode="timing", mem_ranges=[AddrRange("512MB")], cache_line_size=64, @@ -89,8 +89,7 @@ system.cpu_clk_domain = SrcClockDomain( clock="1GHz", voltage_domain=system.cpu_voltage_domain ) -# Setup CPU and its L1 caches: -system.cpu.createInterruptController() +# Setup CPU's L1 caches: system.cpu.icache = L1_ICache(size="32kB") system.cpu.dcache = L1_DCache(size="32kB") system.cpu.icache.cpu_side = system.cpu.icache_port @@ -114,10 +113,10 @@ system.tlm.port_data = "transactor" # Connect everything: system.membus = SystemXBar() -system.system_port = system.membus.slave -system.cpu.icache.mem_side = system.membus.slave -system.cpu.dcache.mem_side = system.membus.slave -system.membus.master = system.tlm.port +system.system_port = system.membus.cpu_side_ports +system.cpu.icache.mem_side = system.membus.cpu_side_ports +system.cpu.dcache.mem_side = system.membus.cpu_side_ports +system.membus.mem_side_ports = system.tlm.port # Start the simulation: root = Root(full_system=False, system=system) diff --git a/util/tlm/examples/tlm_elastic_slave_with_l2.py b/util/tlm/examples/tlm_elastic_slave_with_l2.py index c72bc8976c..6b3f7b43fb 100644 --- a/util/tlm/examples/tlm_elastic_slave_with_l2.py +++ b/util/tlm/examples/tlm_elastic_slave_with_l2.py @@ -72,7 +72,7 @@ from Caches import * # Setup System: system = System( - cpu=TraceCPU(cpu_id=0), + cpu=TraceCPU(), mem_mode="timing", mem_ranges=[AddrRange("1024MB")], cache_line_size=64, @@ -96,8 +96,7 @@ system.cpu_clk_domain = SrcClockDomain( clock="1GHz", voltage_domain=system.cpu_voltage_domain ) -# Setup CPU and its L1 caches: -system.cpu.createInterruptController() +# Setup CPU's L1 caches: system.cpu.icache = L1_ICache(size="32kB") system.cpu.dcache = L1_DCache(size="32kB") system.cpu.icache.cpu_side = system.cpu.icache_port @@ -122,12 +121,12 @@ system.tlm.port_data = "transactor1" # Connect everything: system.membus = SystemXBar() -system.system_port = system.membus.slave -system.cpu.icache.mem_side = system.tol2bus.slave -system.cpu.dcache.mem_side = system.tol2bus.slave -system.tol2bus.master = system.l2cache.cpu_side -system.l2cache.mem_side = system.membus.slave -system.membus.master = system.tlm.port +system.system_port = system.membus.cpu_side_ports +system.cpu.icache.mem_side = system.tol2bus.cpu_side_ports +system.cpu.dcache.mem_side = system.tol2bus.cpu_side_ports +system.tol2bus.mem_side_ports = system.l2cache.cpu_side +system.l2cache.mem_side = system.membus.cpu_side_ports +system.membus.mem_side_ports = system.tlm.port # Start the simulation: root = Root(full_system=False, system=system) From 87db6df8f615feb0f7510aba11b86fdc3a02c520 Mon Sep 17 00:00:00 2001 From: Gautham Pathak Date: Fri, 8 Sep 2023 23:28:50 -0400 Subject: [PATCH 305/693] mem-ruby: This commit patches an error in AbstractController.cc After calling m5_dump_reset_stats(0,0) in a test program, some statistics like l1_controllers.L1Dcache.m_demand_hits, l1_controllers.L1Dcache.m_demand_misses, l1_controllers.L1Dcache.m_demand_accesses were not getting reset in the newer stat dumps. This one line patch fixes that. Changes were tested with calling two m5_dump_reset_stats(0,0) in a row for a system with 1 core, tested on both SE and FS. Credits to Gabriel Busnot for finding the fix. Change-Id: I19d75996fa53d31ef20f7b206024fd38dbeac643 --- src/mem/ruby/slicc_interface/AbstractController.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc index f7b01cf939..36092387ac 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.cc +++ b/src/mem/ruby/slicc_interface/AbstractController.cc @@ -125,6 +125,7 @@ AbstractController::resetStats() for (uint32_t i = 0; i < size; i++) { stats.delayVCHistogram[i]->reset(); } + ClockedObject::resetStats(); } void From d463f73a43200f1b8e3d8e0483b5d9586573c59c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 14:14:27 -0700 Subject: [PATCH 306/693] scons: Revert "Add an option specifying the..." Change-Id: I2bd952d3cfd6c3c671b5ab3458e44c53f93bf649 --- SConstruct | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/SConstruct b/SConstruct index ee913bf782..32e0c36e09 100755 --- a/SConstruct +++ b/SConstruct @@ -84,7 +84,6 @@ from os import mkdir, remove, environ from os.path import abspath, dirname, expanduser from os.path import isdir, isfile from os.path import join, split -from pathlib import Path import logging logging.basicConfig() @@ -122,8 +121,6 @@ AddOption('--ignore-style', action='store_true', help='Disable style checking hooks') AddOption('--linker', action='store', default=None, choices=linker_options, help=f'Select which linker to use ({", ".join(linker_options)})') -AddOption('--mold-path', action='store', default='/usr/libexec/mold/', - help='Path to the binary of mold linker.') AddOption('--gold-linker', action='store_const', const='gold', dest='linker', help='Use the gold linker. Deprecated: Use --linker=gold') AddOption('--no-compress-debug', action='store_true', @@ -428,36 +425,19 @@ for variant_path in variant_paths: conf.CheckLinkFlag('-Wl,--as-needed') linker = GetOption('linker') - # check for mold linker when -fuse-ld=mold fails - # this checks whether mold_dir has ld or ld.mold and - # whether -B{mold_dir} works - mold_check = lambda mold_dir: \ - isdir(mold_dir) and \ - (isfile(mold_dir/'ld') or isfile(mold_dir/'ld.mold')) and \ - conf.CheckLinkFlag('-B' + str(mold_dir)) - mold_check_message = \ - "You are seeing this error because -fuse-ld=mold failed.\n" \ - "If you did not add the folder containing mold to $PATH, you " \ - "should do so and recompile gem5.\n" \ - "If that does not work, you can manually specify the path to " \ - "the binary of mold using the --mold-path option. This will " \ - "cause scons to look for ld or ld.mold in the same folder as " \ - "the binary of mold." if linker: with gem5_scons.Configure(env) as conf: if not conf.CheckLinkFlag(f'-fuse-ld={linker}'): - # If -fuse-ld=mold fails, we use "-B$mold_path" instead. - mold_path = Path(GetOption('mold_path')).parent - if linker == 'mold': - if any(map(mold_check, [mold_path, - Path("/usr/libexec/mold"), - Path("/usr/libexec/mold")])): - pass # support mold - else: - error( - f'Linker "{linker}" is not supported. ' - f'{mold_check_message}' - ) + # check mold support for gcc older than 12.1.0 + if linker == 'mold' and \ + (env['GCC'] and \ + compareVersions(env['CXXVERSION'], + "12.1.0") < 0) and \ + ((isdir('/usr/libexec/mold') and \ + conf.CheckLinkFlag('-B/usr/libexec/mold')) or \ + (isdir('/usr/local/libexec/mold') and \ + conf.CheckLinkFlag('-B/usr/local/libexec/mold'))): + pass # support mold else: error(f'Linker "{linker}" is not supported') if linker == 'gold' and not GetOption('with_lto'): From e42d71e802d66090e3b0ef4735e758fa2630e779 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 14:30:22 -0700 Subject: [PATCH 307/693] configs: 'memoy' -> 'memory' spelling mistake fix Fixes https://github.com/gem5/gem5/issues/309 Change-Id: I41ac7c5559d49353d01b3676b5bdf7b91e4efbda --- configs/common/MemConfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/common/MemConfig.py b/configs/common/MemConfig.py index baa0d233af..02af2b8449 100644 --- a/configs/common/MemConfig.py +++ b/configs/common/MemConfig.py @@ -40,7 +40,7 @@ from common import HMC def create_mem_intf(intf, r, i, intlv_bits, intlv_size, xor_low_bit): """ - Helper function for creating a single memoy controller from the given + Helper function for creating a single memory controller from the given options. This function is invoked multiple times in config_mem function to create an array of controllers. """ From 178db9e27039b4229684277e5a6252aad9086439 Mon Sep 17 00:00:00 2001 From: Gautham Pathak Date: Wed, 13 Sep 2023 19:00:15 -0400 Subject: [PATCH 308/693] mem-ruby: patch fixes a protocol error in MOESI_CMP_Directory When there is race between FwdGetX and PUTX on owner. Owner in this case hands off ownership to GetX requestor and PUTX still goes through. But since owner has changed, state should go back to M and PUTX is essentially trashed. An Unblock to the Directory in this case will give an undefined transition. I have added transitions which indicate that when an Unblock is served to the Directory, it means that some kind of ownership transfer has happened while a PUTX/PUTO was in progress. Change-Id: I37439b5a363417096030a0875a51c605bd34c127 --- .../ruby/protocol/MOESI_CMP_directory-dir.sm | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm index f21400c945..4a513d6d3f 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm @@ -1014,6 +1014,31 @@ machine(MachineType:Directory, "Directory protocol") i_popIncomingRequestQueue; } + //this happens when there is race between FwdGetX + //and PUTX on owner. Owner in this case hands off + //ownership to GetX requestor and PUTX still goes + //through. But since owner has changed, state should + //go back to M and PUTX is essentially trashed. + transition(MI, Unblock, M) { + w_deallocateTBE; + j_popIncomingUnblockQueue; + } + + transition(MIS, Unblock, M) { + w_deallocateTBE; + j_popIncomingUnblockQueue; + } + + transition(OS, Unblock, O) { + //In OS state there is no TBE for some reason + // w_deallocateTBE; + j_popIncomingUnblockQueue; + } + + transition(OSS, Unblock, O) { + j_popIncomingUnblockQueue; + } + transition(WBI, Memory_Ack, I) { clearWBAck; w_deallocateTBE; From 5102072950cba0c6b5447ba4aee48b480a1d64fb Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 17:50:56 -0700 Subject: [PATCH 309/693] misc,tests: Rm duplicate running of daily gem5_library_tests The long/daily tests in "tests/gem5/gem5_library_tests" were running in both the "testlib-long-tests" and the "testlib-long-gem5_library_example_tests" job in the Daily tests Workflow. The running in "testlib-long-tests" is removed in this patch. Change-Id: I1c665529e3dcb594ffb7f6e2224077ae366772d6 --- .github/workflows/daily-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index cf57d804bc..06d37c86a8 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -76,7 +76,7 @@ jobs: strategy: fail-fast: false matrix: - test-type: [arm_boot_tests, fs, gem5_library_example_tests, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] + test-type: [arm_boot_tests, fs, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] runs-on: [self-hosted, linux, x64, run] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] From dc02862c56a49177a77cb062d0dcf93806b9d405 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 22:47:08 -0700 Subject: [PATCH 310/693] misc: Fix docker build workflow Change-Id: Ib66cc124a4c3ce1354faee092f14543e699dca40 --- .github/workflows/docker-build.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 73ea3c93c6..d8b98dc714 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -30,7 +30,6 @@ jobs: - uses: actions/download-artifact@v2 with: name: dockerfiles - path: dockerfiles - uses: docker/setup-qemu-action@v2 name: Setup QEMU @@ -48,5 +47,5 @@ jobs: - name: Build and push with bake uses: docker/bake-action@v3 with: - files: dockerfiles/docker-bake.hcl + files: docker-bake.hcl push: true From 772a316dab76ed6b551bbd809b0c02bfdfd17ede Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 22:52:26 -0700 Subject: [PATCH 311/693] misc: Use 'workdir' for docker-build.yaml Change-Id: If8b30a31e1a8c3fdba84d69da4bb28e09179cb96 --- .github/workflows/docker-build.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index d8b98dc714..4797e073e9 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -30,6 +30,7 @@ jobs: - uses: actions/download-artifact@v2 with: name: dockerfiles + path: dockerfiles-docker-build - uses: docker/setup-qemu-action@v2 name: Setup QEMU @@ -45,7 +46,8 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push with bake - uses: docker/bake-action@v3 + uses: docker/bake-action@v4 with: + workdir: ./dockerfiles-docker-build files: docker-bake.hcl push: true From 040f4d5ae06e70d20efb4215967881b00fcbded7 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 14 Sep 2023 01:04:05 -0700 Subject: [PATCH 312/693] misc,tests: Use GitHub Docker registry for 22.04 all-deps Via this workflow we now can build and push our docker images to the GitHub Docker container registry: https://github.com/gem5/gem5/blob/26a1ee4e61de85189b261fca1d595315a3f33721/.github/workflows/docker-build.yaml GitHub does not charge for downloads to runners (hosted or self-hosted). This can therefore save the project money if we download from GitHub's Docker reigstry over Google Cloud's. This is a test to ensure this works as intended. Change-Id: Iccdb1b7a912f1e0a0d82b7f888694958099315b3 --- .github/workflows/ci-tests.yaml | 6 +++--- .github/workflows/docker-build.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 9987083731..656f41f4bc 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -49,7 +49,7 @@ jobs: build-gem5: runs-on: [self-hosted, linux, x64, build] if: github.event.pull_request.draft == false - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes outputs: artifactname: ${{ steps.name.outputs.test }} @@ -70,7 +70,7 @@ jobs: unittests-all-opt: runs-on: [self-hosted, linux, x64, run] if: github.event.pull_request.draft == false - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes timeout-minutes: 60 steps: @@ -83,7 +83,7 @@ jobs: testlib-quick: runs-on: [self-hosted, linux, x64, run] if: github.event.pull_request.draft == false - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, build-gem5, check-for-change-id] timeout-minutes: 360 # 6 hours steps: diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 4797e073e9..5fc48f0f59 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -5,7 +5,7 @@ on: jobs: obtain-dockerfiles: runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest steps: - uses: actions/checkout@v3 From 210ab04bcad81ca268547be2500a51a33a482d23 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 14 Sep 2023 01:28:10 -0700 Subject: [PATCH 313/693] misc: Update docker-build.yaml artifact actions to v3 Change-Id: I4dea25fcfb786758942e6245133d32949b921774 --- .github/workflows/docker-build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 4797e073e9..7afb1393cd 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -13,7 +13,7 @@ jobs: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. ref: develop - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: dockerfiles path: util/dockerfiles @@ -27,7 +27,7 @@ jobs: contents: read steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: dockerfiles path: dockerfiles-docker-build From 29fa894e19b3a00b980ea70b379be5763620a1fc Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Fri, 1 Sep 2023 10:35:06 -0700 Subject: [PATCH 314/693] misc: Add HACC GPU tests This adds the HACC GPU tests to be run weekly Change-Id: I77d58ee9a3d067a749bae83826266bf89bb5020f --- .github/workflows/gpu-tests.yaml | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/gpu-tests.yaml diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml new file mode 100644 index 0000000000..c6e0155ecf --- /dev/null +++ b/.github/workflows/gpu-tests.yaml @@ -0,0 +1,60 @@ +# This workflow runs all of the very-long tests within main.py + +name: Weekly Tests + +on: + # Runs every Sunday from 7AM UTC + schedule: + - cron: '00 7 * * 6' + # Allows us to manually start workflow for testing + workflow_dispatch: + +jobs: + build-gem5: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/gcn-gpu:latest + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Build gem5 + run: scons build/GCN3_X86/gem5.opt -j $(nproc) --ignore-style + - uses: actions/upload-artifact@v3 + with: + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 + path: build/GCN3_X86/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + + HACC-tests: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/gcn-gpu:latest + needs: build-gem5 + timeout-minutes: 120 # 2 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - uses: actions/download-artifact@v3 + with: + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 + path: build/GCN3_X86 + - run: chmod u+x build/GCN3_X86/gem5.opt + - name: make hip directory + run: mkdir hip + - name: Compile m5ops and x86 + working-directory: ${{ github.workspace }}/util/m5 + run: | + export TERM=xterm-256color + scons build/x86/out/m5 + - name: Download tests + working-directory: ${{ github.workspace }}/hip + run: wget http://dist.gem5.org/dist/v22-1/test-progs/halo-finder/ForceTreeTest + - name: Run HACC tests + working-directory: ${{ github.workspace }} + run: | + build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --reg-alloc-policy=dynamic --benchmark-root=hip -c ForceTreeTest --options="0.5 0.1 64 0.1 1 N 12 rcb" From 020bc05928bc6abc8ec3325c2039544badad9674 Mon Sep 17 00:00:00 2001 From: Leo Redivo Date: Thu, 14 Sep 2023 11:47:19 -0700 Subject: [PATCH 315/693] misc: moved logic of get_disk_device to workload.command_line Change-Id: I5313bb381d5d8983b050047849fae61ea7dfc63b --- .../components/boards/kernel_disk_workload.py | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index ed12d33ac1..1ca70f8f3f 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -39,7 +39,6 @@ import os from pathlib import Path import m5 -from m5.util import inform class KernelDiskWorkload: @@ -85,20 +84,6 @@ class KernelDiskWorkload: """ raise NotImplementedError - def get_disk_device(self) -> str: - """ - Get the disk device, e.g., "/dev/sda", where the disk image is placed. - - :returns: The disk device. - """ - to_return = ( - self._disk_device - if self._disk_device - else self.get_default_disk_device() - ) - assert to_return is not None - return to_return - @abstractmethod def get_default_disk_device(self) -> str: """ @@ -202,7 +187,11 @@ class KernelDiskWorkload: " ".join(kernel_args or self.get_default_kernel_args()) ).format( root_value=self.get_default_kernel_root_val(disk_image=disk_image), - disk_device=self.get_disk_device(), + disk_device=( + self._disk_device + if self._disk_device + else self.get_default_disk_device() + ), ) # Setting the bootloader information for ARM board. The current From b12f28af969ea83ae78e22ce8592ebb9627af992 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 16:36:01 -0700 Subject: [PATCH 316/693] stdlib: Add 'quiet' option to obtain_resource func Change-Id: I15d3be959ba7ab8af328fc6ec2912a8151941a1e --- src/python/gem5/resources/downloader.py | 38 +++++++++++++++---------- src/python/gem5/resources/resource.py | 3 ++ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index 5bca67f677..3260c97a4b 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -204,6 +204,7 @@ def get_resource( resource_version: Optional[str] = None, clients: Optional[List] = None, gem5_version: Optional[str] = core.gem5Version, + quiet: bool = False, ) -> None: """ Obtains a gem5 resource and stored it to a specified location. If the @@ -236,6 +237,9 @@ def get_resource( By default, the version of gem5 being used is used. This is used primarily for testing purposes. + :param quiet: If true, no output will be printed to the console (baring + exceptions). False by default. + :raises Exception: An exception is thrown if a file is already present at `to_path` but it does not have the correct md5 sum. An exception will also be thrown is a directory is present at `to_path` @@ -326,37 +330,41 @@ def get_resource( ) shutil.copy(file_uri_path, download_dest) else: - # TODO: Might be nice to have some kind of download status bar here. - # TODO: There might be a case where this should be silenced. - print( - "Resource '{}' was not found locally. Downloading to '{}'...".format( - resource_name, download_dest + # TODO: Might be nice to have some kind of download status bar here.. + if not quiet: + print( + f"Resource '{resource_name}' was not found locally. " + f"Downloading to '{download_dest}'..." ) - ) # Get the URL. url = resource_json["url"] _download(url=url, download_to=download_dest) - print(f"Finished downloading resource '{resource_name}'.") + if not quiet: + print(f"Finished downloading resource '{resource_name}'.") if run_unzip: - print( - f"Decompressing resource '{resource_name}' ('{download_dest}')..." - ) + if not quiet: + print( + f"Decompressing resource '{resource_name}' " + f"('{download_dest}')..." + ) unzip_to = download_dest[: -len(zip_extension)] with gzip.open(download_dest, "rb") as f: with open(unzip_to, "wb") as o: shutil.copyfileobj(f, o) os.remove(download_dest) download_dest = unzip_to - print(f"Finished decompressing resource '{resource_name}'.") + if not quiet: + print(f"Finished decompressing resource '{resource_name}'.") if run_tar_extract: - print( - f"Unpacking the the resource '{resource_name}' " - f"('{download_dest}')" - ) + if not quiet: + print( + f"Unpacking the the resource '{resource_name}' " + f"('{download_dest}')" + ) unpack_to = download_dest[: -len(tar_extension)] with tarfile.open(download_dest) as f: diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 9e6c79ab01..b640e12920 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -621,6 +621,7 @@ def obtain_resource( resource_version: Optional[str] = None, clients: Optional[List] = None, gem5_version=core.gem5Version, + quiet: bool = False, ) -> AbstractResource: """ This function primarily serves as a factory for resources. It will return @@ -644,6 +645,7 @@ def obtain_resource( :param gem5_version: The gem5 version to use to filter incompatible resource versions. By default set to the current gem5 version. If None, this filtering is not performed. + :param quiet: If True, suppress output. False by default. """ # Obtain the resource object entry for this resource @@ -695,6 +697,7 @@ def obtain_resource( resource_version=resource_version, clients=clients, gem5_version=gem5_version, + quiet=quiet, ) # Obtain the type from the JSON. From this we will determine what subclass From a101b1aba3d502c019cf061de066bc0d96fa53dd Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 16:37:26 -0700 Subject: [PATCH 317/693] stdlib: Add 'to_path' arg to obtain_resource This allows for a user to specify the exact path they want a resource to be downloaded to. This differs from 'resource_direcctory' in that a user may specify the file/directory name of the resource (using just the 'resource_directory' will have the resource as its ID in that directory. Change-Id: I887be6216c7607c22e49cf38226a5e4600f39057 --- src/python/gem5/resources/resource.py | 78 +++++++++++++++++---------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index b640e12920..aafb3b70b0 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -621,6 +621,7 @@ def obtain_resource( resource_version: Optional[str] = None, clients: Optional[List] = None, gem5_version=core.gem5Version, + to_path: Optional[str] = None, quiet: bool = False, ) -> AbstractResource: """ @@ -634,6 +635,7 @@ def obtain_resource( resource is to be stored. If this parameter is not set, it will set to the environment variable `GEM5_RESOURCE_DIR`. If the environment is not set it will default to `~/.cache/gem5` if available, otherwise the CWD. + **Note**: This argument is ignored if the `to_path` parameter is specified. :param download_md5_mismatch: If the resource is present, but does not have the correct md5 value, the resoruce will be deleted and re-downloaded if this value is True. Otherwise an exception will be @@ -645,6 +647,10 @@ def obtain_resource( :param gem5_version: The gem5 version to use to filter incompatible resource versions. By default set to the current gem5 version. If None, this filtering is not performed. + :param to_path: The path to which the resource is to be downloaded. If + None, the resource will be downloaded to the resource directory with + the file/directory name equal to the ID of the resource. **Note**: Usage + of this parameter will override the `resource_directory` parameter. :param quiet: If True, suppress output. False by default. """ @@ -656,43 +662,59 @@ def obtain_resource( gem5_version=gem5_version, ) - to_path = None # If the "url" field is specified, the resoruce must be downloaded. if "url" in resource_json and resource_json["url"]: - # If the `resource_directory` parameter is not set via this function, we - # check the "GEM5_RESOURCE_DIR" environment variable. If this too is not - # set we call `_get_default_resource_dir()` to determine where the - # resource directory is, or should be, located. - if resource_directory == None: - resource_directory = os.getenv( - "GEM5_RESOURCE_DIR", _get_default_resource_dir() - ) - - # Small checks here to ensure the resource directory is valid. - if os.path.exists(resource_directory): - if not os.path.isdir(resource_directory): - raise Exception( - "gem5 resource directory, " - "'{}', exists but is not a directory".format( - resource_directory - ) + # If the `to_path` parameter is set, we use that as the path to which + # the resource is to be downloaded. Otherwise, default to the + # `resource_directory` parameter plus the resource ID. + if not to_path: + # If the `resource_directory` parameter is not set via this + # function, we heck the "GEM5_RESOURCE_DIR" environment variable. + # If this too is not set we call `_get_default_resource_dir()` to + # determine where the resource directory is, or should be, located. + if resource_directory == None: + resource_directory = os.getenv( + "GEM5_RESOURCE_DIR", _get_default_resource_dir() ) - else: - # `exist_ok=True` here as, occasionally, if multiple instance of - # gem5 are started simultaneously, a race condition can exist to - # create the resource directory. Without `exit_ok=True`, threads - # which lose this race will thrown a `FileExistsError` exception. - # `exit_ok=True` ensures no exception is thrown. - os.makedirs(resource_directory, exist_ok=True) - # This is the path to which the resource is to be stored. - to_path = os.path.join(resource_directory, resource_id) + # Small checks here to ensure the resource directory is valid. + if os.path.exists(resource_directory): + if not os.path.isdir(resource_directory): + raise Exception( + "gem5 resource directory, " + "'{}', exists but is not a directory".format( + resource_directory + ) + ) + + # This is the path to which the resource is to be stored. + to_path = os.path.join(resource_directory, resource_id) + + assert to_path + + # Here we ensure the directory in which the resource is to be stored + # is created. + # + # `exist_ok=True` here as, occasionally, if multiple instance of gem5 + # are started simultaneously, a race condition can exist to create the + # resource directory. Without `exit_ok=True`, threads which lose this + # race will thrown a `FileExistsError` exception. `exit_ok=True` + # ensures no exception is thrown. + try: + Path(to_path).parent.mkdir(parents=True, exist_ok=True) + except Exception as e: + fatal( + f"Recursive creation of the directory " + f"'{Path(to_path).parent.absolute}' failed. \n" + f"Perhaps the path specified, '{to_path}', is incorrect?\n" + f"Failed with Exception:\n{e}" + ) # Download the resource if it does not already exist. get_resource( resource_name=resource_id, - to_path=os.path.join(resource_directory, resource_id), + to_path=to_path, download_md5_mismatch=download_md5_mismatch, resource_version=resource_version, clients=clients, From 600ea81031456c916b21aad8211320ced5a5c055 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 13 Sep 2023 17:13:10 -0700 Subject: [PATCH 318/693] util: Add 'obtain-resource.py' utility This can be used to obtain a resource from gem5-resources. Change-Id: I922d78ae0450bf011f18893ffc05cb1ad6c97572 --- util/obtain-resource.py | 87 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 util/obtain-resource.py diff --git a/util/obtain-resource.py b/util/obtain-resource.py new file mode 100644 index 0000000000..de6a7b90e2 --- /dev/null +++ b/util/obtain-resource.py @@ -0,0 +1,87 @@ +# Copyright (c) 2023 The Regents of the University of California +# All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +Obtain a resource from gem5 resource. + +Usage +----- + +```sh +scons build/ALL/gem5.opt -j$(nproc) +build/ALL/gem5.opt util/obtain-resource.py [-p ] [-q] +# Example: +# `build/ALL/gem5.opt util/obtain-resource.py arm-hello64-static -p arm-hello` +# This will download the resource with id `arm-hello64-static` to the +# "arm-hello" in the CWD. +``` +""" + +if __name__ == "__m5_main__": + from gem5.resources.resource import obtain_resource + import argparse + + parser = argparse.ArgumentParser() + + parser.add_argument( + "id", + type=str, + help="The resource id to download.", + ) + + parser.add_argument( + "-p", + "--path", + type=str, + required=False, + help="The path the resource is to be downloaded to. If not specified, " + "the resource will be downloaded to the default location in the " + "gem5 local cache of resources", + ) + + parser.add_argument( + "-q", + "--quiet", + action="store_true", + default=False, + help="Suppress output.", + ) + + args = parser.parse_args() + + resource = obtain_resource( + resource_id=args.id, + quiet=args.quiet, + to_path=args.path, + ) + + if not args.quiet: + print(f"Resource at: '" + str(resource.get_local_path()) + "'") + + exit(0) + +print("Error: This script is meant to be run with the gem5 binary") +exit(1) From 320454b75f5d60a2f4cf33fff211050a92cf5047 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 15 Sep 2023 12:13:00 +0100 Subject: [PATCH 319/693] mem-ruby: Populate missing txnId field to CompI response Change-Id: I02030f61dd4e64a29b16e47d49bcde8c723260b5 Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index ad1935a119..83698bb321 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -2567,6 +2567,8 @@ action(Send_CompI, desc="") { out_msg.type := CHIResponseType:Comp_I; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.Destination.add(tbe.requestor); + out_msg.txnId := tbe.txnId; out_msg.dbid := tbe.txnId; } } From f3ce343a26f8f657d85953960b9fb6099ffca0e1 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 15 Sep 2023 10:21:27 -0700 Subject: [PATCH 320/693] stdlib, resources: Added pretty printing resource - Implemented a __str__ for AbstractResource __str__ prints resource category, id and version. link to resources website is also printed. Change-Id: Iad5825ff7d8d505ceb236e00dc49bb56055fc8f0 --- src/python/gem5/resources/resource.py | 62 ++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 9e6c79ab01..fd55995bbe 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import ABCMeta +import json import os from pathlib import Path from m5.util import warn, fatal @@ -70,6 +71,8 @@ class AbstractResource: def __init__( self, + category: Optional[str] = None, + id: Optional[str] = None, resource_version: Optional[str] = None, local_path: Optional[str] = None, description: Optional[str] = None, @@ -91,12 +94,16 @@ class AbstractResource: f"Local path specified for resource, '{local_path}', does not " "exist." ) - + self._id = id + self._category = category self._local_path = local_path self._description = description self._source = source self._version = resource_version + def __str__(self): + return f"{self._category} resource({self._id}, {self._version})\nFor more information, please visit https://resources.gem5.org/resources/{self._id}?version={self._version}" + def get_resource_version(self) -> str: """Returns the version of the resource.""" return self._version @@ -122,6 +129,8 @@ class FileResource(AbstractResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -134,6 +143,8 @@ class FileResource(AbstractResource): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -146,6 +157,8 @@ class DirectoryResource(AbstractResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -159,6 +172,8 @@ class DirectoryResource(AbstractResource): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -171,6 +186,8 @@ class DiskImageResource(FileResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -179,6 +196,8 @@ class DiskImageResource(FileResource): ): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -196,6 +215,8 @@ class BinaryResource(FileResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -204,6 +225,8 @@ class BinaryResource(FileResource): ): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -227,6 +250,8 @@ class BootloaderResource(BinaryResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -235,6 +260,8 @@ class BootloaderResource(BinaryResource): ): super().__init__( local_path=local_path, + id=id, + category=category, description=description, architecture=architecture, source=source, @@ -248,6 +275,8 @@ class GitResource(DirectoryResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -255,6 +284,8 @@ class GitResource(DirectoryResource): ): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -267,6 +298,8 @@ class KernelResource(BinaryResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -275,6 +308,8 @@ class KernelResource(BinaryResource): ): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, architecture=architecture, @@ -293,6 +328,8 @@ class CheckpointResource(DirectoryResource): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -300,6 +337,8 @@ class CheckpointResource(DirectoryResource): ): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -320,6 +359,8 @@ class SimpointResource(AbstractResource): simpoint_list: List[int] = None, weight_list: List[float] = None, warmup_interval: int = 0, + id: Optional[str] = None, + category: Optional[str] = None, workload_name: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -340,6 +381,8 @@ class SimpointResource(AbstractResource): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -429,6 +472,8 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -437,6 +482,8 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): FileResource.__init__( self, local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -448,6 +495,8 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): def __init__( self, local_path: str, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, region_id: Optional[Union[str, int]] = None, description: Optional[str] = None, @@ -457,6 +506,8 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): FileResource.__init__( self, local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -477,6 +528,8 @@ class SimpointDirectoryResource(SimpointResource): weight_file: str, simpoint_interval: int, warmup_interval: int, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, workload_name: Optional[str] = None, description: Optional[str] = None, @@ -510,6 +563,8 @@ class SimpointDirectoryResource(SimpointResource): warmup_interval=warmup_interval, workload_name=workload_name, local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -563,6 +618,8 @@ class WorkloadResource(AbstractResource): def __init__( self, function: str = None, + id: Optional[str] = None, + category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -577,6 +634,8 @@ class WorkloadResource(AbstractResource): super().__init__( local_path=local_path, + id=id, + category=category, description=description, source=source, resource_version=resource_version, @@ -741,6 +800,7 @@ def obtain_resource( # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the # subclass contructor, so we can pass the resource_json map directly. + return resource_class(local_path=to_path, **resource_json) From 7225da4ac6946700a4893df33f8e56746f852b1f Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 15 Sep 2023 10:41:45 -0700 Subject: [PATCH 321/693] stdlib, resources: Removed unused import Change-Id: Iee54cc695c7c8ce146719ef583be424b792e2232 --- src/python/gem5/resources/resource.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index fd55995bbe..6b33f10971 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -25,7 +25,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import ABCMeta -import json import os from pathlib import Path from m5.util import warn, fatal @@ -800,7 +799,6 @@ def obtain_resource( # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the # subclass contructor, so we can pass the resource_json map directly. - return resource_class(local_path=to_path, **resource_json) From aec1d081c85efd6806b453398292d450dd1b8e6f Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 18 Sep 2023 15:20:04 +0100 Subject: [PATCH 322/693] mem-ruby: Populate missing txnId field to CompDBID_Stale response Change-Id: I6861d27063b13cd710e09c153d15062640c887fe Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 83698bb321..42e07eb46b 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -2644,6 +2644,7 @@ action(Send_CompDBIDResp_Stale, desc="") { out_msg.type := CHIResponseType:CompDBIDResp; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); + out_msg.txnId := tbe.txnId; out_msg.dbid := tbe.txnId; // We don't know if this is a stale writeback or a bug, so flag the // reponse so the requestor can make further checks From 9057eeabec7304df714f48e0df3641ddf60910d2 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Tue, 19 Sep 2023 12:54:18 -0700 Subject: [PATCH 323/693] cpu: Explicitly define cache_line_size -> 64-bit unsigned int While it makes sense to define the cache_line_size as a 32-bit unsigned int, the use of cache_line_size is way out of its original scope. cache_line_size has been used to produce an address mask, which masking out the offset bits from an address. For example, [1], [2], [3], and [4]. However, since the cache_line_size is an "unsigned int", the type of the value is not guaranteed to be 64-bit long. Subsequently, the bit twiddling hacks in [1], [2], [3], and [4] produce 32-bit mask, i.e., 0x00000000FFFFFFC0. This behavior at least caused a problem in LLSC in RISC-V [5], where the load reservation (LR) relies on the mask to produce the cache block address. Two distinct 64-bit addresses can be mapped to the same cache block using the above mask. This patch explicitly defines cache_line_size as a 64-bit unsigned int so the cache block mask can be produced correctly for 64-bit addresses. [1] https://github.com/gem5/gem5/blob/3bdcfd6f7abdf0c9125ec37018df76a29998a055/src/cpu/simple/atomic.hh#L147 [2] https://github.com/gem5/gem5/blob/3bdcfd6f7abdf0c9125ec37018df76a29998a055/src/cpu/simple/timing.hh#L224 [3] https://github.com/gem5/gem5/blob/3bdcfd6f7abdf0c9125ec37018df76a29998a055/src/cpu/o3/lsq_unit.cc#L241 [4] https://github.com/gem5/gem5/blob/3bdcfd6f7abdf0c9125ec37018df76a29998a055/src/cpu/minor/lsq.cc#L1425 [5] https://github.com/gem5/gem5/blob/3bdcfd6f7abdf0c9125ec37018df76a29998a055/src/arch/riscv/isa.cc#L787 Change-Id: I29abc7aaab266a37326846bbf7a82219071c4ffe Signed-off-by: Hoa Nguyen --- src/cpu/base.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 3976b66fe4..a05102a107 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -143,7 +143,7 @@ class BaseCPU : public ClockedObject bool _switchedOut; /** Cache the cache line size that we get from the system */ - const unsigned int _cacheLineSize; + const uint64_t _cacheLineSize; /** Global CPU statistics that are merged into the Root object. */ struct GlobalStats : public statistics::Group @@ -394,7 +394,7 @@ class BaseCPU : public ClockedObject /** * Get the cache line size of the system. */ - inline unsigned int cacheLineSize() const { return _cacheLineSize; } + inline uint64_t cacheLineSize() const { return _cacheLineSize; } /** * Serialize this object to the given output stream. From c36a4d12aaf045cd20071bfa6666d63107535bf9 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 22:25:42 -0700 Subject: [PATCH 324/693] tests: Replace print with testlib.log for PARSEC warn Using just a print was causing this warning to print even with the `-q` flag was passed. The `-q` flag sets the output to machine readable, which the warning statement is not. Change-Id: I139e2565dbc53aaee9027c0e003d34ba800a7ef4 --- .../test_gem5_library_examples.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py index b88862fc0d..0882fb0dfd 100644 --- a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py +++ b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py @@ -29,6 +29,7 @@ This runs simple tests to ensure the examples in `configs/example/gem5_library` still function. They simply check the simulation completed. """ from testlib import * +from testlib.log import * import re import os @@ -171,10 +172,11 @@ gem5_verify_config( length=constants.long_tag, ) -print( - "WARNING: PARSEC tests are disabled. This is due to our GitHub " +log.test_log.message( + "PARSEC tests are disabled. This is due to our GitHub " "Actions self-hosted runners only having 60GB of disk space. The " - "PARSEC Disk image is too big to use." + "PARSEC Disk image is too big to use.", + level=LogLevel.Warn, ) # 'False' is used to disable the tests. if False: # os.access("/dev/kvm", mode=os.R_OK | os.W_OK): From 43226004a108fa60bd858a1c6977976a358a4f12 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 15:42:35 -0700 Subject: [PATCH 325/693] ext,tests: Fix `--figures` flag when using `./main.py list` Now the "tests/main.py" script will accept the `--fixtures` flag when using the `list` command. This will only list the fixtures needed. To have this implemented `__str__` for the `Fixture` class has been implemented. Change-Id: I4bba26e923c8b0001163726637f2e48c801e92b1 --- ext/testlib/fixture.py | 4 ++++ ext/testlib/main.py | 2 ++ ext/testlib/query.py | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/ext/testlib/fixture.py b/ext/testlib/fixture.py index 148229a597..0138f018bb 100644 --- a/ext/testlib/fixture.py +++ b/ext/testlib/fixture.py @@ -27,6 +27,7 @@ # Authors: Sean Wilson import testlib.helper as helper +from testlib.configuration import constants class SkipException(Exception): @@ -79,6 +80,9 @@ class Fixture(object): def teardown(self, testitem): pass + def __str__(self): + return f"{self.name} fixture" + def set_global(self): self._is_global = True diff --git a/ext/testlib/main.py b/ext/testlib/main.py index 3888a1ec6b..59ce050bfd 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -253,6 +253,8 @@ def do_list(): qrunner.list_tests() elif configuration.config.all_tags: qrunner.list_tags() + elif configuration.config.fixtures: + qrunner.list_fixtures() else: qrunner.list_suites() qrunner.list_tests() diff --git a/ext/testlib/query.py b/ext/testlib/query.py index 7b69d7d76b..74541002cd 100644 --- a/ext/testlib/query.py +++ b/ext/testlib/query.py @@ -55,6 +55,13 @@ class QueryRunner(object): for test in suite: log.test_log.message(test.uid, machine_readable=True) + def list_fixtures(self): + log.test_log.message(terminal.separator()) + log.test_log.message('Listing all Test Fixtures.', bold=True) + log.test_log.message(terminal.separator()) + for fixture in self.schedule.all_fixtures(): + log.test_log.message(fixture, machine_readable=True) + def list_suites(self): log.test_log.message(terminal.separator()) log.test_log.message("Listing all Test Suites.", bold=True) From 13b77b3e4173a24ae8ad5dac53d7ae675daf8395 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 15:46:07 -0700 Subject: [PATCH 326/693] ext,tests: Allow passing of `--uid` to `./main.py list` This is useful for listing the fixtures of a Suite. Change-Id: Id2f1294cc7dea03a6b26e8abc5083886fe0299d9 --- ext/testlib/configuration.py | 7 +++++++ ext/testlib/main.py | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/ext/testlib/configuration.py b/ext/testlib/configuration.py index 600f0e13cc..918a3f92b3 100644 --- a/ext/testlib/configuration.py +++ b/ext/testlib/configuration.py @@ -751,6 +751,13 @@ class ListParser(ArgParser): default=False, help="Quiet output (machine readable).", ).add_to(parser) + Argument( + '--uid', + action='store', + default=None, + help='UID of a specific test item to list.' + ).add_to(parser) + common_args.directories.add_to(parser) common_args.bin_path.add_to(parser) diff --git a/ext/testlib/main.py b/ext/testlib/main.py index 59ce050bfd..e9dd892947 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -242,7 +242,25 @@ def do_list(): entry_message() - test_schedule = load_tests().schedule + if configuration.config.uid: + uid_ = uid.UID.from_uid(configuration.config.uid) + if isinstance(uid_, uid.TestUID): + log.test_log.error('Unable to list a standalone test.\n' + 'Gem5 expects test suites to be the smallest unit ' + ' of test.\n\n' + 'Pass a SuiteUID instead.') + return + test_schedule = loader_mod.Loader().load_schedule_for_suites(uid_) + if get_config_tags(): + log.test_log.warn( + "The '--uid' flag was supplied," + " '--include-tags' and '--exclude-tags' will be ignored." + ) + else: + test_schedule = load_tests().schedule + # Filter tests based on tags + filter_with_config_tags(test_schedule) + filter_with_config_tags(test_schedule) qrunner = query.QueryRunner(test_schedule) From 0337613afcf9803eaa977d787c6d5c03f743db4d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Sep 2023 23:34:39 -0700 Subject: [PATCH 327/693] ext,tests: Add `--build-targets` option to `./main.py list` This allows for build target information (i.e., the gem5 binary to be built for the tests) to be returned. Change-Id: I6638b54cbb1822555f58e74938d36043c11108ba --- ext/testlib/configuration.py | 13 +++++++++---- ext/testlib/fixture.py | 14 ++++++++++++++ ext/testlib/main.py | 13 +++++++++---- ext/testlib/query.py | 14 +++++++++++++- tests/gem5/fixture.py | 12 ++++++++++++ 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/ext/testlib/configuration.py b/ext/testlib/configuration.py index 918a3f92b3..07f636b03b 100644 --- a/ext/testlib/configuration.py +++ b/ext/testlib/configuration.py @@ -744,6 +744,12 @@ class ListParser(ArgParser): default=False, help="List all tags.", ).add_to(parser) + Argument( + "--build-targets", + action="store_true", + default=False, + help="List all the gem5 build targets.", + ).add_to(parser) Argument( "-q", dest="quiet", @@ -752,12 +758,11 @@ class ListParser(ArgParser): help="Quiet output (machine readable).", ).add_to(parser) Argument( - '--uid', - action='store', + "--uid", + action="store", default=None, - help='UID of a specific test item to list.' + help="UID of a specific test item to list.", ).add_to(parser) - common_args.directories.add_to(parser) common_args.bin_path.add_to(parser) diff --git a/ext/testlib/fixture.py b/ext/testlib/fixture.py index 0138f018bb..aa735cc1c5 100644 --- a/ext/testlib/fixture.py +++ b/ext/testlib/fixture.py @@ -29,6 +29,8 @@ import testlib.helper as helper from testlib.configuration import constants +from typing import Optional + class SkipException(Exception): def __init__(self, fixture, testitem): @@ -80,6 +82,18 @@ class Fixture(object): def teardown(self, testitem): pass + def get_get_build_info(self) -> Optional[dict]: + # If this is a gem5 build it will return the target gem5 build path + # and any additional build information. E.g.: + # + # /path/to/gem5/build/NULL/gem5.opt--default=NULL PROTOCOL=MI_example + # + # In this example this may be passed to scons to build gem5 in + # accordance to the test's build requirements. + # + # If this fixtures is not a build of gem5, None is returned. + return None + def __str__(self): return f"{self.name} fixture" diff --git a/ext/testlib/main.py b/ext/testlib/main.py index e9dd892947..f8d04cec56 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -245,10 +245,12 @@ def do_list(): if configuration.config.uid: uid_ = uid.UID.from_uid(configuration.config.uid) if isinstance(uid_, uid.TestUID): - log.test_log.error('Unable to list a standalone test.\n' - 'Gem5 expects test suites to be the smallest unit ' - ' of test.\n\n' - 'Pass a SuiteUID instead.') + log.test_log.error( + "Unable to list a standalone test.\n" + "Gem5 expects test suites to be the smallest unit " + " of test.\n\n" + "Pass a SuiteUID instead." + ) return test_schedule = loader_mod.Loader().load_schedule_for_suites(uid_) if get_config_tags(): @@ -273,10 +275,13 @@ def do_list(): qrunner.list_tags() elif configuration.config.fixtures: qrunner.list_fixtures() + elif configuration.config.build_targets: + qrunner.list_build_targets() else: qrunner.list_suites() qrunner.list_tests() qrunner.list_tags() + qrunner.list_build_targets() return 0 diff --git a/ext/testlib/query.py b/ext/testlib/query.py index 74541002cd..be1c5a6792 100644 --- a/ext/testlib/query.py +++ b/ext/testlib/query.py @@ -57,11 +57,23 @@ class QueryRunner(object): def list_fixtures(self): log.test_log.message(terminal.separator()) - log.test_log.message('Listing all Test Fixtures.', bold=True) + log.test_log.message("Listing all Test Fixtures.", bold=True) log.test_log.message(terminal.separator()) for fixture in self.schedule.all_fixtures(): log.test_log.message(fixture, machine_readable=True) + def list_build_targets(self): + log.test_log.message(terminal.separator()) + log.test_log.message("Listing all gem5 Build Targets.", bold=True) + log.test_log.message(terminal.separator()) + builds = [] + for fixture in self.schedule.all_fixtures(): + build = fixture.get_get_build_info() + if build and build not in builds: + builds.append(build) + for build in builds: + log.test_log.message(build, machine_readable=True) + def list_suites(self): log.test_log.message(terminal.separator()) log.test_log.message("Listing all Test Suites.", bold=True) diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index d3312c9a63..0f53539b40 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -53,6 +53,8 @@ from testlib.helper import log_call, cacheresult, joinpath, absdirpath import testlib.log as log from testlib.state import Result +from typing import Optional, List + class VariableFixture(Fixture): def __init__(self, value=None, name=None): @@ -147,6 +149,10 @@ class SConsFixture(UniqueFixture): obj = super(SConsFixture, cls).__new__(cls, target) return obj + def _setup(self, testitem): + if config.skip_build: + return + def _setup(self, testitem): if config.skip_build: return @@ -204,6 +210,12 @@ class Gem5Fixture(SConsFixture): self.options = ["--default=" + isa.upper(), "PROTOCOL=" + protocol] self.set_global() + def get_get_build_info(self) -> Optional[str]: + build_target = self.target + if self.options: + build_target += " ".join(self.options) + return build_target + class MakeFixture(Fixture): def __init__(self, directory, *args, **kwargs): From efd58f9b723c788200838e9004aa1d652ddddf38 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 8 Sep 2023 10:17:36 -0700 Subject: [PATCH 328/693] tests: Remove ":" from testing results output dir name Colons in path names is not advisable. Change-Id: I7748a36cabafde69759f7a9892f7b8910470b85e --- tests/gem5/fixture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index 0f53539b40..05b599dd80 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -76,7 +76,7 @@ class TempdirFixture(Fixture): suiteUID = testitem.metadata.uid.suite testUID = testitem.metadata.name testing_result_folder = os.path.join( - config.result_path, "SuiteUID:" + suiteUID, "TestUID:" + testUID + config.result_path, "SuiteUID-" + suiteUID, "TestUID-" + testUID ) # Copy the output files of the run from /tmp to testing-results From 6921d943735905ec1f6b7cc3216d957d7e26c755 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 11 Sep 2023 15:25:16 -0700 Subject: [PATCH 329/693] python: Recursively create checkpoint dir While there was code present in "serialize.cc" to create the checkpoint directory, it did not do recursively. This patch ensures all the directories are created in a path to the checkpoint directory. Change-Id: Ibcf7f800358fd89946f550b8cfb0cef8b51fceac --- src/python/m5/simulate.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 70ed11a9b6..19d5604568 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -318,6 +318,10 @@ def checkpoint(dir): drain() memWriteback(root) + + # Recursively create the checkpoint directory if it does not exist. + os.makedirs(dir, exist_ok=True) + print("Writing checkpoint") _m5.core.serializeAll(dir) From 561f3bd75b7bb940515c0e7acd8d46f4d2f0a4d7 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sun, 3 Sep 2023 23:33:59 -0700 Subject: [PATCH 330/693] misc,tests: Split testlib CI Tests to one dir-per-job This splits the CI Tests to one job per sub-directory in "tests/gem5" via a matrix. Advantages: * We can utilize more runners to run the quick tests. This should mean tests run quicker. * This approach does not require editing of the workflow as more tests are added or taken away. * There is now an output artifact for each directory in "tests/gem5" instead of one for the entriety of every quick test in "tests". In addition: * The artifact retention for the test outputs has been increased to 30 days. * The output test artifacts have been renamed to be more descriptive of the job, run, attempt, directory run, and the status. * The 'tar' step has been removed. GitHub's 'action/artifact' can handle directories. Change-Id: I5b3132b424e3769d81d9cd75db2a8c59dbe4a7e5 --- .github/workflows/ci-tests.yaml | 140 +++++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 656f41f4bc..5a92422e79 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -46,27 +46,6 @@ jobs: "curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f\n Then amend the commit with git commit --amend --no-edit, and update your pull request." exit 1 - build-gem5: - runs-on: [self-hosted, linux, x64, build] - if: github.event.pull_request.draft == false - container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes - outputs: - artifactname: ${{ steps.name.outputs.test }} - steps: - - uses: actions/checkout@v3 - - id: name - run: echo "test=$(date +"%Y-%m-%d_%H.%M.%S")-artifact" >> $GITHUB_OUTPUT - - - name: Build gem5 - run: | - scons build/ALL/gem5.opt -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.name.outputs.test }} - path: build/ALL/gem5.opt - - run: echo "This job's status is ${{ job.status }}." - unittests-all-opt: runs-on: [self-hosted, linux, x64, run] if: github.event.pull_request.draft == false @@ -80,39 +59,122 @@ jobs: run: scons build/ALL/unittests.opt -j $(nproc) - run: echo "This job's status is ${{ job.status }}." - testlib-quick: + testlib-quick-matrix: + runs-on: [self-hosted, linux, x64, run] + if: github.event.pull_request.draft == false + # In order to make sure the environment is exactly the same, we run in + # the same container we use to build gem5 and run the testlib tests. This + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, check-for-change-id] + steps: + - uses: actions/checkout@v3 + + # Unfortunately the 'ubunutu-latest' image doesn't have jq installed. + # We therefore need to install it as a step here. + - name: Install jq + run: apt install -y jq + + - name: Get directories for testlib-quick + working-directory: "${{ github.workspace }}/tests" + id: dir-matrix + run: echo "test-dirs-matrix=$(find gem5/* -type d -maxdepth 0 | jq -ncR '[inputs]')" >>$GITHUB_OUTPUT + + - name: Get the build targets for testlib-quick-gem5-builds + working-directory: "${{ github.workspace }}/tests" + id: build-matrix + run: echo "build-matrix=$(./main.py list --build-targets -q | jq -ncR '[inputs]')" >>$GITHUB_OUTPUT + + outputs: + build-matrix: ${{ steps.build-matrix.outputs.build-matrix }} + test-dirs-matrix: ${{ steps.dir-matrix.outputs.test-dirs-matrix }} + + testlib-quick-gem5-builds: + runs-on: [self-hosted, linux, x64, build] + if: github.event.pull_request.draft == false + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, check-for-change-id, testlib-quick-matrix] + strategy: + matrix: + build-target: ${{ fromJson(needs.testlib-quick-matrix.outputs.build-matrix) }} + steps: + - uses: actions/checkout@v3 + - name: Build gem5 + run: scons ${{ matrix.build-target }} -j $(nproc) + + # Upload the gem5 binary as an artifact. + # Note: the "achor.txt" file is a hack to make sure the paths are + # preserverd in the artifact. The upload-artifact action finds the + # closest common directory and uploads everything relative to that. + # E.g., if we upload "build/ARM/gem5.opt" and "build/RISCV/gem5.opt" + # Then upload-artifact will upload "ARM/gem5.opt" and "RISCV/gem5.opt", + # stripping the "build" directory. By adding the "anchor.txt" file, we + # ensure the "build" directory is preserved. + - run: echo "anchor" > anchor.txt + - uses: actions/upload-artifact@v3 + with: + name: ci-tests-${{ github.run_number }}-testlib-quick-all-gem5-builds + path: | + build/*/gem5.* + anchor.txt + retention-days: 7 + + testlib-quick-execution: runs-on: [self-hosted, linux, x64, run] if: github.event.pull_request.draft == false container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, build-gem5, check-for-change-id] + needs: [pre-commit, check-for-change-id, testlib-quick-matrix, testlib-quick-gem5-builds] timeout-minutes: 360 # 6 hours + strategy: + fail-fast: false + matrix: + test-dir: ${{ fromJson(needs.testlib-quick-matrix.outputs.test-dirs-matrix) }} steps: - name: Clean runner run: rm -rf ./* || true rm -rf ./.??* || true rm -rf ~/.cache || true + + # Checkout the repository then download the gem5.opt artifact. - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 with: - name: ${{needs.build-gem5.outputs.artifactname}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: The TestLib CI Tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --skip-build -vv - - name: create zip of results - if: success() || failure() + name: ci-tests-${{ github.run_number }}-testlib-quick-all-gem5-builds + + # Check that the gem5.opt artifact exists and is executable. + - name: Chmod gem5.{opt,debug,fast} to be executable run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip + find . -name "gem5.opt" -exec chmod u+x {} \; + find . -name "gem5.debug" -exec chmod u+x {} \; + find . -name "gem5.fast" -exec chmod u+x {} \; + + # Run the testlib quick tests in the given directory. + - name: Run "tests/${{ matrix.test-dir }}" TestLib quick tests + id: run-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --skip-build -vv ${{ matrix.test-dir }} + + # Get the basename of the matrix.test-dir path (to name the artifact). + - name: Sanatize test-dir for artifact name + id: sanitize-test-dir + if: success() || failure() + run: echo "sanatized-test-dir=$(echo '${{ matrix.test-dir }}' | sed 's/\//-/g')" >> $GITHUB_OUTPUT + + # Upload the tests/testing-results directory as an artifact. + - name: Upload test results if: success() || failure() uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{github.job}}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 + name: ci-tests-run-${{ github.run_number }}-attempt-${{ github.run_attempt }}-testlib-quick-${{ steps.sanitize-test-dir.outputs.sanatized-test-dir }}-status-${{ steps.run-tests.outcome }}-output + path: tests/testing-results + retention-days: 30 + + testlib-quick: + # It is 'testlib-quick' which needs to pass for the pull request to be + # merged. The 'testlib-quick-execution' is a matrix job which runs all the + # the testlib quick tests. This job is therefore a stub which will pass if + # all the testlib-quick-execution jobs pass. + runs-on: [self-hosted, linux, x64, run] + needs: testlib-quick-execution + steps: - run: echo "This job's status is ${{ job.status }}." From 741a901d8d735ce0ce2d2875eff84fd3d494f4aa Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Wed, 20 Sep 2023 05:09:32 +0000 Subject: [PATCH 331/693] arch-x86: fix negative overflow check bug in PACK micro-op The implementation of the x86 PACK micro-op had a logical bug that caused the `PACKSSWB` and `PACKSSDW` instructions to produce incorrect results. Specifically, due to a signedness error, the overflow check for negative integers being packed always evaluated to true, resulting in all negative integers being packed as -1 in the output. This patch fixes the signedness error that causes the bug. GitHub issue: https://github.com/gem5/gem5/issues/331 Change-Id: I44b7328a8ce31742a3c0dfaebd747f81751e8851 --- src/arch/x86/isa/microops/mediaop.isa | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/isa/microops/mediaop.isa b/src/arch/x86/isa/microops/mediaop.isa index 599b5faef5..0b1d1fe0eb 100644 --- a/src/arch/x86/isa/microops/mediaop.isa +++ b/src/arch/x86/isa/microops/mediaop.isa @@ -393,7 +393,7 @@ let {{ // Handle saturation. if (signBit) { - if (overflow != mask(destBits - srcBits + 1)) { + if (overflow != mask(srcBits - destBits + 1)) { if (signedOp()) picked = (1ULL << (destBits - 1)); else @@ -421,7 +421,7 @@ let {{ // Handle saturation. if (signBit) { - if (overflow != mask(destBits - srcBits + 1)) { + if (overflow != mask(srcBits - destBits + 1)) { if (signedOp()) picked = (1ULL << (destBits - 1)); else From 70c1d762c70cd1f4d32721be42f01d9e61a7c376 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 18 Sep 2023 13:28:12 +0800 Subject: [PATCH 332/693] arch-riscv: Fix inst flags for jal and jalr The jal and jalr share the same instruction format JumpConstructor, which sets the IsCall and IsReturn flags by the register ID. However, it may cause wrong instruction flags set for jal because the section "handle the 'Jalr' instruction" misses the opcode checking. The PR fix the issue to ensure the IsReturn can be only set in Jalr. Change-Id: I9ad867a389256f9253988552e6567d2b505a6901 --- src/arch/riscv/isa/formats/standard.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/isa/formats/standard.isa b/src/arch/riscv/isa/formats/standard.isa index bb500f5f49..98b0af1e2d 100644 --- a/src/arch/riscv/isa/formats/standard.isa +++ b/src/arch/riscv/isa/formats/standard.isa @@ -267,7 +267,7 @@ def template JumpConstructor {{ flags[IsCall] = true; // Handle "Jalr" instruction - if (FUNCT3 == 0x0) { + if (FUNCT3 == 0x0 && OPCODE5 == 0x19) { // If RD is not link and RS1 is link, then pop RAS if (!rd_link && rs1_link) flags[IsReturn] = true; else if (rd_link) { From 63cabf28485b1bfc0f3998e917e85dd8752ab416 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Tue, 19 Sep 2023 13:22:35 -0500 Subject: [PATCH 333/693] dev-amdgpu: Handle GPU atomics on host memory addresses It is possible to execute a GPU atomic instruction using a memory address that is in the host memory space (e.g, HMM, __managed__, hipHostMalloc'd address). Since these are in host memory they are passed to the SystemHub DmaDevice. However, this currently executes as a write packet without modifying data. This leads to hangs in applications that use atomics for forward progress (e.g., HeteroSync). It is not clear where these are handled on a real GPU, but they are certianly not handled by the software stack nor driver, so they must be handled in hardware and therefore implemented in gem5. Handling for atomics in the SystemHub makes the most sense. To make atomics work a few extra changes need to be made to the SystemHub. (1) The atomic is implemented as a host memory read, followed by calling the AtomicOpFunctor, followed by a write. This requires a second event to handle read response, performing atomic, and issuing a write. (2) Atomics must be serialized otherwise two atomics might return the same value which is incorrect. This patch adds serialization logic for all request types to the same address to handle this. (3) With the added complexity of the SystemHub, a new debug flag explicitly for SystemHub is added. Testing done: The heterosync application with input "sleepMutex 10 16 4" previously hung before this patch. It passes with the patch applied. This application tests both (1) and (2) above, as it allocates locks with hipHostMalloc and has multiple workgroups sending an atomic request in the same Tick, verifying the serialization mechanism. Change-Id: Ife84b30037d1447dd384340cfeb06fdfd472fff9 --- src/dev/amdgpu/SConscript | 1 + src/dev/amdgpu/system_hub.cc | 142 +++++++++++++++++++++++++++++++++-- src/dev/amdgpu/system_hub.hh | 27 ++++++- 3 files changed, 162 insertions(+), 8 deletions(-) diff --git a/src/dev/amdgpu/SConscript b/src/dev/amdgpu/SConscript index 9f8eeacd00..428d1c56bc 100644 --- a/src/dev/amdgpu/SConscript +++ b/src/dev/amdgpu/SConscript @@ -50,6 +50,7 @@ Source('system_hub.cc', tags='x86 isa') DebugFlag('AMDGPUDevice', tags='x86 isa') DebugFlag('AMDGPUMem', tags='x86 isa') +DebugFlag('AMDGPUSystemHub', tags='x86 isa') DebugFlag('PM4PacketProcessor', tags='x86 isa') DebugFlag('SDMAEngine', tags='x86 isa') DebugFlag('SDMAData', tags='x86 isa') diff --git a/src/dev/amdgpu/system_hub.cc b/src/dev/amdgpu/system_hub.cc index 7a252ea0fa..892a7c4535 100644 --- a/src/dev/amdgpu/system_hub.cc +++ b/src/dev/amdgpu/system_hub.cc @@ -31,6 +31,8 @@ #include "dev/amdgpu/system_hub.hh" +#include "debug/AMDGPUSystemHub.hh" +#include "mem/packet_access.hh" #include "mem/port.hh" namespace gem5 @@ -39,16 +41,92 @@ namespace gem5 void AMDGPUSystemHub::sendRequest(PacketPtr pkt, Event *callback) { - ResponseEvent *dmaRespEvent = new ResponseEvent(callback); - Tick delay = 0; + // Some requests, in particular atomics, need to be sent in order + // to receive the correct values. If there is an atomic in progress + // we must block it until that request is complete. This is overly + // conservative and blocks reads/writes but this situation is rare + // so it should not impact simulated performance. + DeferredReq this_req(pkt, callback); + outstandingReqs[pkt->getAddr()].push_back(this_req); + + if (outstandingReqs[pkt->getAddr()].size () > 1) { + // There is another request in progress, Delay this one. + DPRINTF(AMDGPUSystemHub, "SystemHub deferring request for %#lx\n", + pkt->getAddr()); + } else { + // No other requests, we can send immediately. + sendDeferredRequest(this_req); + } +} + +void +AMDGPUSystemHub::sendDeferredRequest(DeferredReq& deferredReq) +{ + PacketPtr pkt = deferredReq.first; + Event *callback = deferredReq.second; + Tick delay = 0; + std::string req_type; + + if (pkt->isAtomicOp()) { + AtomicResponseEvent *atomicRespEvent = + new AtomicResponseEvent(*this, callback, pkt); + + // First read the value. The response event will do the atomic/write + // This places the current value in the packet, which is correct since + // atomics return the value prior to performing the atomic. + dmaRead(pkt->getAddr(), pkt->getSize(), atomicRespEvent, + pkt->getPtr(), 0, 0, delay); + + req_type = "Atomic"; + } else if (pkt->isWrite()) { + ResponseEvent *dmaRespEvent = + new ResponseEvent(*this, callback, pkt); - if (pkt->isWrite()) { dmaWrite(pkt->getAddr(), pkt->getSize(), dmaRespEvent, pkt->getPtr(), 0, 0, delay); + + req_type = "Write"; } else { + ResponseEvent *dmaRespEvent = + new ResponseEvent(*this, callback, pkt); + assert(pkt->isRead()); dmaRead(pkt->getAddr(), pkt->getSize(), dmaRespEvent, pkt->getPtr(), 0, 0, delay); + + req_type = "Read"; + } + + DPRINTF(AMDGPUSystemHub, "SystemHub %s request for %#lx size %d\n", + req_type.c_str(), pkt->getAddr(), pkt->getSize()); +} + +void +AMDGPUSystemHub::sendNextRequest(Addr addr, const PacketPtr donePkt) +{ + // Remove our request + assert(outstandingReqs.count(addr)); + + [[maybe_unused]] DeferredReq& frontPkt = outstandingReqs[addr].front(); + assert(frontPkt.first == donePkt); + + outstandingReqs[addr].pop_front(); + + // If there are no more requests this can be removed from the map. + // Otherwise issue the next request in the list + if (outstandingReqs[addr].empty()) { + DPRINTF(AMDGPUSystemHub, "SystemHub done with packets for addr %#lx\n", + donePkt->getAddr()); + + outstandingReqs.erase(addr); + } else { + DeferredReq& nextPkt = outstandingReqs[addr].front(); + + DPRINTF(AMDGPUSystemHub, "SystemHub sending deferred request for addr" + " %#lx size %d\n", nextPkt.first->getAddr(), + nextPkt.first->getSize()); + + sendDeferredRequest(nextPkt); } } @@ -57,8 +135,9 @@ AMDGPUSystemHub::dmaResponse(PacketPtr pkt) { } -AMDGPUSystemHub::ResponseEvent::ResponseEvent(Event *_callback) - : callback(_callback) +AMDGPUSystemHub::ResponseEvent::ResponseEvent( + AMDGPUSystemHub& _hub, Event *_callback, PacketPtr _pkt) + : systemHub(_hub), callback(_callback), pkt(_pkt) { // Delete this event after process is called setFlags(Event::AutoDelete); @@ -67,9 +146,62 @@ AMDGPUSystemHub::ResponseEvent::ResponseEvent(Event *_callback) void AMDGPUSystemHub::ResponseEvent::process() { + DPRINTF(AMDGPUSystemHub, "SystemHub response for addr %#lx size %d\n", + pkt->getAddr(), pkt->getSize()); + + systemHub.sendNextRequest(pkt->getAddr(), pkt); + callback->process(); } +AMDGPUSystemHub::AtomicResponseEvent::AtomicResponseEvent( + AMDGPUSystemHub& _hub, Event *_callback, PacketPtr _pkt) + : systemHub(_hub), callback(_callback), pkt(_pkt) +{ + // Delete this event after process is called + setFlags(Event::AutoDelete); +} + +void +AMDGPUSystemHub::AtomicResponseEvent::process() +{ + // Make a second response with the original sender's callback + ResponseEvent *dmaRespEvent = new ResponseEvent(systemHub, callback, pkt); + Tick delay = 0; + + // Create a new write packet which will be modifed then written + RequestPtr write_req = + std::make_shared(pkt->getAddr(), pkt->getSize(), 0, + pkt->requestorId()); + + PacketPtr write_pkt = Packet::createWrite(write_req); + uint8_t *write_data = new uint8_t[pkt->getSize()]; + std::memcpy(write_data, pkt->getPtr(), pkt->getSize()); + write_pkt->dataDynamic(write_data); + + // Perform the atomic on the write packet data. The atomic op is not + // copied from the original packet, so use the original packet. + assert(pkt->isAtomicOp()); + (*pkt->getAtomicOp())(write_pkt->getPtr()); + + // Write back the new value. The atomic is not considered done until + // this packet's response event is triggered. + systemHub.dmaWrite(write_pkt->getAddr(), write_pkt->getSize(), + dmaRespEvent, write_pkt->getPtr(), 0, 0, delay); + + // Atomics from the GPU are at most 64-bit and usually 32-bit. + // We can take a peek at the data for debugging purposes. + [[maybe_unused]] uint64_t req_data = 0x12345678; + if (write_pkt->getSize() == 8) { + req_data = write_pkt->getLE(); + } else if (pkt->getSize() == 4) { + req_data = write_pkt->getLE(); + } + + DPRINTF(AMDGPUSystemHub, "SystemHub atomic %#lx writing %lx size %d\n", + write_pkt->getAddr(), req_data, write_pkt->getSize()); +} + AddrRangeList AMDGPUSystemHub::getAddrRanges() const { diff --git a/src/dev/amdgpu/system_hub.hh b/src/dev/amdgpu/system_hub.hh index 0b48c3bc01..7955f5e694 100644 --- a/src/dev/amdgpu/system_hub.hh +++ b/src/dev/amdgpu/system_hub.hh @@ -63,16 +63,37 @@ class AMDGPUSystemHub : public DmaDevice AddrRangeList getAddrRanges() const override; private: + typedef std::pair DeferredReq; + typedef std::list DeferredReqList; + std::unordered_map outstandingReqs; + + void sendNextRequest(Addr addr, const PacketPtr donePkt); + void sendDeferredRequest(DeferredReq& deferredReq); class ResponseEvent : public Event { - Event *callback; + AMDGPUSystemHub &systemHub; + Event *callback; + PacketPtr pkt; - public: - ResponseEvent(Event *_callback); + public: + ResponseEvent(AMDGPUSystemHub& _hub, + Event *_callback, PacketPtr _pkt); void process(); + }; + class AtomicResponseEvent : public Event + { + AMDGPUSystemHub &systemHub; + Event *callback; + PacketPtr pkt; + + public: + AtomicResponseEvent(AMDGPUSystemHub& _hub, + Event *_callback, PacketPtr _pkt); + + void process(); }; }; From 3c38d4952acde02e88b96d3c8565eeb35561c4c9 Mon Sep 17 00:00:00 2001 From: "Pu (Luke) Yi" Date: Mon, 4 Sep 2023 02:16:32 -0700 Subject: [PATCH 334/693] mem: fix bug in 3-level cache Change-Id: I5b875908ac8f81180d781e609869e2f6fe1a8dc4 --- .../ruby/mesi_three_level_cache_hierarchy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 89b6b21177..3646418572 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 @@ -193,10 +193,10 @@ class MESIThreeLevelCacheHierarchy( if board.has_dma_ports(): dma_ports = board.get_dma_ports() for i, port in enumerate(dma_ports): - ctrl = DMAController(self.ruby_system.network, cache_line_size) - ctrl.dma_sequencer = DMASequencer(version=i, in_ports=port) + ctrl = DMAController( + DMASequencer(version=i, in_ports=port), self.ruby_system + ) self._dma_controllers.append(ctrl) - ctrl.ruby_system = self.ruby_system self.ruby_system.num_of_sequencers = len(self._l1_controllers) + len( self._dma_controllers From ac5280fedc9ed72382534e4784377d97dfbeaaa1 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 20 Sep 2023 13:49:10 -0700 Subject: [PATCH 335/693] mem,sim: Change the type of cache_line_size to Addr Change-Id: Id39e8249fef89c0d59bb39f8104650257ff00245 Signed-off-by: Hoa Nguyen --- src/mem/port_proxy.cc | 4 ++-- src/mem/port_proxy.hh | 8 ++++---- src/sim/system.hh | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mem/port_proxy.cc b/src/mem/port_proxy.cc index 44e8fbbc90..a3c82452e2 100644 --- a/src/mem/port_proxy.cc +++ b/src/mem/port_proxy.cc @@ -44,12 +44,12 @@ namespace gem5 { -PortProxy::PortProxy(ThreadContext *tc, unsigned int cache_line_size) : +PortProxy::PortProxy(ThreadContext *tc, Addr cache_line_size) : PortProxy([tc](PacketPtr pkt)->void { tc->sendFunctional(pkt); }, cache_line_size) {} -PortProxy::PortProxy(const RequestPort &port, unsigned int cache_line_size) : +PortProxy::PortProxy(const RequestPort &port, Addr cache_line_size) : PortProxy([&port](PacketPtr pkt)->void { port.sendFunctional(pkt); }, cache_line_size) {} diff --git a/src/mem/port_proxy.hh b/src/mem/port_proxy.hh index 2e60a527cd..49c6d6f811 100644 --- a/src/mem/port_proxy.hh +++ b/src/mem/port_proxy.hh @@ -92,7 +92,7 @@ class PortProxy : FunctionalRequestProtocol SendFunctionalFunc sendFunctional; /** Granularity of any transactions issued through this proxy. */ - const unsigned int _cacheLineSize; + const Addr _cacheLineSize; void recvFunctionalSnoop(PacketPtr pkt) override @@ -103,13 +103,13 @@ class PortProxy : FunctionalRequestProtocol } public: - PortProxy(SendFunctionalFunc func, unsigned int cache_line_size) : + PortProxy(SendFunctionalFunc func, Addr cache_line_size) : sendFunctional(func), _cacheLineSize(cache_line_size) {} // Helpers which create typical SendFunctionalFunc-s from other objects. - PortProxy(ThreadContext *tc, unsigned int cache_line_size); - PortProxy(const RequestPort &port, unsigned int cache_line_size); + PortProxy(ThreadContext *tc, Addr cache_line_size); + PortProxy(const RequestPort &port, Addr cache_line_size); virtual ~PortProxy() {} diff --git a/src/sim/system.hh b/src/sim/system.hh index d2725c32a9..bb64f639b5 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -305,7 +305,7 @@ class System : public SimObject, public PCEventScope /** * Get the cache line size of the system. */ - unsigned int cacheLineSize() const { return _cacheLineSize; } + Addr cacheLineSize() const { return _cacheLineSize; } Threads threads; @@ -405,7 +405,7 @@ class System : public SimObject, public PCEventScope enums::MemoryMode memoryMode; - const unsigned int _cacheLineSize; + const Addr _cacheLineSize; uint64_t workItemsBegin = 0; uint64_t workItemsEnd = 0; From 1fc89bc8aeb1b2a11f89372093d2107873651e3f Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 20 Sep 2023 14:16:46 -0700 Subject: [PATCH 336/693] cpu,mem,dev: Use Addr for cacheLineSize Change-Id: I2f056571dbf35081d58afda09726c600141d5a05 Signed-off-by: Hoa Nguyen --- src/cpu/base.cc | 8 ++++---- src/cpu/base.hh | 4 ++-- src/cpu/minor/fetch1.hh | 4 ++-- src/cpu/minor/lsq.hh | 2 +- src/cpu/o3/fetch.hh | 2 +- src/cpu/testers/memtest/memtest.hh | 2 +- src/cpu/trace/trace_cpu.cc | 2 +- src/cpu/trace/trace_cpu.hh | 2 +- src/dev/dma_device.hh | 6 +++--- src/learning_gem5/part2/simple_cache.hh | 2 +- src/mem/snoop_filter.hh | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cpu/base.cc b/src/cpu/base.cc index a61c99796c..bea21a1928 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -257,8 +257,8 @@ BaseCPU::mwait(ThreadID tid, PacketPtr pkt) AddressMonitor &monitor = addressMonitor[tid]; if (!monitor.gotWakeup) { - int block_size = cacheLineSize(); - uint64_t mask = ~((uint64_t)(block_size - 1)); + Addr block_size = cacheLineSize(); + Addr mask = ~(block_size - 1); assert(pkt->req->hasPaddr()); monitor.pAddr = pkt->getAddr() & mask; @@ -282,8 +282,8 @@ BaseCPU::mwaitAtomic(ThreadID tid, ThreadContext *tc, BaseMMU *mmu) RequestPtr req = std::make_shared(); Addr addr = monitor.vAddr; - int block_size = cacheLineSize(); - uint64_t mask = ~((uint64_t)(block_size - 1)); + Addr block_size = cacheLineSize(); + Addr mask = ~(block_size - 1); int size = block_size; //The address of the next line if it crosses a cache line boundary. diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a05102a107..a6c80dadbe 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -143,7 +143,7 @@ class BaseCPU : public ClockedObject bool _switchedOut; /** Cache the cache line size that we get from the system */ - const uint64_t _cacheLineSize; + const Addr _cacheLineSize; /** Global CPU statistics that are merged into the Root object. */ struct GlobalStats : public statistics::Group @@ -394,7 +394,7 @@ class BaseCPU : public ClockedObject /** * Get the cache line size of the system. */ - inline uint64_t cacheLineSize() const { return _cacheLineSize; } + inline Addr cacheLineSize() const { return _cacheLineSize; } /** * Serialize this object to the given output stream. diff --git a/src/cpu/minor/fetch1.hh b/src/cpu/minor/fetch1.hh index f6a796ce82..b65bb70d7b 100644 --- a/src/cpu/minor/fetch1.hh +++ b/src/cpu/minor/fetch1.hh @@ -213,13 +213,13 @@ class Fetch1 : public Named /** Line snap size in bytes. All fetches clip to make their ends not * extend beyond this limit. Setting this to the machine L1 cache line * length will result in fetches never crossing line boundaries. */ - unsigned int lineSnap; + Addr lineSnap; /** Maximum fetch width in bytes. Setting this (and lineSnap) to the * machine L1 cache line length will result in fetches of whole cache * lines. Setting this to sizeof(MachInst) will result it fetches of * single instructions (except near the end of lineSnap lines) */ - unsigned int maxLineWidth; + Addr maxLineWidth; /** Maximum number of fetches allowed in flight (in queues or memory) */ unsigned int fetchLimit; diff --git a/src/cpu/minor/lsq.hh b/src/cpu/minor/lsq.hh index 4d7c351e7a..e30a615803 100644 --- a/src/cpu/minor/lsq.hh +++ b/src/cpu/minor/lsq.hh @@ -548,7 +548,7 @@ class LSQ : public Named const unsigned int inMemorySystemLimit; /** Memory system access width (and snap) in bytes */ - const unsigned int lineWidth; + const Addr lineWidth; public: /** The LSQ consists of three queues: requests, transfers and the diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 6add31444d..2c6da6708a 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -470,7 +470,7 @@ class Fetch ThreadID retryTid; /** Cache block size. */ - unsigned int cacheBlkSize; + Addr cacheBlkSize; /** The size of the fetch buffer in bytes. The fetch buffer * itself may be smaller than a cache line. diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index 3fd1674191..1aa170b2db 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -142,7 +142,7 @@ class MemTest : public ClockedObject // store the expected value for the addresses we have touched std::unordered_map referenceData; - const unsigned blockSize; + const Addr blockSize; const Addr blockAddrMask; diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc index d5c6b4fb3c..336a13beda 100644 --- a/src/cpu/trace/trace_cpu.cc +++ b/src/cpu/trace/trace_cpu.cc @@ -585,7 +585,7 @@ TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr) // stat counting this is useful to keep a check on how frequently this // happens. If required the code could be revised to mimick splitting such // a request into two. - unsigned blk_size = owner.cacheLineSize; + Addr blk_size = owner.cacheLineSize; Addr blk_offset = (node_ptr->physAddr & (Addr)(blk_size - 1)); if (!(blk_offset + node_ptr->size <= blk_size)) { node_ptr->size = blk_size - blk_offset; diff --git a/src/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh index d54b3c4227..cd32230aca 100644 --- a/src/cpu/trace/trace_cpu.hh +++ b/src/cpu/trace/trace_cpu.hh @@ -286,7 +286,7 @@ class TraceCPU : public ClockedObject }; /** Cache the cache line size that we get from the system */ - const unsigned int cacheLineSize; + const Addr cacheLineSize; /** Port to connect to L1 instruction cache. */ IcachePort icachePort; diff --git a/src/dev/dma_device.hh b/src/dev/dma_device.hh index 92b44bf5f6..3fd77860f4 100644 --- a/src/dev/dma_device.hh +++ b/src/dev/dma_device.hh @@ -187,7 +187,7 @@ class DmaPort : public RequestPort, public Drainable /** Default substreamId */ const uint32_t defaultSSid; - const int cacheLineSize; + const Addr cacheLineSize; protected: @@ -257,7 +257,7 @@ class DmaDevice : public PioDevice void init() override; - unsigned int cacheBlockSize() const { return sys->cacheLineSize(); } + Addr cacheBlockSize() const { return sys->cacheLineSize(); } Port &getPort(const std::string &if_name, PortID idx=InvalidPortID) override; @@ -526,7 +526,7 @@ class DmaReadFifo : public Drainable, public Serializable DmaPort &port; - const int cacheLineSize; + const Addr cacheLineSize; private: class DmaDoneEvent : public Event diff --git a/src/learning_gem5/part2/simple_cache.hh b/src/learning_gem5/part2/simple_cache.hh index 25d195d4f1..1ca87dd126 100644 --- a/src/learning_gem5/part2/simple_cache.hh +++ b/src/learning_gem5/part2/simple_cache.hh @@ -267,7 +267,7 @@ class SimpleCache : public ClockedObject const Cycles latency; /// The block size for the cache - const unsigned blockSize; + const Addr blockSize; /// Number of blocks in the cache (size of cache / block size) const unsigned capacity; diff --git a/src/mem/snoop_filter.hh b/src/mem/snoop_filter.hh index 7d4a222874..23cf77fcdd 100644 --- a/src/mem/snoop_filter.hh +++ b/src/mem/snoop_filter.hh @@ -302,7 +302,7 @@ class SnoopFilter : public SimObject /** Track the mapping from port ids to the local mask ids. */ std::vector localResponsePortIds; /** Cache line size. */ - const unsigned linesize; + const Addr linesize; /** Latency for doing a lookup in the filter */ const Cycles lookupLatency; /** Max capacity in terms of cache blocks tracked, for sanity checking */ From 516dcf3bcd24dfcae843b35e2c6c43f4e7dfe1ef Mon Sep 17 00:00:00 2001 From: Marco Kurzynski Date: Wed, 20 Sep 2023 21:42:56 +0000 Subject: [PATCH 337/693] configs: Fixed Typo Fixed a typo importing obtain_resource Change-Id: I5792ca161187c6576e2501e5aaea610d8b8ee5ea --- configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py index f25ffb62f8..233efd92b8 100644 --- a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py +++ b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py @@ -52,7 +52,7 @@ from gem5.isas import ISA from gem5.coherence_protocol import CoherenceProtocol from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent -from gem5.resources.resoruce import obtain_resource +from gem5.resources.resource import obtain_resource # This simulation requires using KVM with gem5 compiled for X86 simulation # and with MESI_Two_Level cache coherence protocol. From 83374bdf999f96f933172e9c54e53d7ac97e60c0 Mon Sep 17 00:00:00 2001 From: Leo Redivo Date: Wed, 20 Sep 2023 15:28:49 -0700 Subject: [PATCH 338/693] misc: changed name get_default_disk_device to get_disk_device Change-Id: Ida9673445a4426ddedc8221010204bd2b71103a5 --- src/python/gem5/components/boards/arm_board.py | 2 +- src/python/gem5/components/boards/experimental/lupv_board.py | 2 +- src/python/gem5/components/boards/kernel_disk_workload.py | 2 +- src/python/gem5/components/boards/riscv_board.py | 2 +- src/python/gem5/components/boards/x86_board.py | 2 +- src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index ae4b84f859..db215bd029 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -354,7 +354,7 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): ) @overrides(KernelDiskWorkload) - def get_default_disk_device(self): + def get_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index 9136c5b797..51db66913a 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -535,7 +535,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def get_default_disk_device(self) -> str: + def get_disk_device(self) -> str: return "/dev/lda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 1ca70f8f3f..c8c6e58878 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -85,7 +85,7 @@ class KernelDiskWorkload: raise NotImplementedError @abstractmethod - def get_default_disk_device(self) -> str: + def get_disk_device(self) -> str: """ Set a default disk device, in case user does not specify a disk device. diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index c70216c52d..d0000daffa 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -467,7 +467,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def get_default_disk_device(self): + def get_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index a0db8da10f..01a0ac1f6b 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -296,7 +296,7 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): ] @overrides(KernelDiskWorkload) - def get_default_disk_device(self): + def get_disk_device(self): return "/dev/hda" @overrides(KernelDiskWorkload) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index bd7d0acc27..a4e639801d 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -539,7 +539,7 @@ class RISCVMatchedBoard( fdt.writeDtbFile(os.path.join(outdir, "device.dtb")) @overrides(KernelDiskWorkload) - def get_default_disk_device(self): + def get_disk_device(self): return "/dev/vda" @overrides(KernelDiskWorkload) From 5697bf26a86c34bfad8f4b9f454813b105842d2c Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Thu, 21 Sep 2023 04:29:05 +0000 Subject: [PATCH 339/693] arch-x86: make popx87 micro-op actually pop st(0) The popx87 micro-op did not in fact pop the st(0) floating-point register off the stack; it acted as a no-op. This patch fixes the bug by passing the spm=1 argument to PopX87's superclass to indicate the floating-point stack pointer should be incremented. GitHub issue: https://github.com/gem5/gem5/issues/344 Change-Id: I6e731882b6bcf8f0e06ebd2f66f673bf9da80717 --- src/arch/x86/isa/microops/fpop.isa | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa index 5365c587ec..b0b925f679 100644 --- a/src/arch/x86/isa/microops/fpop.isa +++ b/src/arch/x86/isa/microops/fpop.isa @@ -430,4 +430,6 @@ let {{ class Pop87(Fp0Op): code = '' op_class = 'IntAluOp' + def __init__(self): + super().__init__(spm=1) }}; From 7298ebd49b4eef335ec5b78709e74aad8931e261 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Thu, 21 Sep 2023 05:16:17 +0000 Subject: [PATCH 340/693] arch-x86: properly initialize the auxv platform string The auxv platform string was not copied to the same location that was pointed to by the value of AT_PLATFORM; instead, it was copied over the auxv random buffer. This patch fixes this by copying the auxv platform string to the right offset in the initial program stack. GitHub issue: https://github.com/gem5/gem5/issues/346 Change-Id: Ied4b660d5fc444a94acb97b799be0a3722438b5e --- src/arch/x86/process.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 6589ee821d..17cc7ba801 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -997,7 +997,8 @@ X86Process::argsInit(int pageSize, initVirtMem->write(auxv_array_end, zero); auxv_array_end += sizeof(zero); - initVirtMem->writeString(aux_data_base, platform.c_str()); + initVirtMem->writeString(aux_data_base + numRandomBytes, + platform.c_str()); copyStringArray(envp, envp_array_base, env_data_base, ByteOrder::little, *initVirtMem); From d297da3654d990cd9b0083ec003835f90c160db7 Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Thu, 21 Sep 2023 10:11:39 -0700 Subject: [PATCH 341/693] cpu: Add override to TraceCPU init function This introduces a fix that caused the clang compiler tests to fail here: https://github.com/gem5/gem5/actions/runs/6195015407 Change-Id: I48c61539f497976c038c6e8e379d00285e1c39c7 --- src/cpu/trace/trace_cpu.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh index d54b3c4227..3633ed332f 100644 --- a/src/cpu/trace/trace_cpu.hh +++ b/src/cpu/trace/trace_cpu.hh @@ -147,7 +147,7 @@ class TraceCPU : public ClockedObject public: TraceCPU(const TraceCPUParams ¶ms); - void init(); + void init() override; /** * Return totalOps as the number of committed micro-ops plus the From 391f62b2130285f096239e555541576502e5695d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 31 Aug 2023 10:26:45 -0700 Subject: [PATCH 342/693] misc: 'sim{out/err}' -> 'sim{out/err}.txt' By default, the --stderr-file and --stdout-file arguments were directing the simulator output to files named "simerr" and "simout" respectively if an output redirect was requested. A small annoyance is these files lack an extension meaning programs refuse to open them, or to do so without some additional effort. On many systems they are assumed to scripts. This patch adds the .txt extension to both, thus clearly indicating to other programs these are text files and can be opened to be read as such. Change-Id: Iff5af4a9e6966b4467d005a029dbf401099fbd35 --- ext/testlib/configuration.py | 4 ++-- src/python/m5/main.py | 4 ++-- src/systemc/tests/verify.py | 2 +- tests/gem5/dram_lowp/ref/{simout => simout.txt} | 0 tests/gem5/dram_lowp/test_dram_lowp.py | 4 +++- tests/gem5/insttest_se/ref/{simout => simout.txt} | 0 tests/gem5/insttest_se/test.py | 4 +++- .../ref/sparc64/{simout => simout.txt} | 0 tests/gem5/m5threads_test_atomic/test.py | 2 +- tests/gem5/stdlib/simulator/ref/{simout => simout.txt} | 0 tests/gem5/stdlib/simulator/test_event_event.py | 4 +++- tests/gem5/verifier.py | 2 +- util/plot_dram/dram_lat_mem_rd_plot.py | 8 ++++---- util/plot_dram/dram_sweep_plot.py | 8 +++++--- 14 files changed, 25 insertions(+), 17 deletions(-) rename tests/gem5/dram_lowp/ref/{simout => simout.txt} (100%) rename tests/gem5/insttest_se/ref/{simout => simout.txt} (100%) rename tests/gem5/m5threads_test_atomic/ref/sparc64/{simout => simout.txt} (100%) rename tests/gem5/stdlib/simulator/ref/{simout => simout.txt} (100%) diff --git a/ext/testlib/configuration.py b/ext/testlib/configuration.py index 600f0e13cc..f4d4d42440 100644 --- a/ext/testlib/configuration.py +++ b/ext/testlib/configuration.py @@ -318,8 +318,8 @@ def define_constants(constants): constants.supported_hosts = constants.supported_tags["host"] constants.tempdir_fixture_name = "tempdir" - constants.gem5_simulation_stderr = "simerr" - constants.gem5_simulation_stdout = "simout" + constants.gem5_simulation_stderr = "simerr.txt" + constants.gem5_simulation_stdout = "simout.txt" constants.gem5_simulation_stats = "stats.txt" constants.gem5_simulation_config_ini = "config.ini" constants.gem5_simulation_config_json = "config.json" diff --git a/src/python/m5/main.py b/src/python/m5/main.py index e07e9562ab..20dd7caad6 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -126,13 +126,13 @@ def parse_options(): option( "--stdout-file", metavar="FILE", - default="simout", + default="simout.txt", help="Filename for -r redirection [Default: %default]", ) option( "--stderr-file", metavar="FILE", - default="simerr", + default="simerr.txt", help="Filename for -e redirection [Default: %default]", ) option( diff --git a/src/systemc/tests/verify.py b/src/systemc/tests/verify.py index c0e072e3c2..acd9cb15e8 100755 --- a/src/systemc/tests/verify.py +++ b/src/systemc/tests/verify.py @@ -508,7 +508,7 @@ class VerifyPhase(TestPhaseBase): missing = [] log_file = ".".join([test.name, "log"]) log_path = gd.entry(log_file) - simout_path = os.path.join(out_dir, "simout") + simout_path = os.path.join(out_dir, "simout.txt") if not os.path.exists(simout_path): missing.append("log output") elif log_path: diff --git a/tests/gem5/dram_lowp/ref/simout b/tests/gem5/dram_lowp/ref/simout.txt similarity index 100% rename from tests/gem5/dram_lowp/ref/simout rename to tests/gem5/dram_lowp/ref/simout.txt diff --git a/tests/gem5/dram_lowp/test_dram_lowp.py b/tests/gem5/dram_lowp/test_dram_lowp.py index 2e146bbe46..ec38acacc1 100644 --- a/tests/gem5/dram_lowp/test_dram_lowp.py +++ b/tests/gem5/dram_lowp/test_dram_lowp.py @@ -26,7 +26,9 @@ from testlib import * -verifiers = (verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref", "simout")),) +verifiers = ( + verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref", "simout.txt")), +) gem5_verify_config( name="test-low_power-close_adaptive", diff --git a/tests/gem5/insttest_se/ref/simout b/tests/gem5/insttest_se/ref/simout.txt similarity index 100% rename from tests/gem5/insttest_se/ref/simout rename to tests/gem5/insttest_se/ref/simout.txt diff --git a/tests/gem5/insttest_se/test.py b/tests/gem5/insttest_se/test.py index a9991b7102..bf59382b52 100644 --- a/tests/gem5/insttest_se/test.py +++ b/tests/gem5/insttest_se/test.py @@ -41,7 +41,9 @@ else: for isa in test_progs: for binary in test_progs[isa]: ref_path = joinpath(getcwd(), "ref") - verifiers = (verifier.MatchStdoutNoPerf(joinpath(ref_path, "simout")),) + verifiers = ( + verifier.MatchStdoutNoPerf(joinpath(ref_path, "simout.txt")), + ) for cpu in cpu_types[isa]: gem5_verify_config( diff --git a/tests/gem5/m5threads_test_atomic/ref/sparc64/simout b/tests/gem5/m5threads_test_atomic/ref/sparc64/simout.txt similarity index 100% rename from tests/gem5/m5threads_test_atomic/ref/sparc64/simout rename to tests/gem5/m5threads_test_atomic/ref/sparc64/simout.txt diff --git a/tests/gem5/m5threads_test_atomic/test.py b/tests/gem5/m5threads_test_atomic/test.py index 531de83b2f..0af973bd14 100644 --- a/tests/gem5/m5threads_test_atomic/test.py +++ b/tests/gem5/m5threads_test_atomic/test.py @@ -45,7 +45,7 @@ url = config.resource_url + "/test-progs/pthreads/sparc64/" + binary test_atomic = DownloadedProgram(url, base_path, binary) verifiers = ( - verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref/sparc64/simout")), + verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref/sparc64/simout.txt")), ) for cpu in cpu_types: diff --git a/tests/gem5/stdlib/simulator/ref/simout b/tests/gem5/stdlib/simulator/ref/simout.txt similarity index 100% rename from tests/gem5/stdlib/simulator/ref/simout rename to tests/gem5/stdlib/simulator/ref/simout.txt diff --git a/tests/gem5/stdlib/simulator/test_event_event.py b/tests/gem5/stdlib/simulator/test_event_event.py index ed755c2e36..23204f0026 100644 --- a/tests/gem5/stdlib/simulator/test_event_event.py +++ b/tests/gem5/stdlib/simulator/test_event_event.py @@ -32,7 +32,9 @@ tests/gem5/configs/simple_binary_run.py to run a simple SE-mode simualation with different configurations of the BaseCPUProcessor. """ -verifiers = (verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref", "simout")),) +verifiers = ( + verifier.MatchStdoutNoPerf(joinpath(getcwd(), "ref", "simout.txt")), +) gem5_verify_config( diff --git a/tests/gem5/verifier.py b/tests/gem5/verifier.py index c725fc68b9..9bc5e8f8b5 100644 --- a/tests/gem5/verifier.py +++ b/tests/gem5/verifier.py @@ -84,7 +84,7 @@ class MatchGoldStandard(Verifier): """ def __init__( - self, standard_filename, ignore_regex=None, test_filename="simout" + self, standard_filename, ignore_regex=None, test_filename="simout.txt" ): """ :param standard_filename: The path of the standard file to compare diff --git a/util/plot_dram/dram_lat_mem_rd_plot.py b/util/plot_dram/dram_lat_mem_rd_plot.py index 0d0e8d052b..541fa9808c 100755 --- a/util/plot_dram/dram_lat_mem_rd_plot.py +++ b/util/plot_dram/dram_lat_mem_rd_plot.py @@ -47,7 +47,7 @@ import sys import re # This script is intended to post process and plot the output from -# running configs/dram/lat_mem_rd.py, as such it parses the simout and +# running configs/dram/lat_mem_rd.py, as such it parses the simout.txt and # stats.txt to get the relevant data points. def main(): @@ -62,9 +62,9 @@ def main(): exit(-1) try: - simout = open(sys.argv[1] + "/simout", "r") + simout = open(sys.argv[1] + "/simout.txt", "r") except IOError: - print("Failed to open ", sys.argv[1] + "/simout", " for reading") + print("Failed to open ", sys.argv[1] + "/simout.txt", " for reading") exit(-1) # Get the address ranges @@ -85,7 +85,7 @@ def main(): simout.close() if not got_ranges: - print("Failed to get address ranges, ensure simout is up-to-date") + print("Failed to get address ranges, ensure simout.txt is up-to-date") exit(-1) # Now parse the stats diff --git a/util/plot_dram/dram_sweep_plot.py b/util/plot_dram/dram_sweep_plot.py index 1350f7af77..89c0dda7da 100755 --- a/util/plot_dram/dram_sweep_plot.py +++ b/util/plot_dram/dram_sweep_plot.py @@ -79,9 +79,9 @@ def main(): exit(-1) try: - simout = open(sys.argv[2] + "/simout", "r") + simout = open(sys.argv[2] + "/simout.txt", "r") except IOError: - print("Failed to open ", sys.argv[2] + "/simout", " for reading") + print("Failed to open ", sys.argv[2] + "/simout.txt", " for reading") exit(-1) # Get the burst size, number of banks and the maximum stride from @@ -102,7 +102,9 @@ def main(): simout.close() if not got_sweep: - print("Failed to establish sweep details, ensure simout is up-to-date") + print( + "Failed to establish sweep details, ensure simout.txt is up-to-date" + ) exit(-1) # Now parse the stats From 5b41112e036b4d18f36e908dbc7412790d2767e4 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 19 Sep 2023 14:12:57 +0800 Subject: [PATCH 343/693] arch-riscv: Make RISC-V decodeInst overridable The change will allow developers to implement and decode their non-standard instructions to the CPU models Bug: 289467440 Test: None Change-Id: I67f4abc71596f819c1265e325784f51c8e9bb359 --- src/arch/riscv/decoder.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh index 6ce72ee35a..c827e85f90 100644 --- a/src/arch/riscv/decoder.hh +++ b/src/arch/riscv/decoder.hh @@ -60,7 +60,7 @@ class Decoder : public InstDecoder ExtMachInst emi; uint32_t machInst; - StaticInstPtr decodeInst(ExtMachInst mach_inst); + virtual StaticInstPtr decodeInst(ExtMachInst mach_inst); /// Decode a machine instruction. /// @param mach_inst The binary instruction to decode. From d55f8f271610c9ba821dccc4fc8e6b07e07b850c Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 19 Sep 2023 14:31:11 +0800 Subject: [PATCH 344/693] arch: Enable customized decoder class name Developers can make the own ISADesc action in the SConscript with their decoder class name. Change-Id: I011cf059642e178913e1f62df4e5c02401cc132e --- src/arch/isa_parser/isa_parser.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/arch/isa_parser/isa_parser.py b/src/arch/isa_parser/isa_parser.py index 5be50a11bf..ef035c5fcb 100755 --- a/src/arch/isa_parser/isa_parser.py +++ b/src/arch/isa_parser/isa_parser.py @@ -512,7 +512,7 @@ class InstObjParams(object): class ISAParser(Grammar): - def __init__(self, output_dir): + def __init__(self, output_dir, decoder_name="Decoder"): super().__init__() self.lex_kwargs["reflags"] = int(re.MULTILINE) self.output_dir = output_dir @@ -542,6 +542,9 @@ class ISAParser(Grammar): self.isa_name = None self.namespace = None + # decoder_name is class name for cpu decoder. + self.decoder_name = decoder_name + # The format stack. self.formatStack = Stack(NoFormat()) @@ -1231,7 +1234,7 @@ del wrap """ using namespace gem5; StaticInstPtr -%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst) +%(isa_name)s::%(decoder_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) { using namespace %(namespace)s; """ From 37b6824c4cfbfe35ba0f3463c58607940928ae00 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 18 Apr 2023 15:51:06 +0100 Subject: [PATCH 345/693] arch-arm: Fix disassembly for NZCV read/writes At the moment the instruction is disassembled as an integer operation: msrNZCV x547, x0 Instead of msr nzcv x0 Change-Id: I3f6576dccbe86db401c73747750ca3cfdf4055d5 Signed-off-by: Giacomo Travaglini --- src/arch/arm/isa/insts/data64.isa | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/arch/arm/isa/insts/data64.isa b/src/arch/arm/isa/insts/data64.isa index a617dc3ebb..87f87130ce 100644 --- a/src/arch/arm/isa/insts/data64.isa +++ b/src/arch/arm/isa/insts/data64.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2011-2013, 2016-2022 Arm Limited +// Copyright (c) 2011-2013, 2016-2023 Arm Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -335,13 +335,18 @@ let {{ decoder_output += RegMiscRegOp64Constructor.subst(mrsIop) exec_output += BasicExecute.subst(mrsIop) - buildDataXRegInst("mrsNZCV", 1, ''' + mrsNZCVCode = ''' CPSR cpsr = 0; cpsr.nz = CondCodesNZ; cpsr.c = CondCodesC; cpsr.v = CondCodesV; XDest = cpsr; - ''') + ''' + mrsNZCViop = ArmInstObjParams("mrs", "MrsNZCV64", + "RegMiscRegImmOp64", mrsNZCVCode) + header_output += RegMiscRegOp64Declare.subst(mrsNZCViop) + decoder_output += RegMiscRegOp64Constructor.subst(mrsNZCViop) + exec_output += BasicExecute.subst(mrsNZCViop) msrCode = msr_check_code + ''' MiscDest_ud = XOp1; @@ -382,12 +387,17 @@ let {{ exec_output += DvmInitiateAcc.subst(msrTlbiSIop) exec_output += DvmCompleteAcc.subst(msrTlbiSIop) - buildDataXRegInst("msrNZCV", 1, ''' + msrNZCVCode = ''' CPSR cpsr = XOp1; CondCodesNZ = cpsr.nz; CondCodesC = cpsr.c; CondCodesV = cpsr.v; - ''') + ''' + msrNZCVIop = ArmInstObjParams("msr", "MsrNZCV64", "MiscRegRegImmOp64", + msrNZCVCode) + header_output += MiscRegRegOp64Declare.subst(msrNZCVIop) + decoder_output += MiscRegRegOp64Constructor.subst(msrNZCVIop) + exec_output += BasicExecute.subst(msrNZCVIop) msrdczva_ea_code = msr_check_code From df60b0f5c941254d3e8a20035e1ec57255ce2423 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 17 Apr 2023 13:44:11 +0100 Subject: [PATCH 346/693] arch-arm: Implement FEAT_FGT Change-Id: I89391f17f353ab6ce555d65783977c1f30f64fc5 Signed-off-by: Giacomo Travaglini --- src/arch/arm/ArmSystem.py | 14 +- src/arch/arm/isa/insts/branch64.isa | 18 +- src/arch/arm/isa/insts/misc.isa | 9 +- src/arch/arm/isa/insts/misc64.isa | 26 +- src/arch/arm/regs/misc.cc | 490 ++++++++++++++++++++-------- src/arch/arm/regs/misc.hh | 15 +- src/arch/arm/regs/misc_types.hh | 114 ++++++- src/arch/arm/types.hh | 3 +- src/arch/arm/utility.cc | 10 +- src/arch/arm/utility.hh | 4 +- 10 files changed, 555 insertions(+), 148 deletions(-) diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index 40a3a04b90..3da9bdadcb 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -1,4 +1,4 @@ -# Copyright (c) 2009, 2012-2013, 2015-2022 ARM Limited +# Copyright (c) 2009, 2012-2013, 2015-2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -96,6 +96,8 @@ class ArmExtension(ScopedEnum): "FEAT_RNG", "FEAT_RNG_TRAP", "FEAT_EVT", + # Armv8.6 + "FEAT_FGT", # Armv8.7 "FEAT_HCX", # Armv9.2 @@ -186,6 +188,8 @@ class ArmDefaultRelease(Armv8): # Armv8.5 "FEAT_FLAGM2", "FEAT_EVT", + # Armv8.6 + "FEAT_FGT", # Armv8.7 "FEAT_HCX", # Armv9.2 @@ -239,8 +243,14 @@ class Armv85(Armv84): ] -class Armv87(Armv85): +class Armv86(Armv85): extensions = Armv85.extensions + [ + "FEAT_FGT", + ] + + +class Armv87(Armv86): + extensions = Armv86.extensions + [ "FEAT_HCX", ] diff --git a/src/arch/arm/isa/insts/branch64.isa b/src/arch/arm/isa/insts/branch64.isa index f437651af3..73ab70b5f1 100644 --- a/src/arch/arm/isa/insts/branch64.isa +++ b/src/arch/arm/isa/insts/branch64.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2011-2013, 2016, 2018, 2020 ARM Limited +// Copyright (c) 2011-2013, 2016, 2018, 2020, 2023 Arm Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -200,11 +200,19 @@ let {{ HtmFailureFaultCause::EXCEPTION); return fault; } + Addr newPc; CPSR cpsr = Cpsr; CPSR spsr = Spsr; ExceptionLevel curr_el = currEL(cpsr); + + if (fgtEnabled(xc->tcBase()) && curr_el == EL1 && + static_cast(xc->tcBase()->readMiscReg(MISCREG_HFGITR_EL2)).eret) { + return std::make_shared( + machInst, %(trap_iss)d, ExceptionClass::TRAPPED_ERET); + } + switch (curr_el) { case EL3: newPc = xc->tcBase()->readMiscReg(MISCREG_ELR_EL3); @@ -268,7 +276,7 @@ let {{ ''' instFlags = ['IsSerializeAfter', 'IsNonSpeculative', 'IsSquashAfter'] bIop = ArmInstObjParams('eret', 'Eret64', "BranchEret64", - bCode%{'op': ''}, instFlags) + bCode%{'op': '', 'trap_iss' : 0b00}, instFlags) header_output += BasicDeclare.subst(bIop) decoder_output += BasicConstructor64.subst(bIop) exec_output += BasicExecute.subst(bIop) @@ -278,7 +286,8 @@ let {{ fault = authIA(xc->tcBase(), newPc, XOp1, &newPc); ''' bIop = ArmInstObjParams('eretaa', 'Eretaa', "BranchEretA64", - bCode % {'op': pac_code} , instFlags) + bCode % {'op': pac_code, 'trap_iss' : 0b10}, + instFlags) header_output += BasicDeclare.subst(bIop) decoder_output += BasicConstructor64.subst(bIop) exec_output += BasicExecute.subst(bIop) @@ -288,7 +297,8 @@ let {{ fault = authIB(xc->tcBase(), newPc, XOp1, &newPc); ''' bIop = ArmInstObjParams('eretab', 'Eretab', "BranchEretA64", - bCode % {'op': pac_code} , instFlags) + bCode % {'op': pac_code, 'trap_iss' : 0b11}, + instFlags) header_output += BasicDeclare.subst(bIop) decoder_output += BasicConstructor64.subst(bIop) exec_output += BasicExecute.subst(bIop) diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index bfcb69340d..86e9e8943c 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2010-2013,2017-2021 Arm Limited +// Copyright (c) 2010-2013,2017-2021,2023 Arm Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -40,6 +40,13 @@ let {{ svcCode = ''' ThreadContext *tc = xc->tcBase(); + if (fgtEnabled(tc) && currEL(tc) == EL0 && !ELIsInHost(tc, EL0) && + ELIs64(tc, EL1) && static_cast( + tc->readMiscReg(MISCREG_HFGITR_EL2)).svcEL0) { + return std::make_shared( + machInst, imm, ExceptionClass::SVC); + } + bool have_semi = ArmSystem::haveSemihosting(tc); if (have_semi && Thumb && imm == ArmSemihosting::T32Imm) { // Enable gem5 extensions since we can't distinguish in thumb. diff --git a/src/arch/arm/isa/insts/misc64.isa b/src/arch/arm/isa/insts/misc64.isa index 46d72d21c3..5678195415 100644 --- a/src/arch/arm/isa/insts/misc64.isa +++ b/src/arch/arm/isa/insts/misc64.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2011-2013, 2016-2018, 2020-2021 Arm Limited +// Copyright (c) 2011-2013, 2016-2018, 2020-2021, 2023 Arm Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -43,7 +43,29 @@ let {{ HtmFailureFaultCause::EXCEPTION); return fault; } - fault = std::make_shared(machInst, bits(machInst, 20, 5)); + + const uint32_t iss = bits(machInst, 20, 5); + if (fgtEnabled(xc->tcBase())) { + ExceptionLevel curr_el = currEL(xc->tcBase()); + HFGITR hfgitr = xc->tcBase()->readMiscReg(MISCREG_HFGITR_EL2); + switch (curr_el) { + case EL0: + if (!ELIsInHost(xc->tcBase(), curr_el) && hfgitr.svcEL0) { + return std::make_shared( + machInst, iss, ExceptionClass::SVC_64); + } + break; + case EL1: + if (hfgitr.svcEL1) { + return std::make_shared( + machInst, iss, ExceptionClass::SVC_64); + } + break; + default: + break; + } + } + fault = std::make_shared(machInst, iss); ''' svcIop = ArmInstObjParams("svc", "Svc64", "ImmOp64", diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index f1c69cc007..25993829a3 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -1114,6 +1114,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 4, 1, 1, 3), MISCREG_HSTR_EL2 }, { MiscRegNum64(3, 4, 1, 1, 4), MISCREG_HFGRTR_EL2 }, { MiscRegNum64(3, 4, 1, 1, 5), MISCREG_HFGWTR_EL2 }, + { MiscRegNum64(3, 4, 1, 1, 6), MISCREG_HFGITR_EL2 }, { MiscRegNum64(3, 4, 1, 1, 7), MISCREG_HACR_EL2 }, { MiscRegNum64(3, 4, 1, 2, 0), MISCREG_ZCR_EL2 }, { MiscRegNum64(3, 4, 1, 2, 2), MISCREG_HCRX_EL2 }, @@ -1249,6 +1250,164 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 7, 14, 2, 2), MISCREG_CNTPS_CVAL_EL1 } }; +template +HFGTR +fgtRegister(ThreadContext *tc) +{ + if constexpr (read) { + return tc->readMiscReg(MISCREG_HFGRTR_EL2); + } else { + return tc->readMiscReg(MISCREG_HFGWTR_EL2); + } +} + +/** + * Template helper for fine grained traps at EL0 + * + * @tparam read: is this a read access to the register? + * @tparam r_bitfield: register (HFGTR) bitfield + */ +template +Fault +faultFgtEL0(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + const bool in_host = EL2Enabled(tc) && hcr.e2h && hcr.tge; + if (fgtEnabled(tc) && !in_host && + fgtRegister(tc).*r_bitfield) { + return inst.generateTrap(EL2); + } else { + return NoFault; + } +} + +/** + * Template helper for fine grained traps at EL1 + * + * @tparam read: is this a read access to the register? + * @tparam r_bitfield: register (HFGTR) bitfield + */ +template +Fault +faultFgtEL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (fgtEnabled(tc) && fgtRegister(tc).*r_bitfield) { + return inst.generateTrap(EL2); + } else { + return NoFault; + } +} + +/** + * Template helper for fine grained traps at EL1 + * + * @tparam r_bitfield: register (HFGITR) bitfield + */ +template +Fault +faultFgtInstEL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (fgtEnabled(tc) && + static_cast(tc->readMiscReg(MISCREG_HFGITR_EL2)).*r_bitfield) { + return inst.generateTrap(EL2); + } else { + return NoFault; + } +} + +/** + * Template helper for fine grained traps at EL1 + * + * @tparam g_bitfield: group (HCR) bitfield + */ +template +Fault +faultHcrEL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (EL2Enabled(tc) && hcr.*g_bitfield) { + return inst.generateTrap(EL2); + } else { + return NoFault; + } +} + +/** + * Template helper for fine grained traps at EL0 + * + * @tparam read: is this a read access to the register? + * @tparam g_bitfield: group (HCR) bitfield + * @tparam r_bitfield: register (HFGTR) bitfield + */ +template +Fault +faultHcrFgtEL0(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + const bool in_host = EL2Enabled(tc) && hcr.e2h && hcr.tge; + + if (EL2Enabled(tc) && !in_host && hcr.*g_bitfield) { + return inst.generateTrap(EL2); + } else if (auto fault = faultFgtEL0(entry, tc, inst); + fault != NoFault) { + return fault; + } else { + return NoFault; + } +} + +/** + * Template helper for fine grained traps at EL1 + * + * @tparam read: is this a read access to the register? + * @tparam g_bitfield: group (HCR) bitfield + * @tparam r_bitfield: register (HFGTR) bitfield + */ +template +Fault +faultHcrFgtEL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + if (EL2Enabled(tc) && hcr.*g_bitfield) { + return inst.generateTrap(EL2); + } else if (auto fault = faultFgtEL1(entry, tc, inst); + fault != NoFault) { + return fault; + } else { + return NoFault; + } +} + +/** + * Template helper for fine grained traps at EL1 + * + * @tparam g_bitfield: group (HCR) bitfield + * @tparam r_bitfield: register (HFGITR) bitfield + */ +template +Fault +faultHcrFgtInstEL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + if (EL2Enabled(tc) && hcr.*g_bitfield) { + return inst.generateTrap(EL2); + } else if (auto fault = faultFgtInstEL1(entry, tc, inst); + fault != NoFault) { + return fault; + } else { + return NoFault; + } +} + Fault faultSpEL0(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -1455,6 +1614,7 @@ faultPouEL0(const MiscRegLUTEntry &entry, } } +template Fault faultPouEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -1466,11 +1626,15 @@ faultPouEL1(const MiscRegLUTEntry &entry, } else if (el2_enabled && HaveExt(tc, ArmExtension::FEAT_EVT) && hcr.tocu) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtInstEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else { return NoFault; } } +template Fault faultPouIsEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -1482,6 +1646,9 @@ faultPouIsEL1(const MiscRegLUTEntry &entry, } else if (el2_enabled && HaveExt(tc, ArmExtension::FEAT_EVT) && hcr.ticab) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtInstEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else { return NoFault; } @@ -1503,8 +1670,10 @@ faultCtrEL0(const MiscRegLUTEntry &entry, } else { return inst.generateTrap(EL1); } - } else if (el2_enabled && !in_host && hcr.tid2) { - return inst.generateTrap(EL2); + } else if (auto fault = faultHcrFgtEL0< + true, &HCR::tid2, &HFGTR::ctrEL0>(entry, tc, inst); + fault != NoFault) { + return fault; } else if (el2_enabled && in_host && !sctlr2.uct) { return inst.generateTrap(EL2); } else { @@ -1714,14 +1883,20 @@ faultIccSgiEL2(const MiscRegLUTEntry &entry, } } +template Fault faultCpacrEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) { const CPTR cptr_el2 = tc->readMiscReg(MISCREG_CPTR_EL2); const CPTR cptr_el3 = tc->readMiscReg(MISCREG_CPTR_EL3); - if (EL2Enabled(tc) && cptr_el2.tcpac) { + + const bool el2_enabled = EL2Enabled(tc); + if (el2_enabled && cptr_el2.tcpac) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else if (ArmSystem::haveEL(tc, EL3) && cptr_el3.tcpac) { return inst.generateTrap(EL3); } else { @@ -1753,17 +1928,7 @@ faultCpacrVheEL2(const MiscRegLUTEntry &entry, } } -#define HCR_TRAP(bitfield) [] (const MiscRegLUTEntry &entry, \ - ThreadContext *tc, const MiscRegOp64 &inst) -> Fault \ -{ \ - const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); \ - if (EL2Enabled(tc) && hcr.bitfield) { \ - return inst.generateTrap(EL2); \ - } else { \ - return NoFault; \ - } \ -} - +template Fault faultTlbiOsEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -1775,11 +1940,15 @@ faultTlbiOsEL1(const MiscRegLUTEntry &entry, } else if (el2_enabled && HaveExt(tc, ArmExtension::FEAT_EVT) && hcr.ttlbos) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtInstEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else { return NoFault; } } +template Fault faultTlbiIsEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -1791,11 +1960,15 @@ faultTlbiIsEL1(const MiscRegLUTEntry &entry, } else if (el2_enabled && HaveExt(tc, ArmExtension::FEAT_EVT) && hcr.ttlbis) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtInstEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else { return NoFault; } } +template Fault faultCacheEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -1807,19 +1980,28 @@ faultCacheEL1(const MiscRegLUTEntry &entry, } else if (el2_enabled && HaveExt(tc, ArmExtension::FEAT_EVT) && hcr.tid4) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else { return NoFault; } } +template Fault faultPauthEL1(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) { const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); - if (EL2Enabled(tc) && !hcr.apk) { + const bool el2_enabled = EL2Enabled(tc); + + if (el2_enabled && !hcr.apk) { return inst.generateTrap(EL2); + } else if (auto fault = faultFgtEL1(entry, tc, inst); + fault != NoFault) { + return fault; } else if (ArmSystem::haveEL(tc, EL3) && !scr.apk) { return inst.generateTrap(EL3); } else { @@ -2140,6 +2322,22 @@ faultRng(const MiscRegLUTEntry &entry, } } +Fault +faultFgtCtrlRegs(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_FGT)) { + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + if (ArmSystem::haveEL(tc, EL3) && !scr.fgten) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } +} + Fault faultIdst(const MiscRegLUTEntry &entry, ThreadContext *tc, const MiscRegOp64 &inst) @@ -3908,108 +4106,110 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_MIDR_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) + .faultRead(EL1, faultFgtEL1) .mapsTo(MISCREG_MIDR); InitReg(MISCREG_MPIDR_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) + .faultRead(EL1, faultFgtEL1) .mapsTo(MISCREG_MPIDR); InitReg(MISCREG_REVIDR_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid1)) + .faultRead(EL1, faultHcrFgtEL1) .allPrivileges().exceptUserMode().writes(0); InitReg(MISCREG_ID_PFR0_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_PFR0); InitReg(MISCREG_ID_PFR1_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_PFR1); InitReg(MISCREG_ID_DFR0_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_DFR0); InitReg(MISCREG_ID_AFR0_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_AFR0); InitReg(MISCREG_ID_MMFR0_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_MMFR0); InitReg(MISCREG_ID_MMFR1_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_MMFR1); InitReg(MISCREG_ID_MMFR2_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_MMFR2); InitReg(MISCREG_ID_MMFR3_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_MMFR3); InitReg(MISCREG_ID_MMFR4_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_MMFR4); InitReg(MISCREG_ID_ISAR0_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR0); InitReg(MISCREG_ID_ISAR1_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR1); InitReg(MISCREG_ID_ISAR2_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR2); InitReg(MISCREG_ID_ISAR3_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR3); InitReg(MISCREG_ID_ISAR4_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR4); InitReg(MISCREG_ID_ISAR5_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR5); InitReg(MISCREG_ID_ISAR6_EL1) .allPrivileges().exceptUserMode().writes(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .mapsTo(MISCREG_ID_ISAR6); InitReg(MISCREG_MVFR0_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().exceptUserMode().writes(0) .mapsTo(MISCREG_MVFR0); InitReg(MISCREG_MVFR1_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().exceptUserMode().writes(0) .mapsTo(MISCREG_MVFR1); InitReg(MISCREG_MVFR2_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().exceptUserMode().writes(0); InitReg(MISCREG_ID_AA64PFR0_EL1) .reset([this,release=release,tc=tc](){ @@ -4025,14 +4225,14 @@ ISA::initializeMiscRegMetadata() }()) .unserialize(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64PFR1_EL1) .reset(release->has(ArmExtension::FEAT_SME) ? 0x1 << 24 : 0) .unserialize(0) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64DFR0_EL1) .reset([p](){ @@ -4041,22 +4241,22 @@ ISA::initializeMiscRegMetadata() return dfr0_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64DFR1_EL1) .reset(p.id_aa64dfr1_el1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64AFR0_EL1) .reset(p.id_aa64afr0_el1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64AFR1_EL1) .reset(p.id_aa64afr1_el1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64ISAR0_EL1) .reset([p,release=release](){ @@ -4084,7 +4284,7 @@ ISA::initializeMiscRegMetadata() return isar0_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64ISAR1_EL1) .reset([p,release=release](){ @@ -4097,7 +4297,7 @@ ISA::initializeMiscRegMetadata() return isar1_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64MMFR0_EL1) .reset([p,asidbits=haveLargeAsid64,parange=physAddrRange](){ @@ -4107,7 +4307,7 @@ ISA::initializeMiscRegMetadata() return mmfr0_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64MMFR1_EL1) .reset([p,release=release](){ @@ -4120,7 +4320,7 @@ ISA::initializeMiscRegMetadata() return mmfr1_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_ID_AA64MMFR2_EL1) .reset([p,release=release](){ @@ -4132,73 +4332,86 @@ ISA::initializeMiscRegMetadata() return mmfr2_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_APDAKeyHi_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APDAKeyLo_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APDBKeyHi_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APDBKeyLo_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APGAKeyHi_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APGAKeyLo_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APIAKeyHi_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APIAKeyLo_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APIBKeyHi_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_APIBKeyLo_EL1) - .fault(EL1, faultPauthEL1) + .faultRead(EL1, faultPauthEL1) + .faultWrite(EL1, faultPauthEL1) .fault(EL2, faultPauthEL2) .allPrivileges().exceptUserMode(); InitReg(MISCREG_CCSIDR_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, faultCacheEL1) + .faultRead(EL1, faultCacheEL1) .allPrivileges().writes(0); InitReg(MISCREG_CLIDR_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, faultCacheEL1) + .faultRead(EL1, faultCacheEL1) .allPrivileges().writes(0); InitReg(MISCREG_AIDR_EL1) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid1)) + .faultRead(EL1, faultHcrFgtEL1) .allPrivileges().writes(0); InitReg(MISCREG_CSSELR_EL1) .allPrivileges().exceptUserMode() - .fault(EL1, faultCacheEL1) + .faultRead(EL1, faultCacheEL1) + .faultWrite(EL1, faultCacheEL1) .mapsTo(MISCREG_CSSELR_NS); InitReg(MISCREG_CTR_EL0) .faultRead(EL0, faultCtrEL0) - .faultRead(EL1, HCR_TRAP(tid2)) + .faultRead(EL1, faultHcrFgtEL1) .reads(1) .mapsTo(MISCREG_CTR); InitReg(MISCREG_DCZID_EL0) .reset(0x04) // DC ZVA clear 64-byte chunks + .faultRead(EL0, faultFgtEL0) + .faultRead(EL1, faultFgtEL1) .reads(1); InitReg(MISCREG_VPIDR_EL2) .hyp().mon() @@ -4210,8 +4423,8 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_VMPIDR); InitReg(MISCREG_SCTLR_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .res0( 0x20440 | (EnDB ? 0 : 0x2000) | (IESB ? 0 : 0x200000) | (EnDA ? 0 : 0x8000000) @@ -4235,11 +4448,12 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_SCTLR_EL1); InitReg(MISCREG_ACTLR_EL1) .allPrivileges().exceptUserMode() - .fault(EL1, HCR_TRAP(tacr)) + .fault(EL1, faultHcrEL1<&HCR::tacr>) .mapsTo(MISCREG_ACTLR_NS); InitReg(MISCREG_CPACR_EL1) .allPrivileges().exceptUserMode() - .fault(EL1, faultCpacrEL1) + .faultRead(EL1, faultCpacrEL1) + .faultWrite(EL1, faultCpacrEL1) .fault(EL2, faultCpacrEL2) .mapsTo(MISCREG_CPACR); InitReg(MISCREG_CPACR_EL12) @@ -4302,8 +4516,8 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_SDCR); InitReg(MISCREG_TTBR0_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_TTBR0_NS); InitReg(MISCREG_TTBR0_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4311,8 +4525,8 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_TTBR0_EL1); InitReg(MISCREG_TTBR1_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_TTBR1_NS); InitReg(MISCREG_TTBR1_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4320,8 +4534,8 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_TTBR1_EL1); InitReg(MISCREG_TCR_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_TTBCR_NS); InitReg(MISCREG_TCR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4424,8 +4638,8 @@ ISA::initializeMiscRegMetadata() .mon(); InitReg(MISCREG_AFSR0_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_ADFSR_NS); InitReg(MISCREG_AFSR0_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4433,16 +4647,16 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_ADFSR_NS); InitReg(MISCREG_AFSR1_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_AIFSR_NS); InitReg(MISCREG_AFSR1_EL12) .fault(EL2, defaultFaultE2H_EL2) .fault(EL3, defaultFaultE2H_EL3) .mapsTo(MISCREG_AIFSR_NS); InitReg(MISCREG_ESR_EL1) - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .allPrivileges().exceptUserMode(); InitReg(MISCREG_ESR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4472,8 +4686,8 @@ ISA::initializeMiscRegMetadata() .mon(); InitReg(MISCREG_FAR_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_DFAR_NS, MISCREG_IFAR_NS); InitReg(MISCREG_FAR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4489,61 +4703,61 @@ ISA::initializeMiscRegMetadata() .mon(); InitReg(MISCREG_IC_IALLUIS) .warnNotFail() - .faultWrite(EL1, faultPouIsEL1) + .faultWrite(EL1, faultPouIsEL1<&HFGITR::icialluis>) .writes(1).exceptUserMode(); InitReg(MISCREG_PAR_EL1) .allPrivileges().exceptUserMode() .mapsTo(MISCREG_PAR_NS); InitReg(MISCREG_IC_IALLU) .warnNotFail() - .faultWrite(EL1, faultPouEL1) + .faultWrite(EL1, faultPouEL1<&HFGITR::iciallu>) .writes(1).exceptUserMode(); InitReg(MISCREG_DC_IVAC_Xt) - .faultWrite(EL1, HCR_TRAP(tpc)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::tpc, &HFGITR::dcivac>) .writes(1).exceptUserMode(); InitReg(MISCREG_DC_ISW_Xt) .warnNotFail() - .faultWrite(EL1, HCR_TRAP(tsw)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::tsw, &HFGITR::dcisw>) .writes(1).exceptUserMode(); InitReg(MISCREG_AT_S1E1R_Xt) - .faultWrite(EL1, HCR_TRAP(at)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::at, &HFGITR::ats1e1r>) .writes(1).exceptUserMode(); InitReg(MISCREG_AT_S1E1W_Xt) - .faultWrite(EL1, HCR_TRAP(at)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::at, &HFGITR::ats1e1w>) .writes(1).exceptUserMode(); InitReg(MISCREG_AT_S1E0R_Xt) - .faultWrite(EL1, HCR_TRAP(at)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::at, &HFGITR::ats1e0r>) .writes(1).exceptUserMode(); InitReg(MISCREG_AT_S1E0W_Xt) - .faultWrite(EL1, HCR_TRAP(at)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::at, &HFGITR::ats1e0w>) .writes(1).exceptUserMode(); InitReg(MISCREG_DC_CSW_Xt) .warnNotFail() - .faultWrite(EL1, HCR_TRAP(tsw)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::tsw, &HFGITR::dccsw>) .writes(1).exceptUserMode(); InitReg(MISCREG_DC_CISW_Xt) .warnNotFail() - .faultWrite(EL1, HCR_TRAP(tsw)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::tsw, &HFGITR::dccisw>) .writes(1).exceptUserMode(); InitReg(MISCREG_DC_ZVA_Xt) .writes(1) .faultWrite(EL0, faultDczvaEL0) - .faultWrite(EL1, HCR_TRAP(tdz)); + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::tdz, &HFGITR::dczva>); InitReg(MISCREG_IC_IVAU_Xt) .faultWrite(EL0, faultPouEL0) - .faultWrite(EL1, faultPouEL1) + .faultWrite(EL1, faultPouEL1<&HFGITR::icivau>) .writes(1); InitReg(MISCREG_DC_CVAC_Xt) .faultWrite(EL0, faultCvacEL0) - .faultWrite(EL1, HCR_TRAP(tpc)) + .faultWrite(EL1, faultHcrEL1<&HCR::tpc>) .writes(1); InitReg(MISCREG_DC_CVAU_Xt) .faultWrite(EL0, faultPouEL0) - .faultWrite(EL1, faultPouEL1) + .faultWrite(EL1, faultPouEL1<&HFGITR::dccvau>) .writes(1); InitReg(MISCREG_DC_CIVAC_Xt) .faultWrite(EL0, faultCvacEL0) - .faultWrite(EL1, HCR_TRAP(tpc)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::tpc, &HFGITR::dccivac>) .writes(1); InitReg(MISCREG_AT_S1E2R_Xt) .monNonSecureWrite().hypWrite(); @@ -4562,58 +4776,58 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_AT_S1E3W_Xt) .monSecureWrite().monNonSecureWrite(); InitReg(MISCREG_TLBI_VMALLE1OS) - .faultWrite(EL1, faultTlbiOsEL1) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbivmalle1os>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAE1OS_Xt) - .faultWrite(EL1, faultTlbiOsEL1) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbivae1os>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_ASIDE1OS_Xt) - .faultWrite(EL1, faultTlbiOsEL1) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbiaside1os>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAAE1OS_Xt) - .faultWrite(EL1, faultTlbiOsEL1) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbivaae1os>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VALE1OS_Xt) - .faultWrite(EL1, faultTlbiOsEL1) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbivale1os>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAALE1OS_Xt) - .faultWrite(EL1, faultTlbiOsEL1) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbivaale1os>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VMALLE1IS) - .faultWrite(EL1, faultTlbiIsEL1) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbivmalle1is>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAE1IS_Xt) - .faultWrite(EL1, faultTlbiIsEL1) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbivae1is>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_ASIDE1IS_Xt) - .faultWrite(EL1, faultTlbiIsEL1) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbiaside1is>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAAE1IS_Xt) - .faultWrite(EL1, faultTlbiIsEL1) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbivaae1is>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VALE1IS_Xt) - .faultWrite(EL1, faultTlbiIsEL1) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbivale1is>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAALE1IS_Xt) - .faultWrite(EL1, faultTlbiIsEL1) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbivaale1is>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VMALLE1) - .faultWrite(EL1, HCR_TRAP(ttlb)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbivmalle1>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAE1_Xt) - .faultWrite(EL1, HCR_TRAP(ttlb)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbivae1>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_ASIDE1_Xt) - .faultWrite(EL1, HCR_TRAP(ttlb)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbiaside1>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAAE1_Xt) - .faultWrite(EL1, HCR_TRAP(ttlb)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbivaae1>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VALE1_Xt) - .faultWrite(EL1, HCR_TRAP(ttlb)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbivale1>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_VAALE1_Xt) - .faultWrite(EL1, HCR_TRAP(ttlb)) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbivaale1>) .writes(1).exceptUserMode(); InitReg(MISCREG_TLBI_IPAS2E1OS_Xt) .hypWrite().monSecureWrite().monNonSecureWrite(); @@ -4724,8 +4938,8 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_PMOVSSET); InitReg(MISCREG_MAIR_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_PRRR_NS, MISCREG_NMRR_NS); InitReg(MISCREG_MAIR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4733,8 +4947,8 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_PRRR_NS, MISCREG_NMRR_NS); InitReg(MISCREG_AMAIR_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_AMAIR0_NS, MISCREG_AMAIR1_NS); InitReg(MISCREG_AMAIR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4756,6 +4970,8 @@ ISA::initializeMiscRegMetadata() .allPrivileges().exceptUserMode(); InitReg(MISCREG_VBAR_EL1) .allPrivileges().exceptUserMode() + .faultRead(EL1, faultFgtEL1) + .faultWrite(EL1, faultFgtEL1) .mapsTo(MISCREG_VBAR_NS); InitReg(MISCREG_VBAR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4785,8 +5001,8 @@ ISA::initializeMiscRegMetadata() .mon(); InitReg(MISCREG_CONTEXTIDR_EL1) .allPrivileges().exceptUserMode() - .faultRead(EL1, HCR_TRAP(trvm)) - .faultWrite(EL1, HCR_TRAP(tvm)) + .faultRead(EL1, faultHcrFgtEL1) + .faultWrite(EL1, faultHcrFgtEL1) .mapsTo(MISCREG_CONTEXTIDR_NS); InitReg(MISCREG_CONTEXTIDR_EL12) .fault(EL2, defaultFaultE2H_EL2) @@ -4794,12 +5010,21 @@ ISA::initializeMiscRegMetadata() .mapsTo(MISCREG_CONTEXTIDR_NS); InitReg(MISCREG_TPIDR_EL1) .allPrivileges().exceptUserMode() + .faultRead(EL1, faultFgtEL1) + .faultWrite(EL1, faultFgtEL1) .mapsTo(MISCREG_TPIDRPRW_NS); InitReg(MISCREG_TPIDR_EL0) .allPrivileges() + .faultRead(EL0, faultFgtEL0) + .faultWrite(EL0, faultFgtEL0) + .faultRead(EL1, faultFgtEL1) + .faultWrite(EL1, faultFgtEL1) .mapsTo(MISCREG_TPIDRURW_NS); InitReg(MISCREG_TPIDRRO_EL0) .allPrivileges().userNonSecureWrite(0).userSecureWrite(0) + .faultRead(EL0, faultFgtEL0) + .faultRead(EL1, faultFgtEL1) + .faultWrite(EL1, faultFgtEL1) .mapsTo(MISCREG_TPIDRURO_NS); InitReg(MISCREG_TPIDR_EL2) .hyp().mon() @@ -5187,9 +5412,13 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_ICC_IGRPEN0_EL1) .res0(0xFFFFFFFE) // [31:1] .allPrivileges().exceptUserMode() + .faultRead(EL1, faultFgtEL1) + .faultWrite(EL1, faultFgtEL1) .mapsTo(MISCREG_ICC_IGRPEN0); InitReg(MISCREG_ICC_IGRPEN1_EL1) .banked64() + .faultRead(EL1, faultFgtEL1) + .faultWrite(EL1, faultFgtEL1) .mapsTo(MISCREG_ICC_IGRPEN1); InitReg(MISCREG_ICC_IGRPEN1_EL1_NS) .bankedChild() @@ -5502,7 +5731,7 @@ ISA::initializeMiscRegMetadata() return zfr0_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().exceptUserMode().writes(0); InitReg(MISCREG_ZCR_EL3) .reset(sveVL - 1) @@ -5542,7 +5771,7 @@ ISA::initializeMiscRegMetadata() return smfr0_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid3)) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); InitReg(MISCREG_SVCR) .res0([](){ @@ -5565,7 +5794,7 @@ ISA::initializeMiscRegMetadata() return smidr_el1; }()) .faultRead(EL0, faultIdst) - .faultRead(EL1, HCR_TRAP(tid1)) + .faultRead(EL1, faultHcrEL1<&HCR::tid1>) .allPrivileges().writes(0); InitReg(MISCREG_SMPRI_EL1) .res0(mask(63, 4)) @@ -5644,6 +5873,17 @@ ISA::initializeMiscRegMetadata() .unverifiable() .allPrivileges().writes(0); + // FEAT_FGT extension + InitReg(MISCREG_HFGRTR_EL2) + .fault(EL2, faultFgtCtrlRegs) + .hyp().mon(release->has(ArmExtension::FEAT_FGT)); + InitReg(MISCREG_HFGWTR_EL2) + .fault(EL2, faultFgtCtrlRegs) + .hyp().mon(release->has(ArmExtension::FEAT_FGT)); + InitReg(MISCREG_HFGITR_EL2) + .fault(EL2, faultFgtCtrlRegs) + .hyp().mon(release->has(ArmExtension::FEAT_FGT)); + // Dummy registers InitReg(MISCREG_NOP) .allPrivileges(); @@ -5691,14 +5931,6 @@ ISA::initializeMiscRegMetadata() .warnNotFail() .fault(faultUnimplemented); - // FGT extension (unimplemented) - InitReg(MISCREG_HFGRTR_EL2) - .unimplemented() - .warnNotFail(); - InitReg(MISCREG_HFGWTR_EL2) - .unimplemented() - .warnNotFail(); - // Register mappings for some unimplemented registers: // ESR_EL1 -> DFSR // RMR_EL1 -> RMR diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index cb03841848..2077040e57 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -1096,6 +1096,11 @@ namespace ArmISA MISCREG_RNDR, MISCREG_RNDRRS, + // FEAT_FGT + MISCREG_HFGITR_EL2, + MISCREG_HFGRTR_EL2, + MISCREG_HFGWTR_EL2, + // NUM_PHYS_MISCREGS specifies the number of actual physical // registers, not considering the following pseudo-registers // (dummy registers), like MISCREG_UNKNOWN, MISCREG_IMPDEF_UNIMPL. @@ -1126,10 +1131,6 @@ namespace ArmISA MISCREG_VSESR_EL2, MISCREG_VDISR_EL2, - // FGT extension (unimplemented) - MISCREG_HFGRTR_EL2, - MISCREG_HFGWTR_EL2, - // PSTATE MISCREG_PAN, MISCREG_UAO, @@ -2766,6 +2767,10 @@ namespace ArmISA "rndr", "rndrrs", + "hfgitr_el2", + "hfgrtr_el2", + "hfgwtr_el2", + "num_phys_regs", // Dummy registers @@ -2784,8 +2789,6 @@ namespace ArmISA "disr_el1", "vsesr_el2", "vdisr_el2", - "hfgrtr_el2", - "hfgwtr_el2", // PSTATE "pan", diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index 00640dd339..f9a16c297a 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2022 Arm Limited + * Copyright (c) 2010-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -363,6 +363,7 @@ namespace ArmISA BitUnion64(SCR) Bitfield<40> trndr; Bitfield<38> hxen; + Bitfield<27> fgten; Bitfield<21> fien; Bitfield<20> nmea; Bitfield<19> ease; @@ -931,6 +932,117 @@ namespace ArmISA Bitfield<3,0> pcsample; EndBitUnion(DEVID) + BitUnion64(HFGITR) + Bitfield<54> dccvac; + Bitfield<53> svcEL1; + Bitfield<52> svcEL0; + Bitfield<51> eret; + Bitfield<47> tlbivaale1; + Bitfield<46> tlbivale1; + Bitfield<45> tlbivaae1; + Bitfield<44> tlbiaside1; + Bitfield<43> tlbivae1; + Bitfield<42> tlbivmalle1; + Bitfield<41> tlbirvaale1; + Bitfield<40> tlbirvale1; + Bitfield<39> tlbirvaae1; + Bitfield<38> tlbirvae1; + Bitfield<37> tlbirvaale1is; + Bitfield<36> tlbirvale1is; + Bitfield<35> tlbirvaae1is; + Bitfield<34> tlbirvae1is; + Bitfield<33> tlbivaale1is; + Bitfield<32> tlbivale1is; + Bitfield<31> tlbivaae1is; + Bitfield<30> tlbiaside1is; + Bitfield<29> tlbivae1is; + Bitfield<28> tlbivmalle1is; + Bitfield<27> tlbirvaale1os; + Bitfield<26> tlbirvale1os; + Bitfield<25> tlbirvaae1os; + Bitfield<24> tlbirvae1os; + Bitfield<23> tlbivaale1os; + Bitfield<22> tlbivale1os; + Bitfield<21> tlbivaae1os; + Bitfield<20> tlbiaside1os; + Bitfield<19> tlbivae1os; + Bitfield<18> tlbivmalle1os; + Bitfield<17> ats1e1wp; + Bitfield<16> ats1e1rp; + Bitfield<15> ats1e0w; + Bitfield<14> ats1e0r; + Bitfield<13> ats1e1w; + Bitfield<12> ats1e1r; + Bitfield<11> dczva; + Bitfield<10> dccivac; + Bitfield<9> dccvapd; + Bitfield<8> dccvap; + Bitfield<7> dccvau; + Bitfield<6> dccisw; + Bitfield<5> dccsw; + Bitfield<4> dcisw; + Bitfield<3> dcivac; + Bitfield<2> icivau; + Bitfield<1> iciallu; + Bitfield<0> icialluis; + EndBitUnion(HFGITR) + + // HFGRTR and HFGWTR. Some fields are + // for HFGRTR only (RO registers) + BitUnion64(HFGTR) + Bitfield<50> nAccdataEL1; + Bitfield<49> erxaddrEL1; + Bitfield<48> erxpfgcdnEL1; + Bitfield<47> erxpfgctlEL1; + Bitfield<46> erxpfgfEL1; // RES0 for HFGWTR + Bitfield<45> erxmiscNEL1; + Bitfield<44> erxstatusEL1; + Bitfield<43> erxctlrEL1; + Bitfield<42> erxfrEL1; + Bitfield<41> errselrEL1; + Bitfield<40> erridrEL1; // RES0 for HFGWTR + Bitfield<39> iccIgrpEnEL1; + Bitfield<38> vbarEL1; + Bitfield<37> ttbr1EL1; + Bitfield<36> ttbr0EL1; + Bitfield<35> tpidrEL0; + Bitfield<34> tpidrroEL0; + Bitfield<33> tpidrEL1; + Bitfield<32> tcrEL1; + Bitfield<31> scxtnumEL0; + Bitfield<30> scxtnumEL1; + Bitfield<29> sctlrEL1; + Bitfield<28> revidrEL1; // RES0 for HFGWTR + Bitfield<27> parEL1; + Bitfield<26> mpidrEL1; // RES0 for HFGWTR + Bitfield<25> midrEL1; // RES0 for HFGWTR + Bitfield<24> mairEL1; + Bitfield<23> lorsaEL1; + Bitfield<22> lornEL1; + Bitfield<21> loridEL1; // RES0 for HFGWTR + Bitfield<20> loreaEL1; + Bitfield<19> lorcEL1; + Bitfield<18> isrEL1; // RES0 for HFGWTR + Bitfield<17> farEL1; + Bitfield<16> esrEL1; + Bitfield<15> dczidEL0; // RES0 for HFGWTR + Bitfield<14> ctrEL0; // RES0 for HFGWTR + Bitfield<13> csselrEL1; + Bitfield<12> cpacrEL1; + Bitfield<11> contextidrEL1; + Bitfield<10> clidrEL1; // RES0 for HFGWTR + Bitfield<9> ccsidrEL1; // RES0 for HFGWTR + Bitfield<8> apibKey; + Bitfield<7> apiaKey; + Bitfield<6> apgaKey; + Bitfield<5> apdbKey; + Bitfield<4> apdaKey; + Bitfield<3> amairEL1; + Bitfield<2> aidrEL1; // RES0 for HFGWTR + Bitfield<1> afsr1EL1; + Bitfield<0> afsr0EL1; + EndBitUnion(HFGTR) + } // namespace ArmISA } // namespace gem5 diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 2251d57c0b..f7b6cbf86b 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013, 2017-2018, 2022 Arm Limited + * Copyright (c) 2010, 2012-2013, 2017-2018, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -323,6 +323,7 @@ namespace ArmISA SMC_64 = 0x17, TRAPPED_MSR_MRS_64 = 0x18, TRAPPED_SVE = 0x19, + TRAPPED_ERET = 0x1A, TRAPPED_SME = 0x1D, PREFETCH_ABORT_TO_HYP = 0x20, PREFETCH_ABORT_LOWER_EL = 0x20, // AArch64 alias diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 05d1cab06c..9051eaa151 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2014, 2016-2020, 2022 Arm Limited + * Copyright (c) 2009-2014, 2016-2020, 2022-2023 Arm Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -1347,5 +1347,13 @@ syncVecElemsToRegs(ThreadContext *tc) } } +bool +fgtEnabled(ThreadContext *tc) +{ + return EL2Enabled(tc) && HaveExt(tc, ArmExtension::FEAT_FGT) && + (!ArmSystem::haveEL(tc, EL3) || + static_cast(tc->readMiscReg(MISCREG_SCR_EL3)).fgten); +} + } // namespace ArmISA } // namespace gem5 diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index b5a5dd72dd..d317651db5 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013, 2016-2020, 2022 Arm Limited + * Copyright (c) 2010, 2012-2013, 2016-2020, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -364,6 +364,8 @@ bool isUnpriviledgeAccess(ThreadContext *tc); void syncVecRegsToElems(ThreadContext *tc); void syncVecElemsToRegs(ThreadContext *tc); +bool fgtEnabled(ThreadContext *tc); + } // namespace ArmISA } // namespace gem5 From 7cb308db90480ad75a375fc680dbdb34cc57caf5 Mon Sep 17 00:00:00 2001 From: David Schall Date: Mon, 26 Jun 2023 18:46:01 +0000 Subject: [PATCH 347/693] sim: Probe listener template with lambda Adds a new probe listener template which can be used to instantiate with a lambda function that is called by notify(). It is similar to ProbeListenerArg with class but provides more flexibility. I.e. the can be another object than the one instantiating the lambda which allows to listen to any object. Furthermore additional parameters can be passed in easily. Change-Id: Iba451357182caf25097b9ae201cd5c647aff3a4f Signed-off-by: David Schall --- src/sim/probe/probe.hh | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/sim/probe/probe.hh b/src/sim/probe/probe.hh index 3dd428effd..8d5366670a 100644 --- a/src/sim/probe/probe.hh +++ b/src/sim/probe/probe.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2013 ARM Limited + * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -317,6 +318,47 @@ class ProbePointArg : public ProbePoint } }; + +/** + * ProbeListenerArgFunc generates a listener for the class of Arg and + * a lambda callback function that is called by the notify. + * + * Note that the function is passed as lambda function on construction + * Example: + * ProbeListenerArgFunc (myobj->getProbeManager(), + * "MyProbePointName", [this](const MyArg &arg) + * { my_own_func(arg, xyz...); // do something with arg + * })); + */ +template +class ProbeListenerArgFunc : public ProbeListenerArgBase +{ + typedef std::function NotifyFunction; + private: + NotifyFunction function; + + public: + /** + * @param obj the class of type Tcontaining the method to call on notify. + * @param pm A probe manager that is not part of the obj + * @param name the name of the ProbePoint to add this listener to. + * @param func a pointer to the function on obj (called on notify). + */ + ProbeListenerArgFunc(ProbeManager *pm, const std::string &name, + const NotifyFunction &func) + : ProbeListenerArgBase(pm, name), + function(func) + {} + + /** + * @brief called when the ProbePoint calls notify. This is a shim through + * to the function passed during construction. + * @param val the argument value to pass. + */ + void notify(const Arg &val) override { function(val); } +}; + + } // namespace gem5 #endif//__SIM_PROBE_PROBE_HH__ From b759f22cc9468739c456c26098729cd60864c644 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 25 Sep 2023 12:29:28 -0700 Subject: [PATCH 348/693] cpu-o3: Mark getWritableRegOperand() in O3CPU as a regwrite As discussed here, [1], O3CPU counts getWritableRegOperand() as a reg read, while SimpleCPU variants count getWriableRegOperand() as a reg write. This patch fixes this inconsistency. Here, I assume that if getWritableRegOperand() is used, setReg() will not be used again to write to the destination register. [1] https://github.com/gem5/gem5/pull/341 Change-Id: If00049eb598f6722285e9e09419aef98ceed759f Signed-off-by: Hoa Nguyen --- src/cpu/o3/cpu.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 85cc3dbf71..a93d5bc74d 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -989,10 +989,10 @@ CPU::getWritableReg(PhysRegIdPtr phys_reg, ThreadID tid) { switch (phys_reg->classValue()) { case VecRegClass: - executeStats[tid]->numVecRegReads++; + executeStats[tid]->numVecRegWrites++; break; case VecPredRegClass: - executeStats[tid]->numVecPredRegReads++; + executeStats[tid]->numVecPredRegWrites++; break; default: break; From 91e55d9c60bb0fe8a307d1bd013e94841fc96ffe Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 25 Sep 2023 16:23:17 -0700 Subject: [PATCH 349/693] base: Add warning when failing to insert a whole symbol table Current we drop the insertion of a whole symbol table if the name of one symbol already exists in the base table. Having similar symbols across different binaries is very common. This change adds a warning and recommends a fix instead of silently dropping the table. This is useful for debugging when there are two or more workloads, e.g. bootloader + kernel, are added separately. Change-Id: I9e4cf06037cd70926fb5cee3c4dab464daf0912e Signed-off-by: Hoa Nguyen --- src/base/loader/symtab.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/base/loader/symtab.cc b/src/base/loader/symtab.cc index 941ea101c9..041476bf7d 100644 --- a/src/base/loader/symtab.cc +++ b/src/base/loader/symtab.cc @@ -79,8 +79,11 @@ SymbolTable::insert(const SymbolTable &other) nameMap.begin(), nameMap.end(), std::inserter(intersection, intersection.begin()), nameMap.value_comp()); - if (!intersection.empty()) + if (!intersection.empty()) { + warn("Cannot insert a new symbol table due to name collisions. " + "Adding prefix to each symbol's name can resolve this issue."); return false; + } for (const Symbol &symbol: other) insert(symbol); From 9ca2672cabcd40e71732d920af268ab439d6b59f Mon Sep 17 00:00:00 2001 From: Yu-hsin Wang Date: Wed, 27 Sep 2023 12:48:26 +0800 Subject: [PATCH 350/693] misc: fix g++13 overloaded-virtual warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two overloaded-virtual issues reported by g++13. 1. Copy assignment and move assignment overload is hidden in the derived class [ CXX] src/mem/cache/replacement_policies/weighted_lru_rp.cc -> ALL/mem/cache/replacement_policies/weighted_lru_rp.o In file included from src/mem/cache/base.hh:61, from src/mem/cache/base.cc:46: src/mem/cache/cache_blk.hh:172:5: error: ‘virtual gem5::CacheBlk& gem5::CacheBlk::operator=(gem5::CacheBlk&&)’ was hidden [-Werror=overloaded-virtual=] 172 | operator=(CacheBlk&& other) | ^~~~~~~~ src/mem/cache/cache_blk.hh:518:19: note: by ‘gem5::TempCacheBlk& gem5::TempCacheBlk::operator=(const gem5::TempCacheBlk&)’ 518 | TempCacheBlk& operator=(const TempCacheBlk&) = delete; | ^~~~~~~~ In this case, we can exiplict using parent operator= to keep the function overload. 2. Intended overload hidden in SystemC is reported as error. In file included from src/systemc/ext/tlm_utils/simple_initiator_socket.h:24, from src/systemc/tlm_bridge/gem5_to_tlm.hh:72, from build/ALL/python/_m5/param_Gem5ToTlmBridge256.cc:17: src/systemc/ext/tlm_utils/../tlm_core/2/sockets/initiator_socket.hh: In instantiation of ‘class tlm::tlm_base_initiator_socket<256, tlm::tlm_fw_transport_if<>, tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ONE_OR_MORE_BOUND>’: src/systemc/ext/tlm_utils/../tlm_core/2/sockets/initiator_socket.hh:185:7: required from ‘class tlm::tlm_initiator_socket<256, tlm::tlm_base_protocol_types, 1, sc_core::SC_ONE_OR_MORE_BOUND>’ src/systemc/ext/tlm_utils/simple_initiator_socket.h:37:7: required from ‘class tlm_utils::simple_initiator_socket_b, 256, tlm::tlm_base_protocol_types, sc_core::SC_ONE_OR_MORE_BOUND>’ src/systemc/ext/tlm_utils/simple_initiator_socket.h:156:7: required from ‘class tlm_utils::simple_initiator_socket, 256, tlm::tlm_base_protocol_types>’ src/systemc/tlm_bridge/gem5_to_tlm.hh:147:46: required from ‘class sc_gem5::Gem5ToTlmBridge<256>’ /usr/include/c++/13/type_traits:1411:38: required from ‘struct std::is_base_of >’ ext/pybind11/include/pybind11/detail/../detail/common.h:880:59: required from ‘struct pybind11::class_, sc_gem5::Gem5ToTlmBridgeBase, std::unique_ptr, pybind11::nodelete> >::is_valid_class_option’ ext/pybind11/include/pybind11/detail/../detail/common.h:719:35: required by substitution of ‘template using pybind11::detail::all_of = pybind11::detail::bool_constant<(Ts::value && ...)> [with Ts = {pybind11::class_, sc_gem5::Gem5ToTlmBridgeBase, std::unique_ptr, pybind11::nodelete> >::is_valid_class_option, pybind11::class_, sc_gem5::Gem5ToTlmBridgeBase, std::unique_ptr, pybind11::nodelete> >::is_valid_class_option, pybind11::nodelete> >}]’ ext/pybind11/include/pybind11/pybind11.h:1506:70: required from ‘class pybind11::class_, sc_gem5::Gem5ToTlmBridgeBase, std::unique_ptr, pybind11::nodelete> >’ build/ALL/python/_m5/param_Gem5ToTlmBridge256.cc:34:179: required from here src/systemc/ext/tlm_utils/../core/sc_port.hh:125:18: error: ‘void sc_core::sc_port_b::bind(sc_core::sc_port_b&) [with IF = tlm::tlm_fw_transport_if<>]’ was hidden [-Werror=overloaded-virtual=] 125 | virtual void bind(sc_port_b &p) { sc_port_base::bind(p); } | ^~~~ In file included from src/systemc/ext/tlm_utils/simple_initiator_socket.h:27: src/systemc/ext/tlm_utils/../tlm_core/2/sockets/initiator_socket.hh:133:18: note: by ‘tlm::tlm_base_initiator_socket<256, tlm::tlm_fw_transport_if<>, tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ONE_OR_MORE_BOUND>::bind’ 133 | virtual void bind(bw_interface_type &ifs) { (get_base_export())(ifs); } | ^~~~ src/systemc/ext/tlm_utils/../core/sc_port.hh:124:18: error: ‘void sc_core::sc_port_b::bind(IF&) [with IF = tlm::tlm_fw_transport_if<>]’ was hidden [-Werror=overloaded-virtual=] 124 | virtual void bind(IF &i) { sc_port_base::bind(i); } | ^~~~ src/systemc/ext/tlm_utils/../tlm_core/2/sockets/initiator_socket.hh:133:18: note: by ‘tlm::tlm_base_initiator_socket<256, tlm::tlm_fw_transport_if<>, tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ONE_OR_MORE_BOUND>::bind’ 133 | virtual void bind(bw_interface_type &ifs) { (get_base_export())(ifs); } | ^~~~ From the code comment, it's intended in SystemC header. // The overloaded virtual is intended in SystemC, so we'll disable the warning. // Please check section 9.3 of SystemC 2.3.1 release note for more details. The issue is we should move the skip to the base class. Change-Id: I6683919e594ffe1fb3b87ccca1602bffdb788e7d --- src/mem/cache/cache_blk.hh | 1 + src/mem/cache/tags/fa_lru.hh | 1 + src/mem/cache/tags/sector_blk.hh | 1 + src/systemc/ext/core/sc_port.hh | 5 +++++ src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh | 5 ----- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index 775efbe673..e476ab639d 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -515,6 +515,7 @@ class TempCacheBlk final : public CacheBlk data = new uint8_t[size]; } TempCacheBlk(const TempCacheBlk&) = delete; + using CacheBlk::operator=; TempCacheBlk& operator=(const TempCacheBlk&) = delete; ~TempCacheBlk() { delete [] data; }; diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index cd07817007..dba89f809d 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -85,6 +85,7 @@ class FALRUBlk : public CacheBlk { public: FALRUBlk() : CacheBlk(), prev(nullptr), next(nullptr), inCachesMask(0) {} + using CacheBlk::operator=; /** The previous block in LRU order. */ FALRUBlk *prev; diff --git a/src/mem/cache/tags/sector_blk.hh b/src/mem/cache/tags/sector_blk.hh index dae8741e39..fbfea64d93 100644 --- a/src/mem/cache/tags/sector_blk.hh +++ b/src/mem/cache/tags/sector_blk.hh @@ -64,6 +64,7 @@ class SectorSubBlk : public CacheBlk public: SectorSubBlk() : CacheBlk(), _sectorBlk(nullptr), _sectorOffset(0) {} SectorSubBlk(const SectorSubBlk&) = delete; + using CacheBlk::operator=; SectorSubBlk& operator=(const SectorSubBlk&) = delete; SectorSubBlk(SectorSubBlk&&) = delete; /** diff --git a/src/systemc/ext/core/sc_port.hh b/src/systemc/ext/core/sc_port.hh index 796950e29b..bd57553559 100644 --- a/src/systemc/ext/core/sc_port.hh +++ b/src/systemc/ext/core/sc_port.hh @@ -114,6 +114,10 @@ class sc_port_base : public sc_object virtual sc_port_policy _portPolicy() const = 0; }; +// The overloaded virtual is intended in SystemC, so we'll disable the warning. +// Please check section 9.3 of SystemC 2.3.1 release note for more details. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" template class sc_port_b : public sc_port_base { @@ -244,6 +248,7 @@ class sc_port_b : public sc_port_base sc_port_b(const sc_port_b &) {} sc_port_b &operator = (const sc_port_b &) { return *this; } }; +#pragma GCC diagnostic pop template class sc_port : public sc_port_b diff --git a/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh b/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh index 4f67b59237..71fbf1b900 100644 --- a/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh +++ b/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh @@ -51,10 +51,6 @@ template class tlm_base_target_socket; -// The overloaded virtual is intended in SystemC, so we'll disable the warning. -// Please check section 9.3 of SystemC 2.3.1 release note for more details. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverloaded-virtual" template , typename BW_IF=tlm_bw_transport_if<>, int N=1, sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND> @@ -174,7 +170,6 @@ class tlm_base_initiator_socket : protected: export_type m_export; }; -#pragma GCC diagnostic pop // // Convenience socket classes From 34c3676105c68a7de5f99186cfdf8ad0967fe73f Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Wed, 27 Sep 2023 09:33:53 -0700 Subject: [PATCH 351/693] misc: Update gem5 to use clang-15 and clang-16 This introduces the changes necessary for clang-15 and clang-16 to run within gem5, and adds them to the compiler tests. Change-Id: If809eae1bd8c366b4d62476891feff0625bdf210 --- .github/workflows/compiler-tests.yaml | 4 ++-- src/cpu/o3/commit.cc | 2 +- src/cpu/o3/rename.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 7c9493cbba..595e231323 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] + image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-16, clang-version-15, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] runs-on: [self-hosted, linux, x64, build] timeout-minutes: 2880 # 48 hours @@ -36,7 +36,7 @@ jobs: fail-fast: false matrix: gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, GCN3_X86] - image: [gcc-version-12, clang-version-14] + image: [gcc-version-12, clang-version-16] opts: [.opt] runs-on: [self-hosted, linux, x64, build] timeout-minutes: 2880 # 48 hours diff --git a/src/cpu/o3/commit.cc b/src/cpu/o3/commit.cc index 538505bcf9..f5e601f679 100644 --- a/src/cpu/o3/commit.cc +++ b/src/cpu/o3/commit.cc @@ -254,7 +254,7 @@ Commit::setActiveThreads(std::list *at_ptr) } void -Commit::setRenameMap(UnifiedRenameMap rm_ptr[]) +Commit::setRenameMap(UnifiedRenameMap rm_ptr[MaxThreads]) { for (ThreadID tid = 0; tid < numThreads; tid++) renameMap[tid] = &rm_ptr[tid]; diff --git a/src/cpu/o3/rename.cc b/src/cpu/o3/rename.cc index 3a78efb1b0..c20edc2e46 100644 --- a/src/cpu/o3/rename.cc +++ b/src/cpu/o3/rename.cc @@ -286,7 +286,7 @@ Rename::setActiveThreads(std::list *at_ptr) void -Rename::setRenameMap(UnifiedRenameMap rm_ptr[]) +Rename::setRenameMap(UnifiedRenameMap rm_ptr[MaxThreads]) { for (ThreadID tid = 0; tid < numThreads; tid++) renameMap[tid] = &rm_ptr[tid]; From 633bdc08f2e32d24990132336c16788a2161fdc8 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 27 Sep 2023 11:36:51 -0700 Subject: [PATCH 352/693] stdlib: Addressed requested changes - Added mulitline string for print message - Added get_category_name method instead of having category as variable Change-Id: I51e0e14a70e802453c21070711b200bc47994ba3 --- src/python/gem5/resources/resource.py | 78 +++++++++++++++++---------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 6b33f10971..5b70f9561b 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -70,7 +70,6 @@ class AbstractResource: def __init__( self, - category: Optional[str] = None, id: Optional[str] = None, resource_version: Optional[str] = None, local_path: Optional[str] = None, @@ -94,14 +93,22 @@ class AbstractResource: "exist." ) self._id = id - self._category = category self._local_path = local_path self._description = description self._source = source self._version = resource_version + def get_category_name(cls) -> str: + raise NotImplementedError + def __str__(self): - return f"{self._category} resource({self._id}, {self._version})\nFor more information, please visit https://resources.gem5.org/resources/{self._id}?version={self._version}" + message = ( + f"{self.get_category_name()}({self._id}, {self._version})\n" + "For more information, please visit " + f"https://resources.gem5.org/resources/{self._id}?" + f"version={self._version}" + ) + return message def get_resource_version(self) -> str: """Returns the version of the resource.""" @@ -129,7 +136,6 @@ class FileResource(AbstractResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -143,12 +149,14 @@ class FileResource(AbstractResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, ) + def get_category_name(cls) -> str: + return "FileResource" + class DirectoryResource(AbstractResource): """A resource consisting of a directory.""" @@ -157,7 +165,6 @@ class DirectoryResource(AbstractResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -172,12 +179,14 @@ class DirectoryResource(AbstractResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, ) + def get_category_name(cls) -> str: + return "DirectoryResource" + class DiskImageResource(FileResource): """A Disk Image resource.""" @@ -186,7 +195,6 @@ class DiskImageResource(FileResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -196,7 +204,6 @@ class DiskImageResource(FileResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, @@ -207,6 +214,9 @@ class DiskImageResource(FileResource): """Returns, if applicable, the Root Partition of the disk image.""" return self._root_partition + def get_category_name(cls) -> str: + return "DiskImageResource" + class BinaryResource(FileResource): """A binary resource.""" @@ -215,7 +225,6 @@ class BinaryResource(FileResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -225,7 +234,6 @@ class BinaryResource(FileResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, @@ -238,6 +246,9 @@ class BinaryResource(FileResource): elif isinstance(architecture, ISA): self._architecture = architecture + def get_category_name(cls) -> str: + return "BinaryResource" + def get_architecture(self) -> Optional[ISA]: """Returns the ISA this binary is compiled to.""" return self._architecture @@ -250,7 +261,6 @@ class BootloaderResource(BinaryResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -260,13 +270,15 @@ class BootloaderResource(BinaryResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, architecture=architecture, source=source, resource_version=resource_version, ) + def get_category_name(cls) -> str: + return "BootloaderResource" + class GitResource(DirectoryResource): """A git resource.""" @@ -275,7 +287,6 @@ class GitResource(DirectoryResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -284,12 +295,14 @@ class GitResource(DirectoryResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, ) + def get_category_name(cls) -> str: + return "GitResource" + class KernelResource(BinaryResource): """A kernel resource.""" @@ -298,7 +311,6 @@ class KernelResource(BinaryResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -308,13 +320,15 @@ class KernelResource(BinaryResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, architecture=architecture, resource_version=resource_version, ) + def get_category_name(cls) -> str: + return "KernelResource" + class CheckpointResource(DirectoryResource): """A checkpoint resource. The following directory structure is expected: @@ -328,7 +342,6 @@ class CheckpointResource(DirectoryResource): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -337,12 +350,14 @@ class CheckpointResource(DirectoryResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, ) + def get_category_name(cls) -> str: + return "CheckpointResource" + class SimpointResource(AbstractResource): """A simpoint resource. This resource stores all information required to @@ -359,7 +374,6 @@ class SimpointResource(AbstractResource): weight_list: List[float] = None, warmup_interval: int = 0, id: Optional[str] = None, - category: Optional[str] = None, workload_name: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -381,7 +395,6 @@ class SimpointResource(AbstractResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, @@ -463,6 +476,9 @@ class SimpointResource(AbstractResource): self._simpoint_start_insts[index] = start_inst - warmup_inst return warmup_list + def get_category_name(cls) -> str: + return "SimpointResource" + class LooppointCsvResource(FileResource, LooppointCsvLoader): """This Looppoint resource used to create a Looppoint resource from a @@ -472,7 +488,6 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -482,20 +497,21 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): self, local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, ) LooppointCsvLoader.__init__(self, pinpoints_file=Path(local_path)) + def get_category_name(cls) -> str: + return "LooppointCsvResource" + class LooppointJsonResource(FileResource, LooppointJsonLoader): def __init__( self, local_path: str, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, region_id: Optional[Union[str, int]] = None, description: Optional[str] = None, @@ -506,7 +522,6 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): self, local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, @@ -515,6 +530,9 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): self, looppoint_file=local_path, region_id=region_id ) + def get_category_name(cls) -> str: + return "LooppointJsonResource" + class SimpointDirectoryResource(SimpointResource): """A Simpoint diretory resource. This Simpoint Resource assumes the @@ -528,7 +546,6 @@ class SimpointDirectoryResource(SimpointResource): simpoint_interval: int, warmup_interval: int, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, workload_name: Optional[str] = None, description: Optional[str] = None, @@ -563,7 +580,6 @@ class SimpointDirectoryResource(SimpointResource): workload_name=workload_name, local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, @@ -607,6 +623,9 @@ class SimpointDirectoryResource(SimpointResource): weight_list.append(weight) return simpoint_list, weight_list + def get_category_name(cls) -> str: + return "SimpointDirectoryResource" + class WorkloadResource(AbstractResource): """A workload resource. This resource is used to specify a workload to run @@ -618,7 +637,6 @@ class WorkloadResource(AbstractResource): self, function: str = None, id: Optional[str] = None, - category: Optional[str] = None, resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, @@ -634,7 +652,6 @@ class WorkloadResource(AbstractResource): super().__init__( local_path=local_path, id=id, - category=category, description=description, source=source, resource_version=resource_version, @@ -671,6 +688,9 @@ class WorkloadResource(AbstractResource): """ self._params[parameter] = value + def get_category_name(cls) -> str: + return "WorkloadResource" + def obtain_resource( resource_id: str, From aaad79cf51eb99f307450870340e1e7c4459b40f Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Mon, 14 Aug 2023 16:15:50 -0700 Subject: [PATCH 353/693] python: Add importer to standalone gem5py_m5 I believe the point of this binary was to allow people to use the m5 objects without the entire gem5 binary. However, without adding the importer call, this did not work. Unfortunately, with the importer call there is a circular dependence on the original gem5py.cc file. Therefore, this change creates a new file that has the importer call. Now, with the `gem5py_m5` binary you can run python code that references modules in `src/python`. Note that `_m5` is not available, so anything that depends on the gem5 SimObjects' implementation will not work. However, thic can still be useful for things like getting Resources, processing stats, etc. Change-Id: I5c0e5d1a669fe5ce491458df916f2049c81292eb Signed-off-by: Jason Lowe-Power --- src/SConscript | 2 +- src/python/gem5py_m5.cc | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/python/gem5py_m5.cc diff --git a/src/SConscript b/src/SConscript index 62ae807b55..52051b3256 100644 --- a/src/SConscript +++ b/src/SConscript @@ -639,7 +639,7 @@ gem5py_env.Program(gem5py, 'python/gem5py.cc')[0] m5_module_source = \ Source.all.with_all_tags(env, 'm5_module', 'gem5 lib') m5_module_static = list(map(lambda s: s.static(gem5py_env), m5_module_source)) -gem5py_env.Program(gem5py_m5, [ 'python/gem5py.cc' ] + m5_module_static) +gem5py_env.Program(gem5py_m5, [ 'python/gem5py_m5.cc' ] + m5_module_static) # version tags diff --git a/src/python/gem5py_m5.cc b/src/python/gem5py_m5.cc new file mode 100644 index 0000000000..78337c1ffe --- /dev/null +++ b/src/python/gem5py_m5.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2019 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. + * + * 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. + */ + +#include + +#include +#include + +namespace py = pybind11; + +/* + * This wrapper program runs python scripts using the python interpretter which + * will be built into gem5. Its first argument is the script to run, and then + * all subsequent arguments are passed to the python script as its argv. + */ + +int +main(int argc, const char **argv) +{ + py::scoped_interpreter guard; + + // Embedded python doesn't set up sys.argv, so we'll do that ourselves. + py::list py_argv; + auto sys = py::module::import("sys"); + if (py::hasattr(sys, "argv")) { + // sys.argv already exists, so grab that. + py_argv = sys.attr("argv"); + } else { + // sys.argv doesn't exist, so create it. + sys.add_object("argv", py_argv); + } + + auto importer = py::module_::import("importer"); + importer.attr("install")(); + + // Clear out argv just in case it has something in it. + py_argv.attr("clear")(); + + if (argc < 2) { + std::cerr << "Usage: gem5py SCRIPT [arg] ..." << std::endl; + std::exit(1); + } + + // Fill it with our argvs. + for (int i = 1; i < argc; i++) + py_argv.append(argv[i]); + + // Actually call the script. + py::eval_file(argv[1]); + + return 0; +} From 6640447c1ed6ff41d54791f4eeb8849551cdaeb2 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Thu, 28 Sep 2023 19:14:29 -0700 Subject: [PATCH 354/693] arch-riscv: Update FS bits when doing floating point loads This problem is similar to the problem described in [1]. This problem produces symptoms as described in [2]. In short, the Linux kernel relies on the CSR_STATUS's FS bits to decide whether to save the floating point registers. If the FS bits are set to DIRTY, the floating point registers will be saved during context switching / task switching. Currently, with the patch in [1], we only change the FS bits upon every floating arithmetic instruction. However, since floating load instructions also mutate the state of floating point registers, the FS bits should be updated to DIRTY. The problem in [2] arose when the program populates the content of one floating register to an array by repeatedly using `fld fa5, EA`. A context switch occured upon a page fault, and while handling that page fault, the kernel might have to handle an interrupt. This caused the kernel to task switch between handling page fault and handling interrupt. This caused __switch_to() to be called, which will save the floating point registers only if the SD (indirectly set by FS) bits are set to DIRTY, while restoring the floating point registers to the switch-to task [3]. This caused the floating point registers to be zeroed out when it was restored as it was never saved before. [1] https://gem5-review.googlesource.com/c/public/gem5/+/65272 [2] https://github.com/gem5/gem5/issues/349 [3] https://github.com/torvalds/linux/blob/v6.5/arch/riscv/include/asm/switch_to.h#L56 Change-Id: Ia5656da5a589a8e29fb699d2ee12885b8f3fa2d2 Signed-off-by: Hoa Nguyen --- src/arch/riscv/isa/decoder.isa | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index aeebfd6bf5..0ad7283fcd 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -61,6 +61,11 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("FPU is off", machInst); + // Mutating any floating point register changes the FS bit + // of the STATUS CSR. + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + Fp2_bits = Mem; }}, {{ EA = rvZext(Rp1 + offset); @@ -312,6 +317,11 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("FPU is off", machInst); + // Mutating any floating point register changes the FS bit + // of the STATUS CSR. + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + Fc1_bits = Mem; }}, {{ EA = rvZext(sp + offset); @@ -495,6 +505,12 @@ decode QUADRANT default Unknown::unknown() { if (status.fs == FPUStatus::OFF) return std::make_shared( "FPU is off", machInst); + + // Mutating any floating point register changes the FS bit + // of the STATUS CSR. + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + freg_t fd; fd = freg(f64(Mem)); Fd_bits = fd.v; From a79dc3f23c7411927def5ed43b642e57c5b1836f Mon Sep 17 00:00:00 2001 From: Melissa Jost Date: Wed, 27 Sep 2023 09:38:39 -0700 Subject: [PATCH 355/693] util: Add steps to compile clang-15 and clang-16 This updates the dockerfiles for ubuntu 22.04 to include the steps necessary to compile clang-15 and clang-16. Change-Id: I2bba6393ab93a6ce05a2c3ce31f3bbc71bcdca7c --- util/dockerfiles/docker-compose.yaml | 12 ++++ .../ubuntu-22.04_clang-16/Dockerfile | 57 +++++++++++++++++++ .../ubuntu-22.04_clang-version/Dockerfile | 1 + 3 files changed, 70 insertions(+) create mode 100644 util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile diff --git a/util/dockerfiles/docker-compose.yaml b/util/dockerfiles/docker-compose.yaml index e2d327b0b2..fcbc3e9f70 100644 --- a/util/dockerfiles/docker-compose.yaml +++ b/util/dockerfiles/docker-compose.yaml @@ -127,6 +127,18 @@ services: args: - version=14 image: gcr.io/gem5-test/clang-version-14:latest + clang-15: + build: + context: ubuntu-22.04_clang-version + dockerfile: Dockerfile + args: + - version=15 + image: gcr.io/gem5-test/clang-version-15:latest + clang-16: + build: + context: ubuntu-22.04_clang-16 + dockerfile: Dockerfile + image: gcr.io/gem5-test/clang-version-16:latest llvm-gnu-cross-compiler-riscv64: build: context: llvm-gnu-cross-compiler-riscv64 diff --git a/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile b/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile new file mode 100644 index 0000000000..d06cf6fd67 --- /dev/null +++ b/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile @@ -0,0 +1,57 @@ +# Copyright (c) 2023 The Regents of the University of California +# All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +FROM ubuntu:22.04 + +# Valid version values: +# 16 +ARG version + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt -y update && apt -y upgrade && \ + apt -y install git m4 scons zlib1g zlib1g-dev libprotobuf-dev \ + protobuf-compiler libprotoc-dev libgoogle-perftools-dev python3-dev \ + python-is-python3 doxygen libboost-all-dev libhdf5-serial-dev \ + python3-pydot libpng-dev make + +RUN apt-get update && apt-get -y install sudo wget + +# extra installations to have wget work +RUN apt -y install lsb-release wget software-properties-common gnupg +RUN wget https://apt.llvm.org/llvm.sh ++ +RUN chmod u+x llvm.sh +RUN ./llvm.sh 16 + +RUN apt-get --purge -y remove gcc + +RUN update-alternatives --install \ + /usr/bin/clang++ clang++ /usr/bin/clang++-${version} 100 +RUN update-alternatives --install \ + /usr/bin/clang clang /usr/bin/clang-${version} 100 +RUN update-alternatives --install \ + /usr/bin/c++ c++ /usr/bin/clang++-${version} 100 +RUN update-alternatives --install \ + /usr/bin/cc cc /usr/bin/clang-${version} 100 diff --git a/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile b/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile index 148b71dea3..2c8d7c7b21 100644 --- a/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile @@ -27,6 +27,7 @@ FROM ubuntu:22.04 # Valid version values: # 13 +# 15 ARG version ENV DEBIAN_FRONTEND=noninteractive From 8182f8084b0c0b33f7148930e7d37352bbef88ff Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 16 Aug 2023 15:14:19 -0700 Subject: [PATCH 356/693] stdlib, resources, tests: Introduce Suite of Workloads This patch introduces a new category called "suite". A suite is a collection of workloads. Each workload in a SuiteResource has a tag that can be narrowed down through the function with_input_group. Also, the set of input groups can be seen through list_input_groups. Added unit tests to test all functions of SuiteResource class. Change-Id: Iddda5c898b32b7cd874987dbe694ac09aa231f08 Co-authored-by: Kunal Pai --- .../riscvmatched-microbenchmark-suite.py | 86 +++++++++ src/python/gem5/resources/resource.py | 140 ++++++++++++++- .../stdlib/resources/pyunit_suite_checks.py | 170 ++++++++++++++++++ .../stdlib/resources/refs/suite-checks.json | 97 ++++++++++ 4 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 configs/example/gem5_library/riscvmatched-microbenchmark-suite.py create mode 100644 tests/pyunit/stdlib/resources/pyunit_suite_checks.py create mode 100644 tests/pyunit/stdlib/resources/refs/suite-checks.json diff --git a/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py b/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py new file mode 100644 index 0000000000..2d189717e2 --- /dev/null +++ b/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py @@ -0,0 +1,86 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +This script shows how to use a suite. In this example, we will use the +RISCVMatchedBoard and the RISCV Vertical Microbenchmark Suite, +and show the different functionalities of the suite. + +The print statements in the script are for illustrative purposes only, +and are not required to run the script. +""" + +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard +from gem5.isas import ISA +from gem5.utils.requires import requires + +requires(isa_required=ISA.RISCV) + +# instantiate the riscv matched board with default parameters +board = RISCVMatchedBoard() + +# obtain the RISC-V Vertical Microbenchmarks +microbenchmarks = obtain_resource("riscv-vertical-microbenchmarks") + +# list all the microbenchmarks present in the suite +print("Microbenchmarks present in the suite:") +print("====================================") +for ( + id, + resource_version, + input_group, + workload, +) in microbenchmarks.get_all_workloads(): + print(f"Workload ID: {id}") + print(f"Workload Version: {resource_version}") + print(f"Workload Input Groups: {input_group}") + print(f"WorkloadResource Object: {workload}") + print("====================================") + +# list all the WorkloadResource objects present in the suite +for resource in microbenchmarks: + print(f"WorkloadResource Object: {resource}") + +# list all the available input groups in the suite +print("Input groups present in the suite:") +print(microbenchmarks.get_input_groups()) + +# for this example, we will filter the suite +# to run the Workload "riscv-cca-run" +# it has the input group 'cca', which is used as the filter +board.set_workload(list(microbenchmarks.with_input_group("cca"))[0]) + +# run the simulation with the RISCV Matched board +simulator = Simulator(board=board, full_system=False) +simulator.run() +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), + simulator.get_last_exit_event_cause(), + ) +) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 4b4e3c0b79..ac7769b83f 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import ABCMeta +import json import os from pathlib import Path from m5.util import warn, fatal @@ -35,7 +36,17 @@ from .downloader import get_resource from .looppoint import LooppointCsvLoader, LooppointJsonLoader from ..isas import ISA, get_isa_from_str -from typing import Optional, Dict, Union, Type, Tuple, List, Any +from typing import ( + Optional, + Dict, + Union, + Type, + Tuple, + List, + Any, + Set, + Generator, +) from .client import get_resource_json_obj @@ -627,6 +638,111 @@ class SimpointDirectoryResource(SimpointResource): return "SimpointDirectoryResource" +class SuiteResource(AbstractResource): + """ + A suite resource. This resource is used to specify a suite of workloads to + run on a board. It contains a list of workloads to run, along with their + IDs and versions. + + Each workload in a suite is used to create a `WorkloadResource` object. + These objects are stored in a list and can be iterated over. + """ + + def __init__( + self, + workloads: Dict["WorkloadResource", Set[str]] = {}, + resource_version: Optional[str] = None, + description: Optional[str] = None, + source: Optional[str] = None, + id: Optional[str] = None, + **kwargs, + ) -> None: + """ + :param workloads: A list of `WorkloadResource` objects + created from the `_workloads` parameter. + :param local_path: The path on the host system where this resource is + located. + :param description: Description describing this resource. Not a + required parameter. By default is None. + :param source: The source (as in "source code") for this resource + on gem5-resources. Not a required parameter. By default is None. + :param resource_version: Version of the resource itself. + """ + self._workloads = workloads + self._description = description + self._source = source + self._resource_version = resource_version + + super().__init__( + id=id, + description=description, + source=source, + resource_version=resource_version, + ) + + def __iter__(self) -> Generator["WorkloadResource", None, None]: + """ + Returns a generator that iterates over the workloads in the suite. + + :yields: A generator that iterates over the workloads in the suite. + """ + for workload in self._workloads.keys(): + yield workload + + def __len__(self): + """ + Returns the number of workloads in the suite. + + :returns: The number of workloads in the suite. + """ + return len(self._workloads) + + def get_category_name(cls) -> str: + return "SuiteResource" + + def with_input_group(self, input_group: str) -> "SuiteResource": + """ + Returns a new SuiteResource object with only the workloads that use the + specified input group. + + :param input_group: The input group to filter the workloads by. + :returns: A new SuiteResource object with only the workloads that use + the specified input group. + """ + + if input_group not in self.get_input_groups(): + raise Exception( + f"Input group {input_group} not found in Suite.\n" + f"Available input groups are {self.get_input_groups()}" + ) + + filtered_workloads = {} + + for workload, input_groups in self._workloads.items(): + if input_group in input_groups: + filtered_workloads[workload] = input_groups + + return SuiteResource( + local_path=self._local_path, + resource_version=self._resource_version, + description=self._description, + source=self._source, + workloads=filtered_workloads, + ) + + def get_input_groups(self) -> Set[str]: + """ + Returns a set of all input groups used by the workloads in a suite. + + :returns: A set of all input groups used by the workloads in a suite. + """ + return { + input_group + for input_groups in self._workloads.values() + for input_group in input_groups + } + + class WorkloadResource(AbstractResource): """A workload resource. This resource is used to specify a workload to run on a board. It contains the function to call and the parameters to pass to @@ -657,9 +773,14 @@ class WorkloadResource(AbstractResource): resource_version=resource_version, ) + self._id = id self._func = function self._params = parameters + def get_id(self) -> str: + """Returns the ID of the workload.""" + return self._id + def get_function_str(self) -> str: """ Returns the name of the workload function to be run. @@ -821,6 +942,21 @@ def obtain_resource( assert resources_category in _get_resource_json_type_map resource_class = _get_resource_json_type_map[resources_category] + if resources_category == "suite": + workloads = resource_json["workloads"] + workloads_obj = {} + for workload in workloads: + workloads_obj[ + obtain_resource( + workload["id"], + resource_version=workload["resource_version"], + resource_directory=resource_directory, + clients=clients, + gem5_version=gem5_version, + ) + ] = set(workload["input_group"]) + resource_json["workloads"] = workloads_obj + if resources_category == "workload": # This parses the "resources" and "additional_params" fields of the # workload resource into a dictionary of AbstractResource objects and @@ -844,6 +980,7 @@ def obtain_resource( # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the # subclass contructor, so we can pass the resource_json map directly. + return resource_class(local_path=to_path, **resource_json) @@ -995,5 +1132,6 @@ _get_resource_json_type_map = { "resource": Resource, "looppoint-pinpoint-csv": LooppointCsvResource, "looppoint-json": LooppointJsonResource, + "suite": SuiteResource, "workload": WorkloadResource, } diff --git a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py new file mode 100644 index 0000000000..5de68a6b1a --- /dev/null +++ b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py @@ -0,0 +1,170 @@ +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import contextlib +import io +import unittest +import tempfile +import os +import shutil +from pathlib import Path +from gem5.resources.resource import ( + obtain_resource, + SuiteResource, + WorkloadResource, +) +from gem5.resources.client_api.client_wrapper import ClientWrapper +from unittest.mock import patch + +mock_config_json = { + "sources": { + "baba": { + "url": Path(__file__).parent / "refs/suite-checks.json", + "isMongo": False, + } + }, +} + + +class CustomSuiteResourceTestSuite(unittest.TestCase): + @classmethod + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def setUpClass(cls): + cls.workload1 = obtain_resource("simple-workload-1") + cls.workload2 = obtain_resource("simple-workload-2") + cls.SuiteResource = SuiteResource( + workload_obj_list={cls.workload1: set(), cls.workload2: set()} + ) + + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def test_with_input_group(self) -> None: + """ + Tests the `with_input_group` function. + """ + # test if an input group can return a single workload in a suite resource + + with self.assertRaises(Exception) as context: + filtered_suite = self.SuiteResource.with_input_group("testtag2") + self.assertIsInstance(filtered_suite, SuiteResource) + self.assertEqual(len(filtered_suite), 0) + self.assertTrue( + f"Input group invalid not found in Suite.\n" + f"Available input groups are {filtered_suite.get_input_groups()}" + in str(context.exception) + ) + + def test_get_input_groups(self): + """ + Tests the `list_input_groups` function. + """ + self.assertEqual(self.SuiteResource.get_input_groups(), set()) + + +class SuiteResourceTestSuite(unittest.TestCase): + @classmethod + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def setUpClass(cls): + cls.suite = obtain_resource("suite-example", gem5_version="develop") + + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def test_with_input_group(self) -> None: + """ + Tests the `with_input_group` function. + """ + # test if an input group can return a single workload in a suite resource + filtered_suite = self.suite.with_input_group("testtag2") + self.assertIsInstance(filtered_suite, SuiteResource) + self.assertEqual(len(filtered_suite), 1) + for workload in filtered_suite: + self.assertIsInstance(workload, WorkloadResource) + + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def test_with_input_group_multiple(self) -> None: + # test if an input group can return multiple workloads in a suite resource + filtered_suite = self.suite.with_input_group("testtag1") + self.assertIsInstance(filtered_suite, SuiteResource) + self.assertEqual(len(filtered_suite), 2) + for workload in filtered_suite: + self.assertIsInstance(workload, WorkloadResource) + + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def test_with_input_group_invalid(self) -> None: + """ + Tests the `with_input_group` function with an invalid input group. + """ + with self.assertRaises(Exception) as context: + filtered_suite = self.suite.with_input_group("invalid") + # check if exception is raised + self.assertTrue( + f"Input group invalid not found in Suite.\n" + f"Available input groups are {filtered_suite.get_input_groups()}" + in str(context.exception) + ) + + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def test_get_input_groups(self) -> None: + """ + Tests the `list_input_groups` function. + """ + expected_input_groups = set(["testtag1", "testtag2", "testtag3"]) + self.assertEqual(self.suite.get_input_groups(), expected_input_groups) + + @patch( + "gem5.resources.client.clientwrapper", + new=ClientWrapper(mock_config_json), + ) + def test_get_input_groups_not_found(self) -> None: + """ + Tests the `list_input_groups` function with an invalid input group. + """ + with self.assertRaises(Exception) as context: + self.suite.get_input_groups("invalid") + self.assertTrue( + f"Input group invalid not found in Suite.\n" + f"Available input groups are {self.suite.get_input_groups()}" + in str(context.exception) + ) diff --git a/tests/pyunit/stdlib/resources/refs/suite-checks.json b/tests/pyunit/stdlib/resources/refs/suite-checks.json new file mode 100644 index 0000000000..7583020292 --- /dev/null +++ b/tests/pyunit/stdlib/resources/refs/suite-checks.json @@ -0,0 +1,97 @@ +[ + { + "id": "suite-example", + "category": "suite", + "resource_version": "1.0.0", + "gem5_versions": ["develop","23.1"], + "workloads": [ + { + "id": "simple-workload-1", + "resource_version": "1.0.0", + "input_group": ["testtag1", "testtag2"] + }, + { + "id": "simple-workload-2", + "resource_version": "1.0.0", + "input_group": ["testtag1", "testtag3"] + } + ] + }, + { + "category": "workload", + "id": "simple-workload-1", + "description": "Description of workload here", + "function": "set_kernel_disk_workload", + "resources": { + "kernel": "x86-linux-kernel-5.2.3-example", + "disk-image": "x86-ubuntu-18.04-img-example" + }, + "additional_params": { + "readfile_contents": "echo 'Boot successful'; m5 exit" + }, + "resource_version": "1.0.0", + "gem5_versions": [ + "develop" + ] + }, + { + "category": "workload", + "id": "simple-workload-2", + "description": "Description of workload here", + "function": "set_kernel_disk_workload", + "resources": { + "kernel": "x86-linux-kernel-5.2.3-example", + "disk-image": "x86-ubuntu-18.04-img-example" + }, + "additional_params": { + "readfile_contents": "echo 'Boot successful'; m5 exit" + }, + "resource_version": "1.0.0", + "gem5_versions": [ + "develop" + ] + }, + { + "category": "kernel", + "id": "x86-linux-kernel-5.2.3-example", + "description": "The linux kernel (v5.2.3), compiled to X86.", + "architecture": "X86", + "is_zipped": false, + "md5sum": "4838c99b77d33c8307b939c16624e4ac", + "url": "http://dist.gem5.org/dist/develop/kernels/x86/static/vmlinux-5.2.3", + "source": "src/linux-kernel", + "resource_version": "1.0.0", + "gem5_versions": [ + "develop" + ] + }, + { + "category": "disk-image", + "id": "x86-ubuntu-18.04-img-example", + "description": "A disk image containing Ubuntu 18.04 for x86..", + "architecture": "X86", + "is_zipped": false, + "md5sum": "dbf120338b37153e3334603970cebd8c", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/x86/linux/hello64-static", + "source": "src/x86-ubuntu", + "root_partition": "1", + "resource_version": "1.0.0", + "gem5_versions": [ + "develop" + ] + }, + { + "category": "binary", + "id": "x86-hello64-static-example", + "description": "A 'Hello World!' binary.", + "architecture": "X86", + "is_zipped": false, + "md5sum": "dbf120338b37153e3334603970cebd8c", + "url": "http://dist.gem5.org/dist/develop/test-progs/hello/bin/x86/linux/hello64-static", + "source": "src/simple", + "resource_version": "1.0.0", + "gem5_versions": [ + "develop" + ] + } +] From e211674625c1a20089808e11da60e3132cd5c052 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 29 Sep 2023 13:12:19 -0700 Subject: [PATCH 357/693] util-docker: Fix/Improve ubuntu-22.04_clang-16 * Removes `+` symbol accidently left in (this broke building). * Removes `ARG` thus making the Docker exclusively for clang-16. * Adds "llvm.sh" to the repo. This stops us being dependent on the url download. The script is under the apache license therefore compatible. * Merges several `apt install` commands into one. Change-Id: Iaf411656aac83f67f5395b20efd96ecc1eabb263 --- .../ubuntu-22.04_clang-16/Dockerfile | 22 +-- .../dockerfiles/ubuntu-22.04_clang-16/llvm.sh | 176 ++++++++++++++++++ 2 files changed, 183 insertions(+), 15 deletions(-) create mode 100755 util/dockerfiles/ubuntu-22.04_clang-16/llvm.sh diff --git a/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile b/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile index d06cf6fd67..efefcc063f 100644 --- a/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile @@ -25,33 +25,25 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. FROM ubuntu:22.04 -# Valid version values: -# 16 -ARG version ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ apt -y install git m4 scons zlib1g zlib1g-dev libprotobuf-dev \ protobuf-compiler libprotoc-dev libgoogle-perftools-dev python3-dev \ python-is-python3 doxygen libboost-all-dev libhdf5-serial-dev \ - python3-pydot libpng-dev make + python3-pydot libpng-dev make lsb-release wget \ + software-properties-common gnupg -RUN apt-get update && apt-get -y install sudo wget - -# extra installations to have wget work -RUN apt -y install lsb-release wget software-properties-common gnupg -RUN wget https://apt.llvm.org/llvm.sh -+ -RUN chmod u+x llvm.sh +COPY llvm.sh /llvm.sh RUN ./llvm.sh 16 RUN apt-get --purge -y remove gcc RUN update-alternatives --install \ - /usr/bin/clang++ clang++ /usr/bin/clang++-${version} 100 + /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 RUN update-alternatives --install \ - /usr/bin/clang clang /usr/bin/clang-${version} 100 + /usr/bin/clang clang /usr/bin/clang-16 100 RUN update-alternatives --install \ - /usr/bin/c++ c++ /usr/bin/clang++-${version} 100 + /usr/bin/c++ c++ /usr/bin/clang++-16 100 RUN update-alternatives --install \ - /usr/bin/cc cc /usr/bin/clang-${version} 100 + /usr/bin/cc cc /usr/bin/clang-16 100 diff --git a/util/dockerfiles/ubuntu-22.04_clang-16/llvm.sh b/util/dockerfiles/ubuntu-22.04_clang-16/llvm.sh new file mode 100755 index 0000000000..200c0390fe --- /dev/null +++ b/util/dockerfiles/ubuntu-22.04_clang-16/llvm.sh @@ -0,0 +1,176 @@ +#!/bin/bash +################################################################################ +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +################################################################################ +# +# This script will install the llvm toolchain on the different +# Debian and Ubuntu versions + +set -eux + +usage() { + set +x + echo "Usage: $0 [llvm_major_version] [all] [OPTIONS]" 1>&2 + echo -e "all\t\t\tInstall all packages." 1>&2 + echo -e "-n=code_name\t\tSpecifies the distro codename, for example bionic" 1>&2 + echo -e "-h\t\t\tPrints this help." 1>&2 + echo -e "-m=repo_base_url\tSpecifies the base URL from which to download." 1>&2 + exit 1; +} + +CURRENT_LLVM_STABLE=17 +BASE_URL="http://apt.llvm.org" + +# Check for required tools +needed_binaries=(lsb_release wget add-apt-repository gpg) +missing_binaries=() +for binary in "${needed_binaries[@]}"; do + if ! which $binary &>/dev/null ; then + missing_binaries+=($binary) + fi +done +if [[ ${#missing_binaries[@]} -gt 0 ]] ; then + echo "You are missing some tools this script requires: ${missing_binaries[@]}" + echo "(hint: apt install lsb-release wget software-properties-common gnupg)" + exit 4 +fi + +# Set default values for commandline arguments +# We default to the current stable branch of LLVM +LLVM_VERSION=$CURRENT_LLVM_STABLE +ALL=0 +DISTRO=$(lsb_release -is) +VERSION=$(lsb_release -sr) +UBUNTU_CODENAME="" +CODENAME_FROM_ARGUMENTS="" +# Obtain VERSION_CODENAME and UBUNTU_CODENAME (for Ubuntu and its derivatives) +source /etc/os-release +DISTRO=${DISTRO,,} +case ${DISTRO} in + debian) + # Debian Trixie has a workaround because of + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1038383 + if [[ "${VERSION}" == "unstable" ]] || [[ "${VERSION}" == "testing" ]] || [[ "${VERSION_CODENAME}" == "trixie" ]]; then + CODENAME=unstable + LINKNAME= + else + # "stable" Debian release + CODENAME=${VERSION_CODENAME} + LINKNAME=-${CODENAME} + fi + ;; + *) + # ubuntu and its derivatives + if [[ -n "${UBUNTU_CODENAME}" ]]; then + CODENAME=${UBUNTU_CODENAME} + if [[ -n "${CODENAME}" ]]; then + LINKNAME=-${CODENAME} + fi + fi + ;; +esac + +# read optional command line arguments +if [ "$#" -ge 1 ] && [ "${1::1}" != "-" ]; then + if [ "$1" != "all" ]; then + LLVM_VERSION=$1 + else + # special case for ./llvm.sh all + ALL=1 + fi + OPTIND=2 + if [ "$#" -ge 2 ]; then + if [ "$2" == "all" ]; then + # Install all packages + ALL=1 + OPTIND=3 + fi + fi +fi + +while getopts ":hm:n:" arg; do + case $arg in + h) + usage + ;; + m) + BASE_URL=${OPTARG} + ;; + n) + CODENAME=${OPTARG} + if [[ "${CODENAME}" == "unstable" ]]; then + # link name does not apply to unstable repository + LINKNAME= + else + LINKNAME=-${CODENAME} + fi + CODENAME_FROM_ARGUMENTS="true" + ;; + esac +done + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root!" + exit 1 +fi + +declare -A LLVM_VERSION_PATTERNS +LLVM_VERSION_PATTERNS[9]="-9" +LLVM_VERSION_PATTERNS[10]="-10" +LLVM_VERSION_PATTERNS[11]="-11" +LLVM_VERSION_PATTERNS[12]="-12" +LLVM_VERSION_PATTERNS[13]="-13" +LLVM_VERSION_PATTERNS[14]="-14" +LLVM_VERSION_PATTERNS[15]="-15" +LLVM_VERSION_PATTERNS[16]="-16" +LLVM_VERSION_PATTERNS[17]="-17" +LLVM_VERSION_PATTERNS[18]="" + +if [ ! ${LLVM_VERSION_PATTERNS[$LLVM_VERSION]+_} ]; then + echo "This script does not support LLVM version $LLVM_VERSION" + exit 3 +fi + +LLVM_VERSION_STRING=${LLVM_VERSION_PATTERNS[$LLVM_VERSION]} + +# join the repository name +if [[ -n "${CODENAME}" ]]; then + REPO_NAME="deb ${BASE_URL}/${CODENAME}/ llvm-toolchain${LINKNAME}${LLVM_VERSION_STRING} main" + + # check if the repository exists for the distro and version + if ! wget -q --method=HEAD ${BASE_URL}/${CODENAME} &> /dev/null; then + if [[ -n "${CODENAME_FROM_ARGUMENTS}" ]]; then + echo "Specified codename '${CODENAME}' is not supported by this script." + else + echo "Distribution '${DISTRO}' in version '${VERSION}' is not supported by this script." + fi + exit 2 + fi +fi + + +# install everything + +if [[ ! -f /etc/apt/trusted.gpg.d/apt.llvm.org.asc ]]; then + # download GPG key once + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc +fi + +if [[ -z "`apt-key list 2> /dev/null | grep -i llvm`" ]]; then + # Delete the key in the old format + apt-key del AF4F7421 +fi +add-apt-repository "${REPO_NAME}" +apt-get update +PKG="clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION" +if [[ $ALL -eq 1 ]]; then + # same as in test-install.sh + # No worries if we have dups + PKG="$PKG clang-tidy-$LLVM_VERSION clang-format-$LLVM_VERSION clang-tools-$LLVM_VERSION llvm-$LLVM_VERSION-dev lld-$LLVM_VERSION lldb-$LLVM_VERSION llvm-$LLVM_VERSION-tools libomp-$LLVM_VERSION-dev libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev libclang-common-$LLVM_VERSION-dev libclang-$LLVM_VERSION-dev libclang-cpp$LLVM_VERSION-dev libunwind-$LLVM_VERSION-dev" + if test $LLVM_VERSION -gt 14; then + PKG="$PKG libclang-rt-$LLVM_VERSION-dev libpolly-$LLVM_VERSION-dev" + fi +fi +apt-get install -y $PKG From da72590c1961d05f6ce678deecf115372b2930e5 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 1 Oct 2023 22:52:07 -0700 Subject: [PATCH 358/693] arch-riscv: FS bits -> DIRTY for more floating point loads The affected instructions are, - c.flw - c.flwsp - flh - flw This change is related to [1] [2], which also aim to change the FS bits to DIRTY when the state of any floating point register might change. [1] https://gem5-review.googlesource.com/c/public/gem5/+/65272 [2] https://github.com/gem5/gem5/pull/370 Change-Id: I098e1b1812fb352bd5d3614ff5d3547e58903b65 Signed-off-by: Hoa Nguyen --- src/arch/riscv/isa/decoder.isa | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 0ad7283fcd..2f110fca35 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -90,6 +90,9 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("FPU is off", machInst); + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + freg_t fd = freg(f32(Mem_uw)); Fp2_bits = fd.v; }}, {{ @@ -317,8 +320,6 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("FPU is off", machInst); - // Mutating any floating point register changes the FS bit - // of the STATUS CSR. status.fs = FPUStatus::DIRTY; xc->setMiscReg(MISCREG_STATUS, status); @@ -350,6 +351,9 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("FPU is off", machInst); + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + freg_t fd; fd = freg(f32(Mem_uw)); Fd_bits = fd.v; @@ -487,6 +491,10 @@ decode QUADRANT default Unknown::unknown() { if (status.fs == FPUStatus::OFF) return std::make_shared( "FPU is off", machInst); + + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + freg_t fd; fd = freg(f16(Mem_uh)); Fd_bits = fd.v; @@ -496,6 +504,10 @@ decode QUADRANT default Unknown::unknown() { if (status.fs == FPUStatus::OFF) return std::make_shared( "FPU is off", machInst); + + status.fs = FPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + freg_t fd; fd = freg(f32(Mem_uw)); Fd_bits = fd.v; @@ -506,8 +518,6 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared( "FPU is off", machInst); - // Mutating any floating point register changes the FS bit - // of the STATUS CSR. status.fs = FPUStatus::DIRTY; xc->setMiscReg(MISCREG_STATUS, status); From 7d2e1ee789413e6ace8bcf009897eea10b603f51 Mon Sep 17 00:00:00 2001 From: David Schall Date: Tue, 27 Jun 2023 08:46:39 +0000 Subject: [PATCH 359/693] arch: Add instruction size and PC set methods Adds the instruction size to all static instruction. x86, arm and RISC-V decoders add the instruction size to every decoded macro instruction. As microops should reflect the size of the their parent macroop the set method is overwritten to pass the size to all microops. Furthermore, we add a set method to the PC state. It allows setting a PC state to a certain address. Both methods are required for the decoupled front-end. Change-Id: I311fe3f637e867c42dee7781f5373ea2e69e2072 Signed-off-by: David Schall --- src/arch/arm/decoder.hh | 1 + src/arch/arm/insts/pred_inst.hh | 9 +++++++++ src/arch/generic/pcstate.hh | 22 +++++++++++++++++++--- src/arch/riscv/decoder.cc | 3 +++ src/arch/riscv/insts/static_inst.hh | 9 +++++++++ src/arch/x86/decoder.cc | 5 +++-- src/arch/x86/insts/macroop.hh | 8 ++++++++ src/cpu/static_inst.hh | 17 +++++++++++++++++ 8 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/arch/arm/decoder.hh b/src/arch/arm/decoder.hh index 83690936c0..75488b6750 100644 --- a/src/arch/arm/decoder.hh +++ b/src/arch/arm/decoder.hh @@ -138,6 +138,7 @@ class Decoder : public InstDecoder StaticInstPtr si = defaultCache.decode(this, mach_inst, addr); DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n", si->getName(), mach_inst); + si->size((!emi.thumb || emi.bigThumb) ? 4 : 2); return si; } diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh index da3db6c6a5..6f46831edb 100644 --- a/src/arch/arm/insts/pred_inst.hh +++ b/src/arch/arm/insts/pred_inst.hh @@ -378,6 +378,15 @@ class PredMacroOp : public PredOp std::string generateDisassembly( Addr pc, const loader::SymbolTable *symtab) const override; + + + void size(size_t newSize) override + { + for (int i = 0; i < numMicroops; i++) { + microOps[i]->size(newSize); + } + _size = newSize; + } }; /** diff --git a/src/arch/generic/pcstate.hh b/src/arch/generic/pcstate.hh index f1df6e7c39..5c278a4233 100644 --- a/src/arch/generic/pcstate.hh +++ b/src/arch/generic/pcstate.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 ARM Limited + * Copyright (c) 2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -126,6 +127,13 @@ class PCStateBase : public Serializable _upc = 0; } + virtual void + set(Addr val) + { + _pc = val; + _upc = 0; + } + virtual void advance() = 0; virtual bool branching() const = 0; @@ -309,6 +317,14 @@ class PCStateWithNext : public PCStateBase _npc == ps._npc && _nupc == ps._nupc; } + void + set(Addr val) override + { + PCStateBase::set(val); + _npc = 0; + _nupc = 1; + } + void serialize(CheckpointOut &cp) const override { @@ -359,9 +375,9 @@ class SimplePCState : public PCStateWithNext * @param val The value to set the PC to. */ void - set(Addr val) + set(Addr val) override { - this->pc(val); + Base::set(val); this->npc(val + InstWidth); }; @@ -402,7 +418,7 @@ class UPCState : public SimplePCState } void - set(Addr val) + set(Addr val) override { Base::set(val); this->upc(0); diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index d225871241..b1e2948e93 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -96,6 +96,8 @@ Decoder::decode(ExtMachInst mach_inst, Addr addr) if (!si) si = decodeInst(mach_inst); + si->size(compressed(mach_inst) ? 2 : 4); + DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n", si->getName(), mach_inst); return si; @@ -122,6 +124,7 @@ Decoder::decode(PCStateBase &_next_pc) emi.vtype8 = next_pc.vtype() & 0xff; emi.vill = next_pc.vtype().vill; emi.rv_type = static_cast(next_pc.rvType()); + return decode(emi, next_pc.instAddr()); } diff --git a/src/arch/riscv/insts/static_inst.hh b/src/arch/riscv/insts/static_inst.hh index 74f9ddb452..2e4d94864a 100644 --- a/src/arch/riscv/insts/static_inst.hh +++ b/src/arch/riscv/insts/static_inst.hh @@ -146,6 +146,15 @@ class RiscvMacroInst : public RiscvStaticInst { panic("Tried to execute a macroop directly!\n"); } + + void size(size_t newSize) override + { + for (int i = 0; i < microops.size(); i++) { + microops[i]->size(newSize); + } + _size = newSize; + } + }; /** diff --git a/src/arch/x86/decoder.cc b/src/arch/x86/decoder.cc index ef87ff37c4..af2456d6ab 100644 --- a/src/arch/x86/decoder.cc +++ b/src/arch/x86/decoder.cc @@ -687,6 +687,8 @@ Decoder::decode(ExtMachInst mach_inst, Addr addr) (*instMap)[mach_inst] = si; } + si->size(basePC + offset - origPC); + DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n", si->getName(), mach_inst); return si; @@ -732,8 +734,7 @@ Decoder::decode(PCStateBase &next_pc) start = 0; } - si = decode(emi, origPC); - return si; + return decode(emi, origPC); } StaticInstPtr diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh index 36718f77fd..071037b173 100644 --- a/src/arch/x86/insts/macroop.hh +++ b/src/arch/x86/insts/macroop.hh @@ -103,6 +103,14 @@ class MacroopBase : public X86StaticInst { return env; } + + void size(size_t newSize) override + { + for (int i = 0; i < numMicroops; i++) { + microops[i]->size(newSize); + } + _size = newSize; + } }; } // namespace X86ISA diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 7ecc57d2f0..b98c01f872 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, 2020 ARM Limited + * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -250,6 +251,11 @@ class StaticInst : public RefCounted, public StaticInstFlags _destRegIdxPtr = dest; } + /** + * Instruction size in bytes. Necessary for dynamic instruction sizes + */ + size_t _size = 0; + /** * Base mnemonic (e.g., "add"). Used by generateDisassembly() * methods. Also useful to readily identify instructions from @@ -307,6 +313,17 @@ class StaticInst : public RefCounted, public StaticInstFlags panic("buildRetPC not defined!"); } + size_t size() const + { + if (_size == 0) fatal( + "Instruction size for this instruction not set! It's size is " + "required for the decoupled front-end. Either use the standard " + "front-end or this ISA needs to be extended with the instruction " + "size. Refer to the X86, Arm or RiscV decoders for an example."); + return _size; + } + virtual void size(size_t newSize) { _size = newSize; } + /** * Return the microop that goes with a particular micropc. This should * only be defined/used in macroops which will contain microops From 107e05266d9cd03b2f9ff5ba7ac4d8be430a3aa0 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Fri, 29 Sep 2023 14:29:47 -0500 Subject: [PATCH 360/693] dev-amdgpu: Add aql, hsa queue information to checkpoint-restore GPUFS uses aql information from PM4 queues to initialize doorbells. This commit adds aql information to the checkpoint so that it can be used during restoration to correctly initialize all doorbells. Additionally, this commit also sets the hsa queue correctly during checkpoint-restoration Change-Id: Ief3ef6dc973f70f27255234872a12c396df05d89 --- src/dev/amdgpu/pm4_packet_processor.cc | 29 +++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/dev/amdgpu/pm4_packet_processor.cc b/src/dev/amdgpu/pm4_packet_processor.cc index e7b846529e..63a3bf8887 100644 --- a/src/dev/amdgpu/pm4_packet_processor.cc +++ b/src/dev/amdgpu/pm4_packet_processor.cc @@ -1044,6 +1044,7 @@ PM4PacketProcessor::serialize(CheckpointOut &cp) const int num_queues = queues.size(); Addr id[num_queues]; Addr mqd_base[num_queues]; + uint64_t mqd_read_index[num_queues]; Addr base[num_queues]; Addr rptr[num_queues]; Addr wptr[num_queues]; @@ -1060,6 +1061,7 @@ PM4PacketProcessor::serialize(CheckpointOut &cp) const uint32_t hqd_active[num_queues]; uint32_t hqd_vmid[num_queues]; Addr aql_rptr[num_queues]; + uint32_t aql[num_queues]; uint32_t doorbell[num_queues]; uint32_t hqd_pq_control[num_queues]; @@ -1068,9 +1070,10 @@ PM4PacketProcessor::serialize(CheckpointOut &cp) const PM4Queue *q = iter.second; id[i] = q->id(); mqd_base[i] = q->mqdBase(); + mqd_read_index[i] = q->getMQD()->mqdReadIndex; bool cur_state = q->ib(); q->ib(false); - base[i] = q->base() >> 8; + base[i] = q->base(); rptr[i] = q->getRptr(); wptr[i] = q->getWptr(); q->ib(true); @@ -1088,6 +1091,7 @@ PM4PacketProcessor::serialize(CheckpointOut &cp) const hqd_active[i] = q->getMQD()->hqd_active; hqd_vmid[i] = q->getMQD()->hqd_vmid; aql_rptr[i] = q->getMQD()->aqlRptr; + aql[i] = q->getMQD()->aql; doorbell[i] = q->getMQD()->doorbell; hqd_pq_control[i] = q->getMQD()->hqd_pq_control; i++; @@ -1096,6 +1100,7 @@ PM4PacketProcessor::serialize(CheckpointOut &cp) const SERIALIZE_SCALAR(num_queues); SERIALIZE_ARRAY(id, num_queues); SERIALIZE_ARRAY(mqd_base, num_queues); + SERIALIZE_ARRAY(mqd_read_index, num_queues); SERIALIZE_ARRAY(base, num_queues); SERIALIZE_ARRAY(rptr, num_queues); SERIALIZE_ARRAY(wptr, num_queues); @@ -1112,6 +1117,7 @@ PM4PacketProcessor::serialize(CheckpointOut &cp) const SERIALIZE_ARRAY(hqd_active, num_queues); SERIALIZE_ARRAY(hqd_vmid, num_queues); SERIALIZE_ARRAY(aql_rptr, num_queues); + SERIALIZE_ARRAY(aql, num_queues); SERIALIZE_ARRAY(doorbell, num_queues); SERIALIZE_ARRAY(hqd_pq_control, num_queues); } @@ -1127,6 +1133,7 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) Addr id[num_queues]; Addr mqd_base[num_queues]; + uint64_t mqd_read_index[num_queues]; Addr base[num_queues]; Addr rptr[num_queues]; Addr wptr[num_queues]; @@ -1143,11 +1150,13 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) uint32_t hqd_active[num_queues]; uint32_t hqd_vmid[num_queues]; Addr aql_rptr[num_queues]; + uint32_t aql[num_queues]; uint32_t doorbell[num_queues]; uint32_t hqd_pq_control[num_queues]; UNSERIALIZE_ARRAY(id, num_queues); UNSERIALIZE_ARRAY(mqd_base, num_queues); + UNSERIALIZE_ARRAY(mqd_read_index, num_queues); UNSERIALIZE_ARRAY(base, num_queues); UNSERIALIZE_ARRAY(rptr, num_queues); UNSERIALIZE_ARRAY(wptr, num_queues); @@ -1164,6 +1173,7 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) UNSERIALIZE_ARRAY(hqd_active, num_queues); UNSERIALIZE_ARRAY(hqd_vmid, num_queues); UNSERIALIZE_ARRAY(aql_rptr, num_queues); + UNSERIALIZE_ARRAY(aql, num_queues); UNSERIALIZE_ARRAY(doorbell, num_queues); UNSERIALIZE_ARRAY(hqd_pq_control, num_queues); @@ -1172,19 +1182,20 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) memset(mqd, 0, sizeof(QueueDesc)); mqd->mqdBase = mqd_base[i] >> 8; - mqd->base = base[i]; - mqd->rptr = rptr[i]; - mqd->ibBase = ib_base[i]; - mqd->ibRptr = ib_rptr[i]; + mqd->mqdReadIndex = mqd_read_index[i]; + mqd->base = base[i] >> 8; + mqd->aql = aql[i]; PM4MapQueues* pkt = new PM4MapQueues; memset(pkt, 0, sizeof(PM4MapQueues)); newQueue(mqd, offset[i], pkt, id[i]); queues[id[i]]->ib(false); + queues[id[i]]->rptr(rptr[i]); queues[id[i]]->wptr(wptr[i]); queues[id[i]]->ib(true); queues[id[i]]->wptr(ib_wptr[i]); + queues[id[i]]->rptr(ib_rptr[i]); queues[id[i]]->offset(offset[i]); queues[id[i]]->processing(processing[i]); queues[id[i]]->ib(ib[i]); @@ -1195,6 +1206,14 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) queues[id[i]]->getMQD()->doorbell = doorbell[i]; queues[id[i]]->getMQD()->hqd_pq_control = hqd_pq_control[i]; + if (mqd->aql) { + int mqd_size = (1 << ((hqd_pq_control[i] & 0x3f) + 1)) * 4; + auto &hsa_pp = gpuDevice->CP()->hsaPacketProc(); + hsa_pp.setDeviceQueueDesc(aql_rptr[i], base[i], id[i], + mqd_size, 8, GfxVersion::gfx900, offset[i], + mqd_read_index[i]); + } + DPRINTF(PM4PacketProcessor, "PM4 queue %d, rptr: %p wptr: %p\n", queues[id[i]]->id(), queues[id[i]]->rptr(), queues[id[i]]->wptr()); From a50ead5907771d4b38bcfed615069d9e3ad9283d Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Fri, 29 Sep 2023 16:32:22 -0500 Subject: [PATCH 361/693] mem-ruby: Add Flush as a supported memory type in VIPERCoalescer This commit adds flush as a recognized memory type in VIPERCoalescer. Change-Id: I0f1b6f4518548e8e893ef681955b12a49293d8b4 --- src/mem/ruby/system/VIPERCoalescer.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mem/ruby/system/VIPERCoalescer.cc b/src/mem/ruby/system/VIPERCoalescer.cc index ea95129841..a5198cce63 100644 --- a/src/mem/ruby/system/VIPERCoalescer.cc +++ b/src/mem/ruby/system/VIPERCoalescer.cc @@ -75,12 +75,14 @@ VIPERCoalescer::makeRequest(PacketPtr pkt) // ReadReq : cache read // WriteReq : cache write // AtomicOp : cache atomic + // Flush : flush and invalidate cache // // VIPER does not expect MemSyncReq & Release since in GCN3, compute unit // does not specify an equivalent type of memory request. assert((pkt->cmd == MemCmd::MemSyncReq && pkt->req->isInvL1()) || pkt->cmd == MemCmd::ReadReq || pkt->cmd == MemCmd::WriteReq || + pkt->cmd == MemCmd::FlushReq || pkt->isAtomicOp()); if (pkt->req->isInvL1() && m_cache_inv_pkt) { From 61e39d5b26465ce362249bd544cc68a725af1fdf Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Fri, 29 Sep 2023 16:37:41 -0500 Subject: [PATCH 362/693] mem-ruby: Add cache cooldown and warmup support to GPUCoalescer The GPU Coalescer does not contain cache cooldown and warmup support. This commit updates the coalsecer to support cache cooldown during flush and warmup during checkpoint restore. Change-Id: I5459471dec20ff304fd5954af1079a7486ee860a --- src/mem/ruby/system/GPUCoalescer.cc | 94 ++++++++++++++++++++++------- src/mem/ruby/system/GPUCoalescer.hh | 3 + 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/mem/ruby/system/GPUCoalescer.cc b/src/mem/ruby/system/GPUCoalescer.cc index beb8da3f9c..a70af07467 100644 --- a/src/mem/ruby/system/GPUCoalescer.cc +++ b/src/mem/ruby/system/GPUCoalescer.cc @@ -73,6 +73,14 @@ UncoalescedTable::insertPacket(PacketPtr pkt) pkt->getAddr(), seqNum, instMap.size(), instMap[seqNum].size()); } +void +UncoalescedTable::insertReqType(PacketPtr pkt, RubyRequestType type) +{ + uint64_t seqNum = pkt->req->getReqInstSeqNum(); + + reqTypeMap[seqNum] = type; +} + bool UncoalescedTable::packetAvailable() { @@ -128,9 +136,21 @@ UncoalescedTable::updateResources() instMap.erase(iter++); instPktsRemaining.erase(seq_num); - // Release the token - DPRINTF(GPUCoalescer, "Returning token seqNum %d\n", seq_num); - coalescer->getGMTokenPort().sendTokens(1); + // Release the token if the Ruby system is not in cooldown + // or warmup phases. When in these phases, the RubyPorts + // are accessed directly using the makeRequest() command + // instead of accessing through the port. This makes + // sending tokens through the port unnecessary + if (!RubySystem::getWarmupEnabled() + && !RubySystem::getCooldownEnabled()) { + if (reqTypeMap[seq_num] != RubyRequestType_FLUSH) { + DPRINTF(GPUCoalescer, + "Returning token seqNum %d\n", seq_num); + coalescer->getGMTokenPort().sendTokens(1); + } + } + + reqTypeMap.erase(seq_num); } else { ++iter; } @@ -565,6 +585,14 @@ GPUCoalescer::hitCallback(CoalescedRequest* crequest, for (auto& pkt : pktList) { offset = getOffset(pkt->getAddr()); pkt_size = pkt->getSize(); + request_address = pkt->getAddr(); + + // When the Ruby system is cooldown phase, the requests come from + // the cache recorder. These requests do not get coalesced and + // do not return valid data. + if (RubySystem::getCooldownEnabled()) + continue; + if (pkt->getPtr()) { switch(type) { // Store and AtomicNoReturns follow the same path, as the @@ -627,7 +655,6 @@ GPUCoalescer::getRequestType(PacketPtr pkt) assert(!pkt->req->isLLSC()); assert(!pkt->req->isLockedRMW()); assert(!pkt->req->isInstFetch()); - assert(!pkt->isFlush()); if (pkt->req->isAtomicReturn()) { req_type = RubyRequestType_ATOMIC_RETURN; @@ -637,6 +664,8 @@ GPUCoalescer::getRequestType(PacketPtr pkt) req_type = RubyRequestType_LD; } else if (pkt->isWrite()) { req_type = RubyRequestType_ST; + } else if (pkt->isFlush()) { + req_type = RubyRequestType_FLUSH; } else { panic("Unsupported ruby packet type\n"); } @@ -658,7 +687,7 @@ GPUCoalescer::makeRequest(PacketPtr pkt) issueMemSyncRequest(pkt); } else { // otherwise, this must be either read or write command - assert(pkt->isRead() || pkt->isWrite()); + assert(pkt->isRead() || pkt->isWrite() || pkt->isFlush()); InstSeqNum seq_num = pkt->req->getReqInstSeqNum(); @@ -667,10 +696,17 @@ GPUCoalescer::makeRequest(PacketPtr pkt) // number of lanes actives for that vmem request (i.e., the popcnt // of the exec_mask. int num_packets = 1; - if (!m_usingRubyTester) { - num_packets = 0; - for (int i = 0; i < TheGpuISA::NumVecElemPerVecReg; i++) { - num_packets += getDynInst(pkt)->getLaneStatus(i); + + // When Ruby is in warmup or cooldown phase, the requests come from + // the cache recorder. There is no dynamic instruction associated + // with these requests either + if (!RubySystem::getWarmupEnabled() + && !RubySystem::getCooldownEnabled()) { + if (!m_usingRubyTester) { + num_packets = 0; + for (int i = 0; i < TheGpuISA::NumVecElemPerVecReg; i++) { + num_packets += getDynInst(pkt)->getLaneStatus(i); + } } } @@ -679,6 +715,7 @@ GPUCoalescer::makeRequest(PacketPtr pkt) // future cycle. Packets remaining is set to the number of excepted // requests from the instruction based on its exec_mask. uncoalescedTable.insertPacket(pkt); + uncoalescedTable.insertReqType(pkt, getRequestType(pkt)); uncoalescedTable.initPacketsRemaining(seq_num, num_packets); DPRINTF(GPUCoalescer, "Put pkt with addr 0x%X to uncoalescedTable\n", pkt->getAddr()); @@ -945,21 +982,27 @@ void GPUCoalescer::completeHitCallback(std::vector & mylist) { for (auto& pkt : mylist) { - RubyPort::SenderState *ss = - safe_cast(pkt->senderState); - MemResponsePort *port = ss->port; - assert(port != NULL); + // When Ruby is in warmup or cooldown phase, the requests come + // from the cache recorder. They do not track which port to use + // and do not need to send the response back + if (!RubySystem::getWarmupEnabled() + && !RubySystem::getCooldownEnabled()) { + RubyPort::SenderState *ss = + safe_cast(pkt->senderState); + MemResponsePort *port = ss->port; + assert(port != NULL); - pkt->senderState = ss->predecessor; + pkt->senderState = ss->predecessor; - if (pkt->cmd != MemCmd::WriteReq) { - // for WriteReq, we keep the original senderState until - // writeCompleteCallback - delete ss; + if (pkt->cmd != MemCmd::WriteReq) { + // for WriteReq, we keep the original senderState until + // writeCompleteCallback + delete ss; + } + + port->hitCallback(pkt); + trySendRetries(); } - - port->hitCallback(pkt); - trySendRetries(); } // We schedule an event in the same tick as hitCallback (similar to @@ -971,7 +1014,14 @@ GPUCoalescer::completeHitCallback(std::vector & mylist) schedule(issueEvent, curTick()); } - testDrainComplete(); + RubySystem *rs = m_ruby_system; + if (RubySystem::getWarmupEnabled()) { + rs->m_cache_recorder->enqueueNextFetchRequest(); + } else if (RubySystem::getCooldownEnabled()) { + rs->m_cache_recorder->enqueueNextFlushRequest(); + } else { + testDrainComplete(); + } } void diff --git a/src/mem/ruby/system/GPUCoalescer.hh b/src/mem/ruby/system/GPUCoalescer.hh index dd28855547..d6db5c00ba 100644 --- a/src/mem/ruby/system/GPUCoalescer.hh +++ b/src/mem/ruby/system/GPUCoalescer.hh @@ -71,6 +71,7 @@ class UncoalescedTable ~UncoalescedTable() {} void insertPacket(PacketPtr pkt); + void insertReqType(PacketPtr pkt, RubyRequestType type); bool packetAvailable(); void printRequestTable(std::stringstream& ss); @@ -101,6 +102,8 @@ class UncoalescedTable std::map instMap; std::map instPktsRemaining; + + std::map reqTypeMap; }; class CoalescedRequest From 085789d00c4391b6b863981fb25e9cb8a7e7a445 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Fri, 29 Sep 2023 18:19:37 -0500 Subject: [PATCH 363/693] mem-ruby: Add flush support to GPU_VIPER protocol This commit adds flush support to the GPU VIPER coherence protocol. The L1 cache will now initiate a flush request if the packet it receives is of type RubyRequestType_FLUSH. During the flush process, the L1 cache will a request to L2 if its in either V or I state. L2 will issue a flush request to the directory if its cache line is in the valid state before invalidating its copy. The directory, on receiving this request, writes data to memory and sends an ack back to the L2. L2 forwards this ack back to the L1, which then ends the flush by calling the write callback Change-Id: I9dfc0c7b71a1e9f6d5e9e6ed4977c1e6a3b5ba46 --- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 52 ++++++++++++++++++- src/mem/ruby/protocol/GPU_VIPER-TCP.sm | 46 ++++++++++++++++- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 55 +++++++++++++++++++++ 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index 20a0979af1..be1243aaa5 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -65,7 +65,8 @@ machine(MachineType:TCC, "TCC Cache") AtomicPassOn, desc="Atomic Op Passed on to Directory"; AtomicDone, desc="AtomicOps Complete"; AtomicNotDone, desc="AtomicOps not Complete"; - Data, desc="data messgae"; + Data, desc="Data message"; + Flush, desc="Flush cache entry"; // Coming from this TCC L2_Repl, desc="L2 Replacement"; // Probes @@ -376,6 +377,8 @@ machine(MachineType:TCC, "TCC Cache") } else { trigger(Event:RdBlk, in_msg.addr, cache_entry, tbe); } + } else if (in_msg.Type == CoherenceRequestType:WriteFlush) { + trigger(Event:Flush, in_msg.addr, cache_entry, tbe); } else { DPRINTF(RubySlicc, "%s\n", in_msg); error("Unexpected Response Message to Core"); @@ -509,6 +512,20 @@ machine(MachineType:TCC, "TCC Cache") } } + action(fw_sendFlushResponse, "fw", desc="send Flush Response") { + peek(coreRequestNetwork_in, CPURequestMsg) { + enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { + out_msg.addr := address; + out_msg.Type := CoherenceResponseType:TDSysWBAck; + out_msg.Destination.clear(); + out_msg.Destination.add(in_msg.Requestor); + out_msg.Sender := machineID; + out_msg.MessageSize := MessageSizeType:Writeback_Control; + out_msg.instSeqNum := in_msg.instSeqNum; + } + } + } + action(ar_sendAtomicResponse, "ar", desc="send Atomic Ack") { peek(coreRequestNetwork_in, CPURequestMsg) { enqueue(responseToCore_out, ResponseMsg, l2_response_latency + glc_atomic_latency, true) { @@ -628,6 +645,22 @@ machine(MachineType:TCC, "TCC Cache") } } + action(f_flush, "f", desc="write back data") { + peek(coreRequestNetwork_in, CPURequestMsg) { + enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { + out_msg.addr := address; + out_msg.Requestor := machineID; + out_msg.WTRequestor := in_msg.Requestor; + out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); + out_msg.MessageSize := MessageSizeType:Data; + out_msg.Type := CoherenceRequestType:WriteFlush; + out_msg.Dirty := true; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.writeMask.orMask(cache_entry.writeMask); + } + } + } + action(at_atomicThrough, "at", desc="write back data") { peek(coreRequestNetwork_in, CPURequestMsg) { enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { @@ -1075,4 +1108,21 @@ machine(MachineType:TCC, "TCC Cache") transition(WIB, WBAck,I) { pr_popResponseQueue; } + + transition({A, IV, WI, WIB}, Flush) { + st_stallAndWaitRequest; + } + + transition(I, Flush) { + fw_sendFlushResponse; + p_popRequestQueue; + } + + transition({V, W}, Flush, I) {TagArrayRead, TagArrayWrite} { + t_allocateTBE; + ut_updateTag; + f_flush; + i_invL2; + p_popRequestQueue; + } } diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm index 7e0ad4ed96..8244879c55 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm @@ -55,6 +55,8 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") I, AccessPermission:Invalid, desc="Invalid"; V, AccessPermission:Read_Only, desc="Valid"; A, AccessPermission:Invalid, desc="Waiting on Atomic"; + + F, AccessPermission:Invalid, desc="Flushing; Waiting for Ack"; } enumeration(Event, desc="TCP Events") { @@ -256,6 +258,8 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") peek(responseToTCP_in, ResponseMsg, block_on="addr") { Entry cache_entry := getCacheEntry(in_msg.addr); TBE tbe := TBEs.lookup(in_msg.addr); + DPRINTF(RubySlicc, "In responseToTCP_in with %s\n", in_msg); + if (in_msg.Type == CoherenceResponseType:TDSysResp) { if (disableL1 || in_msg.isGLCSet || in_msg.isSLCSet) { // If L1 is disabled or requests have GLC or SLC flag set, @@ -273,6 +277,7 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") } else if (in_msg.Type == CoherenceResponseType:TDSysWBAck || in_msg.Type == CoherenceResponseType:NBSysWBAck) { trigger(Event:TCC_AckWB, in_msg.addr, cache_entry, tbe); + DPRINTF(RubySlicc, "Issuing TCC_AckWB\n"); } else { error("Unexpected Response Message to Core"); } @@ -469,6 +474,24 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") action(sf_setFlush, "sf", desc="set flush") { inFlush := true; APPEND_TRANSITION_COMMENT(" inFlush is true"); + enqueue(requestNetwork_out, CPURequestMsg, issue_latency) { + out_msg.addr := address; + out_msg.Requestor := machineID; + assert(is_valid(cache_entry)); + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.writeMask.clear(); + out_msg.writeMask.orMask(cache_entry.writeMask); + out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC, + TCC_select_low_bit, TCC_select_num_bits)); + out_msg.MessageSize := MessageSizeType:Data; + out_msg.Type := CoherenceRequestType:WriteFlush; + out_msg.InitialRequestTime := curCycle(); + out_msg.Shared := false; + out_msg.isSLCSet := false; + peek(mandatoryQueue_in, RubyRequest) { + out_msg.instSeqNum := in_msg.instSeqNum; + } + } } action(p_popMandatoryQueue, "pm", desc="Pop Mandatory Queue") { @@ -524,6 +547,16 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") cache_entry.Dirty := true; } + action(f_flushDone, "f", desc="flush done") { + assert(is_valid(cache_entry)); + + if (use_seq_not_coal) { + sequencer.writeCallback(address, cache_entry.DataBlk, false, MachineType:L1Cache); + } else { + coalescer.writeCallback(address, MachineType:L1Cache, cache_entry.DataBlk); + } + } + action(inv_invDone, "inv", desc="local inv done") { if (use_seq_not_coal) { DPRINTF(RubySlicc, "Sequencer does not define invCallback!\n"); @@ -695,11 +728,16 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") ic_invCache; } - transition({V, I, A},Flush) {TagArrayFlash} { + transition({V,I}, Flush, F) {TagArrayFlash} { + a_allocate; sf_setFlush; p_popMandatoryQueue; } + transition(A, Flush) { + z_stall; + } + transition({I, V}, Evict, I) {TagArrayFlash} { inv_invDone; p_popMandatoryQueue; @@ -716,4 +754,10 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") wd_wtDone; pr_popResponseQueue; } + + transition(F, TCC_AckWB, I) { + f_flushDone; + pr_popResponseQueue; + ic_invCache; + } } diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index 774b54a432..eed750832f 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -83,6 +83,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") BM_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory"; B_Pm, AccessPermission:Backing_Store, desc="blocked waiting for probes, already got memory"; B, AccessPermission:Backing_Store, desc="sent response, Blocked til ack"; + + F, AccessPermission:Busy, desc="sent Flus, blocked till ack"; } // Events @@ -120,6 +122,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") // DMA DmaRead, desc="DMA read"; DmaWrite, desc="DMA write"; + + // Flush + Flush, desc="Flush entry"; } enumeration(RequestType, desc="To communicate stats from transitions to recordStats") { @@ -411,6 +416,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") DPRINTF(RubySlicc, "Got VicClean from %s on %s\n", in_msg.Requestor, in_msg.addr); trigger(Event:VicClean, in_msg.addr, entry, tbe); } + } else if (in_msg.Type == CoherenceRequestType:WriteFlush) { + DPRINTF(RubySlicc, "Got Flush from %s on %s\n", in_msg.Requestor, in_msg.addr); + trigger(Event:Flush, in_msg.addr, entry, tbe); } else { error("Bad request message type"); } @@ -562,6 +570,23 @@ machine(MachineType:Directory, "AMD Baseline protocol") } } + action(rf_sendResponseFlush, "rf", desc="send Flush Ack") { + peek(memQueue_in, MemoryMsg) { + enqueue(responseNetwork_out, ResponseMsg, 1) { + out_msg.addr := address; + out_msg.Type := CoherenceResponseType:NBSysWBAck; + out_msg.Destination.add(tbe.OriginalRequestor); + out_msg.WTRequestor := tbe.WTRequestor; + out_msg.Sender := machineID; + out_msg.MessageSize := MessageSizeType:Writeback_Control; + out_msg.InitialRequestTime := tbe.InitialRequestTime; + out_msg.ForwardRequestTime := curCycle(); + out_msg.ProbeRequestStartTime := curCycle(); + //out_msg.instSeqNum := in_msg.instSeqNum; + } + } + } + action(l_queueMemWBReq, "lq", desc="Write WB data to memory") { peek(responseNetwork_in, ResponseMsg) { enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) { @@ -933,6 +958,23 @@ machine(MachineType:Directory, "AMD Baseline protocol") } } + action(f_writeFlushDataToMemory, "f", desc="Write flush data to memory") { + peek(requestNetwork_in, CPURequestMsg) { + enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) { + out_msg.addr := address; + out_msg.Type := MemoryRequestType:MEMORY_WB; + out_msg.Sender := machineID; + out_msg.MessageSize := MessageSizeType:Writeback_Data; + out_msg.DataBlk := in_msg.DataBlk; + } + if (tbe.Dirty == false) { + // have to update the TBE, too, because of how this + // directory deals with functional writes + tbe.DataBlk := in_msg.DataBlk; + } + } + } + action(atd_allocateTBEforDMA, "atd", desc="allocate TBE Entry for DMA") { check_allocate(TBEs); peek(dmaRequestQueue_in, DMARequestMsg) { @@ -1553,4 +1595,17 @@ machine(MachineType:Directory, "AMD Baseline protocol") dt_deallocateTBE; pt_popTriggerQueue; } + + transition(U, Flush, F) {L3TagArrayRead, L3TagArrayWrite} { + t_allocateTBE; + f_writeFlushDataToMemory; + w_sendResponseWBAck; + p_popRequestQueue; + } + + transition(F, WBAck, U) { + pm_popMemQueue; + dt_deallocateTBE; + } + } From ae5a51994c112d04bfe0eb84189ca9ec5a46102e Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Fri, 29 Sep 2023 18:27:46 -0500 Subject: [PATCH 364/693] mem-ruby: Update cache recorder to use GPUCoalescer port for GPUs Previously, the cache recorder used the Sequencer to issue flush requests and cache warmup requests. The GPU however uses GPUCoalescer to access the cache, and not the Sequencer. This commit adds a GPUCoalescer map to the cache recorder and uses it to send flushes and cache warmup requests to any GPU caches in the system Change-Id: I10490cf5e561c8559a98d4eb0550c62eefe769c9 --- src/mem/ruby/system/CacheRecorder.cc | 34 ++++++++++++++++++++++++---- src/mem/ruby/system/CacheRecorder.hh | 3 +++ src/mem/ruby/system/RubySystem.cc | 17 +++++++++++++- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/mem/ruby/system/CacheRecorder.cc b/src/mem/ruby/system/CacheRecorder.cc index 20a8a30ebc..ec552c07c5 100644 --- a/src/mem/ruby/system/CacheRecorder.cc +++ b/src/mem/ruby/system/CacheRecorder.cc @@ -30,8 +30,11 @@ #include "mem/ruby/system/CacheRecorder.hh" #include "debug/RubyCacheTrace.hh" +#include "mem/packet.hh" +#include "mem/ruby/system/GPUCoalescer.hh" #include "mem/ruby/system/RubySystem.hh" #include "mem/ruby/system/Sequencer.hh" +#include "sim/sim_exit.hh" namespace gem5 { @@ -57,11 +60,13 @@ CacheRecorder::CacheRecorder() CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, uint64_t uncompressed_trace_size, std::vector& seq_map, + std::vector& coal_map, uint64_t block_size_bytes) : m_uncompressed_trace(uncompressed_trace), m_uncompressed_trace_size(uncompressed_trace_size), - m_seq_map(seq_map), m_bytes_read(0), m_records_read(0), - m_records_flushed(0), m_block_size_bytes(block_size_bytes) + m_seq_map(seq_map), m_coalescer_map(coal_map), m_bytes_read(0), + m_records_read(0), m_records_flushed(0), + m_block_size_bytes(block_size_bytes) { if (m_uncompressed_trace != NULL) { if (m_block_size_bytes < RubySystem::getBlockSizeBytes()) { @@ -81,6 +86,7 @@ CacheRecorder::~CacheRecorder() m_uncompressed_trace = NULL; } m_seq_map.clear(); + m_coalescer_map.clear(); } void @@ -96,11 +102,21 @@ CacheRecorder::enqueueNextFlushRequest() Packet *pkt = new Packet(req, requestType); Sequencer* m_sequencer_ptr = m_seq_map[rec->m_cntrl_id]; + GPUCoalescer* m_coal_ptr = m_coalescer_map[rec->m_cntrl_id]; assert(m_sequencer_ptr != NULL); - m_sequencer_ptr->makeRequest(pkt); + if (m_coal_ptr == NULL) + m_sequencer_ptr->makeRequest(pkt); + else { + pkt->req->setReqInstSeqNum(m_records_flushed - 1); + m_coal_ptr->makeRequest(pkt); + } DPRINTF(RubyCacheTrace, "Flushing %s\n", *rec); + } else { + if (m_records_flushed > 0) { + exitSimLoop("Finished Drain", 0); + } DPRINTF(RubyCacheTrace, "Flushed all %d records\n", m_records_flushed); } } @@ -143,13 +159,21 @@ CacheRecorder::enqueueNextFetchRequest() pkt->dataStatic(traceRecord->m_data + rec_bytes_read); Sequencer* m_sequencer_ptr = m_seq_map[traceRecord->m_cntrl_id]; + GPUCoalescer* m_coal_ptr; + m_coal_ptr = m_coalescer_map[traceRecord->m_cntrl_id]; assert(m_sequencer_ptr != NULL); - m_sequencer_ptr->makeRequest(pkt); + if (m_coal_ptr == NULL) + m_sequencer_ptr->makeRequest(pkt); + else { + pkt->req->setReqInstSeqNum(m_records_read); + m_coal_ptr->makeRequest(pkt); + } } m_bytes_read += (sizeof(TraceRecord) + m_block_size_bytes); m_records_read++; } else { + exitSimLoop("Finished Warmup", 0); DPRINTF(RubyCacheTrace, "Fetched all %d records\n", m_records_read); } } @@ -168,6 +192,8 @@ CacheRecorder::addRecord(int cntrl, Addr data_addr, Addr pc_addr, memcpy(rec->m_data, data.getData(0, m_block_size_bytes), m_block_size_bytes); + DPRINTF(RubyCacheTrace, "Inside addRecord with cntrl id %d and type %d\n", + cntrl, type); m_records.push_back(rec); } diff --git a/src/mem/ruby/system/CacheRecorder.hh b/src/mem/ruby/system/CacheRecorder.hh index be95590313..9363e2fde7 100644 --- a/src/mem/ruby/system/CacheRecorder.hh +++ b/src/mem/ruby/system/CacheRecorder.hh @@ -50,6 +50,7 @@ namespace ruby { class Sequencer; +class GPUCoalescer; /*! * Class for recording cache contents. Note that the last element of the @@ -79,6 +80,7 @@ class CacheRecorder CacheRecorder(uint8_t* uncompressed_trace, uint64_t uncompressed_trace_size, std::vector& SequencerMap, + std::vector& CoalescerMap, uint64_t block_size_bytes); void addRecord(int cntrl, Addr data_addr, Addr pc_addr, RubyRequestType type, Tick time, DataBlock& data); @@ -115,6 +117,7 @@ class CacheRecorder uint8_t* m_uncompressed_trace; uint64_t m_uncompressed_trace_size; std::vector m_seq_map; + std::vector m_coalescer_map; uint64_t m_bytes_read; uint64_t m_records_read; uint64_t m_records_flushed; diff --git a/src/mem/ruby/system/RubySystem.cc b/src/mem/ruby/system/RubySystem.cc index b38c903b09..232e337752 100644 --- a/src/mem/ruby/system/RubySystem.cc +++ b/src/mem/ruby/system/RubySystem.cc @@ -178,13 +178,22 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, uint64_t block_size_bytes) { std::vector sequencer_map; + std::vector coalescer_map; Sequencer* sequencer_ptr = NULL; + GPUCoalescer* coalescer_ptr = NULL; for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getCPUSequencer()); + coalescer_map.push_back(m_abs_cntrl_vec[cntrl]->getGPUCoalescer()); + if (sequencer_ptr == NULL) { sequencer_ptr = sequencer_map[cntrl]; } + + if (coalescer_ptr == NULL) { + coalescer_ptr = coalescer_map[cntrl]; + } + } assert(sequencer_ptr != NULL); @@ -193,6 +202,11 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, if (sequencer_map[cntrl] == NULL) { sequencer_map[cntrl] = sequencer_ptr; } + + if (coalescer_map[cntrl] == NULL) { + coalescer_map[cntrl] = coalescer_ptr; + } + } // Remove the old CacheRecorder if it's still hanging about. @@ -202,7 +216,8 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, // Create the CacheRecorder and record the cache trace m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size, - sequencer_map, block_size_bytes); + sequencer_map, coalescer_map, + block_size_bytes); } void From f69191a31d091562201f544c28462b87d6c46206 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Mon, 2 Oct 2023 19:37:46 -0500 Subject: [PATCH 365/693] dev-amdgpu: Remove duplicate writes to PM4 queue pointers During checkpoint restoration, the unserialize() function writes rptr, wptr, and indirect buffer rptr, wptr to PM4 queue's rptr, wptr fields. This commit updates this to write only the relevant pointers to the queue structure. If indirect buffers are used, then it writes only the indirect buffer pointers to the queue. If they are not used, then it writes rptr, wptr values to the queue. Change-Id: Iedb25a726112e1af99cc1e7bc012de51c4ebfd45 --- src/dev/amdgpu/pm4_packet_processor.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/dev/amdgpu/pm4_packet_processor.cc b/src/dev/amdgpu/pm4_packet_processor.cc index 63a3bf8887..fdb6f9d7ce 100644 --- a/src/dev/amdgpu/pm4_packet_processor.cc +++ b/src/dev/amdgpu/pm4_packet_processor.cc @@ -1190,15 +1190,16 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) memset(pkt, 0, sizeof(PM4MapQueues)); newQueue(mqd, offset[i], pkt, id[i]); - queues[id[i]]->ib(false); - queues[id[i]]->rptr(rptr[i]); - queues[id[i]]->wptr(wptr[i]); - queues[id[i]]->ib(true); - queues[id[i]]->wptr(ib_wptr[i]); - queues[id[i]]->rptr(ib_rptr[i]); + if (ib[i]) { + queues[id[i]]->wptr(ib_wptr[i]); + queues[id[i]]->rptr(ib_rptr[i]); + } else { + queues[id[i]]->rptr(rptr[i]); + queues[id[i]]->wptr(wptr[i]); + } + queues[id[i]]->ib(ib[i]); queues[id[i]]->offset(offset[i]); queues[id[i]]->processing(processing[i]); - queues[id[i]]->ib(ib[i]); queues[id[i]]->setPkt(me[i], pipe[i], queue[i], privileged[i]); queues[id[i]]->getMQD()->hqd_active = hqd_active[i]; queues[id[i]]->getMQD()->hqd_vmid = hqd_vmid[i]; From 3af3c1121b2bfead7d9a6a3893fe27cedb93238a Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Mon, 2 Oct 2023 23:27:32 -0700 Subject: [PATCH 366/693] stdlib, resources: Addressed requested changes Change-Id: I22abdc3bdcdde52301ed10cb3113e8925159c245 Co-authored-by: Kunal Pai --- .../riscvmatched-microbenchmark-suite.py | 12 +++--------- src/python/gem5/resources/resource.py | 1 - .../test_gem5_library_examples.py | 17 +++++++++++++++++ .../stdlib/resources/pyunit_suite_checks.py | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py b/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py index 2d189717e2..7e08355e31 100644 --- a/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py +++ b/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py @@ -50,15 +50,9 @@ microbenchmarks = obtain_resource("riscv-vertical-microbenchmarks") # list all the microbenchmarks present in the suite print("Microbenchmarks present in the suite:") print("====================================") -for ( - id, - resource_version, - input_group, - workload, -) in microbenchmarks.get_all_workloads(): - print(f"Workload ID: {id}") - print(f"Workload Version: {resource_version}") - print(f"Workload Input Groups: {input_group}") +for workload in microbenchmarks: + print(f"Workload ID: {workload.get_id()}") + print(f"Workload Version: {workload.get_resource_version()}") print(f"WorkloadResource Object: {workload}") print("====================================") diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index ac7769b83f..af8a8d9acd 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -980,7 +980,6 @@ def obtain_resource( # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the # subclass contructor, so we can pass the resource_json map directly. - return resource_class(local_path=to_path, **resource_json) diff --git a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py index 0882fb0dfd..1967560d99 100644 --- a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py +++ b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py @@ -334,6 +334,23 @@ gem5_verify_config( length=constants.very_long_tag, ) +gem5_verify_config( + name="test-gem5-library-example-riscvmatched-microbenchmark-suite", + fixtures=(), + verifiers=(), + config=joinpath( + config.base_dir, + "configs", + "example", + "gem5_library", + "riscvmatched-microbenchmark-suite.py", + ), + config_args=[], + valid_isas=(constants.all_compiled_tag,), + valid_hosts=constants.supported_hosts, + length=constants.long_tag, +) + # The LoopPoint-Checkpointing feature is still under development, therefore # these tests are temporarily disabled until this feature is complete.# diff --git a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py index 5de68a6b1a..480ba9f024 100644 --- a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py @@ -59,7 +59,7 @@ class CustomSuiteResourceTestSuite(unittest.TestCase): cls.workload1 = obtain_resource("simple-workload-1") cls.workload2 = obtain_resource("simple-workload-2") cls.SuiteResource = SuiteResource( - workload_obj_list={cls.workload1: set(), cls.workload2: set()} + workloads={cls.workload1: set(), cls.workload2: set()} ) @patch( From 53627cc39cb64ff55f92df554821eb7a953ec2aa Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Tue, 3 Oct 2023 11:36:11 -0500 Subject: [PATCH 367/693] configs: Add configurable GPU L1,L2 num banks and L2 latencies Previously, the L1, L2 number of banks and L2 latencies were not configurable through command line arguments. This commit adds support to configure them through the arguments '--tcp-num-banks' for number of banks in L1, '--tcc-num-banks' for number of banks in L2, and '--tcc-tag-access-latency', and '--tcc-data-access-latency' Change-Id: Ie3b713ead16865fd7120e2d809ebfa56b69bc4a1 --- configs/ruby/GPU_VIPER.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index 1e95964a40..2948b6eeda 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -154,6 +154,8 @@ class TCPCntrl(TCP_Controller, CntrlBase): dataAccessLatency=options.TCP_latency, ) self.L1cache.resourceStalls = options.no_resource_stalls + self.L1cache.dataArrayBanks = options.tcp_num_banks + self.L1cache.tagArrayBanks = options.tcp_num_banks self.L1cache.create(options) self.issue_latency = 1 # TCP_Controller inherits this from RubyController @@ -298,7 +300,10 @@ class TCC(RubyCache): class TCCCntrl(TCC_Controller, CntrlBase): def create(self, options, ruby_system, system): self.version = self.versionCount() - self.L2cache = TCC() + self.L2cache = TCC( + tagAccessLatency=options.tcc_tag_access_latency, + dataAccessLatency=options.tcc_data_access_latency, + ) self.L2cache.create(options) self.L2cache.resourceStalls = options.no_tcc_resource_stalls @@ -492,6 +497,30 @@ def define_options(parser): parser.add_argument( "--glc-atomic-latency", type=int, default=1, help="GLC Atomic Latency" ) + parser.add_argument( + "--tcp-num-banks", + type=int, + default="16", + help="Num of banks in L1 cache", + ) + parser.add_argument( + "--tcc-num-banks", + type=int, + default="16", + help="Num of banks in L2 cache", + ) + parser.add_argument( + "--tcc-tag-access-latency", + type=int, + default="2", + help="Tag access latency in L2 cache", + ) + parser.add_argument( + "--tcc-data-access-latency", + type=int, + default="8", + help="Data access latency in L2 cache", + ) def construct_dirs(options, system, ruby_system, network): From d3637a489d6ddcc8ca5d99f20b53a1ea64bbc422 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Tue, 3 Oct 2023 12:10:42 -0500 Subject: [PATCH 368/693] configs: Add option to disable AVX in GPUFS GPUFS+KVM simulations automatically enable AVX. This commit adds a command line option to disable AVX if its not needed for a GPUFS simulation. Change-Id: Ic22592767dbdca86f3718eca9c837a8e29b6b781 --- configs/example/gpufs/runfs.py | 10 ++++++++++ configs/example/gpufs/system/system.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index 0f090e2f89..5d29959eff 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -158,6 +158,16 @@ def addRunFSOptions(parser): help="Root partition of disk image", ) + parser.add_argument( + "--disable-avx", + action="store_true", + default=False, + help="Disables AVX. AVX is used in some ROCm libraries but " + "does not have checkpointing support yet. If simulation either " + "creates a checkpoint or restores from one, then AVX needs to " + "be disabled for correct functionality ", + ) + def runGpuFSSystem(args): """ diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index 7ddc4f0752..7cb0ce1aa5 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -234,7 +234,7 @@ def makeGpuFSSystem(args): # If we are using KVM cpu, enable AVX. AVX is used in some ROCm libraries # such as rocBLAS which is used in higher level libraries like PyTorch. use_avx = False - if ObjectList.is_kvm_cpu(TestCPUClass): + if ObjectList.is_kvm_cpu(TestCPUClass) and not args.disable_avx: # AVX also requires CR4.osxsave to be 1. These must be set together # of KVM will error out. system.workload.enable_osxsave = 1 From 2b97f17fe1714ef5429e59de12232b0c39599704 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 4 Oct 2023 09:09:56 -0500 Subject: [PATCH 369/693] gpu-compute: Fix dynamic scratch size test ROCm supports dynamically allocating scratch space, which resides in framebuffer memory, to reduce the amount of memory allocated for kernels that have not yet launched. The size of the scratch space allocated is located in task->amdQueue.compute_tmpring_size_wavesize. This size is in kilobytes. The AQL task contains the number of bytes requested *per work item*, however we currently check if there is enough tmpring space by comparing a single work item. This should instead check the size *per wavefront*. This causes problems in applications where multiple kernels use dynamic scratch allocation and a later kernel requires more space than the earlier kernel. The only application being tested that does this is LULESH. This was resulting in the scratch space being too small, resulting in workgroups clobbering each other's private memory leading to some nasty bugs. It is fixed by this patch as task->amdQueue will be re-read from the host and will contain the updated tmpring size. After this there is enough scratch space and LULESH makes forward progress. Change-Id: Ie9e0f92bb98fd3c3d6c2da3db9ee65352f9ae070 --- src/gpu-compute/gpu_command_processor.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gpu-compute/gpu_command_processor.hh b/src/gpu-compute/gpu_command_processor.hh index d2ddf5c78f..10407b9f93 100644 --- a/src/gpu-compute/gpu_command_processor.hh +++ b/src/gpu-compute/gpu_command_processor.hh @@ -46,6 +46,7 @@ #include #include +#include "arch/amdgpu/vega/gpu_registers.hh" #include "base/logging.hh" #include "base/trace.hh" #include "base/types.hh" @@ -206,7 +207,7 @@ class GPUCommandProcessor : public DmaVirtDevice * the signal is reset we should check that the runtime was * successful and then proceed to launch the kernel. */ - if (task->privMemPerItem() > + if ((task->privMemPerItem() * VegaISA::NumVecElemPerVecReg) > task->amdQueue.compute_tmpring_size_wavesize * 1024) { // TODO: Raising this signal will potentially nuke scratch // space for in-flight kernels that were launched from this From 4fd9d66c537671f0950687cac327c4513c9c8eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Soria?= Date: Mon, 24 Jul 2023 16:20:10 +0200 Subject: [PATCH 370/693] tests,mem-ruby: Enhance ruby false sharing test with Atomics New ruby mem test includes a percentages of AMOs that will be executed randomly in ruby mem test Change-Id: Ie95ed78e59ea773ce6b59060eaece3701fe4478c --- configs/example/ruby_mem_test.py | 11 ++++- src/cpu/testers/memtest/MemTest.py | 1 + src/cpu/testers/memtest/memtest.cc | 72 +++++++++++++++++++++++++----- src/cpu/testers/memtest/memtest.hh | 4 ++ src/mem/request.hh | 7 +++ 5 files changed, 81 insertions(+), 14 deletions(-) diff --git a/configs/example/ruby_mem_test.py b/configs/example/ruby_mem_test.py index c90950107e..27751376fc 100644 --- a/configs/example/ruby_mem_test.py +++ b/configs/example/ruby_mem_test.py @@ -62,6 +62,12 @@ parser.add_argument( default=0, help="percentage of accesses that should be functional", ) +parser.add_argument( + "--atomic", + type=int, + default=30, + help="percentage of accesses that should be atomic", +) parser.add_argument( "--suppress-func-errors", action="store_true", @@ -105,6 +111,7 @@ cpus = [ max_loads=args.maxloads, percent_functional=args.functional, percent_uncacheable=0, + percent_atomic=args.atomic, progress_interval=args.progress, suppress_func_errors=args.suppress_func_errors, ) @@ -133,7 +140,7 @@ else: dmas = [] dma_ports = [] -for (i, dma) in enumerate(dmas): +for i, dma in enumerate(dmas): dma_ports.append(dma.test) Ruby.create_system(args, False, system, dma_ports=dma_ports) @@ -155,7 +162,7 @@ system.ruby.randomization = True assert len(cpus) == len(system.ruby._cpu_ports) -for (i, cpu) in enumerate(cpus): +for i, cpu in enumerate(cpus): # # Tie the cpu memtester ports to the correct system ports # diff --git a/src/cpu/testers/memtest/MemTest.py b/src/cpu/testers/memtest/MemTest.py index 24bd974804..15c329ee85 100644 --- a/src/cpu/testers/memtest/MemTest.py +++ b/src/cpu/testers/memtest/MemTest.py @@ -63,6 +63,7 @@ class MemTest(ClockedObject): percent_reads = Param.Percent(65, "Percentage reads") percent_functional = Param.Percent(50, "Percentage functional accesses") percent_uncacheable = Param.Percent(10, "Percentage uncacheable") + percent_atomic = Param.Percent(50, "Percentage atomics") # Determine how often to print progress messages and what timeout # to use for checking progress of both requests and responses diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index 7c256d8642..a84bf67cd9 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -94,6 +94,7 @@ MemTest::MemTest(const Params &p) percentReads(p.percent_reads), percentFunctional(p.percent_functional), percentUncacheable(p.percent_uncacheable), + percentAtomic(p.percent_atomic), requestorId(p.system->getRequestorId(this)), blockSize(p.system->cacheLineSize()), blockAddrMask(blockSize - 1), @@ -115,6 +116,7 @@ MemTest::MemTest(const Params &p) // set up counters numReads = 0; numWrites = 0; + numAtomics = 0; // kick things into action schedule(tickEvent, curTick()); @@ -142,7 +144,7 @@ MemTest::completeRequest(PacketPtr pkt, bool functional) outstandingAddrs.erase(remove_addr); DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n", - pkt->isWrite() ? "write" : "read", + pkt->isWrite() ? pkt->isAtomicOp() ? "atomic" : "write" : "read", req->getPaddr(), blockAlign(req->getPaddr()), pkt->isError() ? "error" : "success"); @@ -153,7 +155,25 @@ MemTest::completeRequest(PacketPtr pkt, bool functional) panic( "%s access failed at %#x\n", pkt->isWrite() ? "Write" : "Read", req->getPaddr()); } else { - if (pkt->isRead()) { + if (pkt->isAtomicOp()) { + uint8_t ref_data = referenceData[req->getPaddr()]; + if (pkt_data[0] != ref_data) { + panic("%s: read of %x (blk %x) @ cycle %d " + "returns %x, expected %x\n", name(), + req->getPaddr(), blockAlign(req->getPaddr()), curTick(), + pkt_data[0], ref_data); + } + DPRINTF(MemTest, + "Completing atomic at address %x (blk %x) value %x\n", + req->getPaddr(), blockAlign(req->getPaddr()), + pkt_data[0]); + + referenceData[req->getPaddr()] = + atomicPendingData[req->getPaddr()]; + + numAtomics++; + stats.numAtomics++; + } else if (pkt->isRead()) { uint8_t ref_data = referenceData[req->getPaddr()]; if (pkt_data[0] != ref_data) { panic("%s: read of %x (blk %x) @ cycle %d " @@ -167,9 +187,10 @@ MemTest::completeRequest(PacketPtr pkt, bool functional) if (numReads == (uint64_t)nextProgressMessage) { ccprintf(std::cerr, - "%s: completed %d read, %d write accesses @%d\n", - name(), numReads, numWrites, curTick()); - nextProgressMessage += progressInterval; + "%s: completed %d read, %d write, " + "%d atomic accesses @%d\n", + name(), numReads, numWrites, numAtomics, curTick()); + nextProgressMessage += progressInterval; } if (maxLoads != 0 && numReads >= maxLoads) @@ -205,7 +226,9 @@ MemTest::MemTestStats::MemTestStats(statistics::Group *parent) ADD_STAT(numReads, statistics::units::Count::get(), "number of read accesses completed"), ADD_STAT(numWrites, statistics::units::Count::get(), - "number of write accesses completed") + "number of write accesses completed"), + ADD_STAT(numAtomics, statistics::units::Count::get(), + "number of atomic accesses completed") { } @@ -221,6 +244,8 @@ MemTest::tick() unsigned cmd = random_mt.random(0, 100); uint8_t data = random_mt.random(); bool uncacheable = random_mt.random(0, 100) < percentUncacheable; + bool do_atomic = (random_mt.random(0, 100) < percentAtomic) && + !uncacheable; unsigned base = random_mt.random(0, 1); Request::Flags flags; Addr paddr; @@ -281,13 +306,36 @@ MemTest::tick() pkt = new Packet(req, MemCmd::ReadReq); pkt->dataDynamic(pkt_data); } else { - DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n", - do_functional ? "functional " : "", req->getPaddr(), - blockAlign(req->getPaddr()), data); + if (do_atomic) { + DPRINTF(MemTest, + "Initiating atomic at addr %x (blk %x) value %x\n", + req->getPaddr(), blockAlign(req->getPaddr()), data); - pkt = new Packet(req, MemCmd::WriteReq); - pkt->dataDynamic(pkt_data); - pkt_data[0] = data; + TypedAtomicOpFunctor *_amo_op = + new AtomicGeneric3Op( + data, data, + [](uint8_t* b, uint8_t a, uint8_t c){ + *b = c; + }); + assert(_amo_op); + AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(_amo_op); + req->setAtomicOpFunctor(std::move(amo_op)); + req->setFlags(Request::ATOMIC_RETURN_OP); + + pkt = new Packet(req, MemCmd::WriteReq); + pkt->dataDynamic(pkt_data); + pkt_data[0] = data; + atomicPendingData[req->getPaddr()] = data; + } else { + DPRINTF(MemTest, + "Initiating %swrite at addr %x (blk %x) value %x\n", + do_functional ? "functional " : "", req->getPaddr(), + blockAlign(req->getPaddr()), data); + + pkt = new Packet(req, MemCmd::WriteReq); + pkt->dataDynamic(pkt_data); + pkt_data[0] = data; + } } // there is no point in ticking if we are waiting for a retry diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index 3fd1674191..ee512048c1 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -131,6 +131,7 @@ class MemTest : public ClockedObject const unsigned percentReads; const unsigned percentFunctional; const unsigned percentUncacheable; + const unsigned percentAtomic; /** Request id for all generated traffic */ RequestorID requestorId; @@ -138,6 +139,7 @@ class MemTest : public ClockedObject unsigned int id; std::unordered_set outstandingAddrs; + std::unordered_map atomicPendingData; // store the expected value for the addresses we have touched std::unordered_map referenceData; @@ -169,6 +171,7 @@ class MemTest : public ClockedObject uint64_t numReads; uint64_t numWrites; + uint64_t numAtomics; const uint64_t maxLoads; const bool atomic; @@ -180,6 +183,7 @@ class MemTest : public ClockedObject MemTestStats(statistics::Group *parent); statistics::Scalar numReads; statistics::Scalar numWrites; + statistics::Scalar numAtomics; } stats; /** diff --git a/src/mem/request.hh b/src/mem/request.hh index 491aad0241..df249ac249 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -757,6 +757,13 @@ class Request : public Extensible return atomicOpFunctor.get(); } + void + setAtomicOpFunctor(AtomicOpFunctorPtr amo_op) + { + atomicOpFunctor = std::move(amo_op); + } + + /** * Accessor for hardware transactional memory abort cause. */ From 12dada2dc5623e6b012047d432ffd31780f5b55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Soria?= Date: Mon, 24 Jul 2023 16:25:08 +0200 Subject: [PATCH 371/693] arch-arm: Correct return operand in swap instructions Swap instructions are configured as non returning AMO operations. This is wrong because they return the previous value stored in the target memory position Change-Id: I84d75a571a8eaeaee0dbfac344f7b34c72b47d53 --- src/arch/arm/isa/insts/amo64.isa | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/arch/arm/isa/insts/amo64.isa b/src/arch/arm/isa/insts/amo64.isa index 72eea89518..3de9a41bfe 100644 --- a/src/arch/arm/isa/insts/amo64.isa +++ b/src/arch/arm/isa/insts/amo64.isa @@ -827,35 +827,35 @@ let {{ ret_op=False, flavor="release").emit(OP_DICT['MIN']) AtomicArithmeticSingleOp("swpb", "SWPB", 1, unsign=True, - ret_op=False, flavor="normal").emit(OP_DICT['SWP']) + flavor="normal").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swplb", "SWPLB", 1, unsign=True, - ret_op=False, flavor="release").emit(OP_DICT['SWP']) + flavor="release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpab", "SWPAB", 1, unsign=True, - ret_op=False, flavor="acquire").emit(OP_DICT['SWP']) + flavor="acquire").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swplab", "SWPLAB", 1, unsign=True, - ret_op=False, flavor="acquire_release").emit(OP_DICT['SWP']) + flavor="acquire_release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swph", "SWPH", 2, unsign=True, - ret_op=False, flavor="normal").emit(OP_DICT['SWP']) + flavor="normal").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swplh", "SWPLH", 2, unsign=True, - ret_op=False, flavor="release").emit(OP_DICT['SWP']) + flavor="release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpah", "SWPAH", 2, unsign=True, - ret_op=False, flavor="acquire").emit(OP_DICT['SWP']) + flavor="acquire").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swplah", "SWPLAH", 2, unsign=True, - ret_op=False, flavor="acquire_release").emit(OP_DICT['SWP']) + flavor="acquire_release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swp", "SWP", 4, unsign=True, - ret_op=False, flavor="normal").emit(OP_DICT['SWP']) + flavor="normal").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpl", "SWPL", 4, unsign=True, - ret_op=False, flavor="release").emit(OP_DICT['SWP']) + flavor="release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpa", "SWPA", 4, unsign=True, - ret_op=False, flavor="acquire").emit(OP_DICT['SWP']) + flavor="acquire").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpla", "SWPLA", 4, unsign=True, - ret_op=False, flavor="acquire_release").emit(OP_DICT['SWP']) + flavor="acquire_release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swp64", "SWP64", 8, unsign=True, - ret_op=False, flavor="normal").emit(OP_DICT['SWP']) + flavor="normal").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpl64", "SWPL64", 8, unsign=True, - ret_op=False, flavor="release").emit(OP_DICT['SWP']) + flavor="release").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpa64", "SWPA64", 8, unsign=True, - ret_op=False, flavor="acquire").emit(OP_DICT['SWP']) + flavor="acquire").emit(OP_DICT['SWP']) AtomicArithmeticSingleOp("swpla64", "SWPLA64", 8, unsign=True, - ret_op=False, flavor="acquire_release").emit(OP_DICT['SWP']) + flavor="acquire_release").emit(OP_DICT['SWP']) }}; From 6411b2255ccdab3ad782f385b94cd43b248a46a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Soria?= Date: Thu, 10 Aug 2023 17:04:17 +0200 Subject: [PATCH 372/693] mem-ruby,configs: Add CHI far atomics support Introduce far atomic operations in CHI protocol. Three configuration parameters have been used to tune this behavior: policy_type: sets the atomic policy to one of the described in our paper atomic_op_latency: simulates the AMO ALU operation latency comp_anr: configures the Atomic No return transaction to split CompDBIDResp into two different messages DBIDResp and Comp Change-Id: I087afad9ad9fcb9df42d72893c9e32ad5a5eb478 --- configs/ruby/CHI_config.py | 4 + src/mem/ruby/protocol/RubySlicc_Types.sm | 7 + .../ruby/protocol/chi/CHI-cache-actions.sm | 477 +++++++++++++++++- src/mem/ruby/protocol/chi/CHI-cache-funcs.sm | 51 +- .../protocol/chi/CHI-cache-transitions.sm | 221 +++++++- src/mem/ruby/protocol/chi/CHI-cache.sm | 69 ++- src/mem/ruby/protocol/chi/CHI-msg.sm | 7 + src/mem/ruby/slicc_interface/RubyRequest.cc | 9 + src/mem/ruby/slicc_interface/RubyRequest.hh | 2 + src/mem/ruby/system/Sequencer.cc | 99 +++- src/mem/ruby/system/Sequencer.hh | 8 + 11 files changed, 924 insertions(+), 30 deletions(-) diff --git a/configs/ruby/CHI_config.py b/configs/ruby/CHI_config.py index 4f2580c373..1288cf95d6 100644 --- a/configs/ruby/CHI_config.py +++ b/configs/ruby/CHI_config.py @@ -244,6 +244,7 @@ class CHI_L1Controller(CHI_Cache_Controller): self.alloc_on_readunique = True self.alloc_on_readonce = True self.alloc_on_writeback = True + self.alloc_on_atomic = False self.dealloc_on_unique = False self.dealloc_on_shared = False self.dealloc_backinv_unique = True @@ -280,6 +281,7 @@ class CHI_L2Controller(CHI_Cache_Controller): self.alloc_on_readunique = True self.alloc_on_readonce = True self.alloc_on_writeback = True + self.alloc_on_atomic = False self.dealloc_on_unique = False self.dealloc_on_shared = False self.dealloc_backinv_unique = True @@ -316,6 +318,7 @@ class CHI_HNFController(CHI_Cache_Controller): self.alloc_on_readunique = False self.alloc_on_readonce = True self.alloc_on_writeback = True + self.alloc_on_atomic = True self.dealloc_on_unique = True self.dealloc_on_shared = False self.dealloc_backinv_unique = False @@ -392,6 +395,7 @@ class CHI_DMAController(CHI_Cache_Controller): self.alloc_on_readunique = False self.alloc_on_readonce = False self.alloc_on_writeback = False + self.alloc_on_atomic = False self.dealloc_on_unique = False self.dealloc_on_shared = False self.dealloc_backinv_unique = False diff --git a/src/mem/ruby/protocol/RubySlicc_Types.sm b/src/mem/ruby/protocol/RubySlicc_Types.sm index 8ba9d935ff..293c731c37 100644 --- a/src/mem/ruby/protocol/RubySlicc_Types.sm +++ b/src/mem/ruby/protocol/RubySlicc_Types.sm @@ -139,6 +139,13 @@ structure (Sequencer, external = "yes") { Cycles, Cycles, Cycles); void writeUniqueCallback(Addr, DataBlock); + void atomicCallback(Addr, DataBlock); + void atomicCallback(Addr, DataBlock, bool); + void atomicCallback(Addr, DataBlock, bool, MachineType); + void atomicCallback(Addr, DataBlock, bool, MachineType, + Cycles, Cycles, Cycles); + + void unaddressedCallback(Addr, RubyRequestType); void unaddressedCallback(Addr, RubyRequestType, MachineType); void unaddressedCallback(Addr, RubyRequestType, MachineType, diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 42e07eb46b..4c9498423c 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -148,15 +148,22 @@ action(AllocateTBE_SeqRequest, desc="") { out_msg.is_remote_pf := false; out_msg.txnId := max_outstanding_transactions; + out_msg.atomic_op.clear(); + out_msg.atomic_op.orMask(in_msg.writeMask); + if ((in_msg.Type == RubyRequestType:LD) || (in_msg.Type == RubyRequestType:IFETCH)) { out_msg.type := CHIRequestType:Load; - } else if (in_msg.Type == RubyRequestType:ST) { + } else if (in_msg.Type == RubyRequestType:ST) { if (in_msg.Size == blockSize) { out_msg.type := CHIRequestType:StoreLine; } else { out_msg.type := CHIRequestType:Store; } + } else if (in_msg.Type == RubyRequestType:ATOMIC_RETURN) { + out_msg.type := CHIRequestType:AtomicLoad; + } else if (in_msg.Type == RubyRequestType:ATOMIC_NO_RETURN){ + out_msg.type := CHIRequestType:AtomicStore; } else { error("Invalid RubyRequestType"); } @@ -769,6 +776,148 @@ action(Initiate_StoreMiss, desc="") { } } +action(Initiate_Atomic_UC, desc="") { + if ((policy_type == 0) || // ALL NEAR + (policy_type == 1) || // UNIQUE NEAR + (policy_type == 2) // PRESENT NEAR + ){ + tbe.actions.push(Event:DataArrayRead); + tbe.actions.push(Event:DelayAtomic); + tbe.actions.push(Event:AtomicHit); + tbe.actions.pushNB(Event:DataArrayWrite); + tbe.actions.pushNB(Event:TagArrayWrite); + } else { + error("Invalid policy type"); + } +} + +action(Initiate_Atomic_UD, desc="") { + if ((policy_type == 0) || // ALL NEAR + (policy_type == 1) || // UNIQUE NEAR + (policy_type == 2) // PRESENT NEAR + ){ + tbe.actions.push(Event:DataArrayRead); + tbe.actions.push(Event:DelayAtomic); + tbe.actions.push(Event:AtomicHit); + tbe.actions.pushNB(Event:DataArrayWrite); + tbe.actions.pushNB(Event:TagArrayWrite); + } else { + error("Invalid policy type"); + } +} + +action(Initiate_AtomicReturn_I, desc="") { + if (policy_type == 0){ // ALL NEAR + tbe.actions.push(Event:SendReadUnique); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); + tbe.atomic_to_be_done := true; + } else if ((policy_type == 1) || // UNIQUE NEAR + (policy_type == 2)) { // PRESENT NEAR + tbe.actions.push(Event:SendAtomicReturn_NoWait); + tbe.dataToBeInvalid := true; + tbe.doCacheFill := false; + tbe.atomic_to_be_done := false; + } else { + error("Invalid policy type"); + } +} + +action(Initiate_AtomicNoReturn_I, desc="") { + if (policy_type == 0){ // ALL NEAR + tbe.actions.push(Event:SendReadUnique); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); + tbe.atomic_to_be_done := true; + } else if (policy_type == 1) { // UNIQUE NEAR + tbe.actions.push(Event:SendAtomicNoReturn); + tbe.actions.push(Event:SendANRData); + tbe.dataToBeInvalid := true; + tbe.doCacheFill := false; + tbe.atomic_to_be_done := false; + } else { + error("Invalid policy type"); + } +} + +action(Initiate_AtomicReturn_SD, desc="") { + if (policy_type == 0){ // ALL NEAR + tbe.actions.push(Event:SendReadUnique); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); + tbe.atomic_to_be_done := true; + } else if (policy_type == 1) { // UNIQUE NEAR + tbe.actions.push(Event:SendAtomicReturn_NoWait); + tbe.dataToBeInvalid := true; + tbe.doCacheFill := false; + tbe.atomic_to_be_done := false; + } else { + error("Invalid policy type"); + } +} + +action(Initiate_AtomicNoReturn_SD, desc="") { + if (policy_type == 0){ // ALL NEAR + tbe.actions.push(Event:SendReadUnique); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); + tbe.atomic_to_be_done := true; + } else if (policy_type == 1) { // UNIQUE NEAR + tbe.actions.push(Event:SendAtomicNoReturn); + tbe.actions.push(Event:SendANRData); + tbe.dataToBeInvalid := true; + tbe.doCacheFill := false; + tbe.atomic_to_be_done := false; + } else { + error("Invalid policy type"); + } +} + +action(Initiate_AtomicReturn_SC, desc="") { + if (policy_type == 0){ // ALL NEAR + tbe.actions.push(Event:SendReadUnique); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); + tbe.atomic_to_be_done := true; + } else if (policy_type == 1) { // UNIQUE NEAR + tbe.actions.push(Event:SendAtomicReturn_NoWait); + tbe.dataToBeInvalid := true; + tbe.doCacheFill := false; + tbe.atomic_to_be_done := false; + } else { + error("Invalid policy type"); + } +} + +action(Initiate_AtomicNoReturn_SC, desc="") { + if (policy_type == 0){ // ALL NEAR + tbe.actions.push(Event:SendReadUnique); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); + tbe.atomic_to_be_done := true; + } else if (policy_type == 1) { // UNIQUE NEAR + tbe.actions.push(Event:SendAtomicNoReturn); + tbe.actions.push(Event:SendANRData); + tbe.dataToBeInvalid := true; + tbe.doCacheFill := false; + tbe.atomic_to_be_done := false; + } else { + error("Invalid policy type"); + } +} + action(Initiate_StoreUpgrade, desc="") { assert(tbe.dataValid); assert(is_valid(cache_entry)); @@ -865,8 +1014,111 @@ action(Initiate_WriteUnique_Forward, desc="") { tbe.actions.pushNB(Event:TagArrayWrite); } +action(Initiate_AtomicReturn_LocalWrite, desc="") { + if ((tbe.dir_sharers.count() > 0) && tbe.dataMaybeDirtyUpstream) { + tbe.actions.push(Event:SendSnpUnique); + } else if (tbe.dir_sharers.count() > 0){ + // no one will send us data unless we explicitly ask + tbe.actions.push(Event:SendSnpUniqueRetToSrc); + } + tbe.actions.push(Event:SendDBIDResp_AR); + tbe.actions.pushNB(Event:WriteFEPipe); + tbe.actions.pushNB(Event:SendCompData_AR); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:DelayAtomic); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); +} +action(Initiate_AtomicNoReturn_LocalWrite, desc="") { + if ((tbe.dir_sharers.count() > 0) && tbe.dataMaybeDirtyUpstream) { + tbe.actions.push(Event:SendSnpUnique); + } else if (tbe.dir_sharers.count() > 0){ + // no one will send us data unless we explicitly ask + tbe.actions.push(Event:SendSnpUniqueRetToSrc); + } + if (comp_wu) { + tbe.actions.push(Event:SendDBIDResp_ANR); + tbe.actions.pushNB(Event:WriteFEPipe); + tbe.actions.pushNB(Event:SendComp_ANR); + } else { + tbe.actions.push(Event:SendCompDBIDResp_ANR); + tbe.actions.pushNB(Event:WriteFEPipe); + } + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:DelayAtomic); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); +} + + +action(Initiate_AtomicReturn_Forward, desc="") { + if ((tbe.dir_sharers.count() > 0) && + (tbe.dir_sharers.isElement(tbe.requestor))){ + tbe.dir_sharers.remove(tbe.requestor); + } + tbe.actions.push(Event:SendAtomicReturn); + tbe.actions.push(Event:SendCompData_AR); + tbe.actions.pushNB(Event:TagArrayWrite); + + tbe.dataToBeInvalid := true; +} + +action(Initiate_AtomicNoReturn_Forward, desc="") { + if ((tbe.dir_sharers.count() > 0) && + (tbe.dir_sharers.isElement(tbe.requestor))){ + tbe.dir_sharers.remove(tbe.requestor); + } + if (comp_wu) { + tbe.actions.push(Event:SendAtomicNoReturn); + tbe.actions.push(Event:SendDBIDResp_ANR); + tbe.actions.pushNB(Event:SendComp_ANR); + } else { + tbe.actions.push(Event:SendAtomicNoReturn); + tbe.actions.push(Event:SendCompDBIDResp_ANR); + } + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:SendANRData); + tbe.actions.pushNB(Event:TagArrayWrite); + + tbe.dataToBeInvalid := true; +} + +action(Initiate_AtomicReturn_Miss, desc="") { + tbe.actions.push(Event:SendReadNoSnp); + tbe.actions.pushNB(Event:WriteFEPipe); + tbe.actions.push(Event:SendDBIDResp_AR); + tbe.actions.pushNB(Event:WriteFEPipe); + tbe.actions.pushNB(Event:SendCompData_AR); + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:DelayAtomic); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); +} + +action(Initiate_AtomicNoReturn_Miss, desc="") { + assert(is_HN); + tbe.actions.push(Event:SendReadNoSnp); + if (comp_wu) { + tbe.actions.push(Event:SendDBIDResp_ANR); + tbe.actions.pushNB(Event:WriteFEPipe); + tbe.actions.pushNB(Event:SendComp_ANR); + } else { + tbe.actions.push(Event:SendCompDBIDResp_ANR); + tbe.actions.pushNB(Event:WriteFEPipe); + } + + tbe.actions.push(Event:WriteFEPipe); + tbe.actions.push(Event:CheckCacheFill); + tbe.actions.push(Event:DelayAtomic); + tbe.actions.push(Event:WriteBEPipe); + tbe.actions.push(Event:TagArrayWrite); +} + action(Initiate_CopyBack, desc="") { // expect to receive this data after Send_CompDBIDResp if (tbe.reqType == CHIRequestType:WriteBackFull) { @@ -1157,7 +1409,9 @@ action(Send_ReadShared, desc="") { action(Send_ReadNoSnp, desc="") { assert(is_HN); - assert(tbe.use_DMT == false); + assert((tbe.use_DMT == false) || + ((tbe.reqType == CHIRequestType:AtomicReturn) || + (tbe.reqType == CHIRequestType:AtomicNoReturn))); clearExpectedReqResp(tbe); tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_UC); @@ -1368,6 +1622,45 @@ action(Send_WriteUnique, desc="") { tbe.expected_req_resp.addExpectedCount(1); } +action(Send_AtomicReturn, desc="") { + assert(is_valid(tbe)); + + enqueue(reqOutPort, CHIRequestMsg, request_latency) { + prepareRequestAtomic(tbe, CHIRequestType:AtomicReturn, out_msg); + out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr)); + allowRequestRetry(tbe, out_msg); + } + clearExpectedReqResp(tbe); + tbe.expected_req_resp.addExpectedRespType(CHIResponseType:DBIDResp); + tbe.expected_req_resp.addExpectedCount(1); +} + +action(Send_AtomicReturn_NoWait, desc="") { + assert(is_valid(tbe)); + + enqueue(reqOutPort, CHIRequestMsg, request_latency) { + prepareRequestAtomic(tbe, CHIRequestType:AtomicReturn, out_msg); + out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr)); + allowRequestRetry(tbe, out_msg); + } + + tbe.dataAMOValid := false; +} + +action(Send_AtomicNoReturn, desc="") { + assert(is_valid(tbe)); + + enqueue(reqOutPort, CHIRequestMsg, request_latency) { + prepareRequestAtomic(tbe, CHIRequestType:AtomicNoReturn, out_msg); + out_msg.Destination.add(mapAddressToDownstreamMachine(tbe.addr)); + allowRequestRetry(tbe, out_msg); + } + tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompDBIDResp); + tbe.expected_req_resp.addExpectedRespType(CHIResponseType:DBIDResp); + tbe.expected_req_resp.addExpectedCount(1); +} + + action(Send_SnpCleanInvalid, desc="") { assert(is_valid(tbe)); assert(tbe.expected_snp_resp.hasExpected() == false); @@ -1636,6 +1929,20 @@ action(ExpectNCBWrData, desc="") { tbe.dataBlkValid.setMask(addressOffset(tbe.accAddr, tbe.addr), tbe.accSize, false); } +action(ExpectNCBWrData_A, desc="") { + // Expected data + int num_msgs := tbe.accSize / data_channel_size; + if ((tbe.accSize % data_channel_size) != 0) { + num_msgs := num_msgs + 1; + } + tbe.expected_req_resp.clear(num_msgs); + tbe.expected_req_resp.addExpectedDataType(CHIDataType:NCBWrData); + tbe.expected_req_resp.setExpectedCount(1); + + // In atomic operations we do not expect real data for the current block + // Thus the mask bits do not care +} + action(ExpectCompAck, desc="") { assert(is_valid(tbe)); tbe.expected_req_resp.addExpectedRespType(CHIResponseType:CompAck); @@ -1658,7 +1965,22 @@ action(Receive_ReqDataResp, desc="") { } // Copy data to tbe only if we didn't have valid data or the received // data is dirty - if ((tbe.dataBlkValid.isFull() == false) || + if ((in_msg.type == CHIDataType:NCBWrData) && + ((tbe.reqType == CHIRequestType:AtomicReturn) || + (tbe.reqType == CHIRequestType:AtomicNoReturn))){ + // DO NOTHING + } else if ((in_msg.type == CHIDataType:CompData_I) && + ((tbe.reqType == CHIRequestType:AtomicReturn) || + (tbe.reqType == CHIRequestType:AtomicLoad))) { + if(tbe.dataBlkValid.isFull()){ + tbe.dataBlkValid.clear(); + } + tbe.oldDataBlk.copyPartial(in_msg.dataBlk, in_msg.bitMask); + assert(tbe.dataBlkValid.isOverlap(in_msg.bitMask) == false); + tbe.dataBlkValid.orMask(in_msg.bitMask); + DPRINTF(RubySlicc, "Received %s\n", tbe.oldDataBlk); + DPRINTF(RubySlicc, "dataBlkValid = %s\n", tbe.dataBlkValid); + } else if ((tbe.dataBlkValid.isFull() == false) || (in_msg.type == CHIDataType:CompData_UD_PD) || (in_msg.type == CHIDataType:CompData_SD_PD) || (in_msg.type == CHIDataType:CBWrData_UD_PD) || @@ -1683,7 +2005,8 @@ action(Receive_RespSepDataFromCompData, desc="") { if (tbe.expected_req_resp.receiveResp(CHIResponseType:RespSepData) == false) { error("Received unexpected message"); } - if (is_HN == false) { + if ((is_HN == false) && (tbe.reqType != CHIRequestType:AtomicReturn) && + ((tbe.reqType != CHIRequestType:AtomicLoad) || (tbe.atomic_to_be_done == true))){ // must now ack the responder tbe.actions.pushFrontNB(Event:SendCompAck); } @@ -1905,6 +2228,7 @@ action(UpdateDataState_FromReqDataResp, desc="") { } else if (in_msg.type == CHIDataType:CompData_I) { tbe.dataValid := true; + tbe.dataAMOValid := true; tbe.dataToBeInvalid := true; assert(tbe.dataMaybeDirtyUpstream == false); @@ -1946,7 +2270,9 @@ action(UpdateDataState_FromReqDataResp, desc="") { action(UpdateDataState_FromWUDataResp, desc="") { assert(is_valid(tbe)); - if (tbe.expected_req_resp.hasReceivedData()) { + if (tbe.expected_req_resp.hasReceivedData() && + (tbe.reqType != CHIRequestType:AtomicReturn) && + (tbe.reqType != CHIRequestType:AtomicNoReturn)) { assert(tbe.dataBlkValid.test(addressOffset(tbe.accAddr, tbe.addr))); assert(tbe.dataBlkValid.test(addressOffset(tbe.accAddr, tbe.addr) + tbe.accSize - 1)); @@ -1964,6 +2290,22 @@ action(UpdateDataState_FromWUDataResp, desc="") { printTBEState(tbe); } +action(UpdateDataState_FromADataResp, desc="") { + assert(is_valid(tbe)); + if (is_HN && (tbe.expected_req_resp.hasReceivedData()) && + ((tbe.reqType == CHIRequestType:AtomicReturn) || + (tbe.reqType == CHIRequestType:AtomicNoReturn))) { + DPRINTF(RubySlicc, "Atomic before %s\n", tbe.dataBlk); + + tbe.oldDataBlk := tbe.dataBlk; + tbe.dataBlk.atomicPartial(tbe.dataBlk, tbe.atomic_op); + tbe.dataDirty := true; + + DPRINTF(RubySlicc, "Atomic after %s\n", tbe.dataBlk); + } + printTBEState(tbe); +} + action(UpdateDataState_FromCUResp, desc="") { assert(is_valid(tbe)); peek(rspInPort, CHIResponseMsg) { @@ -2127,6 +2469,10 @@ action(Receive_ReqResp_WUNeedComp, desc="") { tbe.defer_expected_comp := true; } +action(Receive_ReqResp_AR, desc="") { + tbe.actions.pushFrontNB(Event:SendARData); +} + action(Receive_ReqResp_WUComp, desc="") { if (tbe.defer_expected_comp) { tbe.defer_expected_comp := false; @@ -2320,6 +2666,36 @@ action(CheckWUComp, desc="") { } } +action(Send_ARData, desc="") { + assert(is_valid(tbe)); + tbe.snd_msgType := CHIDataType:NCBWrData; + tbe.snd_destination := mapAddressToDownstreamMachine(tbe.addr); + setupPendingAtomicSend(tbe); +} + +action(Send_ANRData, desc="") { + assert(is_valid(tbe)); + tbe.snd_msgType := CHIDataType:NCBWrData; + tbe.snd_destination := mapAddressToDownstreamMachine(tbe.addr); + setupPendingAtomicSend(tbe); +} + +action(CheckARComp, desc="") { + assert(is_valid(tbe)); + tbe.expected_req_resp.addExpectedDataType(CHIDataType:CompData_I); + tbe.expected_req_resp.addExpectedRespType(CHIResponseType:RespSepData); + tbe.expected_req_resp.addExpectedCount(2); +} + +action(CheckANRComp, desc="") { + assert(is_valid(tbe)); + if (tbe.defer_expected_comp) { + tbe.defer_expected_comp := false; + tbe.expected_req_resp.addExpectedCount(1); + tbe.expected_req_resp.addExpectedRespType(CHIResponseType:Comp); + } +} + action(Send_SnpRespData, desc="") { assert(is_HN == false); assert(is_valid(tbe)); @@ -2531,7 +2907,12 @@ action(Send_Data, desc="") { } tbe.snd_pendBytes.setMask(offset, range, false); - out_msg.dataBlk := tbe.dataBlk; + if (tbe.reqType == CHIRequestType:AtomicReturn){ + out_msg.dataBlk := tbe.oldDataBlk; + } else { + out_msg.dataBlk := tbe.dataBlk; + } + out_msg.bitMask.setMask(offset, range); out_msg.responder := machineID; @@ -2673,6 +3054,36 @@ action(Send_Comp_WU, desc="") { } } + +action(Send_CompData_AR, desc="") { + assert(is_valid(tbe)); + assert(tbe.dataValid); + + if (is_HN) { + tbe.oldDataBlk := tbe.dataBlk; + } + + tbe.snd_msgType := CHIDataType:CompData_I; + tbe.dataMaybeDirtyUpstream := false; + tbe.requestorToBeExclusiveOwner := false; + tbe.requestorToBeOwner := false; + tbe.snd_destination := tbe.requestor; + setupPendingSend(tbe); + printTBEState(tbe); + +} + +action(Send_Comp_ANR, desc="") { + assert(is_valid(tbe)); + enqueue(rspOutPort, CHIResponseMsg, comp_anr_latency + response_latency) { + out_msg.addr := address; + out_msg.type := CHIResponseType:Comp; + out_msg.responder := machineID; + out_msg.Destination.add(tbe.requestor); + } +} + + action(Send_SnpRespI, desc="") { enqueue(rspOutPort, CHIResponseMsg, response_latency) { out_msg.addr := address; @@ -3003,6 +3414,22 @@ action(Callback_StoreHit, desc="") { } } +action(Callback_AtomicHit, desc="") { + assert(is_valid(tbe)); + assert(tbe.dataValid); + assert((tbe.reqType == CHIRequestType:AtomicLoad) || + (tbe.reqType == CHIRequestType:AtomicStore)); + DPRINTF(RubySlicc, "Atomic before %s\n", tbe.dataBlk); + + DataBlock oldDataBlk; + oldDataBlk := tbe.dataBlk; + tbe.dataBlk.atomicPartial(tbe.dataBlk, tbe.atomic_op); + + sequencer.atomicCallback(tbe.addr, oldDataBlk, false); + DPRINTF(RubySlicc, "Atomic after %s\n", tbe.dataBlk); + tbe.dataDirty := true; +} + action(Callback_ExpressPrefetchHit, desc="") { // have not allocated TBE, but must clear the reservation assert(is_invalid(tbe)); @@ -3051,6 +3478,25 @@ action(Callback_Miss, desc="") { // also decay the timeout scLockDecayLatency(); } + } else if (tbe.dataValid && tbe.atomic_to_be_done && + ((tbe.reqType == CHIRequestType:AtomicLoad) || + (tbe.reqType == CHIRequestType:AtomicStore))){ + assert(is_valid(tbe)); + assert(tbe.dataValid); + assert((tbe.reqType == CHIRequestType:AtomicLoad) || + (tbe.reqType == CHIRequestType:AtomicStore)); + DPRINTF(RubySlicc, "Atomic before %s\n", tbe.dataBlk); + + DataBlock oldDataBlk; + oldDataBlk := tbe.dataBlk; + tbe.dataBlk.atomicPartial(tbe.dataBlk, tbe.atomic_op); + + sequencer.atomicCallback(tbe.addr, oldDataBlk, false); + DPRINTF(RubySlicc, "Atomic after %s\n", tbe.dataBlk); + tbe.dataDirty := true; + } else if (tbe.dataValid && tbe.dataAMOValid && (tbe.reqType == CHIRequestType:AtomicLoad)) { + DPRINTF(RubySlicc, "Atomic before %s\n", tbe.oldDataBlk); + sequencer.atomicCallback(tbe.addr, tbe.oldDataBlk, false); } } @@ -3070,6 +3516,18 @@ action(Unset_Timeout_Cache, desc="") { wakeup_port(snpRdyPort, address); } +action(Callback_AtomicNoReturn, desc="") { + assert(is_valid(tbe)); + assert((tbe.is_local_pf || tbe.is_remote_pf) == false); + assert((tbe.reqType == CHIRequestType:AtomicNoReturn) || + (tbe.reqType == CHIRequestType:AtomicStore)); + + if(tbe.reqType == CHIRequestType:AtomicStore){ + sequencer.atomicCallback(tbe.addr, tbe.dataBlk); + DPRINTF(RubySlicc, "AtomicNoReturn %s\n", tbe.dataBlk); + } +} + action(Callback_WriteUnique, desc="") { assert(is_valid(tbe)); assert((tbe.is_local_pf || tbe.is_remote_pf) == false); @@ -3183,7 +3641,7 @@ action(Profile_OutgoingEnd_DatalessResp, desc="") { action(TagArrayRead, desc="") { assert(is_valid(tbe)); tbe.delayNextAction := curTick() + cyclesToTicks( - tagLatency(fromSequencer(tbe.reqType))); + tagLatency(fromSequencer(tbe.reqType))); } action(TagArrayWrite, desc="") { @@ -3235,6 +3693,11 @@ action(FillPipe, desc="") { tbe.delayNextAction := curTick() + cyclesToTicks(fill_latency); } +action(DelayAtomic, desc="") { + assert(is_valid(tbe)); + tbe.delayNextAction := curTick() + cyclesToTicks(atomic_op_latency); +} + action(SnpSharedPipe, desc="") { assert(is_valid(tbe)); tbe.delayNextAction := curTick() + cyclesToTicks(snp_latency); diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index 4d8c35053c..371ad05109 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -302,7 +302,9 @@ Cycles dataLatency() { bool fromSequencer(CHIRequestType reqType) { return reqType == CHIRequestType:Load || reqType == CHIRequestType:Store || - reqType == CHIRequestType:StoreLine; + reqType == CHIRequestType:StoreLine || + reqType == CHIRequestType:AtomicLoad || + tbe.reqType == CHIRequestType:AtomicStore; } bool inCache(Addr addr) { @@ -434,6 +436,9 @@ TBE allocateRequestTBE(Addr addr, CHIRequestMsg in_msg), return_by_pointer="yes" tbe.is_local_pf := in_msg.is_local_pf; tbe.is_remote_pf := in_msg.is_remote_pf; + tbe.atomic_op.clear(); + tbe.atomic_op.orMask(in_msg.atomic_op); + tbe.use_DMT := false; tbe.use_DCT := false; @@ -622,6 +627,13 @@ void setupPendingPartialSend(TBE tbe) { scheduleSendData(tbe, 0); } +void setupPendingAtomicSend(TBE tbe) { + assert(blockSize >= data_channel_size); + assert((blockSize % data_channel_size) == 0); + tbe.snd_pendBytes.setMask(0,tbe.accSize,true); + scheduleSendData(tbe, 0); +} + // common code for downstream requests void prepareRequest(TBE tbe, CHIRequestType type, CHIRequestMsg & out_msg) { out_msg.addr := tbe.addr; @@ -644,6 +656,17 @@ void prepareRequest(TBE tbe, CHIRequestType type, CHIRequestMsg & out_msg) { assert(tbe.txnId != static_cast(Addr, "value", -1)); } +void prepareRequestAtomic(TBE tbe, CHIRequestType type, + CHIRequestMsg & out_msg) { + assert((type == CHIRequestType:AtomicReturn) || + (type == CHIRequestType:AtomicNoReturn)); + prepareRequest(tbe, type, out_msg); + out_msg.accAddr := tbe.accAddr; + out_msg.accSize := tbe.accSize; + out_msg.atomic_op.clear(); + out_msg.atomic_op.orMask(tbe.atomic_op); +} + void allowRequestRetry(TBE tbe, CHIRequestMsg & out_msg) { out_msg.allowRetry := true; tbe.pendReqAllowRetry := true; @@ -672,6 +695,8 @@ void prepareRequestRetry(TBE tbe, CHIRequestMsg & out_msg) { out_msg.seqReq := tbe.seqReq; out_msg.is_local_pf := false; out_msg.is_remote_pf := tbe.is_local_pf || tbe.is_remote_pf; + out_msg.atomic_op.clear(); + out_msg.atomic_op.orMask(tbe.atomic_op); } void prepareRequestRetryDVM(TBE tbe, CHIRequestMsg & out_msg) { @@ -773,8 +798,12 @@ bool needCacheEntry(CHIRequestType req_type, (req_type == CHIRequestType:WriteEvictFull) || (is_HN && (req_type == CHIRequestType:WriteUniqueFull)))) || (alloc_on_seq_acc && ((req_type == CHIRequestType:Load) || - (req_type == CHIRequestType:Store))) || - (alloc_on_seq_line_write && (req_type == CHIRequestType:StoreLine)); + (req_type == CHIRequestType:Store) || + (req_type == CHIRequestType:AtomicLoad) || + (req_type == CHIRequestType:AtomicStore))) || + (alloc_on_seq_line_write && (req_type == CHIRequestType:StoreLine)) || + (alloc_on_atomic && ((req_type == CHIRequestType:AtomicReturn) || + (req_type == CHIRequestType:AtomicNoReturn))); } } @@ -1174,6 +1203,10 @@ Event reqToEvent(CHIRequestType type, bool is_prefetch) { return Event:Store; } else if (type == CHIRequestType:StoreLine) { return Event:Store; + } else if (type == CHIRequestType:AtomicLoad) { + return Event:AtomicLoad; + } else if (type == CHIRequestType:AtomicStore){ + return Event:AtomicStore; } else if (type == CHIRequestType:ReadShared) { return Event:ReadShared; } else if (type == CHIRequestType:ReadNotSharedDirty) { @@ -1214,6 +1247,18 @@ Event reqToEvent(CHIRequestType type, bool is_prefetch) { return Event:DvmTlbi_Initiate; } else if (type == CHIRequestType:DvmSync_Initiate) { return Event:DvmSync_Initiate; + } else if (type == CHIRequestType:AtomicReturn){ + if (is_HN) { + return Event:AtomicReturn_PoC; + } else { + return Event:AtomicReturn; + } + } else if (type == CHIRequestType:AtomicNoReturn){ + if (is_HN) { + return Event:AtomicNoReturn_PoC; + } else { + return Event:AtomicNoReturn; + } } else { error("Invalid CHIRequestType"); } diff --git a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm index cb9ffa567a..0e8c6ec0e3 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm @@ -155,6 +155,12 @@ transition({BUSY_INTR,BUSY_BLKD}, FillPipe) { ProcessNextState_ClearPending; } +transition({BUSY_INTR,BUSY_BLKD}, DelayAtomic) { + Pop_TriggerQueue; + DelayAtomic; + ProcessNextState_ClearPending; +} + transition({BUSY_INTR,BUSY_BLKD}, SnpSharedPipe) { Pop_TriggerQueue; SnpSharedPipe; @@ -418,8 +424,82 @@ transition({RSC,RSD,RUSD,RUSC,RU,I}, WriteUnique, BUSY_BLKD) { ProcessNextState; } +// AtomicReturn and AtomicNoReturn -// Load / Store from sequencer & Prefetch from prefetcher +transition({I,SC,SC_RSC,SD,SD_RSD,SD_RSC,RSD,RUSD, + UD,UD_RSC,UD_RSD,UD_RU,UC,UC_RSC,UC_RU,RSC,RU}, AtomicReturn, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicReturn_Forward; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition({I,SC,SC_RSC,SD,SD_RSD,SD_RSC,RSD,RUSD, + UD,UD_RSC,UD_RSD,UD_RU,UC,UC_RSC,UC_RU,RSC,RU}, AtomicNoReturn, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicNoReturn_Forward; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition({UD,UD_RU,UD_RSD,UD_RSC,UC,UC_RU,UC_RSC}, + AtomicReturn_PoC, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicReturn_LocalWrite; + Profile_Hit; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition({UD,UD_RU,UD_RSD,UD_RSC,UC,UC_RU,UC_RSC}, + AtomicNoReturn_PoC, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicNoReturn_LocalWrite; + Profile_Hit; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition({SD, SD_RSD, SD_RSC, SC, SC_RSC, RSC, RSD, RUSC, RUSD, RU}, + AtomicReturn_PoC, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicReturn_LocalWrite; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition({SD, SD_RSD, SD_RSC, SC, SC_RSC, RSC, RSD, RUSC, RUSD, RU}, + AtomicNoReturn_PoC, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicNoReturn_LocalWrite; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(I, AtomicReturn_PoC, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicReturn_Miss; + Allocate_DirEntry; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(I, AtomicNoReturn_PoC, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicNoReturn_Miss; + Allocate_DirEntry; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + + +// Load / Store / Atomic from sequencer & Prefetch from prefetcher transition({UD,UD_T,SD,UC,SC}, Load, BUSY_BLKD) { Initiate_Request; @@ -460,6 +540,28 @@ transition(BUSY_BLKD, StoreHit) { ProcessNextState_ClearPending; } +transition(UC, {AtomicLoad,AtomicStore}, BUSY_BLKD) { + Initiate_Request; + Initiate_Atomic_UC; + Profile_Hit; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition({UD,UD_T}, {AtomicLoad,AtomicStore}, BUSY_BLKD) { + Initiate_Request; + Initiate_Atomic_UD; + Profile_Hit; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(BUSY_BLKD, AtomicHit) { + Pop_TriggerQueue; + Callback_AtomicHit; + ProcessNextState_ClearPending; +} + transition(I, {Load,Prefetch}, BUSY_BLKD) { Initiate_Request; Initiate_LoadMiss; @@ -494,6 +596,55 @@ transition({BUSY_BLKD,BUSY_INTR}, UseTimeout) { Unset_Timeout_TBE; } +transition(I, AtomicLoad, BUSY_BLKD){ + Initiate_Request; + Initiate_AtomicReturn_I; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(I, AtomicStore, BUSY_BLKD){ + Initiate_Request; + Initiate_AtomicNoReturn_I; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(SD, AtomicLoad, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicReturn_SD; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(SC, AtomicLoad, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicReturn_SC; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(SD, AtomicStore, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicNoReturn_SD; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + +transition(SC, AtomicStore, BUSY_BLKD) { + Initiate_Request; + Initiate_AtomicNoReturn_SC; + Profile_Miss; + Pop_ReqRdyQueue; + ProcessNextState; +} + + // Evict from Upstream transition({UD_RSC,SD_RSC,UC_RSC,SC_RSC,RSC,RSD,RUSD,RUSC,UD_RSD,SD_RSD}, Evict, BUSY_BLKD) { @@ -691,13 +842,15 @@ transition(BUSY_INTR, {SnpOnce,SnpOnceFwd}, BUSY_BLKD) { transition({BUSY_BLKD,BUSY_INTR}, {ReadShared, ReadNotSharedDirty, ReadUnique, ReadUnique_PoC, ReadOnce, CleanUnique, CleanUnique_Stale, - Load, Store, Prefetch, + Load, Store, AtomicLoad, AtomicStore, Prefetch, WriteBackFull, WriteBackFull_Stale, WriteEvictFull, WriteEvictFull_Stale, WriteCleanFull, WriteCleanFull_Stale, Evict, Evict_Stale, WriteUnique,WriteUniquePtl_PoC, - WriteUniqueFull_PoC,WriteUniqueFull_PoC_Alloc}) { + WriteUniqueFull_PoC,WriteUniqueFull_PoC_Alloc + AtomicReturn,AtomicReturn_PoC, + AtomicNoReturn,AtomicNoReturn_PoC}) { StallRequest; } @@ -754,6 +907,30 @@ transition(BUSY_BLKD, SendWriteUnique, BUSY_INTR) {DestinationAvailable} { ProcessNextState_ClearPending; } +transition(BUSY_BLKD, SendAtomicReturn, BUSY_INTR) {DestinationAvailable} { + Pop_TriggerQueue; + Send_AtomicReturn; + CheckARComp; + Profile_OutgoingStart; + ProcessNextState_ClearPending; +} + +transition(BUSY_BLKD, SendAtomicReturn_NoWait, BUSY_INTR) { + Pop_TriggerQueue; + Send_AtomicReturn_NoWait; + CheckARComp; + Profile_OutgoingStart; + ProcessNextState_ClearPending; +} + +transition(BUSY_BLKD, SendAtomicNoReturn, BUSY_INTR) {DestinationAvailable} { + Pop_TriggerQueue; + Send_AtomicNoReturn; + Profile_OutgoingStart; + ProcessNextState_ClearPending; +} + + transition(BUSY_BLKD, SendWriteNoSnp, BUSY_INTR) {DestinationAvailable} { Pop_TriggerQueue; Send_WriteNoSnp; @@ -804,6 +981,20 @@ transition(BUSY_BLKD, SendWUDataCB) { ProcessNextState_ClearPending; } +transition({BUSY_BLKD,BUSY_INTR}, SendARData) { + Pop_TriggerQueue; + Send_ARData; + ProcessNextState_ClearPending; +} + +transition({BUSY_BLKD,BUSY_INTR}, SendANRData) { + Pop_TriggerQueue; + Callback_AtomicNoReturn; + Send_ANRData; + CheckANRComp; + ProcessNextState_ClearPending; +} + transition(BUSY_BLKD, SendInvSnpResp) { Pop_TriggerQueue; Send_InvSnpResp; @@ -1025,6 +1216,26 @@ transition({BUSY_BLKD,BUSY_INTR}, SendComp_WU) { ProcessNextState_ClearPending; } +transition(BUSY_BLKD, SendCompDBIDResp_ANR) { + Pop_TriggerQueue; + ExpectNCBWrData_A; + Send_CompDBIDResp; + ProcessNextState_ClearPending; +} + +transition(BUSY_BLKD, SendDBIDResp_AR) { + Pop_TriggerQueue; + ExpectNCBWrData_A; + Send_DBIDResp; + ProcessNextState_ClearPending; +} + +transition({BUSY_BLKD,BUSY_INTR}, SendCompData_AR) { + Pop_TriggerQueue; + Send_CompData_AR; + ProcessNextState_ClearPending; +} + transition(BUSY_BLKD, SendCompDBIDRespStale) { Pop_TriggerQueue; Send_CompDBIDResp_Stale; @@ -1085,6 +1296,7 @@ transition(BUSY_BLKD, transition({BUSY_BLKD,BUSY_INTR}, NCBWrData) { Receive_ReqDataResp; UpdateDataState_FromWUDataResp; + UpdateDataState_FromADataResp; Pop_DataInQueue; ProcessNextState; } @@ -1238,10 +1450,11 @@ transition(BUSY_INTR, CompDBIDResp, BUSY_BLKD) { } // alternative flow for WU with separate Comp -transition(BUSY_INTR, DBIDResp, BUSY_BLKD) { +transition({BUSY_INTR,BUSY_BLKD}, DBIDResp, BUSY_BLKD) { Receive_ReqResp; Receive_ReqResp_CopyDBID; Receive_ReqResp_WUNeedComp; + Receive_ReqResp_AR; Pop_RespInQueue; ProcessNextState; } diff --git a/src/mem/ruby/protocol/chi/CHI-cache.sm b/src/mem/ruby/protocol/chi/CHI-cache.sm index e40989df47..f806488b45 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache.sm @@ -51,6 +51,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : // sending necessary snoops. Cycles read_hit_latency := 0; Cycles read_miss_latency := 0; + Cycles atomic_op_latency := 0; Cycles write_fe_latency := 0; // Front-end: Rcv req -> Snd req Cycles write_be_latency := 0; // Back-end: Rcv ack -> Snd data Cycles fill_latency := 0; // Fill latency @@ -126,11 +127,24 @@ machine(MachineType:Cache, "Cache coherency protocol") : // possible. bool enable_DCT; + // Atomic Operation Policy + // All Near executes all Atomics at L1 (variable set to 0; default) + // Unique Near executes Atomics at HNF for states I, SC, SD (set to 1) + // Present Near execites all Atomics at L1 except when state is I (set to 2) + int policy_type := 1; + + // Use separate Comp/DBIDResp responses for WriteUnique bool comp_wu := "False"; // additional latency for the WU Comp response Cycles comp_wu_latency := 0; + + // Use separate Comp/DBIDResp responses for AtomicNoResponse + bool comp_anr := "False"; + // additional latency for the ANR Comp response + Cycles comp_anr_latency := 0; + // Controls cache clusivity for different request types. // set all alloc_on* to false to completelly disable caching bool alloc_on_readshared; @@ -139,6 +153,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : bool alloc_on_writeback; bool alloc_on_seq_acc; bool alloc_on_seq_line_write; + bool alloc_on_atomic; // Controls if the clusivity is strict. bool dealloc_on_unique; bool dealloc_on_shared; @@ -285,6 +300,8 @@ machine(MachineType:Cache, "Cache coherency protocol") : // See CHIRequestType in CHi-msg.sm for descriptions Load, desc="", in_trans="yes"; Store, desc="", in_trans="yes"; + AtomicLoad, desc="", in_trans="yes"; + AtomicStore, desc="", in_trans="yes"; Prefetch, desc="", in_trans="yes"; ReadShared, desc="", in_trans="yes"; ReadNotSharedDirty, desc="", in_trans="yes"; @@ -300,6 +317,10 @@ machine(MachineType:Cache, "Cache coherency protocol") : WriteUniquePtl_PoC, desc="", in_trans="yes"; WriteUniqueFull_PoC, desc="", in_trans="yes"; WriteUniqueFull_PoC_Alloc, desc="", in_trans="yes"; + AtomicReturn, desc="", in_trans="yes"; + AtomicNoReturn, desc="", in_trans="yes"; + AtomicReturn_PoC, desc="", in_trans="yes"; + AtomicNoReturn_PoC, desc="", in_trans="yes"; SnpCleanInvalid, desc="", in_trans="yes"; SnpShared, desc="", in_trans="yes"; SnpSharedFwd, desc="", in_trans="yes"; @@ -418,11 +439,12 @@ machine(MachineType:Cache, "Cache coherency protocol") : DataArrayWriteOnFill, desc="Write the cache data array (cache fill)"; // Events for modeling the pipeline latency - ReadHitPipe, desc="Latency of reads served from local cache"; - ReadMissPipe, desc="Latency of reads not served from local cache"; - WriteFEPipe, desc="Front-end latency of write requests"; - WriteBEPipe, desc="Back-end latency of write requests"; - FillPipe, desc="Cache fill latency"; + ReadHitPipe, desc="Latency of reads served from local cache"; + ReadMissPipe, desc="Latency of reads not served from local cache"; + WriteFEPipe, desc="Front-end latency of write requests"; + WriteBEPipe, desc="Back-end latency of write requests"; + FillPipe, desc="Cache fill latency"; + DelayAtomic, desc="Atomic operation latency"; SnpSharedPipe, desc="Latency for SnpShared requests"; SnpInvPipe, desc="Latency for SnpUnique and SnpCleanInv requests"; SnpOncePipe, desc="Latency for SnpOnce requests"; @@ -435,9 +457,9 @@ machine(MachineType:Cache, "Cache coherency protocol") : SendReadUnique, out_trans="yes", desc="Send a ReadUnique"; SendCompAck, desc="Send CompAck"; // Read handling at the completer - SendCompData, desc="Send CompData"; - WaitCompAck, desc="Expect to receive CompAck"; - SendRespSepData, desc="Send RespSepData for a DMT request"; + SendCompData, desc="Send CompData"; + WaitCompAck, desc="Expect to receive CompAck"; + SendRespSepData, desc="Send RespSepData for a DMT request"; // Send a write request downstream. SendWriteBackOrWriteEvict, out_trans="yes", desc="Send a WriteBackFull (if line is UD or SD) or WriteEvictFull (if UC)"; @@ -449,11 +471,25 @@ machine(MachineType:Cache, "Cache coherency protocol") : SendWUData, desc="Send write unique data"; SendWUDataCB, desc="Send write unique data from a sequencer callback"; // Write handling at the completer - SendCompDBIDResp, desc="Ack WB with CompDBIDResp"; - SendCompDBIDRespStale, desc="Ack stale WB with CompDBIDResp"; - SendCompDBIDResp_WU, desc="Ack WU with CompDBIDResp and set expected data"; - SendDBIDResp_WU, desc="Ack WU with DBIDResp and set expected data"; - SendComp_WU, desc="Ack WU completion"; + SendCompDBIDResp, desc="Ack WB with CompDBIDResp"; + SendCompDBIDRespStale, desc="Ack stale WB with CompDBIDResp"; + SendCompDBIDResp_WU, desc="Ack WU with CompDBIDResp and set expected data"; + SendDBIDResp_WU, desc="Ack WU with DBIDResp and set expected data"; + SendComp_WU, desc="Ack WU completion"; + + // Send an atomic request downstream. + SendAtomicReturn, out_trans="yes", desc="Send atomic request with return"; + SendAtomicReturn_NoWait, out_trans="yes", desc="Send atomic request with return, but no DBID"; + SendAtomicNoReturn, out_trans="yes", desc="Send atomic request without return"; + SendARData, desc="Send atomic return request data"; + SendANRData, desc="Send atomic no return request data"; + // Atomic handling at the completer + SendDBIDResp_AR, desc="Ack AR with DBIDResp and set expected data"; + SendCompData_AR, desc="Ack AR completion"; + SendCompDBIDResp_ANR, desc="Ack ANR with CompDBIDResp and set expected data"; + SendDBIDResp_ANR, desc="Ack ANR with DBIDResp and set expected data"; + SendComp_ANR, desc="Ack ANR completion"; + // Dataless requests SendEvict, out_trans="yes", desc="Send a Evict"; @@ -502,6 +538,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : // Misc triggers LoadHit, desc="Complete a load hit"; StoreHit, desc="Complete a store hit"; + AtomicHit, desc="Complete an atomic hit"; UseTimeout, desc="Transition from UD_T -> UD"; RestoreFromHazard, desc="Restore from a snoop hazard"; TX_Data, desc="Transmit pending data messages"; @@ -613,6 +650,10 @@ machine(MachineType:Cache, "Cache coherency protocol") : bool is_local_pf, desc="Request generated by a local prefetcher"; bool is_remote_pf, desc="Request generated a prefetcher in another cache"; + // Atomic info associated with the transaction + WriteMask atomic_op, desc="Atomic Operation Wrapper"; + bool atomic_to_be_done, desc="We have yet to perform the atomic"; + // NOTE: seqReq is a smart pointer pointing to original CPU request object // that triggers transactions associated with this TBE. seqReq carries some // information (e.g., PC of requesting instruction, virtual address of this @@ -630,8 +671,10 @@ machine(MachineType:Cache, "Cache coherency protocol") : // stable state. bool hasUseTimeout, desc="Line is locked under store/use timeout"; DataBlock dataBlk, desc="Local copy of the line"; + DataBlock oldDataBlk, desc="Local copy of the line before executing atomic"; WriteMask dataBlkValid, desc="Marks which bytes in the DataBlock are valid"; bool dataValid, desc="Local copy is valid"; + bool dataAMOValid, desc="Local copy is valid for AMO"; bool dataDirty, desc="Local copy is dirtry"; bool dataMaybeDirtyUpstream, desc="Line maybe dirty upstream"; bool dataUnique, desc="Line is unique either locally or upsatream"; diff --git a/src/mem/ruby/protocol/chi/CHI-msg.sm b/src/mem/ruby/protocol/chi/CHI-msg.sm index f3c2d66363..b9e11d9dd9 100644 --- a/src/mem/ruby/protocol/chi/CHI-msg.sm +++ b/src/mem/ruby/protocol/chi/CHI-msg.sm @@ -46,6 +46,8 @@ enumeration(CHIRequestType, desc="") { Load; Store; StoreLine; + AtomicLoad; + AtomicStore; // Incoming DVM-related requests generated by the sequencer DvmTlbi_Initiate; DvmSync_Initiate; @@ -66,6 +68,9 @@ enumeration(CHIRequestType, desc="") { WriteUniquePtl; WriteUniqueFull; + AtomicReturn; + AtomicNoReturn; + SnpSharedFwd; SnpNotSharedDirtyFwd; SnpUniqueFwd; @@ -108,6 +113,8 @@ structure(CHIRequestMsg, desc="", interface="Message") { bool is_local_pf, desc="Request generated by a local prefetcher"; bool is_remote_pf, desc="Request generated a prefetcher in another cache"; + WriteMask atomic_op, desc="Atomic Operation Wrapper"; + bool usesTxnId, desc="True if using a Transaction ID", default="false"; Addr txnId, desc="Transaction ID", default="0"; diff --git a/src/mem/ruby/slicc_interface/RubyRequest.cc b/src/mem/ruby/slicc_interface/RubyRequest.cc index 643c1dec6f..c6faf2d76f 100644 --- a/src/mem/ruby/slicc_interface/RubyRequest.cc +++ b/src/mem/ruby/slicc_interface/RubyRequest.cc @@ -123,5 +123,14 @@ RubyRequest::functionalWrite(Packet *pkt) return cBase < cTail; } +void +RubyRequest::setWriteMask(uint32_t offset, uint32_t len, + std::vector< std::pair> atomicOps) +{ + m_writeMask.setMask(offset, len); + m_writeMask.setAtomicOps(atomicOps); +} + + } // namespace ruby } // namespace gem5 diff --git a/src/mem/ruby/slicc_interface/RubyRequest.hh b/src/mem/ruby/slicc_interface/RubyRequest.hh index 89ce83451e..1e9674b9f5 100644 --- a/src/mem/ruby/slicc_interface/RubyRequest.hh +++ b/src/mem/ruby/slicc_interface/RubyRequest.hh @@ -226,6 +226,8 @@ class RubyRequest : public Message const PrefetchBit& getPrefetch() const { return m_Prefetch; } RequestPtr getRequestPtr() const { return m_pkt->req; } + void setWriteMask(uint32_t offset, uint32_t len, + std::vector< std::pair> atomicOps); void print(std::ostream& out) const; bool functionalRead(Packet *pkt); bool functionalRead(Packet *pkt, WriteMask &mask); diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 82fc19b57c..48054febef 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -466,8 +466,12 @@ Sequencer::writeCallback(Addr address, DataBlock& data, bool ruby_request = true; while (!seq_req_list.empty()) { SequencerRequest &seq_req = seq_req_list.front(); + // Atomic Request may be executed remotly in the cache hierarchy + bool atomic_req = + ((seq_req.m_type == RubyRequestType_ATOMIC_RETURN) || + (seq_req.m_type == RubyRequestType_ATOMIC_NO_RETURN)); - if (noCoales && !ruby_request) { + if ((noCoales || atomic_req) && !ruby_request) { // Do not process follow-up requests // (e.g. if full line no present) // Reissue to the cache hierarchy @@ -479,6 +483,8 @@ Sequencer::writeCallback(Addr address, DataBlock& data, assert(seq_req.m_type != RubyRequestType_LD); assert(seq_req.m_type != RubyRequestType_Load_Linked); assert(seq_req.m_type != RubyRequestType_IFETCH); + assert(seq_req.m_type != RubyRequestType_ATOMIC_RETURN); + assert(seq_req.m_type != RubyRequestType_ATOMIC_NO_RETURN); } // handle write request @@ -594,6 +600,62 @@ Sequencer::readCallback(Addr address, DataBlock& data, } } +void +Sequencer::atomicCallback(Addr address, DataBlock& data, + const bool externalHit, const MachineType mach, + const Cycles initialRequestTime, + const Cycles forwardRequestTime, + const Cycles firstResponseTime) +{ + // + // Free the first request (an atomic operation) from the list. + // Then issue the next request to ruby system as we cannot + // assume the cache line is present in the cache + // (the opperation could be performed remotly) + // + assert(address == makeLineAddress(address)); + assert(m_RequestTable.find(address) != m_RequestTable.end()); + auto &seq_req_list = m_RequestTable[address]; + + // Perform hitCallback only on the first cpu request that + // issued the ruby request + bool ruby_request = true; + while (!seq_req_list.empty()) { + SequencerRequest &seq_req = seq_req_list.front(); + + if (ruby_request) { + // Check that the request was an atomic memory operation + // and record the latency + assert((seq_req.m_type == RubyRequestType_ATOMIC_RETURN) || + (seq_req.m_type == RubyRequestType_ATOMIC_NO_RETURN)); + recordMissLatency(&seq_req, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime); + } else { + // Read, Write or Atomic request: + // reissue request to the cache hierarchy + // (we don't know if op was performed remotly) + issueRequest(seq_req.pkt, seq_req.m_second_type); + break; + } + + // Atomics clean the monitor entry + llscClearMonitor(address); + + markRemoved(); + ruby_request = false; + hitCallback(&seq_req, data, true, mach, externalHit, + initialRequestTime, forwardRequestTime, + firstResponseTime, false); + seq_req_list.pop_front(); + } + + // free all outstanding requests corresponding to this address + if (seq_req_list.empty()) { + m_RequestTable.erase(address); + } +} + void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data, bool llscSuccess, @@ -637,10 +699,16 @@ Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data, (type == RubyRequestType_IFETCH) || (type == RubyRequestType_RMW_Read) || (type == RubyRequestType_Locked_RMW_Read) || - (type == RubyRequestType_Load_Linked)) { + (type == RubyRequestType_Load_Linked) || + (type == RubyRequestType_ATOMIC_RETURN)) { pkt->setData( data.getData(getOffset(request_address), pkt->getSize())); - DPRINTF(RubySequencer, "read data %s\n", data); + + if (type == RubyRequestType_ATOMIC_RETURN) { + DPRINTF(RubySequencer, "ATOMIC RETURN data %s\n", data); + } else { + DPRINTF(RubySequencer, "read data %s\n", data); + } } else if (pkt->req->isSwap()) { assert(!pkt->isMaskedWrite()); std::vector overwrite_val(pkt->getSize()); @@ -807,6 +875,19 @@ Sequencer::makeRequest(PacketPtr pkt) } else if (pkt->req->isTlbiCmd()) { primary_type = secondary_type = tlbiCmdToRubyRequestType(pkt); DPRINTF(RubySequencer, "Issuing TLBI\n"); +#if defined (PROTOCOL_CHI) + } else if (pkt->isAtomicOp()) { + if (pkt->req->isAtomicReturn()){ + DPRINTF(RubySequencer, "Issuing ATOMIC RETURN \n"); + primary_type = secondary_type = + RubyRequestType_ATOMIC_RETURN; + } else { + DPRINTF(RubySequencer, "Issuing ATOMIC NO RETURN\n"); + primary_type = secondary_type = + RubyRequestType_ATOMIC_NO_RETURN; + + } +#endif } else { // // To support SwapReq, we need to check isWrite() first: a SwapReq @@ -914,6 +995,18 @@ Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type) RubyAccessMode_Supervisor, pkt, PrefetchBit_No, proc_id, core_id); + if (pkt->isAtomicOp() && + ((secondary_type == RubyRequestType_ATOMIC_RETURN) || + (secondary_type == RubyRequestType_ATOMIC_NO_RETURN))){ + // Create the blocksize, access mask and atomicops + uint32_t offset = getOffset(pkt->getAddr()); + std::vector> atomicOps; + atomicOps.push_back(std::make_pair + (offset, pkt->getAtomicOp())); + + msg->setWriteMask(offset, pkt->getSize(), atomicOps); + } + DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\n", curTick(), m_version, "Seq", "Begin", "", "", printAddress(msg->getPhysicalAddress()), diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 020a7d8c20..8f736da6d5 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -126,6 +126,14 @@ class Sequencer : public RubyPort const Cycles forwardRequestTime = Cycles(0), const Cycles firstResponseTime = Cycles(0)); + void atomicCallback(Addr address, + DataBlock& data, + const bool externalHit = false, + const MachineType mach = MachineType_NUM, + const Cycles initialRequestTime = Cycles(0), + const Cycles forwardRequestTime = Cycles(0), + const Cycles firstResponseTime = Cycles(0)); + void unaddressedCallback(Addr unaddressedReqId, RubyRequestType requestType, const MachineType mach = MachineType_NUM, From 98a6cd6ee245502fa2ec46acb9eab4691dec65f8 Mon Sep 17 00:00:00 2001 From: Leo Redivo Date: Wed, 4 Oct 2023 13:32:35 -0700 Subject: [PATCH 373/693] misc: changed call get_default_disk_device to get_disk_device Change-Id: I240da78a658208211ede6648547dfa4c971074a1 --- src/python/gem5/components/boards/kernel_disk_workload.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index c8c6e58878..72b143e6ff 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -190,7 +190,7 @@ class KernelDiskWorkload: disk_device=( self._disk_device if self._disk_device - else self.get_default_disk_device() + else self.get_disk_device() ), ) From ea3ee880aa6957291961aa1a4764fe87ed505205 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 5 Jul 2023 16:11:14 +0800 Subject: [PATCH 374/693] arch-riscv: Implement Zcb instructions Added the following instructions: c.lbu c.lh c.lhu c.sb c.sh c.zext.b c.sext.b c.zext.h c.sext.h c.zext.w c.not c.mul Reference: https://github.com/riscv/riscv-code-size-reduction Change-Id: Ib04820bf5591b365a3bfbbd8b90655a8a1d844cf --- src/arch/riscv/isa/bitfields.isa | 2 + src/arch/riscv/isa/decoder.isa | 76 ++++++++++++++++++++++- src/arch/riscv/isa/formats/compressed.isa | 5 +- 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/isa/bitfields.isa b/src/arch/riscv/isa/bitfields.isa index 280bcbab22..66ce74afe3 100644 --- a/src/arch/riscv/isa/bitfields.isa +++ b/src/arch/riscv/isa/bitfields.isa @@ -98,7 +98,9 @@ def bitfield RL <25>; // Compressed def bitfield COPCODE <15:13>; +def bitfield CFUNCT6LOW3 <12:10>; def bitfield CFUNCT1 <12>; +def bitfield CFUNCT1BIT6 <6>; def bitfield CFUNCT2HIGH <11:10>; def bitfield CFUNCT2LOW <6:5>; def bitfield RC1 <11:7>; diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 2f110fca35..2bd3d33a7e 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -107,6 +107,49 @@ decode QUADRANT default Unknown::unknown() { }}); } } + 0x4: decode CFUNCT6LOW3 { + format CompressedLoad { + 0x0: c_lbu({{ + offset = (CIMM2<0:0> << 1) | CIMM2<1:1>; + }}, {{ + Rp2 = Mem_ub; + }}, {{ + EA = rvZext(Rp1 + offset); + }}); + 0x1: decode CFUNCT1BIT6 { + 0x0: c_lhu({{ + offset = CIMM2<0:0> << 1; + }}, {{ + Rp2 = Mem_uh; + }}, {{ + EA = rvZext(Rp1 + offset); + }}); + 0x1: c_lh({{ + offset = CIMM2<0:0> << 1; + }}, {{ + Rp2_sd = Mem_sh; + }}, {{ + EA = rvZext(Rp1 + offset); + }}); + } + } + format CompressedStore { + 0x2: c_sb({{ + offset = (CIMM2<0:0> << 1) | CIMM2<1:1>; + }}, {{ + Mem_ub = Rp2_ub; + }}, ea_code={{ + EA = rvZext(Rp1 + offset); + }}); + 0x3: c_sh({{ + offset = (CIMM2<0:0> << 1); + }}, {{ + Mem_uh = Rp2_uh; + }}, ea_code={{ + EA = rvZext(Rp1 + offset); + }}); + } + } format CompressedStore { 0x5: c_fsd({{ offset = CIMM3 << 3 | CIMM2 << 6; @@ -264,15 +307,42 @@ decode QUADRANT default Unknown::unknown() { Rp1 = rvSext(Rp1 & Rp2); }}); } - 0x1: decode RVTYPE { - 0x1: decode CFUNCT2LOW { - 0x0: c_subw({{ + 0x1: decode CFUNCT2LOW { + 0x0: decode RVTYPE { + 0x1: c_subw({{ Rp1_sd = (int32_t)Rp1_sd - Rp2_sw; }}); + } + 0x1: decode RVTYPE { 0x1: c_addw({{ Rp1_sd = (int32_t)Rp1_sd + Rp2_sw; }}); } + 0x2: c_mul({{ + Rp1_sd = rvSext(Rp1_sd * Rp2_sd); + }}, IntMultOp); + 0x3: decode RP2 { + 0x0: c_zext_b({{ + Rp1 = Rp1 & 0xFFULL; + }}); + 0x1: c_sext_b({{ + Rp1 = sext<8>(Rp1 & 0xFFULL); + }}); + 0x2: c_zext_h({{ + Rp1 = Rp1 & 0xFFFFULL; + }}); + 0x3: c_sext_h({{ + Rp1 = sext<16>(Rp1 & 0xFFFFULL); + }}); + 0x4: decode RVTYPE { + 0x1: c_zext_w({{ + Rp1 = bits(Rp1, 31, 0); + }}); + } + 0x5: c_not({{ + Rp1 = ~Rp1; + }}); + } } } } diff --git a/src/arch/riscv/isa/formats/compressed.isa b/src/arch/riscv/isa/formats/compressed.isa index 3d89ec38a6..7a9fd634c8 100644 --- a/src/arch/riscv/isa/formats/compressed.isa +++ b/src/arch/riscv/isa/formats/compressed.isa @@ -150,8 +150,9 @@ def template CBasicExecute {{ std::vector indices = {%(regs)s}; std::stringstream ss; ss << mnemonic << ' '; - ss << registerName(indices[0]) << ", "; - ss << registerName(indices[1]); + ss << registerName(indices[0]); + if (_numSrcRegs >= 2) + ss << ", " << registerName(indices[1]); return ss.str(); } }}; From 39c7e7d1eddc24ddddecd8abd7dbeae61f7959ac Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 11:37:04 -0700 Subject: [PATCH 375/693] arch: Adding missing `override` to `PCState.set` As highlighed in this failing compiler test: https://github.com/gem5/gem5/actions/runs/6348223508/job/17389057995 Clang was failing when compiling "build/ALL/gem5.opt" due missing overrides in `PCState`'s "set" function. This was observed in Clang-14 and, stangely, Clang-8. Change-Id: I240c1087e8875fd07630e467e7452c62a5d14d5b --- src/arch/arm/pcstate.hh | 2 +- src/arch/generic/pcstate.hh | 4 ++-- src/arch/x86/pcstate.hh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/arch/arm/pcstate.hh b/src/arch/arm/pcstate.hh index 7b75ed8184..a2f0463fab 100644 --- a/src/arch/arm/pcstate.hh +++ b/src/arch/arm/pcstate.hh @@ -92,7 +92,7 @@ class PCState : public GenericISA::UPCState<4> public: void - set(Addr val) + set(Addr val) override { Base::set(val); npc(val + (thumb() ? 2 : 4)); diff --git a/src/arch/generic/pcstate.hh b/src/arch/generic/pcstate.hh index 5c278a4233..25b3af69ea 100644 --- a/src/arch/generic/pcstate.hh +++ b/src/arch/generic/pcstate.hh @@ -489,7 +489,7 @@ class DelaySlotPCState : public SimplePCState void nnpc(Addr val) { _nnpc = val; } void - set(Addr val) + set(Addr val) override { Base::set(val); nnpc(val + 2 * InstWidth); @@ -563,7 +563,7 @@ class DelaySlotUPCState : public DelaySlotPCState } void - set(Addr val) + set(Addr val) override { Base::set(val); this->upc(0); diff --git a/src/arch/x86/pcstate.hh b/src/arch/x86/pcstate.hh index a0ed6ffe9f..95984d7a96 100644 --- a/src/arch/x86/pcstate.hh +++ b/src/arch/x86/pcstate.hh @@ -66,7 +66,7 @@ class PCState : public GenericISA::UPCState<8> } void - set(Addr val) + set(Addr val) override { Base::set(val); _size = 0; From 06bbc43b460a62597eadb55658f2bd77f42fcb00 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 07:25:04 -0700 Subject: [PATCH 376/693] ext: Remove `std::binary_function` from DramPower `std::binary_function` was deprecated in C++11 and officially removed in CPP-17. This caused a compilation error on some systems. Fortunately it can be safely removed. It was unecessary. The commandItemSorter was compliant witih the `sort` regardless. Change-Id: I0d910e50c51cce2545dd89f618c99aef0fe8ab79 --- ext/drampower/src/CmdScheduler.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/drampower/src/CmdScheduler.h b/ext/drampower/src/CmdScheduler.h index 58efd279b1..1497304f54 100644 --- a/ext/drampower/src/CmdScheduler.h +++ b/ext/drampower/src/CmdScheduler.h @@ -84,8 +84,7 @@ class cmdScheduler { std::string name; physicalAddr PhysicalAddr; // sorting the commands according to their scheduling time. - struct commandItemSorter : public std::binary_function{ + struct commandItemSorter { bool operator()(const commandItem& lhs, const commandItem& rhs) const { From f75c0fca8a4e349a25f7e9503cc753dcb48c0212 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 10:20:55 -0700 Subject: [PATCH 377/693] stdlib: Del comment stating SE mode limited to single thread This comment was left in the codebase in error. The `set_se_binary_workload` function works fine with multi-threaded applications. This hasn't been a restriction for some time. Change-Id: I1b1d27c86f8d9284659f62ae27d752bf5325e31b --- src/python/gem5/components/boards/se_binary_workload.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/python/gem5/components/boards/se_binary_workload.py b/src/python/gem5/components/boards/se_binary_workload.py index c62a1b67ea..cba268b2df 100644 --- a/src/python/gem5/components/boards/se_binary_workload.py +++ b/src/python/gem5/components/boards/se_binary_workload.py @@ -75,7 +75,6 @@ class SEBinaryWorkload: """Set up the system to run a specific binary. **Limitations** - * Only supports single threaded applications. * Dynamically linked executables are partially supported when the host ISA and the simulated ISA are the same. From a19667427a96c560b243ffbadbba3b7f4f6db2b4 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Thu, 5 Oct 2023 18:59:54 -0500 Subject: [PATCH 378/693] mem-ruby: Add BUILD_GPU guard to ruby cooldown and warmup phases Ruby was recently updated to support flushes and warmup for GPUs. Since this support uses the GPUCoalescer, non-GPU builds face a compile time issue. This is because GPU code is not built for non-GPU builds. This commit addes "#if BUILD_GPU" guards around the GPU-related code in common files like AbstractController.hh, CacheRecorder.*, RubySystem.cc, GPUCoalescer.hh, and VIPERCoalescer.hh. This support allows GPU builds to use flushing while non-GPU builds compile without problems Change-Id: If8ee4ff881fe154553289e8c00881ee1b6e3f113 --- .../slicc_interface/AbstractController.hh | 2 ++ src/mem/ruby/system/CacheRecorder.cc | 27 +++++++++++++++++++ src/mem/ruby/system/CacheRecorder.hh | 12 +++++++++ src/mem/ruby/system/GPUCoalescer.hh | 5 ++++ src/mem/ruby/system/RubySystem.cc | 16 ++++++++++- src/mem/ruby/system/VIPERCoalescer.hh | 5 ++++ 6 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 72b679d6cf..7d93644bd8 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -70,7 +70,9 @@ namespace ruby { class Network; +#ifdef BUILD_GPU class GPUCoalescer; +#endif class DMASequencer; // used to communicate that an in_port peeked the wrong message type diff --git a/src/mem/ruby/system/CacheRecorder.cc b/src/mem/ruby/system/CacheRecorder.cc index ec552c07c5..057b6aa041 100644 --- a/src/mem/ruby/system/CacheRecorder.cc +++ b/src/mem/ruby/system/CacheRecorder.cc @@ -57,6 +57,7 @@ CacheRecorder::CacheRecorder() { } +#if BUILD_GPU CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, uint64_t uncompressed_trace_size, std::vector& seq_map, @@ -67,6 +68,18 @@ CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, m_seq_map(seq_map), m_coalescer_map(coal_map), m_bytes_read(0), m_records_read(0), m_records_flushed(0), m_block_size_bytes(block_size_bytes) +#else +CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, + uint64_t uncompressed_trace_size, + std::vector& seq_map, + uint64_t block_size_bytes) + : m_uncompressed_trace(uncompressed_trace), + m_uncompressed_trace_size(uncompressed_trace_size), + m_seq_map(seq_map), m_bytes_read(0), + m_records_read(0), m_records_flushed(0), + m_block_size_bytes(block_size_bytes) + +#endif { if (m_uncompressed_trace != NULL) { if (m_block_size_bytes < RubySystem::getBlockSizeBytes()) { @@ -86,7 +99,9 @@ CacheRecorder::~CacheRecorder() m_uncompressed_trace = NULL; } m_seq_map.clear(); +#if BUILD_GPU m_coalescer_map.clear(); +#endif } void @@ -102,14 +117,20 @@ CacheRecorder::enqueueNextFlushRequest() Packet *pkt = new Packet(req, requestType); Sequencer* m_sequencer_ptr = m_seq_map[rec->m_cntrl_id]; +#if BUILD_GPU GPUCoalescer* m_coal_ptr = m_coalescer_map[rec->m_cntrl_id]; +#endif assert(m_sequencer_ptr != NULL); +#if BUILD_GPU if (m_coal_ptr == NULL) m_sequencer_ptr->makeRequest(pkt); else { pkt->req->setReqInstSeqNum(m_records_flushed - 1); m_coal_ptr->makeRequest(pkt); } +#else + m_sequencer_ptr->makeRequest(pkt); +#endif DPRINTF(RubyCacheTrace, "Flushing %s\n", *rec); @@ -159,15 +180,21 @@ CacheRecorder::enqueueNextFetchRequest() pkt->dataStatic(traceRecord->m_data + rec_bytes_read); Sequencer* m_sequencer_ptr = m_seq_map[traceRecord->m_cntrl_id]; +#if BUILD_GPU GPUCoalescer* m_coal_ptr; m_coal_ptr = m_coalescer_map[traceRecord->m_cntrl_id]; +#endif assert(m_sequencer_ptr != NULL); +#if BUILD_GPU if (m_coal_ptr == NULL) m_sequencer_ptr->makeRequest(pkt); else { pkt->req->setReqInstSeqNum(m_records_read); m_coal_ptr->makeRequest(pkt); } +#else + m_sequencer_ptr->makeRequest(pkt); +#endif } m_bytes_read += (sizeof(TraceRecord) + m_block_size_bytes); diff --git a/src/mem/ruby/system/CacheRecorder.hh b/src/mem/ruby/system/CacheRecorder.hh index 9363e2fde7..e94dfad97a 100644 --- a/src/mem/ruby/system/CacheRecorder.hh +++ b/src/mem/ruby/system/CacheRecorder.hh @@ -38,6 +38,7 @@ #include #include "base/types.hh" +#include "config/build_gpu.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/common/TypeDefines.hh" @@ -50,7 +51,9 @@ namespace ruby { class Sequencer; +#if BUILD_GPU class GPUCoalescer; +#endif /*! * Class for recording cache contents. Note that the last element of the @@ -77,11 +80,18 @@ class CacheRecorder CacheRecorder(); ~CacheRecorder(); +#if BUILD_GPU CacheRecorder(uint8_t* uncompressed_trace, uint64_t uncompressed_trace_size, std::vector& SequencerMap, std::vector& CoalescerMap, uint64_t block_size_bytes); +#else + CacheRecorder(uint8_t* uncompressed_trace, + uint64_t uncompressed_trace_size, + std::vector& SequencerMap, + uint64_t block_size_bytes); +#endif void addRecord(int cntrl, Addr data_addr, Addr pc_addr, RubyRequestType type, Tick time, DataBlock& data); @@ -117,7 +127,9 @@ class CacheRecorder uint8_t* m_uncompressed_trace; uint64_t m_uncompressed_trace_size; std::vector m_seq_map; +#if BUILD_GPU std::vector m_coalescer_map; +#endif uint64_t m_bytes_read; uint64_t m_records_read; uint64_t m_records_flushed; diff --git a/src/mem/ruby/system/GPUCoalescer.hh b/src/mem/ruby/system/GPUCoalescer.hh index d6db5c00ba..3f936b4b41 100644 --- a/src/mem/ruby/system/GPUCoalescer.hh +++ b/src/mem/ruby/system/GPUCoalescer.hh @@ -32,6 +32,10 @@ #ifndef __MEM_RUBY_SYSTEM_GPU_COALESCER_HH__ #define __MEM_RUBY_SYSTEM_GPU_COALESCER_HH__ +#include "config/build_gpu.hh" + +#if BUILD_GPU + #include #include @@ -546,4 +550,5 @@ operator<<(std::ostream& out, const GPUCoalescer& obj) } // namespace ruby } // namespace gem5 +#endif // BUILD_GPU #endif // __MEM_RUBY_SYSTEM_GPU_COALESCER_HH__ diff --git a/src/mem/ruby/system/RubySystem.cc b/src/mem/ruby/system/RubySystem.cc index 232e337752..32dec7b9e0 100644 --- a/src/mem/ruby/system/RubySystem.cc +++ b/src/mem/ruby/system/RubySystem.cc @@ -178,21 +178,27 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, uint64_t block_size_bytes) { std::vector sequencer_map; +#if BUILD_GPU std::vector coalescer_map; - Sequencer* sequencer_ptr = NULL; GPUCoalescer* coalescer_ptr = NULL; +#endif + Sequencer* sequencer_ptr = NULL; for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getCPUSequencer()); +#if BUILD_GPU coalescer_map.push_back(m_abs_cntrl_vec[cntrl]->getGPUCoalescer()); +#endif if (sequencer_ptr == NULL) { sequencer_ptr = sequencer_map[cntrl]; } +#if BUILD_GPU if (coalescer_ptr == NULL) { coalescer_ptr = coalescer_map[cntrl]; } +#endif } @@ -203,9 +209,11 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, sequencer_map[cntrl] = sequencer_ptr; } +#if BUILD_GPU if (coalescer_map[cntrl] == NULL) { coalescer_map[cntrl] = coalescer_ptr; } +#endif } @@ -215,9 +223,15 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, } // Create the CacheRecorder and record the cache trace +#if BUILD_GPU m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size, sequencer_map, coalescer_map, block_size_bytes); +#else + m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size, + sequencer_map, + block_size_bytes); +#endif } void diff --git a/src/mem/ruby/system/VIPERCoalescer.hh b/src/mem/ruby/system/VIPERCoalescer.hh index c7e21e946b..d185620244 100644 --- a/src/mem/ruby/system/VIPERCoalescer.hh +++ b/src/mem/ruby/system/VIPERCoalescer.hh @@ -32,6 +32,10 @@ #ifndef __MEM_RUBY_SYSTEM_VIPERCOALESCER_HH__ #define __MEM_RUBY_SYSTEM_VIPERCOALESCER_HH__ +#include "config/build_gpu.hh" + +#if BUILD_GPU + #include #include "mem/ruby/common/Address.hh" @@ -92,4 +96,5 @@ class VIPERCoalescer : public GPUCoalescer } // namespace ruby } // namespace gem5 +#endif // BUILD_GPU #endif //__MEM_RUBY_SYSTEM_VIPERCOALESCER_HH__ From 46a9d85215ec91c277c954944d1db64d28c28537 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 4 Oct 2023 00:56:48 -0700 Subject: [PATCH 379/693] arch-riscv: Add bootloader+kernel workload Aims to boot OpenSBI + Linux kernel. Change-Id: I9ee93cc367e8c06bdd0c7ddf43335d32965be14d Signed-off-by: Hoa Nguyen --- src/arch/riscv/RiscvFsWorkload.py | 34 ++++++++++ src/arch/riscv/SConscript | 4 +- src/arch/riscv/linux/fs_workload.cc | 102 ++++++++++++++++++++++++++++ src/arch/riscv/linux/fs_workload.hh | 61 +++++++++++++++++ 4 files changed, 200 insertions(+), 1 deletion(-) diff --git a/src/arch/riscv/RiscvFsWorkload.py b/src/arch/riscv/RiscvFsWorkload.py index 9e158811da..a71dc1acaf 100644 --- a/src/arch/riscv/RiscvFsWorkload.py +++ b/src/arch/riscv/RiscvFsWorkload.py @@ -52,3 +52,37 @@ class RiscvLinux(KernelWorkload): "", "File that contains the Device Tree Blob. Don't use DTB if empty." ) dtb_addr = Param.Addr(0x87E00000, "DTB address") + + +class RiscvBootloaderKernelWorkload(Workload): + type = "RiscvBootloaderKernelWorkload" + cxx_class = "gem5::RiscvISA::BootloaderKernelWorkload" + cxx_header = "arch/riscv/linux/fs_workload.hh" + + bootloader_filename = Param.String( + "", "File that contains the bootloader. Don't use bootloader if empty." + ) + bootloader_addr = Param.Addr( + 0x0, "Where to place the bootloader in memory." + ) + kernel_filename = Param.String( + "", "vmlinux file. Don't use kernel if empty." + ) + kernel_addr = Param.Addr( + 0x80200000, + "Where to place the kernel in memory. Typically, after the first " + "stage of booting is done, the bootloader will jump to where the " + "`start` symbol of the kernel is.", + ) + entry_point = Param.Addr( + 0x80000000, "Where to find the first instruction to execute." + ) + dtb_filename = Param.String( + "", "File that contains the Device Tree Blob. Don't use DTB if empty." + ) + dtb_addr = Param.Addr(0x87E00000, "Where to place the DTB in memory.") + + # booting parameters + boot_args = Param.String( + "", "Booting arguments, to be passed to the kernel" + ) diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript index 924bba5915..bf40b6eccd 100644 --- a/src/arch/riscv/SConscript +++ b/src/arch/riscv/SConscript @@ -66,7 +66,9 @@ Source('bare_metal/fs_workload.cc', tags='riscv isa') SimObject('PMAChecker.py', sim_objects=['PMAChecker'], tags='riscv isa') SimObject('PMP.py', sim_objects=['PMP'], tags='riscv isa') SimObject('RiscvDecoder.py', sim_objects=['RiscvDecoder'], tags='riscv isa') -SimObject('RiscvFsWorkload.py', sim_objects=['RiscvBareMetal', 'RiscvLinux'], +SimObject('RiscvFsWorkload.py', + sim_objects=['RiscvBareMetal', 'RiscvLinux', + 'RiscvBootloaderKernelWorkload'], tags='riscv isa') SimObject('RiscvInterrupts.py', sim_objects=['RiscvInterrupts'], tags='riscv isa') diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index 4a4a3812ec..0cd0e761d2 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -75,5 +75,107 @@ FsLinux::initState() } } +void +BootloaderKernelWorkload::loadBootloaderSymbolTable() +{ + if (params().bootloader_filename != "") { + Addr bootloader_paddr_offset = params().bootloader_addr; + bootloader = loader::createObjectFile(params().bootloader_filename); + bootloaderSymbolTable = bootloader->symtab(); + auto renamedBootloaderSymbolTable = \ + bootloaderSymbolTable.offset(bootloader_paddr_offset)->rename( + [](std::string &name) { + name = "bootloader." + name; + } + ); + loader::debugSymbolTable.insert(*renamedBootloaderSymbolTable); + } +} + +void +BootloaderKernelWorkload::loadKernelSymbolTable() +{ + if (params().kernel_filename != "") { + Addr kernel_paddr_offset = params().kernel_addr; + kernel = loader::createObjectFile(params().kernel_filename); + kernelSymbolTable = kernel->symtab(); + auto renamedKernelSymbolTable = \ + kernelSymbolTable.offset(kernel_paddr_offset)->rename( + [](std::string &name) { + name = "kernel." + name; + } + ); + loader::debugSymbolTable.insert(*renamedKernelSymbolTable); + } +} + +void +BootloaderKernelWorkload::loadBootloader() +{ + if (params().bootloader_filename != "") { + Addr bootloader_addr_offset = params().bootloader_addr; + bootloader->buildImage().offset(bootloader_addr_offset).write( + system->physProxy + ); + delete bootloader; + } +} + +void +BootloaderKernelWorkload::loadKernel() +{ + if (params().kernel_filename != "") { + Addr kernel_paddr_offset = params().kernel_addr; + kernel->buildImage().offset(kernel_paddr_offset).write( + system->physProxy + ); + delete kernel; + } +} + + +void +BootloaderKernelWorkload::loadDtb() +{ + if (params().dtb_filename != "") { + auto *dtb_file = new loader::DtbFile(params().dtb_filename); + + dtb_file->buildImage().offset(params().dtb_addr) + .write(system->physProxy); + delete dtb_file; + + for (auto *tc: system->threads) { + tc->setReg(int_reg::A1, params().dtb_addr); + } + } +} + +void +BootloaderKernelWorkload::initState() +{ + loadBootloader(); + loadKernel(); + loadDtb(); + + for (auto *tc: system->threads) { + RiscvISA::Reset().invoke(tc); + tc->activate(); + } +} + +void +BootloaderKernelWorkload::serialize(CheckpointOut &checkpoint) const +{ + bootloaderSymbolTable.serialize("bootloader_symbol_table", checkpoint); + kernelSymbolTable.serialize("kernel_symbol_table", checkpoint); +} + +void +BootloaderKernelWorkload::unserialize(CheckpointIn &checkpoint) +{ + bootloaderSymbolTable.unserialize("bootloader_symbol_table", checkpoint); + kernelSymbolTable.unserialize("kernel_symbol_table", checkpoint); +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/linux/fs_workload.hh b/src/arch/riscv/linux/fs_workload.hh index 1dc704d906..a0366a27c4 100644 --- a/src/arch/riscv/linux/fs_workload.hh +++ b/src/arch/riscv/linux/fs_workload.hh @@ -29,7 +29,10 @@ #ifndef __ARCH_RISCV_LINUX_SYSTEM_HH__ #define __ARCH_RISCV_LINUX_SYSTEM_HH__ +#include + #include "arch/riscv/remote_gdb.hh" +#include "params/RiscvBootloaderKernelWorkload.hh" #include "params/RiscvLinux.hh" #include "sim/kernel_workload.hh" @@ -58,6 +61,64 @@ class FsLinux : public KernelWorkload ByteOrder byteOrder() const override { return ByteOrder::little; } }; +class BootloaderKernelWorkload: public Workload +{ + private: + Addr entryPoint = 0; + loader::ObjectFile *kernel = nullptr; + loader::ObjectFile *bootloader = nullptr; + loader::SymbolTable kernelSymbolTable; + loader::SymbolTable bootloaderSymbolTable; + const std::string bootArgs; + + private: + void loadBootloaderSymbolTable(); + void loadKernelSymbolTable(); + void loadBootloader(); + void loadKernel(); + void loadDtb(); + + public: + PARAMS(RiscvBootloaderKernelWorkload); + BootloaderKernelWorkload(const Params &p) + : Workload(p), entryPoint(p.entry_point), bootArgs(p.boot_args) + { + loadBootloaderSymbolTable(); + loadKernelSymbolTable(); + } + + void initState() override; + + void + setSystem(System *sys) override + { + Workload::setSystem(sys); + gdb = BaseRemoteGDB::build( + params().remote_gdb_port, system); + } + + Addr getEntry() const override { return entryPoint; } + + ByteOrder byteOrder() const override { return ByteOrder::little; } + + loader::Arch getArch() const override { return kernel->getArch(); } + + const loader::SymbolTable & + symtab(ThreadContext *tc) override + { + return kernelSymbolTable; + } + + bool + insertSymbol(const loader::Symbol &symbol) override + { + return kernelSymbolTable.insert(symbol); + } + + void serialize(CheckpointOut &checkpoint) const override; + void unserialize(CheckpointIn &checkpoint) override; +}; + } // namespace RiscvISA } // namespace gem5 From e8fd8303fba6bfee3b8abb5cdf08632227e09f1b Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Thu, 5 Oct 2023 23:15:27 -0700 Subject: [PATCH 380/693] stdlib: Add `chosen` node to the device tree of RISC-V board This enables two things, - /chosen/stdout-path is now default to uart@10000000, meaning the linux kernel's boot console will be redirected to uart. - /chosen/bootargs now contains the boot arguments obtained from gem5's library. This allows passing the boot arguments to the linux kernel via the device tree. Change-Id: I53821d85f619e6276da85f41c972c041eaaf3280 Signed-off-by: Hoa Nguyen --- src/python/gem5/components/boards/riscv_board.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 25f1fac562..93dae50244 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -259,6 +259,12 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): ) root.append(node) + node = FdtNode(f"chosen") + bootargs = " ".join(self.get_default_kernel_args()) + node.append(FdtPropertyStrings("bootargs", [bootargs])) + node.append(FdtPropertyStrings("stdout-path", ["/uart@10000000"])) + root.append(node) + # See Documentation/devicetree/bindings/riscv/cpus.txt for details. cpus_node = FdtNode("cpus") cpus_state = FdtState(addr_cells=1, size_cells=0) From 3fc6b67974eba4c5785ab2875aae95b61a22ede1 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Fri, 6 Oct 2023 00:45:21 -0700 Subject: [PATCH 381/693] arch-riscv: Add several inform() to RiscvISA::BootloaderKernelWorkload Signed-off-by: Hoa Nguyen --- src/arch/riscv/linux/fs_workload.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index 0cd0e761d2..8bb35ccd17 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -118,6 +118,12 @@ BootloaderKernelWorkload::loadBootloader() system->physProxy ); delete bootloader; + + inform("Loaded bootloader \'%s\' at 0x%llx\n", + params().bootloader_filename, + bootloader_addr_offset); + } else { + inform("Bootloader is not specified.\n"); } } @@ -130,6 +136,12 @@ BootloaderKernelWorkload::loadKernel() system->physProxy ); delete kernel; + + inform("Loaded kernel \'%s\' at 0x%llx\n", + params().kernel_filename, + kernel_paddr_offset); + } else { + inform("Kernel is not specified.\n"); } } @@ -144,9 +156,15 @@ BootloaderKernelWorkload::loadDtb() .write(system->physProxy); delete dtb_file; + inform("Loaded DTB \'%s\' at 0x%llx\n", + params().dtb_filename, + params().dtb_addr); + for (auto *tc: system->threads) { tc->setReg(int_reg::A1, params().dtb_addr); } + } else { + inform("DTB file is not specified.\n"); } } From 6f8b74ece8f75d63d38e68dbcbf9519867fbf6b1 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Fri, 6 Oct 2023 00:48:12 -0700 Subject: [PATCH 382/693] dev,arch-riscv: Mark gem5's 8250 UART as 16550a compatible 8250 UART is supposed to be compatible to 16550a UART. This enables OpenSBI to print things to UART as OpenSBI only prints if the UART is 16550a compatible [1]. There is a similar change from gem5 gerrit [2] pointing out that this also enables bbl to print things to UART. This is confirmed :) [1] https://github.com/riscv-software-src/opensbi/blob/v1.3.1/lib/utils/serial/fdt_serial_uart8250.c#L29 [2] https://gem5-review.googlesource.com/c/public/gem5/+/68481 Signed-off-by: Hoa Nguyen --- src/dev/serial/Uart.py | 2 +- src/python/gem5/components/boards/riscv_board.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dev/serial/Uart.py b/src/dev/serial/Uart.py index 2ca68b8f12..fb0d91efa4 100644 --- a/src/dev/serial/Uart.py +++ b/src/dev/serial/Uart.py @@ -82,5 +82,5 @@ class RiscvUart8250(Uart8250): node.append(FdtPropertyWords("interrupts", [platform.uart_int_id])) node.append(FdtPropertyWords("clock-frequency", [0x384000])) node.append(FdtPropertyWords("interrupt-parent", state.phandle(plic))) - node.appendCompatible(["ns8250"]) + node.appendCompatible(["ns8250", "ns16550a"]) yield node diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 93dae50244..c8e0df78c2 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -438,7 +438,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): uart_node.append( FdtPropertyWords("interrupt-parent", soc_state.phandle(plic)) ) - uart_node.appendCompatible(["ns8250"]) + uart_node.appendCompatible(["ns8250", "ns16550a"]) soc_node.append(uart_node) # VirtIO MMIO disk node From 00748c790104717fbe38bcbc1687a8fb27b50584 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 6 Oct 2023 14:48:51 +0100 Subject: [PATCH 383/693] mem-ruby: Fix CHI fromSequencer helper function This has been broken by #177 Change-Id: I52feff4b5ab2faf0aa91edd6572e3e767c88e257 Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-funcs.sm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index 371ad05109..ed8358fea4 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -304,7 +304,7 @@ bool fromSequencer(CHIRequestType reqType) { reqType == CHIRequestType:Store || reqType == CHIRequestType:StoreLine || reqType == CHIRequestType:AtomicLoad || - tbe.reqType == CHIRequestType:AtomicStore; + reqType == CHIRequestType:AtomicStore; } bool inCache(Addr addr) { From 6a4b2bb0965a28d1428a60b867318e23511dd168 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Mon, 11 Sep 2023 09:22:26 -0500 Subject: [PATCH 384/693] dev-hsa,gpu-compute: Add timestamps to AMD HSA signals The AMD specific HSA signal contains start/end timestamps for dispatch packet completion signals. These are current always zero. These timestamp values are used for profiling in the ROCr runtime. Unfortunately, the GpuAgent::TranslateTime method in ROCr does not check for zero values before dividing, causing applications that use profiling to crash with SIGFPE. Profiling is used via hipEvents in the HACC application, so these should be supported in gem5. In order to handle writing the timestamp values, we need to DMA the values to memory before writing the completion signal. This changes the flow of the async completion signal write to be (1) read mailbox pointer (2) if valid, write the mailbox data, other skip to 4 (3) write mailbox data if pointer is valid (4) write timestamp values (5) write completion signal. The application will process the timestamp data as soon as the completion signal is received, so we need to ordering to ensure the DMA for timestamps was completed. HACC now runs to completion on GPUFS and has the same output was hardware. Change-Id: I09877cdff901d1402140f2c3bafea7605fa6554e --- src/dev/hsa/hsa_signal.hh | 6 ++ src/gpu-compute/gpu_command_processor.cc | 88 +++++++++++++++++------- src/gpu-compute/gpu_command_processor.hh | 4 ++ 3 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/dev/hsa/hsa_signal.hh b/src/dev/hsa/hsa_signal.hh index 6acbcb7e1b..7d1f316f04 100644 --- a/src/dev/hsa/hsa_signal.hh +++ b/src/dev/hsa/hsa_signal.hh @@ -69,6 +69,12 @@ typedef struct amd_signal_s uint32_t reserved3[2]; } amd_signal_t; +typedef struct +{ + uint64_t start_ts; + uint64_t end_ts; +} amd_event_t; + } // namespace gem5 #endif // DEV_HSA_HSA_SIGNAL_H diff --git a/src/gpu-compute/gpu_command_processor.cc b/src/gpu-compute/gpu_command_processor.cc index db69ad5cbd..ecc5f1d98b 100644 --- a/src/gpu-compute/gpu_command_processor.cc +++ b/src/gpu-compute/gpu_command_processor.cc @@ -248,6 +248,10 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, initABI(task); ++dynamic_task_id; + + // The driver expects the start time to be in ns + Tick start_ts = curTick() / sim_clock::as_int::ns; + dispatchStartTime.insert({disp_pkt->completion_signal, start_ts}); } void @@ -280,16 +284,6 @@ GPUCommandProcessor::sendCompletionSignal(Addr signal_handle) void GPUCommandProcessor::updateHsaSignalAsync(Addr signal_handle, int64_t diff) { - Addr value_addr = getHsaSignalValueAddr(signal_handle); - - uint64_t *signalValue = new uint64_t; - auto cb = new DmaVirtCallback( - [ = ] (const uint64_t &) - { updateHsaSignalData(value_addr, diff, signalValue); }); - dmaReadVirt(value_addr, sizeof(uint64_t), cb, (void *)signalValue); - DPRINTF(GPUCommandProc, "updateHsaSignalAsync reading value addr %lx\n", - value_addr); - Addr mailbox_addr = getHsaSignalMailboxAddr(signal_handle); uint64_t *mailboxValue = new uint64_t; auto cb2 = new DmaVirtCallback( @@ -300,20 +294,6 @@ GPUCommandProcessor::updateHsaSignalAsync(Addr signal_handle, int64_t diff) mailbox_addr); } -void -GPUCommandProcessor::updateHsaSignalData(Addr value_addr, int64_t diff, - uint64_t *prev_value) -{ - // Reuse the value allocated for the read - DPRINTF(GPUCommandProc, "updateHsaSignalData read %ld, writing %ld\n", - *prev_value, *prev_value + diff); - *prev_value += diff; - auto cb = new DmaVirtCallback( - [ = ] (const uint64_t &) - { updateHsaSignalDone(prev_value); }); - dmaWriteVirt(value_addr, sizeof(uint64_t), cb, (void *)prev_value); -} - void GPUCommandProcessor::updateHsaMailboxData(Addr signal_handle, uint64_t *mailbox_value) @@ -331,6 +311,20 @@ GPUCommandProcessor::updateHsaMailboxData(Addr signal_handle, dmaReadVirt(event_addr, sizeof(uint64_t), cb, (void *)mailbox_value); } else { delete mailbox_value; + + Addr ts_addr = signal_handle + offsetof(amd_signal_t, start_ts); + + amd_event_t *event_ts = new amd_event_t; + event_ts->start_ts = dispatchStartTime[signal_handle]; + event_ts->end_ts = curTick() / sim_clock::as_int::ns; + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaEventTs(signal_handle, event_ts); }); + dmaWriteVirt(ts_addr, sizeof(amd_event_t), cb, (void *)event_ts); + DPRINTF(GPUCommandProc, "updateHsaMailboxData reading timestamp addr " + "%lx\n", ts_addr); + + dispatchStartTime.erase(signal_handle); } } @@ -346,6 +340,52 @@ GPUCommandProcessor::updateHsaEventData(Addr signal_handle, [ = ] (const uint64_t &) { updateHsaSignalDone(event_value); }, *event_value); dmaWriteVirt(mailbox_addr, sizeof(uint64_t), cb, &cb->dmaBuffer, 0); + + Addr ts_addr = signal_handle + offsetof(amd_signal_t, start_ts); + + amd_event_t *event_ts = new amd_event_t; + event_ts->start_ts = dispatchStartTime[signal_handle]; + event_ts->end_ts = curTick() / sim_clock::as_int::ns; + auto cb2 = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaEventTs(signal_handle, event_ts); }); + dmaWriteVirt(ts_addr, sizeof(amd_event_t), cb2, (void *)event_ts); + DPRINTF(GPUCommandProc, "updateHsaEventData reading timestamp addr %lx\n", + ts_addr); + + dispatchStartTime.erase(signal_handle); +} + +void +GPUCommandProcessor::updateHsaEventTs(Addr signal_handle, + amd_event_t *ts) +{ + delete ts; + + Addr value_addr = getHsaSignalValueAddr(signal_handle); + int64_t diff = -1; + + uint64_t *signalValue = new uint64_t; + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaSignalData(value_addr, diff, signalValue); }); + dmaReadVirt(value_addr, sizeof(uint64_t), cb, (void *)signalValue); + DPRINTF(GPUCommandProc, "updateHsaSignalAsync reading value addr %lx\n", + value_addr); +} + +void +GPUCommandProcessor::updateHsaSignalData(Addr value_addr, int64_t diff, + uint64_t *prev_value) +{ + // Reuse the value allocated for the read + DPRINTF(GPUCommandProc, "updateHsaSignalData read %ld, writing %ld\n", + *prev_value, *prev_value + diff); + *prev_value += diff; + auto cb = new DmaVirtCallback( + [ = ] (const uint64_t &) + { updateHsaSignalDone(prev_value); }); + dmaWriteVirt(value_addr, sizeof(uint64_t), cb, (void *)prev_value); } void diff --git a/src/gpu-compute/gpu_command_processor.hh b/src/gpu-compute/gpu_command_processor.hh index 10407b9f93..f6783834eb 100644 --- a/src/gpu-compute/gpu_command_processor.hh +++ b/src/gpu-compute/gpu_command_processor.hh @@ -117,6 +117,7 @@ class GPUCommandProcessor : public DmaVirtDevice void updateHsaSignalDone(uint64_t *signal_value); void updateHsaMailboxData(Addr signal_handle, uint64_t *mailbox_value); void updateHsaEventData(Addr signal_handle, uint64_t *event_value); + void updateHsaEventTs(Addr signal_handle, amd_event_t *event_value); uint64_t functionalReadHsaSignal(Addr signal_handle); @@ -148,6 +149,9 @@ class GPUCommandProcessor : public DmaVirtDevice HSAPacketProcessor *hsaPP; TranslationGenPtr translate(Addr vaddr, Addr size) override; + // Keep track of start times for task dispatches. + std::unordered_map dispatchStartTime; + /** * Perform a DMA read of the read_dispatch_id_field_base_byte_offset * field, which follows directly after the read_dispatch_id (the read From 75a7f30dfb9ada69e8fdb35c54f0c3dd7d94164d Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 6 Oct 2023 13:02:31 -0500 Subject: [PATCH 385/693] dev-amdgpu: Implement GPU clock MMIOs The ROCr runtime uses a combination of HSA signal timestamps and hardware MMIOs to calculate profiling times. At the beginning of an application a timestamp is read from the GPU using MMIOs. The clock MMIOs reside in the GFX MMIO region, so a new AMDGPUGfx class is added to handle these MMIOs. The timestamp value is expected to be in nanoseconds, so we simply use the gem5 tick converted to ns. Change-Id: I7d1cba40d5042a7f7a81fd4d132402dc11b71bd4 --- src/dev/amdgpu/SConscript | 1 + src/dev/amdgpu/amdgpu_device.cc | 6 +++ src/dev/amdgpu/amdgpu_device.hh | 2 + src/dev/amdgpu/amdgpu_gfx.cc | 73 ++++++++++++++++++++++++++++++++ src/dev/amdgpu/amdgpu_gfx.hh | 75 +++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+) create mode 100644 src/dev/amdgpu/amdgpu_gfx.cc create mode 100644 src/dev/amdgpu/amdgpu_gfx.hh diff --git a/src/dev/amdgpu/SConscript b/src/dev/amdgpu/SConscript index 428d1c56bc..b8ba454d48 100644 --- a/src/dev/amdgpu/SConscript +++ b/src/dev/amdgpu/SConscript @@ -39,6 +39,7 @@ SimObject('AMDGPU.py', sim_objects=['AMDGPUDevice', 'AMDGPUInterruptHandler', tags='x86 isa') Source('amdgpu_device.cc', tags='x86 isa') +Source('amdgpu_gfx.cc', tags='x86 isa') Source('amdgpu_nbio.cc', tags='x86 isa') Source('amdgpu_vm.cc', tags='x86 isa') Source('interrupt_handler.cc', tags='x86 isa') diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc index 5cc8df424f..1b81c4d0b2 100644 --- a/src/dev/amdgpu/amdgpu_device.cc +++ b/src/dev/amdgpu/amdgpu_device.cc @@ -379,6 +379,9 @@ AMDGPUDevice::readMMIO(PacketPtr pkt, Addr offset) case GRBM_BASE: gpuvm.readMMIO(pkt, aperture_offset >> GRBM_OFFSET_SHIFT); break; + case GFX_BASE: + gfx.readMMIO(pkt, aperture_offset); + break; case MMHUB_BASE: gpuvm.readMMIO(pkt, aperture_offset >> MMHUB_OFFSET_SHIFT); break; @@ -507,6 +510,9 @@ AMDGPUDevice::writeMMIO(PacketPtr pkt, Addr offset) case NBIO_BASE: nbio.writeMMIO(pkt, aperture_offset); break; + case GFX_BASE: + gfx.writeMMIO(pkt, aperture_offset); + break; default: DPRINTF(AMDGPUDevice, "Unknown MMIO aperture for %#x\n", offset); break; diff --git a/src/dev/amdgpu/amdgpu_device.hh b/src/dev/amdgpu/amdgpu_device.hh index 56ed2f4fa8..7f69ec19f6 100644 --- a/src/dev/amdgpu/amdgpu_device.hh +++ b/src/dev/amdgpu/amdgpu_device.hh @@ -36,6 +36,7 @@ #include "base/bitunion.hh" #include "dev/amdgpu/amdgpu_defines.hh" +#include "dev/amdgpu/amdgpu_gfx.hh" #include "dev/amdgpu/amdgpu_nbio.hh" #include "dev/amdgpu/amdgpu_vm.hh" #include "dev/amdgpu/memory_manager.hh" @@ -109,6 +110,7 @@ class AMDGPUDevice : public PciDevice * Blocks of the GPU */ AMDGPUNbio nbio; + AMDGPUGfx gfx; AMDGPUMemoryManager *gpuMemMgr; AMDGPUInterruptHandler *deviceIH; AMDGPUVM gpuvm; diff --git a/src/dev/amdgpu/amdgpu_gfx.cc b/src/dev/amdgpu/amdgpu_gfx.cc new file mode 100644 index 0000000000..3d5b274b86 --- /dev/null +++ b/src/dev/amdgpu/amdgpu_gfx.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. Neither the name of the copyright holder 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 HOLDER 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. + */ + +#include "dev/amdgpu/amdgpu_gfx.hh" + +#include "mem/packet_access.hh" +#include "sim/core.hh" + +namespace gem5 +{ + +void +AMDGPUGfx::readMMIO(PacketPtr pkt, Addr offset) +{ + switch (offset) { + case AMDGPU_MM_RLC_GPU_CLOCK_COUNT_LSB: + pkt->setLE(captured_clock_count); + break; + case AMDGPU_MM_RLC_GPU_CLOCK_COUNT_MSB: + pkt->setLE(captured_clock_count >> 32); + break; + default: + break; + } +} + +void +AMDGPUGfx::writeMMIO(PacketPtr pkt, Addr offset) +{ + switch (offset) { + case AMDGPU_MM_RLC_CAPTURE_GPU_CLOCK_COUNT: + // Use gem5 Ticks in nanoseconds are the counter. The first capture + // is expected to return zero. + if (captured_clock_count == 1) { + captured_clock_count = 0; + } else { + captured_clock_count = curTick() / sim_clock::as_int::ns; + } + break; + default: + break; + } +} + +} // namespace gem5 diff --git a/src/dev/amdgpu/amdgpu_gfx.hh b/src/dev/amdgpu/amdgpu_gfx.hh new file mode 100644 index 0000000000..c32b8624cf --- /dev/null +++ b/src/dev/amdgpu/amdgpu_gfx.hh @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. Neither the name of the copyright holder 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 HOLDER 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. + */ + +#ifndef __DEV_AMDGPU_AMDGPU_GFX_HH__ +#define __DEV_AMDGPU_AMDGPU_GFX_HH__ + +#include "base/types.hh" +#include "mem/packet.hh" + +/** + * MMIO offsets for GFX. This class handles MMIO reads/writes to the GFX_BASE + * aperture which are generally read/written by the gfx driver source here: + * + * drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c + * https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/blob/master/ + * drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c + * + * The MMIO addresses in the file are dword addresses. Here they are converted + * to byte addresses so gem5 does not need to shift the values. + */ + +// Registers used to read GPU clock count used in profiling +#define AMDGPU_MM_RLC_GPU_CLOCK_COUNT_LSB 0x13090 +#define AMDGPU_MM_RLC_GPU_CLOCK_COUNT_MSB 0x13094 +#define AMDGPU_MM_RLC_CAPTURE_GPU_CLOCK_COUNT 0x13098 + +namespace gem5 +{ + +class AMDGPUGfx +{ + public: + AMDGPUGfx() { } + + void readMMIO(PacketPtr pkt, Addr offset); + void writeMMIO(PacketPtr pkt, Addr offset); + + private: + /* + * GPU clock count at the time capture MMIO is received. + */ + uint64_t captured_clock_count = 1; +}; + +} // namespace gem5 + +#endif // __DEV_AMDGPU_AMDGPU_GFX_HH__ From 0dcf0fb8295510b37b913b989dfc86d75e7c59cb Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Thu, 21 Sep 2023 16:06:31 +0000 Subject: [PATCH 386/693] sim-se: unmap reclaimed heap pages in brk syscall emulation gem5::MemState::updateBrkRegion(), which is called during the syscall emulation of brk, did not unmap deallocated heap pages when the brk region is receding. Instead, it kept it mapped for simplicity. This introduced a bug where subequent expansions of the brk region reused prior heap page mappings that were not zero-filled. This violates the assumptions of glibc malloc, resulting in heap corruption and crashes. This patch fixes the bug by always unmapping pages that are deallocated during a call to brk() that reduces the heap size. This makes the gem5::MemState::_endBrkPoint field obsolete, so this patch removes it. GitHub issue: https://github.com/gem5/gem5/issues/342 Change-Id: Ib2244e1aa4d2a26666ad60d231fdde2c22d2df35 --- src/sim/mem_state.cc | 51 ++++++++++++++++++++++++-------------------- src/sim/mem_state.hh | 5 ----- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/sim/mem_state.cc b/src/sim/mem_state.cc index 801226cfb1..93e7ca3773 100644 --- a/src/sim/mem_state.cc +++ b/src/sim/mem_state.cc @@ -49,7 +49,7 @@ MemState::MemState(Process *owner, Addr brk_point, Addr stack_base, _stackBase(stack_base), _stackSize(max_stack_size), _maxStackSize(max_stack_size), _stackMin(stack_base - max_stack_size), _nextThreadStackBase(next_thread_stack_base), - _mmapEnd(mmap_end), _endBrkPoint(brk_point) + _mmapEnd(mmap_end) { } @@ -67,7 +67,6 @@ MemState::operator=(const MemState &in) _stackMin = in._stackMin; _nextThreadStackBase = in._nextThreadStackBase; _mmapEnd = in._mmapEnd; - _endBrkPoint = in._endBrkPoint; _vmaList = in._vmaList; /* This assignment does a deep copy. */ return *this; @@ -107,26 +106,34 @@ MemState::isUnmapped(Addr start_addr, Addr length) void MemState::updateBrkRegion(Addr old_brk, Addr new_brk) { - /** - * To make this simple, avoid reducing the heap memory area if the - * new_brk point is less than the old_brk; this occurs when the heap is - * receding because the application has given back memory. The brk point - * is still tracked in the MemState class as an independent field so that - * it can be returned to the application; we just do not update the - * region unless we expand it out. - */ - if (new_brk < old_brk) { - _brkPoint = new_brk; - return; - } - /** * The regions must be page aligned but the break point can be set on * byte boundaries. Ensure that the restriction is maintained here by * extending the request out to the end of the page. (The roundUp * function will not round up an already aligned page.) */ - auto page_aligned_brk = roundUp(new_brk, _pageBytes); + auto page_aligned_new_brk = roundUp(new_brk, _pageBytes); + auto page_aligned_old_brk = roundUp(old_brk, _pageBytes); + + /** + * Reduce the heap memory area if the new_brk point is less than + * the old_brk; this occurs when the heap is receding because the + * application has given back memory. This may involve unmapping + * heap pages, if new_brk rounds to a lower-address page. The + * previous behavior was to leave such pages mapped for simplicity; + * however, that was not what Linux does in practice and may + * violate the assumptions of applications like glibc malloc, + * whose default configuration for Linux requires all pages + * allocated via brk(2) to be zero-filled (specifically, + * by setting MORECORE_CLEARS to 2). + */ + if (new_brk < old_brk) { + const auto length = page_aligned_old_brk - page_aligned_new_brk; + if (length > 0) + unmapRegion(page_aligned_new_brk, length); + _brkPoint = new_brk; + return; + } /** * Create a new mapping for the heap region. We only create a mapping @@ -135,17 +142,16 @@ MemState::updateBrkRegion(Addr old_brk, Addr new_brk) * * Since we do not track the type of the region and we also do not * coalesce the regions together, we can create a fragmented set of - * heap regions. To resolve this, we keep the furthest point ever mapped - * by the _endBrkPoint field. + * heap regions. */ - if (page_aligned_brk > _endBrkPoint) { - auto length = page_aligned_brk - _endBrkPoint; + if (page_aligned_new_brk > page_aligned_old_brk) { + auto length = page_aligned_new_brk - page_aligned_old_brk; /** * Check if existing mappings impede the expansion of brk expansion. * If brk cannot expand, it must return the original, unmodified brk * address and should not modify the mappings here. */ - if (!isUnmapped(_endBrkPoint, length)) { + if (!isUnmapped(page_aligned_old_brk, length)) { return; } @@ -156,8 +162,7 @@ MemState::updateBrkRegion(Addr old_brk, Addr new_brk) * implemented if it actually becomes necessary; probably only * necessary if the list becomes too long to walk. */ - mapRegion(_endBrkPoint, length, "heap"); - _endBrkPoint = page_aligned_brk; + mapRegion(page_aligned_old_brk, length, "heap"); } _brkPoint = new_brk; diff --git a/src/sim/mem_state.hh b/src/sim/mem_state.hh index b2b50d0760..8c01f7a765 100644 --- a/src/sim/mem_state.hh +++ b/src/sim/mem_state.hh @@ -277,11 +277,6 @@ class MemState : public Serializable Addr _nextThreadStackBase; Addr _mmapEnd; - /** - * Keeps record of the furthest mapped heap location. - */ - Addr _endBrkPoint; - /** * The _vmaList member is a list of virtual memory areas in the target * application space that have been allocated by the target. In most From 7a0e84d8537dcf5452a516df762d3be95c3d1315 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Fri, 6 Oct 2023 20:41:59 +0000 Subject: [PATCH 387/693] cpu-kvm, arch-x86: flush TLB after syscalls Modified the x86 KVM-in-SE syscall handler to flush the TLB following each syscall, in case the page table has been modified. This is done by reloading the value in %cr3. Doing this requires an intermediate GPR, which we store in a new scratch buffer following the syscall code at address `syscallDataBuf`. GitHub issue: https://github.com/gem5/gem5/issues/409 Change-Id: Ibc20018c97ebb1794fa31a0c71e0857d661c7c9d --- src/arch/x86/process.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 17cc7ba801..10833783fd 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -483,13 +483,35 @@ X86_64Process::initState() physProxy.writeBlob(idtPhysAddr + 0xE0, &PFGate, sizeof(PFGate)); /* System call handler */ + // First, we write to the MMIO m5ops range (0xffffc90000007000) + // to trap out of the VM back into gem5 to emulate the system + // call. Upon re-entering the VM, we need to flush the TLB in + // case the system call modified existing page mappings (e.g., + // munmap, mremap, brk). To do this, we can simply read/write + // cr3; however, doing so requires saving the value to an + // intermediate GPR (%rax, in this case). We save/restore the + // value of %rax in the scratch region syscallDataBuf. + const Addr syscallDataBuf = syscallCodeVirtAddr + 0x100; uint8_t syscallBlob[] = { // mov %rax, (0xffffc90000007000) 0x48, 0xa3, 0x00, 0x70, 0x00, 0x00, 0x00, 0xc9, 0xff, 0xff, + // mov %rax, (syscallDataBuf) + 0x48, 0xa3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + // mov %cr3, %rax + 0x0f, 0x20, 0xd8, + // mov %rax, %cr3 + 0x0f, 0x22, 0xd8, + // mov (syscallDataBuf), %rax + 0x48, 0xa1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, // sysret 0x48, 0x0f, 0x07 }; + assert(syscallDataBuf >= syscallCodePhysAddr + sizeof syscallBlob); + std::memcpy(&syscallBlob[12], &syscallDataBuf, sizeof syscallDataBuf); + std::memcpy(&syscallBlob[28], &syscallDataBuf, sizeof syscallDataBuf); physProxy.writeBlob(syscallCodePhysAddr, syscallBlob, sizeof(syscallBlob)); From d1f9f987472a0b28754180c2a9b58c55b5551d46 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 15:07:16 -0700 Subject: [PATCH 388/693] util: Make all runners the same type Having two types of GitHub Action Runners has not yielded much benefit and caused confusion and inefficiencies. This change simplifies things to having just one runner with 8-cores and 16GB of memory. It is sufficient to build gem5 and run most simulations. Change-Id: Ic49ae5e98b02086f153f4ae2a4eedd8a535786c8 --- util/github-runners-vagrant/README.md | 25 +++----- .../{Vagrantfile-runner => Vagrantfile} | 12 +--- .../Vagrantfile-builder | 57 ------------------- util/github-runners-vagrant/vm_manager.sh | 28 +++------ 4 files changed, 17 insertions(+), 105 deletions(-) rename util/github-runners-vagrant/{Vagrantfile-runner => Vagrantfile} (80%) delete mode 100644 util/github-runners-vagrant/Vagrantfile-builder diff --git a/util/github-runners-vagrant/README.md b/util/github-runners-vagrant/README.md index 7d0f116260..2ea5b3e588 100644 --- a/util/github-runners-vagrant/README.md +++ b/util/github-runners-vagrant/README.md @@ -21,10 +21,10 @@ sudo apt-get install qemu libvirt-daemon-system libvirt-clients ebtables dnsmasq sudo apt purge vagrant-libvirt ``` -## Set up the Vagrantfiles for the GitHub repository +## Set up the Vagrant for the GitHub repository First, generate a Personal Access Token, which you can create [here](https://github.com/settings/tokens) -Make sure to set admin permissions on this token, then replace instances of `` in the Vagrantfiles ("Vagrantfile-builder" and "Vagrant-runner") with your token. +Make sure to set admin permissions on this token, then replace the of `` in the Vagrantfile with your token. Next, replace instances of `` with your GitHub account name and the repository name, separated by a forward slash. For example, if your GitHub account name is `example` and your repository name is `example-repo`, you would replace `` with `example/example-repo`. @@ -46,28 +46,19 @@ vagrant plugin install vagrant-libvirt vagrant plugin install vagrant-reload ``` -## The "builder" and "runner" VMs - -The number of CPUs and the memory size differs between the "Vagrantfile-builder" and "Vagrantfile-runner". - -In our work we have two types of machines "runners" and "builders". -Runners are single core machines with 8GB of memory, and builders are 4 core machines with 16GB of memory. -The latter is used for building gem5 binaries while the former is used for running instances of gem5. -You can expect each machine to take up approximately 60GB of disk space though VMs will consume the disk space they require. - -The "Vagrantfile-builder" file is set to create a runner machine and the "Vagrantfile-builder" file is set to create a builder machine. - -Specifying which Vagrantfile to use is done by setting the `VAGRANT_VAGRANTFILE` environment variable. - ## Creating the virtual machine +The Vagrantfile in this directory defines a VM that can be used to create a GitHub Actions runner. +It has 4-cores, 16GB of RAM, and 60GB of disk space. +This is sufficient to both compile gem5 and run most simulations. + Each VM on your host system must have a unique name. Give the VM to be created a unique name by setting the `` variables in the Vagrantfile you wish to utilize. Then run: ```sh -VAGRANT_VAGRANTFILE= vagrant up --provider=libvirt +vagrant up --provider=libvirt ``` This should automatically create your machine, as well as configure and start up a Github Actions runner. @@ -80,7 +71,7 @@ If you wish to create more than one runner you must edit the `` in the ## Helper scripts The "vm_manager" script can be used to set up multiple builder and runner VMs. -To use this script simply modify the `NUM_RUNNERS`, `NUM_BUILDERS`, `RUNNER_PREFIX`, and `BUILDER_PREFIX` variables to the desired values. +To use this script simply modify the `NUM_RUNNERS` and `RUNNER_PREFIX` variables to the desired values. Then run the script with: ```sh diff --git a/util/github-runners-vagrant/Vagrantfile-runner b/util/github-runners-vagrant/Vagrantfile similarity index 80% rename from util/github-runners-vagrant/Vagrantfile-runner rename to util/github-runners-vagrant/Vagrantfile index eb4054ed16..4bc0b85fd7 100644 --- a/util/github-runners-vagrant/Vagrantfile-runner +++ b/util/github-runners-vagrant/Vagrantfile @@ -13,23 +13,15 @@ Vagrant.configure("2") do |config| config.vm.provider "libvirt" do |vb| # Customize the amount of cpus and memory on the VM: - vb.cpus = "1".to_i - vb.memory = "8192".to_i + vb.cpus = "4".to_i + vb.memory = "16384".to_i end # sets up vm config.vm.provision :shell, path: "provision_root.sh" config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" - # To ensure we don't run out of memory, we enable dynamic Swap Space. This is - # done via the "swapspace" daemon: https://pqxx.org/development/swapspace/ - config.vm.provision :shell, inline: "sudo apt install swapspace -y" # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. config.vm.provision :reload - config.vm.provision :shell, run: 'always', inline: <<-SHELL - # When running gem5 in SE mode we must overcommit memory. - # This is run on every startup of the VM. - /sbin/sysctl vm.overcommit_memory=1 - SHELL config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL if [ -d ~/actions-runner ]; then # This will be run everytime the VM is run (once created). diff --git a/util/github-runners-vagrant/Vagrantfile-builder b/util/github-runners-vagrant/Vagrantfile-builder deleted file mode 100644 index c0c2380b95..0000000000 --- a/util/github-runners-vagrant/Vagrantfile-builder +++ /dev/null @@ -1,57 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -Vagrant.configure("2") do |config| - config.vm.box = "generic/ubuntu2204" - config.vm.box_check_update = true - config.vm.define "" - config.vm.hostname = "" - # allows us to ssh into the machine, addressing the problem below - # https://www.reddit.com/r/vagrant/comments/sb7hfl/new_to_vagrant_getting_efault_warning/ - config.ssh.username = "vagrant" - config.ssh.password = "vagrant" - - config.vm.provider "libvirt" do |vb| - # Customize the amount of cpus and memory on the VM: - vb.cpus = "4".to_i - vb.memory = "16384".to_i - end - - # sets up vm - config.vm.provision :shell, path: "provision_root.sh" - config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" - # To ensure we don't run out of memory, we enable dynamic Swap Space. This is - # done via the "swapspace" daemon: https://pqxx.org/development/swapspace/ - config.vm.provision :shell, inline: "sudo apt install swapspace -y" - # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. - config.vm.provision :reload - config.vm.provision :shell, run: 'always', inline: <<-SHELL - # When running gem5 in SE mode we must overcommit memory. - # This is run on every startup of the VM. - /sbin/sysctl vm.overcommit_memory=1 - SHELL - config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL - if [ -d ~/actions-runner ]; then - # This will be run everytime the VM is run (once created). - cd actions-runner - nohup ./run.sh & - else - # This will be run the first time the VM is created. - mkdir ~/actions-runner && cd ~/actions-runner - curl -so actions-runner-linux-x64-2.304.0.tar.gz -L \ - https://github.com/actions/runner/releases/download/v2.304.0/actions-runner-linux-x64-2.304.0.tar.gz - tar xzf ./actions-runner-linux-x64-2.304.0.tar.gz - - # configure the runner - # echo automatically sets the name of the runner, and the tags - # create a personal access token with admin permission and copy it into the curl command - echo -ne '\n\nbuild\n\n' | ./config.sh --url https://github.com/ --token $(curl -L \ - -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer " \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos//actions/runners/registration-token | jq -r '.token') - # start the runner - nohup ./run.sh & - fi - SHELL - -end diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh index ce46eb3fe7..da07217121 100755 --- a/util/github-runners-vagrant/vm_manager.sh +++ b/util/github-runners-vagrant/vm_manager.sh @@ -1,9 +1,7 @@ #!/bin/bash -NUM_RUNNERS=20 -NUM_BUILDERS=3 -RUNNER_PREFIX="$(hostname)-runner-" -BUILDER_PREFIX="$(hostname)-builder-" +NUM_RUNNERS=3 +RUNNER_PREFIX_PREFIX="$(hostname)" SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) export VAGRANT_HOME=${SCRIPT_DIR} @@ -19,25 +17,13 @@ fi for (( i=1; i<=NUM_RUNNERS; i++ )); do - sed -i "s/ config.vm.define.*/ config.vm.define \"${RUNNER_PREFIX}${i}\"/g" Vagrantfile-runner - sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${RUNNER_PREFIX}${i}\"/g" Vagrantfile-runner + sed -i "s/ config.vm.define.*/ config.vm.define \"${RUNNER_PREFIX}-${i}\"/g" Vagrantfile + sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${RUNNER_PREFIX}-${i}\"/g" Vagrantfile if [[ "${param}" == "destroy" ]]; then - VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant destroy -f + VAGRANT_VAGRANTFILE=Vagrantfile vagrant destroy -f elif [[ "${param}" == "shutdown" ]]; then - VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant halt -f + VAGRANT_VAGRANTFILE=Vagrantfile vagrant halt -f else - VAGRANT_VAGRANTFILE=Vagrantfile-runner vagrant up --provider=libvirt - fi -done - -for (( i=1; i<=NUM_BUILDERS; i++ )); do - sed -i "s/ config.vm.define.*/ config.vm.define \"${BUILDER_PREFIX}${i}\"/g" Vagrantfile-builder - sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${BUILDER_PREFIX}${i}\"/g" Vagrantfile-builder - if [[ "${param}" == "destroy" ]]; then - VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant destroy -f - elif [[ "${param}" == "shutdown" ]]; then - VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant halt -f - else - VAGRANT_VAGRANTFILE=Vagrantfile-builder vagrant up --provider=libvirt + VAGRANT_VAGRANTFILE=Vagrantfile vagrant up --provider=libvirt fi done From 3e1c0b0714bddd973670d9a23d033cc077102487 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 15:18:45 -0700 Subject: [PATCH 389/693] util: Move runners from gem5 repository to gem5 org There are two places self-hosted runners can exist on GitHub: 1. At the level of the repository: In this case the runners can only be used by that repository and runners can only be distinguished from one another by labels. 2. At the level of the organization: In this case the runners can be used by any repository in the organization, thus increasing their versatility. In addition to labels, runners in the level of the organization can be organized into groups. While we do not use our self-hosted runners on other repositories, there may be future use for this, so we might as well enable it now. Change-Id: Id5e113194314336221dcdc8c2858b352afcbaf6e --- util/github-runners-vagrant/README.md | 5 ++--- util/github-runners-vagrant/Vagrantfile | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/util/github-runners-vagrant/README.md b/util/github-runners-vagrant/README.md index 2ea5b3e588..0b93ff6693 100644 --- a/util/github-runners-vagrant/README.md +++ b/util/github-runners-vagrant/README.md @@ -26,8 +26,7 @@ sudo apt purge vagrant-libvirt First, generate a Personal Access Token, which you can create [here](https://github.com/settings/tokens) Make sure to set admin permissions on this token, then replace the of `` in the Vagrantfile with your token. -Next, replace instances of `` with your GitHub account name and the repository name, separated by a forward slash. -For example, if your GitHub account name is `example` and your repository name is `example-repo`, you would replace `` with `example/example-repo`. +Next, replace instances of `` with your GitHub organization you wish to add this runner. ## Install Vagrant Plugins @@ -62,7 +61,7 @@ vagrant up --provider=libvirt ``` This should automatically create your machine, as well as configure and start up a Github Actions runner. -You can check the status of the runner here: https://github.com///settings/actions/runners +You can check the status of the runner here: https://github.com/organizations/{GITHUB_ORG}/settings/actions/runners If the runner ever shows as offline, you can rerun the `vagrant up --provider=libvirt` command to make sure everything is working properly. diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 4bc0b85fd7..0f1eb9ee49 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -37,10 +37,10 @@ Vagrant.configure("2") do |config| # configure the runner # echo automatically sets the name of the runner, and the tags # create a personal access token with admin permission and copy it into the curl command - echo -ne '\n\nrun\n\n' | ./config.sh --url https://github.com/ --token $(curl -L \ + echo -ne '\n\nrun\n\n' | ./config.sh --url https://github.com/ --token $(curl -L \ -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer " \ -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos//actions/runners/registration-token | jq -r '.token') + https://api.github.com/orgs/${GITHUB_ORG}/actions/runners/registration-token | jq -r '.token') # start the runner nohup ./run.sh & fi From a924fa3bdcde86894ab24a434cb035a9362bfabf Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 17:21:13 -0700 Subject: [PATCH 390/693] util: Add action-run.sh to run Action Runners The "action-run.sh" action replaces inline scripting in the Vagrantfile. The major improvement is this script runs an infinite loop and configures the runners to be ephemeral. This means they cease to exist after a job is complete. The script then cleans the VM workspace and the loop restarts by configuring and setting up another runner. This means our VMs no longer accumulate files that eventually lead to the VM running out of space. Change-Id: Iba6dc9a480f5805042602f120fc84bdc47a96d55 --- util/github-runners-vagrant/Vagrantfile | 30 +++------ util/github-runners-vagrant/action-run.sh | 81 +++++++++++++++++++++++ 2 files changed, 89 insertions(+), 22 deletions(-) create mode 100755 util/github-runners-vagrant/action-run.sh diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 0f1eb9ee49..b51a8c0a9c 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -1,6 +1,9 @@ # -*- mode: ruby -*- # vi: set ft=ruby : +PERSONAL_ACCESS_TOKEN="" +GITHUB_ORG="" + Vagrant.configure("2") do |config| config.vm.box = "generic/ubuntu2204" config.vm.box_check_update = true @@ -22,27 +25,10 @@ Vagrant.configure("2") do |config| config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. config.vm.provision :reload - config.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL - if [ -d ~/actions-runner ]; then - # This will be run everytime the VM is run (once created). - cd actions-runner - nohup ./run.sh & - else - # This will be run the first time the VM is created. - mkdir ~/actions-runner && cd ~/actions-runner - curl -so actions-runner-linux-x64-2.304.0.tar.gz -L \ - https://github.com/actions/runner/releases/download/v2.304.0/actions-runner-linux-x64-2.304.0.tar.gz - tar xzf ./actions-runner-linux-x64-2.304.0.tar.gz + # Copy the "action-run.sh" script from the host to the VM. + builder.vm.provision "file", source: "./action-run.sh", destination: "/tmp/action-run.sh" + builder.vm.provision :shell, privileged: false, inline: "cp /tmp/action-run.sh ." + # Execute the actions-run.sh script on every boot. This configures the and starts the runner. + config.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} >> action-run.log 2>&1 &" - # configure the runner - # echo automatically sets the name of the runner, and the tags - # create a personal access token with admin permission and copy it into the curl command - echo -ne '\n\nrun\n\n' | ./config.sh --url https://github.com/ --token $(curl -L \ - -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer " \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/orgs/${GITHUB_ORG}/actions/runners/registration-token | jq -r '.token') - # start the runner - nohup ./run.sh & - fi - SHELL end diff --git a/util/github-runners-vagrant/action-run.sh b/util/github-runners-vagrant/action-run.sh new file mode 100755 index 0000000000..b802a7c739 --- /dev/null +++ b/util/github-runners-vagrant/action-run.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -x + +# No argument checking here, this is run directly in the Vagrantfile. +PERSONAL_ACCESS_TOKEN="$1" +GITHUB_ORG="$2" +LABELS="$3" +WORK_DIR="_work" + +# This checks there isn't another instance of this script running. +# If this script is run twice then more than one runner can be active in the +# VM and this causes problems. +if [[ `pgrep -f $0` != "$$" ]]; then + echo "Another instance of shell already exist! Exiting" + exit +fi + +# If the tarball isn't here then download it and extract it. +# Note: we don't delete the tarball, we use it to check if we've already +# downloaded it and extracted it. +if [ ! -f "actions-runner-linux-x64-2.304.0.tar.gz" ]; then + wget https://github.com/actions/runner/releases/download/v2.304.0/actions-runner-linux-x64-2.304.0.tar.gz + tar xzf ./actions-runner-linux-x64-2.304.0.tar.gz +fi + +# An infinite loop to re-configure and re-run the runner after each job. +while true; do + # 1. Obtain the registration token. + token_curl=$(curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${PERSONAL_ACCESS_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/orgs/${GITHUB_ORG}/actions/runners/registration-token) + + token=$(echo ${token_curl} | jq -r '.token') + + # 2. Configure the runner. + ./config.sh --unattended \ + --url https://github.com/${GITHUB_ORG} \ + --ephemeral \ + --replace \ + --work "${WORK_DIR}" \ + --name "$(hostname)" \ + --labels "${LABELS}" \ + --token ${token} + + # 3. Run the runner. + ./run.sh # This will complete with the runner being destroyed + + # 4. Cleanup the machine + rm -rf "${WORK_DIR}" + docker system prune --force --volumes +done From 529423f47acfe53f7fea1df9d7e39c130109d059 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 17:37:11 -0700 Subject: [PATCH 391/693] util: Remove note about ssh use This is confusing and setting the ssh username and password is normal. Change-Id: Ic925e92ade47f455c86a461a267b8cad7aa6d7ba --- util/github-runners-vagrant/Vagrantfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index b51a8c0a9c..504e8e35da 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -9,8 +9,6 @@ Vagrant.configure("2") do |config| config.vm.box_check_update = true config.vm.define "" config.vm.hostname = "" - # allows us to ssh into the machine, addressing the problem below - # https://www.reddit.com/r/vagrant/comments/sb7hfl/new_to_vagrant_getting_efault_warning/ config.ssh.username = "vagrant" config.ssh.password = "vagrant" From c0cb16ba89212ce658ebe0b12b7fbe08d1cccd57 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 17:42:21 -0700 Subject: [PATCH 392/693] util: Create HOSTNAME variable Change-Id: Ia68f1bef2bb9e4e5e18476b6100be80f8cf1c799 --- util/github-runners-vagrant/Vagrantfile | 5 +++-- util/github-runners-vagrant/vm_manager.sh | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 504e8e35da..f81d53e145 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -3,12 +3,13 @@ PERSONAL_ACCESS_TOKEN="" GITHUB_ORG="" +HOSTNAME="" Vagrant.configure("2") do |config| config.vm.box = "generic/ubuntu2204" config.vm.box_check_update = true - config.vm.define "" - config.vm.hostname = "" + config.vm.define "#{HOSTNAME}" + config.vm.hostname = "#{HOSTNAME}" config.ssh.username = "vagrant" config.ssh.password = "vagrant" diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh index da07217121..4854f5a06f 100755 --- a/util/github-runners-vagrant/vm_manager.sh +++ b/util/github-runners-vagrant/vm_manager.sh @@ -17,8 +17,7 @@ fi for (( i=1; i<=NUM_RUNNERS; i++ )); do - sed -i "s/ config.vm.define.*/ config.vm.define \"${RUNNER_PREFIX}-${i}\"/g" Vagrantfile - sed -i "s/ config.vm.hostname.*/ config.vm.hostname = \"${RUNNER_PREFIX}-${i}\"/g" Vagrantfile + sed -i "s/HOSTNAME=.*/HOTNAME=\"${RUNNER_PREFIX}-${i}\"/g" Vagrantfile if [[ "${param}" == "destroy" ]]; then VAGRANT_VAGRANTFILE=Vagrantfile vagrant destroy -f elif [[ "${param}" == "shutdown" ]]; then From 8c2d41422387da3d5d99c09e9865bcedf22abafe Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 17:53:08 -0700 Subject: [PATCH 393/693] util: Cleanup the provision_root.sh Change-Id: I58215dddc34476695c7aedc77b55d338e0304198 --- util/github-runners-vagrant/provision_root.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/util/github-runners-vagrant/provision_root.sh b/util/github-runners-vagrant/provision_root.sh index 660064f8ca..74b4facdda 100644 --- a/util/github-runners-vagrant/provision_root.sh +++ b/util/github-runners-vagrant/provision_root.sh @@ -5,9 +5,9 @@ set -eu -o pipefail # -x: is for debugging apt-get update apt-get upgrade -y -apt-get install -y software-properties-common add-apt-repository --yes --update ppa:git-core/ppa apt-get install -y \ + software-properties-common \ bash \ build-essential \ clang-format \ @@ -25,8 +25,12 @@ apt-get install -y \ tree \ wget \ yamllint \ - zstd -snap install jq + zstd \ + jq \ + apt-transport-https ca-certificates \ + curl \ + gnupg \ + lsb-release # Install docker apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release @@ -34,10 +38,11 @@ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null apt-get update -y apt-get install -y docker-ce docker-ce-cli containerd.io -groupadd docker || true -gpasswd -a vagrant docker -newgrp docker -systemctl restart docker + +# Add the Vagrant user to the docker group. +# Note: The VM needs rebooted for this to take effect. `newgrp docker` doesn't +# work. +usermod -aG docker vagrant # Cleanup apt-get autoremove -y From f36449be983b08c6518402e0c0cf64e4267521ad Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 17:55:45 -0700 Subject: [PATCH 394/693] util: Add missing copyright notices Change-Id: I243046c17264eb5c522285096ecf9c7e5e968322 --- util/github-runners-vagrant/Vagrantfile | 26 +++++++++++++++++++ .../provision_nonroot.sh | 26 +++++++++++++++++++ util/github-runners-vagrant/provision_root.sh | 26 +++++++++++++++++++ util/github-runners-vagrant/vm_manager.sh | 26 +++++++++++++++++++ 4 files changed, 104 insertions(+) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index f81d53e145..ad294a3b38 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -1,6 +1,32 @@ # -*- mode: ruby -*- # vi: set ft=ruby : +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + PERSONAL_ACCESS_TOKEN="" GITHUB_ORG="" HOSTNAME="" diff --git a/util/github-runners-vagrant/provision_nonroot.sh b/util/github-runners-vagrant/provision_nonroot.sh index 4465b5a192..d817959285 100644 --- a/util/github-runners-vagrant/provision_nonroot.sh +++ b/util/github-runners-vagrant/provision_nonroot.sh @@ -1,5 +1,31 @@ #!/usr/bin/env bash +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # fail on unset variables and command errors set -eu -o pipefail # -x: is for debugging diff --git a/util/github-runners-vagrant/provision_root.sh b/util/github-runners-vagrant/provision_root.sh index 74b4facdda..5a42556779 100644 --- a/util/github-runners-vagrant/provision_root.sh +++ b/util/github-runners-vagrant/provision_root.sh @@ -1,5 +1,31 @@ #!/usr/bin/env bash +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # fail on unset variables and command errors set -eu -o pipefail # -x: is for debugging diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh index 4854f5a06f..280ee431bc 100755 --- a/util/github-runners-vagrant/vm_manager.sh +++ b/util/github-runners-vagrant/vm_manager.sh @@ -1,5 +1,31 @@ #!/bin/bash +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + NUM_RUNNERS=3 RUNNER_PREFIX_PREFIX="$(hostname)" From 0e5c6d9f501933ebf19affeb47480cfa8ca5a88c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 18:06:58 -0700 Subject: [PATCH 395/693] util: Resize VM root partition max size to ~128GB Prior to this change we were limited to a root partition with only 60GB of space which caused issues when running larger simulations (see: https://github.com/gem5/gem5/issues/165). There are two factors in this issue which this patch resolves: 1. The root partition in the VM was capped at 60GB despite the virtual machines size being capped at 128GB. This resulted in libvirt giving the VM free space it couldn't use. To fix this `lvextend` was added to the "provision_root.sh" script to resize the root partition to fill the available space. 2. The virtual machine size can be set via the `machine_virtual_size` parameter. The minimum and default value is 128GB. This wasn't exposed previously. Now, if we required, we can increase the size of the VM/Root partition if we require (though I believe 128GB is more than sufficient for now). Fixes: https://github.com/gem5/gem5/issues/165 Change-Id: I82dd500d8807ee0164f92d91515729d5fbd598e3 --- util/github-runners-vagrant/Vagrantfile | 3 ++- util/github-runners-vagrant/provision_root.sh | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index ad294a3b38..2a891b9688 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -40,9 +40,10 @@ Vagrant.configure("2") do |config| config.ssh.password = "vagrant" config.vm.provider "libvirt" do |vb| - # Customize the amount of cpus and memory on the VM: + # Customize the amount of cpus, memory, and storage on the VM: vb.cpus = "4".to_i vb.memory = "16384".to_i + vb.machine_virtual_size = 128 # 128G is the minimum. end # sets up vm diff --git a/util/github-runners-vagrant/provision_root.sh b/util/github-runners-vagrant/provision_root.sh index 5a42556779..f18a170c95 100644 --- a/util/github-runners-vagrant/provision_root.sh +++ b/util/github-runners-vagrant/provision_root.sh @@ -72,3 +72,6 @@ usermod -aG docker vagrant # Cleanup apt-get autoremove -y + +# Resize the root partition to fill up all the free size on the disk +lvextend -l +100%FREE $(df / --output=source | sed 1d) From 6571a54a65a1e65f9118d0a217c61db7c9611dad Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 18:45:53 -0700 Subject: [PATCH 396/693] util: Use a Multi-Machine Vagrantfile This patch removed the bespoke "vm_manager.sh" script in favor of a Multi-Machine Vagrantfile. With this the users needs to only change the variables in Vagrantfile then use the standard `vagrant` commands to launch the VMs/Runners. Change-Id: Ida5d2701319fd844c6a5b6fa7baf0c48b67db975 --- util/github-runners-vagrant/README.md | 68 ++++++----------------- util/github-runners-vagrant/Vagrantfile | 47 +++++++++------- util/github-runners-vagrant/vm_manager.sh | 54 ------------------ 3 files changed, 43 insertions(+), 126 deletions(-) delete mode 100755 util/github-runners-vagrant/vm_manager.sh diff --git a/util/github-runners-vagrant/README.md b/util/github-runners-vagrant/README.md index 0b93ff6693..ea7fd16957 100644 --- a/util/github-runners-vagrant/README.md +++ b/util/github-runners-vagrant/README.md @@ -1,6 +1,6 @@ # Setting up a Github Actions Runner with Vagrant -This directory provides a way to setup a Github Actions runner using Vagrant to host the runner in a Virtual machine. +This directory provides a way to setup Github Actions runners using Vagrant to host them in Virtual machines. This tutorial has been written with the assumption of running on a machine with Ubuntu 22.04. Setting up a runner on a different OS may require some changes. @@ -21,13 +21,6 @@ sudo apt-get install qemu libvirt-daemon-system libvirt-clients ebtables dnsmasq sudo apt purge vagrant-libvirt ``` -## Set up the Vagrant for the GitHub repository - -First, generate a Personal Access Token, which you can create [here](https://github.com/settings/tokens) -Make sure to set admin permissions on this token, then replace the of `` in the Vagrantfile with your token. - -Next, replace instances of `` with your GitHub organization you wish to add this runner. - ## Install Vagrant Plugins Once everything is set properly, set the `VAGRANT_HOME` environment variable to the directory in which the Vagrant files and other scripts are stored (i.e., the CWD). @@ -45,62 +38,35 @@ vagrant plugin install vagrant-libvirt vagrant plugin install vagrant-reload ``` -## Creating the virtual machine +## Creating the virtual machines -The Vagrantfile in this directory defines a VM that can be used to create a GitHub Actions runner. -It has 4-cores, 16GB of RAM, and 60GB of disk space. +The Vagrantfile in this directory defines the VMs that can be built and used to create a GitHub Actions runner. +This standard VM has 4-cores, 16GB of RAM, and 60GB of disk space. This is sufficient to both compile gem5 and run most simulations. -Each VM on your host system must have a unique name. -Give the VM to be created a unique name by setting the `` variables in the Vagrantfile you wish to utilize. +At the top of the Vagrantfile, there are a few variables that must be set prior to creating the VMs. -Then run: +* `NUM_RUNNERS`: The number of runners to create. +* `PERSONAL_ACCESS_TOKEN`: The GitHub personal access token to use. +You can generate a Personal Access Token [here](https://github.com/settings/tokens) +Make sure to set admin permissions on this token. +* `GITHUB_ORG`: The GitHub organization to add the runners to. +E.g., if the URL to your organization is https://github.com/orgs/gem5, then the variable should be set to "gem5". +* `HOSTNAME` : The hostname of the VM to be created (note, this will be appended with a number to create a unique hostname for each VM). +E.g., if set to `my-machine` and the number of runners set to `2`, two VMs will be created. +One called `my-machine-1` and the other `my-machine-2`. + +When set simply run: ```sh vagrant up --provider=libvirt ``` -This should automatically create your machine, as well as configure and start up a Github Actions runner. +This should automatically create your machines then configure and start up a Github Actions runner in each. You can check the status of the runner here: https://github.com/organizations/{GITHUB_ORG}/settings/actions/runners If the runner ever shows as offline, you can rerun the `vagrant up --provider=libvirt` command to make sure everything is working properly. -If you wish to create more than one runner you must edit the `` in the Vagrant file. - -## Helper scripts - -The "vm_manager" script can be used to set up multiple builder and runner VMs. -To use this script simply modify the `NUM_RUNNERS` and `RUNNER_PREFIX` variables to the desired values. -Then run the script with: - -```sh -./vm_manager.sh -``` - -This script will create any VMs that don't already exist and ensure those that do exists are running. - -If you wish to destroy all the VMs you can run: - -```sh -./vm_manager.sh destroy -``` - -**Note:** This script assumes "VAGRANT_HOME" is set to the CWD. - -## Improving stability - -Occasionally GitHub runner services, or VMs, go down. This is often silent and -usually only noticable from going to the GitHub repo page "settings" -> "actions" -> "runners" and observing the status. -When the VMs or the service stop working they need restarted. -To do so you can sun `./vm_manager.sh`. This will cycle through the VMs and execute a `vagrant up` command. -This does one of three things depending on the state of the VM: - -1. If the VM is down this will bring the VM back online and start the GitHub runner service. -2. If the VM is up but the GitHub runner service is down, this will start the GitHub runner service. -3. If the VM is up and the GitHub runner service is running (i.e., everything is fine) then this does nothing. - -Given there is no harm in running this command frequently, we recommend setting up a cron job to automatically execute `./vm_manager.sh` every few hours. - ## Troubleshooting ### The default libvirt disk image storage pool is on the wrong drive diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 2a891b9688..3446f703dd 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -27,34 +27,39 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +NUM_RUNNERS=0 # Set this to the desired number of runners. PERSONAL_ACCESS_TOKEN="" GITHUB_ORG="" HOSTNAME="" Vagrant.configure("2") do |config| - config.vm.box = "generic/ubuntu2204" - config.vm.box_check_update = true - config.vm.define "#{HOSTNAME}" - config.vm.hostname = "#{HOSTNAME}" config.ssh.username = "vagrant" config.ssh.password = "vagrant" - config.vm.provider "libvirt" do |vb| - # Customize the amount of cpus, memory, and storage on the VM: - vb.cpus = "4".to_i - vb.memory = "16384".to_i - vb.machine_virtual_size = 128 # 128G is the minimum. + (1..NUM_RUNNERS).each do |i| + + config.vm.define "#{HOSTNAME}-#{i}" do |runner| + runner.vm.hostname = "#{HOSTNAME}-#{i}" + runner.vm.box = "generic/ubuntu2204" + runner.vm.box_check_update = true + + runner.vm.provider "libvirt" do |vb| + # Customize the amount of cpus, memory, and storage on the VM: + vb.cpus = "4".to_i + vb.memory = "16384".to_i + vb.machine_virtual_size = 128 # 128G is the minimum. + end + + # sets up vm + runner.vm.provision :shell, path: "provision_root.sh" + runner.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" + # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. + runner.vm.provision :reload + # Copy the "action-run.sh" script from the host to the VM. + runner.vm.provision "file", source: "./action-run.sh", destination: "/tmp/action-run.sh" + runner.vm.provision :shell, privileged: false, inline: "cp /tmp/action-run.sh ." + # Execute the actions-run.sh script on every boot. This configures the and starts the runner. + runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} >> action-run.log 2>&1 &" + end end - - # sets up vm - config.vm.provision :shell, path: "provision_root.sh" - config.vm.provision :shell, privileged: false, path: "provision_nonroot.sh" - # The provision_root.sh adds the vagrant user to the docker group, so we need to reload the VM. - config.vm.provision :reload - # Copy the "action-run.sh" script from the host to the VM. - builder.vm.provision "file", source: "./action-run.sh", destination: "/tmp/action-run.sh" - builder.vm.provision :shell, privileged: false, inline: "cp /tmp/action-run.sh ." - # Execute the actions-run.sh script on every boot. This configures the and starts the runner. - config.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} >> action-run.log 2>&1 &" - end diff --git a/util/github-runners-vagrant/vm_manager.sh b/util/github-runners-vagrant/vm_manager.sh deleted file mode 100755 index 280ee431bc..0000000000 --- a/util/github-runners-vagrant/vm_manager.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2023 The Regents of the University of California -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -NUM_RUNNERS=3 -RUNNER_PREFIX_PREFIX="$(hostname)" - -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -export VAGRANT_HOME=${SCRIPT_DIR} - -param="up" -if [[ $# -ge 1 ]]; then - param=$1 - if [[ "${param}" != "destroy" ]] && [[ "${param}" != "shutdown" ]]; then - echo "Only valid parameters are 'destroy' and 'shutdown' to destroy all VMs or shutdown all VMs" - exit 1 - fi -fi - - -for (( i=1; i<=NUM_RUNNERS; i++ )); do - sed -i "s/HOSTNAME=.*/HOTNAME=\"${RUNNER_PREFIX}-${i}\"/g" Vagrantfile - if [[ "${param}" == "destroy" ]]; then - VAGRANT_VAGRANTFILE=Vagrantfile vagrant destroy -f - elif [[ "${param}" == "shutdown" ]]; then - VAGRANT_VAGRANTFILE=Vagrantfile vagrant halt -f - else - VAGRANT_VAGRANTFILE=Vagrantfile vagrant up --provider=libvirt - fi -done From 53219bf82751db700bf66087b889444126ca187f Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 4 Oct 2023 18:48:55 -0700 Subject: [PATCH 397/693] util: Add Troubleshooting for "Vagrant failed..." Change-Id: I01e637f09084acb6c5fbd7800b3e578a43487849 --- util/github-runners-vagrant/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/util/github-runners-vagrant/README.md b/util/github-runners-vagrant/README.md index ea7fd16957..ca504e3c63 100644 --- a/util/github-runners-vagrant/README.md +++ b/util/github-runners-vagrant/README.md @@ -86,3 +86,15 @@ virsh pool-define default-pool.xml # From here we re-add the default. virsh pool-start default virsh pool-autostart default ``` + +### Error: "Vagrant failed to initialize at a very early stage" + +W set the `VAGRANT_HOME` environment variable to the CWD. +It's likely this has become unset The solution is simple. +Within the directory containing "Vagrantfile": + +```sh +VAGRANT_HOME=`pwd` vagrant +``` + +You may want to set `VAGRANT_HOME` in your .bashrc or .zshrc. From df3bcaf143cfd256399d3f7f6b7e6e664d03a23c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 6 Oct 2023 00:27:23 -0700 Subject: [PATCH 398/693] util: Make all runs "build" and "run" Change-Id: If9ecf467efa5c7118d34166953630e6c436c55a4 --- util/github-runners-vagrant/Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 3446f703dd..7743c3e6a4 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -59,7 +59,7 @@ Vagrant.configure("2") do |config| runner.vm.provision "file", source: "./action-run.sh", destination: "/tmp/action-run.sh" runner.vm.provision :shell, privileged: false, inline: "cp /tmp/action-run.sh ." # Execute the actions-run.sh script on every boot. This configures the and starts the runner. - runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} >> action-run.log 2>&1 &" + runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} "run,build" >> action-run.log 2>&1 &" end end end From a8efded6440aa69de6ea9dbdb7d9deacbca9d60b Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 17 Jul 2023 19:58:08 +0100 Subject: [PATCH 399/693] arch-arm: Include Granule Size in a TLB entry This info can be used during TLB invalidation Change-Id: I81247e40b11745f0207178b52c47845ca1b92870 Signed-off-by: Giacomo Travaglini --- src/arch/arm/pagetable.hh | 7 ++++--- src/arch/arm/table_walker.cc | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh index 8300175144..deaf10df9e 100644 --- a/src/arch/arm/pagetable.hh +++ b/src/arch/arm/pagetable.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013, 2021 Arm Limited + * Copyright (c) 2010, 2012-2013, 2021, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -219,6 +219,7 @@ struct TlbEntry : public Serializable uint16_t asid; // Address Space Identifier vmid_t vmid; // Virtual machine Identifier + GrainSize tg; // Translation Granule Size uint8_t N; // Number of bits in pagesize uint8_t innerAttrs; uint8_t outerAttrs; @@ -263,7 +264,7 @@ struct TlbEntry : public Serializable bool uncacheable, bool read_only) : pfn(_paddr >> PageShift), size(PageBytes - 1), vpn(_vaddr >> PageShift), attributes(0), lookupLevel(LookupLevel::L1), - asid(_asn), vmid(0), N(0), + asid(_asn), vmid(0), tg(Grain4KB), N(0), innerAttrs(0), outerAttrs(0), ap(read_only ? 0x3 : 0), hap(0x3), domain(DomainType::Client), mtype(MemoryType::StronglyOrdered), longDescFormat(false), isHyp(false), global(false), valid(true), @@ -281,7 +282,7 @@ struct TlbEntry : public Serializable TlbEntry() : pfn(0), size(0), vpn(0), attributes(0), lookupLevel(LookupLevel::L1), - asid(0), vmid(0), N(0), + asid(0), vmid(0), tg(ReservedGrain), N(0), innerAttrs(0), outerAttrs(0), ap(0), hap(0x3), domain(DomainType::Client), mtype(MemoryType::StronglyOrdered), longDescFormat(false), isHyp(false), global(false), valid(false), diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 60f9e3f76e..5938755d86 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2019, 2021-2022 Arm Limited + * Copyright (c) 2010, 2012-2019, 2021-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -2305,6 +2305,7 @@ TableWalker::insertPartialTableEntry(LongDescriptor &descriptor) te.asid = currState->asid; te.vmid = currState->vmid; te.N = descriptor.offsetBits(); + te.tg = descriptor.grainSize; te.vpn = currState->vaddr >> te.N; te.size = (1ULL << te.N) - 1; te.pfn = descriptor.nextTableAddr(); @@ -2378,6 +2379,7 @@ TableWalker::insertTableEntry(DescriptorBase &descriptor, bool long_descriptor) LongDescriptor l_descriptor = dynamic_cast(descriptor); + te.tg = l_descriptor.grainSize; te.xn |= currState->xnTable; te.pxn = currState->pxnTable || l_descriptor.pxn(); if (isStage2) { From 6b698630a299c03e83250ac5703e8a87a38d0e03 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 17 Jul 2023 14:40:32 +0100 Subject: [PATCH 400/693] arch-arm: Check VMID in secure mode as well (NS=0) This is still trying to completely remove any artifact which implies virtualization is only supported in non-secure mode (NS=1) Change-Id: I83fed1c33cc745ecdf3c5ad60f4f356f3c58aad5 Signed-off-by: Giacomo Travaglini --- src/arch/arm/pagetable.hh | 4 ++-- src/arch/arm/utility.hh | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh index deaf10df9e..98c5f46a61 100644 --- a/src/arch/arm/pagetable.hh +++ b/src/arch/arm/pagetable.hh @@ -320,8 +320,8 @@ struct TlbEntry : public Serializable if (match && !lookup.ignoreAsn) { match = global || (lookup.asn == asid); } - if (match && nstid) { - match = isHyp || (lookup.vmid == vmid); + if (match && useVMID(lookup.targetEL, lookup.inHost)) { + match = lookup.vmid == vmid; } } return match; diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index d317651db5..c231b93bdb 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -366,6 +366,12 @@ void syncVecElemsToRegs(ThreadContext *tc); bool fgtEnabled(ThreadContext *tc); +static inline bool +useVMID(ExceptionLevel el, bool in_host) +{ + return el == EL1 || (el == EL0 && !in_host); +} + } // namespace ArmISA } // namespace gem5 From 39fdfaea5a775e96a3655f09420c6d5f9367447e Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 12 Jul 2022 18:36:54 +0100 Subject: [PATCH 401/693] arch-arm: Implement FEAT_TLBIRANGE Change-Id: I7eb020573420e49a8a54e1fc7a89eb6e2236dacb Signed-off-by: Giacomo Travaglini --- src/arch/arm/ArmSystem.py | 3 + src/arch/arm/insts/misc64.cc | 350 ++++++++++++++++++++++++++- src/arch/arm/isa/formats/aarch64.isa | 32 ++- src/arch/arm/pagetable.hh | 23 +- src/arch/arm/regs/misc.cc | 107 +++++++- src/arch/arm/regs/misc.hh | 67 +++++ src/arch/arm/tlbi_op.cc | 75 ++++-- src/arch/arm/tlbi_op.hh | 107 +++++++- 8 files changed, 743 insertions(+), 21 deletions(-) diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index 3da9bdadcb..e220f92168 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -89,6 +89,7 @@ class ArmExtension(ScopedEnum): # Armv8.4 "FEAT_SEL2", "FEAT_TLBIOS", + "FEAT_TLBIRANGE", "FEAT_FLAGM", "FEAT_IDST", # Armv8.5 @@ -183,6 +184,7 @@ class ArmDefaultRelease(Armv8): # Armv8.4 "FEAT_SEL2", "FEAT_TLBIOS", + "FEAT_TLBIRANGE", "FEAT_FLAGM", "FEAT_IDST", # Armv8.5 @@ -229,6 +231,7 @@ class Armv84(Armv83): extensions = Armv83.extensions + [ "FEAT_SEL2", "FEAT_TLBIOS", + "FEAT_TLBIRANGE", "FEAT_FLAGM", "FEAT_IDST", ] diff --git a/src/arch/arm/insts/misc64.cc b/src/arch/arm/insts/misc64.cc index 4f573fca83..4919d92da8 100644 --- a/src/arch/arm/insts/misc64.cc +++ b/src/arch/arm/insts/misc64.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013,2017-2022 Arm Limited + * Copyright (c) 2011-2013,2017-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -852,6 +852,354 @@ TlbiOp64::performTlbi(ExecContext *xc, MiscRegIndex dest_idx, RegVal value) cons } return; } + case MISCREG_TLBI_RVAE1_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVA tlbiOp(target_el, secure, value, asid, false); + + if (tlbiOp.valid()) + tlbiOp(tc); + return; + } + case MISCREG_TLBI_RVAE1IS_Xt: + case MISCREG_TLBI_RVAE1OS_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVA tlbiOp(target_el, secure, value, asid, false); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + return; + } + case MISCREG_TLBI_RVAAE1_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVAA tlbiOp(target_el, secure, value, false); + + if (tlbiOp.valid()) + tlbiOp(tc); + return; + } + case MISCREG_TLBI_RVAAE1IS_Xt: + case MISCREG_TLBI_RVAAE1OS_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVAA tlbiOp(target_el, secure, value, false); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + return; + } + case MISCREG_TLBI_RVALE1_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVA tlbiOp(target_el, secure, value, asid, true); + + if (tlbiOp.valid()) + tlbiOp(tc); + return; + } + case MISCREG_TLBI_RVALE1IS_Xt: + case MISCREG_TLBI_RVALE1OS_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVA tlbiOp(target_el, secure, value, asid, true); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + return; + } + case MISCREG_TLBI_RVAALE1_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVAA tlbiOp(target_el, secure, value, true); + + if (tlbiOp.valid()) + tlbiOp(tc); + return; + } + case MISCREG_TLBI_RVAALE1IS_Xt: + case MISCREG_TLBI_RVAALE1OS_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + ExceptionLevel target_el = EL1; + if (EL2Enabled(tc)) { + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (hcr.tge && hcr.e2h) { + target_el = EL2; + } + } + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + TLBIRMVAA tlbiOp(target_el, secure, value, true); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + return; + } + case MISCREG_TLBI_RIPAS2E1_Xt: + { + if (EL2Enabled(tc)) { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + bool secure = release->has(ArmExtension::SECURITY) && + !scr.ns && !bits(value, 63); + + TLBIRIPA tlbiOp(EL1, secure, value, false); + + tlbiOp(tc); + } + return; + } + case MISCREG_TLBI_RIPAS2E1IS_Xt: + { + if (EL2Enabled(tc)) { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + bool secure = release->has(ArmExtension::SECURITY) && + !scr.ns && !bits(value, 63); + + TLBIRIPA tlbiOp(EL1, secure, value, false); + + tlbiOp.broadcast(tc); + } + return; + } + case MISCREG_TLBI_RIPAS2LE1_Xt: + { + if (EL2Enabled(tc)) { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + bool secure = release->has(ArmExtension::SECURITY) && + !scr.ns && !bits(value, 63); + + TLBIRIPA tlbiOp(EL1, secure, value, true); + + tlbiOp(tc); + } + return; + } + case MISCREG_TLBI_RIPAS2LE1IS_Xt: + { + if (EL2Enabled(tc)) { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + bool secure = release->has(ArmExtension::SECURITY) && + !scr.ns && !bits(value, 63); + + TLBIRIPA tlbiOp(EL1, secure, value, true); + + tlbiOp.broadcast(tc); + } + return; + } + case MISCREG_TLBI_RVAE2_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + + if (hcr.e2h) { + // The asid will only be used when e2h == 1 + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + TLBIRMVA tlbiOp(EL2, secure, value, asid, false); + + if (tlbiOp.valid()) + tlbiOp(tc); + } else { + TLBIRMVAA tlbiOp(EL2, secure, value, false); + + if (tlbiOp.valid()) + tlbiOp(tc); + } + return; + } + case MISCREG_TLBI_RVAE2IS_Xt: + case MISCREG_TLBI_RVAE2OS_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + + if (hcr.e2h) { + // The asid will only be used when e2h == 1 + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + TLBIRMVA tlbiOp(EL2, secure, value, asid, false); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + } else { + TLBIRMVAA tlbiOp(EL2, secure, value, false); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + } + return; + } + case MISCREG_TLBI_RVALE2_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + + if (hcr.e2h) { + // The asid will only be used when e2h == 1 + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + TLBIRMVA tlbiOp(EL2, secure, value, asid, true); + + if (tlbiOp.valid()) + tlbiOp(tc); + } else { + TLBIRMVAA tlbiOp(EL2, secure, value, true); + + if (tlbiOp.valid()) + tlbiOp(tc); + } + return; + } + case MISCREG_TLBI_RVALE2IS_Xt: + case MISCREG_TLBI_RVALE2OS_Xt: + { + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + bool secure = release->has(ArmExtension::SECURITY) && !scr.ns; + + if (hcr.e2h) { + // The asid will only be used when e2h == 1 + auto asid = asid_16bits ? bits(value, 63, 48) : + bits(value, 55, 48); + + TLBIRMVA tlbiOp(EL2, secure, value, asid, true); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + } else { + TLBIRMVAA tlbiOp(EL2, secure, value, true); + + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + } + return; + } + case MISCREG_TLBI_RVAE3_Xt: + { + TLBIRMVAA tlbiOp(EL3, true, value, false); + if (tlbiOp.valid()) + tlbiOp(tc); + return; + } + case MISCREG_TLBI_RVAE3IS_Xt: + case MISCREG_TLBI_RVAE3OS_Xt: + { + TLBIRMVAA tlbiOp(EL3, true, value, false); + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + return; + } + case MISCREG_TLBI_RVALE3_Xt: + { + TLBIRMVAA tlbiOp(EL3, true, value, true); + if (tlbiOp.valid()) + tlbiOp(tc); + return; + } + case MISCREG_TLBI_RVALE3IS_Xt: + case MISCREG_TLBI_RVALE3OS_Xt: + { + TLBIRMVAA tlbiOp(EL3, true, value, true); + if (tlbiOp.valid()) + tlbiOp.broadcast(tc); + return; + } default: panic("Invalid TLBI\n"); } diff --git a/src/arch/arm/isa/formats/aarch64.isa b/src/arch/arm/isa/formats/aarch64.isa index 68a741a831..30f9009121 100644 --- a/src/arch/arm/isa/formats/aarch64.isa +++ b/src/arch/arm/isa/formats/aarch64.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 Arm Limited +// Copyright (c) 2011-2023 Arm Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -542,6 +542,16 @@ namespace Aarch64 case MISCREG_TLBI_VAALE1_Xt: case MISCREG_TLBI_IPAS2E1_Xt: case MISCREG_TLBI_IPAS2LE1_Xt: + case MISCREG_TLBI_RVAE1_Xt: + case MISCREG_TLBI_RVAAE1_Xt: + case MISCREG_TLBI_RVALE1_Xt: + case MISCREG_TLBI_RVAALE1_Xt: + case MISCREG_TLBI_RIPAS2E1_Xt: + case MISCREG_TLBI_RIPAS2LE1_Xt: + case MISCREG_TLBI_RVAE2_Xt: + case MISCREG_TLBI_RVALE2_Xt: + case MISCREG_TLBI_RVAE3_Xt: + case MISCREG_TLBI_RVALE3_Xt: return new Tlbi64LocalHub( machInst, miscReg, rt); case MISCREG_TLBI_ALLE3IS: @@ -576,6 +586,26 @@ namespace Aarch64 case MISCREG_TLBI_IPAS2E1OS_Xt: case MISCREG_TLBI_IPAS2LE1IS_Xt: case MISCREG_TLBI_IPAS2LE1OS_Xt: + case MISCREG_TLBI_RVAE1IS_Xt: + case MISCREG_TLBI_RVAE1OS_Xt: + case MISCREG_TLBI_RVAAE1IS_Xt: + case MISCREG_TLBI_RVAAE1OS_Xt: + case MISCREG_TLBI_RVALE1IS_Xt: + case MISCREG_TLBI_RVALE1OS_Xt: + case MISCREG_TLBI_RVAALE1IS_Xt: + case MISCREG_TLBI_RVAALE1OS_Xt: + case MISCREG_TLBI_RIPAS2E1IS_Xt: + case MISCREG_TLBI_RIPAS2E1OS_Xt: + case MISCREG_TLBI_RIPAS2LE1IS_Xt: + case MISCREG_TLBI_RIPAS2LE1OS_Xt: + case MISCREG_TLBI_RVAE2IS_Xt: + case MISCREG_TLBI_RVAE2OS_Xt: + case MISCREG_TLBI_RVALE2IS_Xt: + case MISCREG_TLBI_RVALE2OS_Xt: + case MISCREG_TLBI_RVAE3IS_Xt: + case MISCREG_TLBI_RVAE3OS_Xt: + case MISCREG_TLBI_RVALE3IS_Xt: + case MISCREG_TLBI_RVALE3OS_Xt: return new Tlbi64ShareableHub( machInst, miscReg, rt, dec.dvmEnabled); default: diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh index 98c5f46a61..a1e9028e8f 100644 --- a/src/arch/arm/pagetable.hh +++ b/src/arch/arm/pagetable.hh @@ -186,6 +186,12 @@ struct TlbEntry : public Serializable { // virtual address Addr va = 0; + // lookup size: + // * != 0 -> this is a range based lookup. + // end_address = va + size + // * == 0 -> This is a normal lookup. size should + // be ignored + Addr size = 0; // context id/address space id to use uint16_t asn = 0; // if on lookup asn should be ignored @@ -307,12 +313,25 @@ struct TlbEntry : public Serializable return pfn << PageShift; } + bool + matchAddress(const Lookup &lookup) const + { + Addr page_addr = vpn << N; + if (lookup.size) { + // This is a range based loookup + return lookup.va <= page_addr + size && + lookup.va + lookup.size > page_addr; + } else { + // This is a normal lookup + return lookup.va >= page_addr && lookup.va <= page_addr + size; + } + } + bool match(const Lookup &lookup) const { bool match = false; - Addr v = vpn << N; - if (valid && lookup.va >= v && lookup.va <= v + size && + if (valid && matchAddress(lookup) && (lookup.secure == !nstid) && (lookup.hyp == isHyp)) { match = checkELMatch(lookup.targetEL, lookup.inHost); diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 25993829a3..57d0de1686 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -759,12 +759,24 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(1, 0, 8, 1, 3), MISCREG_TLBI_VAAE1OS_Xt }, { MiscRegNum64(1, 0, 8, 1, 5), MISCREG_TLBI_VALE1OS_Xt }, { MiscRegNum64(1, 0, 8, 1, 7), MISCREG_TLBI_VAALE1OS_Xt }, + { MiscRegNum64(1, 0, 8, 2, 1), MISCREG_TLBI_RVAE1IS_Xt }, + { MiscRegNum64(1, 0, 8, 2, 3), MISCREG_TLBI_RVAAE1IS_Xt }, + { MiscRegNum64(1, 0, 8, 2, 5), MISCREG_TLBI_RVALE1IS_Xt }, + { MiscRegNum64(1, 0, 8, 2, 7), MISCREG_TLBI_RVAALE1IS_Xt }, { MiscRegNum64(1, 0, 8, 3, 0), MISCREG_TLBI_VMALLE1IS }, { MiscRegNum64(1, 0, 8, 3, 1), MISCREG_TLBI_VAE1IS_Xt }, { MiscRegNum64(1, 0, 8, 3, 2), MISCREG_TLBI_ASIDE1IS_Xt }, { MiscRegNum64(1, 0, 8, 3, 3), MISCREG_TLBI_VAAE1IS_Xt }, { MiscRegNum64(1, 0, 8, 3, 5), MISCREG_TLBI_VALE1IS_Xt }, { MiscRegNum64(1, 0, 8, 3, 7), MISCREG_TLBI_VAALE1IS_Xt }, + { MiscRegNum64(1, 0, 8, 5, 1), MISCREG_TLBI_RVAE1OS_Xt }, + { MiscRegNum64(1, 0, 8, 5, 3), MISCREG_TLBI_RVAAE1OS_Xt }, + { MiscRegNum64(1, 0, 8, 5, 5), MISCREG_TLBI_RVALE1OS_Xt }, + { MiscRegNum64(1, 0, 8, 5, 7), MISCREG_TLBI_RVAALE1OS_Xt }, + { MiscRegNum64(1, 0, 8, 6, 1), MISCREG_TLBI_RVAE1_Xt }, + { MiscRegNum64(1, 0, 8, 6, 3), MISCREG_TLBI_RVAAE1_Xt }, + { MiscRegNum64(1, 0, 8, 6, 5), MISCREG_TLBI_RVALE1_Xt }, + { MiscRegNum64(1, 0, 8, 6, 7), MISCREG_TLBI_RVAALE1_Xt }, { MiscRegNum64(1, 0, 8, 7, 0), MISCREG_TLBI_VMALLE1 }, { MiscRegNum64(1, 0, 8, 7, 1), MISCREG_TLBI_VAE1_Xt }, { MiscRegNum64(1, 0, 8, 7, 2), MISCREG_TLBI_ASIDE1_Xt }, @@ -783,12 +795,16 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(1, 4, 7, 8, 6), MISCREG_AT_S12E0R_Xt }, { MiscRegNum64(1, 4, 7, 8, 7), MISCREG_AT_S12E0W_Xt }, { MiscRegNum64(1, 4, 8, 0, 1), MISCREG_TLBI_IPAS2E1IS_Xt }, + { MiscRegNum64(1, 4, 8, 0, 2), MISCREG_TLBI_RIPAS2E1IS_Xt }, { MiscRegNum64(1, 4, 8, 0, 5), MISCREG_TLBI_IPAS2LE1IS_Xt }, { MiscRegNum64(1, 4, 8, 1, 0), MISCREG_TLBI_ALLE2OS }, { MiscRegNum64(1, 4, 8, 1, 1), MISCREG_TLBI_VAE2OS_Xt }, { MiscRegNum64(1, 4, 8, 1, 4), MISCREG_TLBI_ALLE1OS }, { MiscRegNum64(1, 4, 8, 1, 5), MISCREG_TLBI_VALE2OS_Xt }, { MiscRegNum64(1, 4, 8, 1, 6), MISCREG_TLBI_VMALLS12E1OS }, + { MiscRegNum64(1, 4, 8, 0, 6), MISCREG_TLBI_RIPAS2LE1IS_Xt }, + { MiscRegNum64(1, 4, 8, 2, 1), MISCREG_TLBI_RVAE2IS_Xt }, + { MiscRegNum64(1, 4, 8, 2, 5), MISCREG_TLBI_RVALE2IS_Xt }, { MiscRegNum64(1, 4, 8, 3, 0), MISCREG_TLBI_ALLE2IS }, { MiscRegNum64(1, 4, 8, 3, 1), MISCREG_TLBI_VAE2IS_Xt }, { MiscRegNum64(1, 4, 8, 3, 4), MISCREG_TLBI_ALLE1IS }, @@ -796,8 +812,16 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(1, 4, 8, 3, 6), MISCREG_TLBI_VMALLS12E1IS }, { MiscRegNum64(1, 4, 8, 4, 0), MISCREG_TLBI_IPAS2E1OS_Xt }, { MiscRegNum64(1, 4, 8, 4, 1), MISCREG_TLBI_IPAS2E1_Xt }, + { MiscRegNum64(1, 4, 8, 4, 2), MISCREG_TLBI_RIPAS2E1_Xt }, + { MiscRegNum64(1, 4, 8, 4, 3), MISCREG_TLBI_RIPAS2E1OS_Xt }, { MiscRegNum64(1, 4, 8, 4, 4), MISCREG_TLBI_IPAS2LE1OS_Xt }, { MiscRegNum64(1, 4, 8, 4, 5), MISCREG_TLBI_IPAS2LE1_Xt }, + { MiscRegNum64(1, 4, 8, 4, 6), MISCREG_TLBI_RIPAS2LE1_Xt }, + { MiscRegNum64(1, 4, 8, 4, 7), MISCREG_TLBI_RIPAS2LE1OS_Xt }, + { MiscRegNum64(1, 4, 8, 5, 1), MISCREG_TLBI_RVAE2OS_Xt }, + { MiscRegNum64(1, 4, 8, 5, 5), MISCREG_TLBI_RVALE2OS_Xt }, + { MiscRegNum64(1, 4, 8, 6, 1), MISCREG_TLBI_RVAE2_Xt }, + { MiscRegNum64(1, 4, 8, 6, 5), MISCREG_TLBI_RVALE2_Xt }, { MiscRegNum64(1, 4, 8, 7, 0), MISCREG_TLBI_ALLE2 }, { MiscRegNum64(1, 4, 8, 7, 1), MISCREG_TLBI_VAE2_Xt }, { MiscRegNum64(1, 4, 8, 7, 4), MISCREG_TLBI_ALLE1 }, @@ -808,9 +832,15 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(1, 6, 8, 1, 0), MISCREG_TLBI_ALLE3OS }, { MiscRegNum64(1, 6, 8, 1, 1), MISCREG_TLBI_VAE3OS_Xt }, { MiscRegNum64(1, 6, 8, 1, 5), MISCREG_TLBI_VALE3OS_Xt }, + { MiscRegNum64(1, 6, 8, 2, 1), MISCREG_TLBI_RVAE3IS_Xt }, + { MiscRegNum64(1, 6, 8, 2, 5), MISCREG_TLBI_RVALE3IS_Xt }, { MiscRegNum64(1, 6, 8, 3, 0), MISCREG_TLBI_ALLE3IS }, { MiscRegNum64(1, 6, 8, 3, 1), MISCREG_TLBI_VAE3IS_Xt }, { MiscRegNum64(1, 6, 8, 3, 5), MISCREG_TLBI_VALE3IS_Xt }, + { MiscRegNum64(1, 6, 8, 5, 1), MISCREG_TLBI_RVAE3OS_Xt }, + { MiscRegNum64(1, 6, 8, 5, 5), MISCREG_TLBI_RVALE3OS_Xt }, + { MiscRegNum64(1, 6, 8, 6, 1), MISCREG_TLBI_RVAE3_Xt }, + { MiscRegNum64(1, 6, 8, 6, 5), MISCREG_TLBI_RVALE3_Xt }, { MiscRegNum64(1, 6, 8, 7, 0), MISCREG_TLBI_ALLE3 }, { MiscRegNum64(1, 6, 8, 7, 1), MISCREG_TLBI_VAE3_Xt }, { MiscRegNum64(1, 6, 8, 7, 5), MISCREG_TLBI_VALE3_Xt }, @@ -4276,7 +4306,9 @@ ISA::initializeMiscRegMetadata() isar0_el1.atomic = release->has(ArmExtension::FEAT_LSE) ? 0x2 : 0x0; isar0_el1.rdm = release->has(ArmExtension::FEAT_RDM) ? 0x1 : 0x0; isar0_el1.tme = release->has(ArmExtension::TME) ? 0x1 : 0x0; - isar0_el1.tlb = release->has(ArmExtension::FEAT_TLBIOS) ? 0x1 : 0x0; + isar0_el1.tlb = release->has(ArmExtension::FEAT_TLBIRANGE) ? + 0x2 : release->has(ArmExtension::FEAT_TLBIOS) ? + 0x1 : 0x0; isar0_el1.ts = release->has(ArmExtension::FEAT_FLAGM2) ? 0x2 : release->has(ArmExtension::FEAT_FLAGM) ? 0x1 : 0x0; @@ -4889,6 +4921,79 @@ ISA::initializeMiscRegMetadata() .monSecureWrite().monNonSecureWrite(); InitReg(MISCREG_TLBI_VALE3_Xt) .monSecureWrite().monNonSecureWrite(); + + InitReg(MISCREG_TLBI_RVAE1_Xt) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvae1>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVAAE1_Xt) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvaae1>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVALE1_Xt) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvale1>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVAALE1_Xt) + .faultWrite(EL1, faultHcrFgtInstEL1<&HCR::ttlb, &HFGITR::tlbirvaale1>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RIPAS2E1_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RIPAS2LE1_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVAE2_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVALE2_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVAE3_Xt) + .monWrite(); + InitReg(MISCREG_TLBI_RVALE3_Xt) + .monWrite(); + InitReg(MISCREG_TLBI_RVAE1IS_Xt) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvae1is>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVAAE1IS_Xt) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvaae1is>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVALE1IS_Xt) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvale1is>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVAALE1IS_Xt) + .faultWrite(EL1, faultTlbiIsEL1<&HFGITR::tlbirvaale1is>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RIPAS2E1IS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RIPAS2LE1IS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVAE2IS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVALE2IS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVAE3IS_Xt) + .monWrite(); + InitReg(MISCREG_TLBI_RVALE3IS_Xt) + .monWrite(); + InitReg(MISCREG_TLBI_RVAE1OS_Xt) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvae1os>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVAAE1OS_Xt) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvaae1os>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVALE1OS_Xt) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvale1os>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RVAALE1OS_Xt) + .faultWrite(EL1, faultTlbiOsEL1<&HFGITR::tlbirvaale1os>) + .writes(1).exceptUserMode(); + InitReg(MISCREG_TLBI_RIPAS2E1OS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RIPAS2LE1OS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVAE2OS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVALE2OS_Xt) + .hypWrite().monWrite(); + InitReg(MISCREG_TLBI_RVAE3OS_Xt) + .monWrite(); + InitReg(MISCREG_TLBI_RVALE3OS_Xt) + .monWrite(); InitReg(MISCREG_PMINTENSET_EL1) .allPrivileges().exceptUserMode() .mapsTo(MISCREG_PMINTENSET); diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index 2077040e57..b6aaee0d2f 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -729,6 +729,36 @@ namespace ArmISA MISCREG_TLBI_ALLE3, MISCREG_TLBI_VAE3_Xt, MISCREG_TLBI_VALE3_Xt, + MISCREG_TLBI_RVAE1_Xt, + MISCREG_TLBI_RVAAE1_Xt, + MISCREG_TLBI_RVALE1_Xt, + MISCREG_TLBI_RVAALE1_Xt, + MISCREG_TLBI_RIPAS2E1_Xt, + MISCREG_TLBI_RIPAS2LE1_Xt, + MISCREG_TLBI_RVAE2_Xt, + MISCREG_TLBI_RVALE2_Xt, + MISCREG_TLBI_RVAE3_Xt, + MISCREG_TLBI_RVALE3_Xt, + MISCREG_TLBI_RVAE1IS_Xt, + MISCREG_TLBI_RVAAE1IS_Xt, + MISCREG_TLBI_RVALE1IS_Xt, + MISCREG_TLBI_RVAALE1IS_Xt, + MISCREG_TLBI_RIPAS2E1IS_Xt, + MISCREG_TLBI_RIPAS2LE1IS_Xt, + MISCREG_TLBI_RVAE2IS_Xt, + MISCREG_TLBI_RVALE2IS_Xt, + MISCREG_TLBI_RVAE3IS_Xt, + MISCREG_TLBI_RVALE3IS_Xt, + MISCREG_TLBI_RVAE1OS_Xt, + MISCREG_TLBI_RVAAE1OS_Xt, + MISCREG_TLBI_RVALE1OS_Xt, + MISCREG_TLBI_RVAALE1OS_Xt, + MISCREG_TLBI_RIPAS2E1OS_Xt, + MISCREG_TLBI_RIPAS2LE1OS_Xt, + MISCREG_TLBI_RVAE2OS_Xt, + MISCREG_TLBI_RVALE2OS_Xt, + MISCREG_TLBI_RVAE3OS_Xt, + MISCREG_TLBI_RVALE3OS_Xt, MISCREG_PMINTENSET_EL1, MISCREG_PMINTENCLR_EL1, MISCREG_PMCR_EL0, @@ -1503,6 +1533,13 @@ namespace ArmISA return *this; } chain + monWrite(bool v = true) const + { + monSecureWrite(v); + monNonSecureWrite(v); + return *this; + } + chain monSecure(bool v = true) const { monSecureRead(v); @@ -2411,6 +2448,36 @@ namespace ArmISA "tlbi_alle3", "tlbi_vae3_xt", "tlbi_vale3_xt", + "tlbi_rvae1_xt", + "tlbi_rvaae1_xt", + "tlbi_rvale1_xt", + "tlbi_rvaale1_xt", + "tlbi_ripas2e1_xt", + "tlbi_ripas2le1_xt", + "tlbi_rvae2_xt", + "tlbi_rvale2_xt", + "tlbi_rvae3_xt", + "tlbi_rvale3_xt", + "tlbi_rvae1is_xt", + "tlbi_rvaae1is_xt", + "tlbi_rvale1is_xt", + "tlbi_rvaale1is_xt", + "tlbi_ripas2e1is_xt", + "tlbi_ripas2le1is_xt", + "tlbi_rvae2is_xt", + "tlbi_rvale2is_xt", + "tlbi_rvae3is_xt", + "tlbi_rvale3is_xt", + "tlbi_rvae1os_xt", + "tlbi_rvaae1os_xt", + "tlbi_rvale1os_xt", + "tlbi_rvaale1os_xt", + "tlbi_ripas2e1os_xt", + "tlbi_ripas2le1os_xt", + "tlbi_rvae2os_xt", + "tlbi_rvale2os_xt", + "tlbi_rvae3os_xt", + "tlbi_rvale3os_xt", "pmintenset_el1", "pmintenclr_el1", "pmcr_el0", diff --git a/src/arch/arm/tlbi_op.cc b/src/arch/arm/tlbi_op.cc index e89f411384..b49139bf3e 100644 --- a/src/arch/arm/tlbi_op.cc +++ b/src/arch/arm/tlbi_op.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2022 Arm Limited + * Copyright (c) 2018-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -209,6 +209,22 @@ TLBIALLN::match(TlbEntry* te, vmid_t vmid) const te->checkELMatch(targetEL, false); } +TlbEntry::Lookup +TLBIMVAA::lookupGen(vmid_t vmid) const +{ + TlbEntry::Lookup lookup_data; + lookup_data.va = sext<56>(addr); + lookup_data.ignoreAsn = true; + lookup_data.vmid = vmid; + lookup_data.hyp = targetEL == EL2; + lookup_data.secure = secureLookup; + lookup_data.functional = true; + lookup_data.targetEL = targetEL; + lookup_data.inHost = inHost; + lookup_data.mode = BaseMMU::Read; + return lookup_data; +} + void TLBIMVAA::operator()(ThreadContext* tc) { @@ -224,10 +240,19 @@ TLBIMVAA::operator()(ThreadContext* tc) bool TLBIMVAA::match(TlbEntry* te, vmid_t vmid) const +{ + TlbEntry::Lookup lookup_data = lookupGen(vmid); + + return te->match(lookup_data) && (!lastLevel || !te->partial); +} + +TlbEntry::Lookup +TLBIMVA::lookupGen(vmid_t vmid) const { TlbEntry::Lookup lookup_data; lookup_data.va = sext<56>(addr); - lookup_data.ignoreAsn = true; + lookup_data.asn = asid; + lookup_data.ignoreAsn = false; lookup_data.vmid = vmid; lookup_data.hyp = targetEL == EL2; lookup_data.secure = secureLookup; @@ -236,7 +261,7 @@ TLBIMVAA::match(TlbEntry* te, vmid_t vmid) const lookup_data.inHost = inHost; lookup_data.mode = BaseMMU::Read; - return te->match(lookup_data) && (!lastLevel || !te->partial); + return lookup_data; } void @@ -255,17 +280,7 @@ TLBIMVA::operator()(ThreadContext* tc) bool TLBIMVA::match(TlbEntry* te, vmid_t vmid) const { - TlbEntry::Lookup lookup_data; - lookup_data.va = sext<56>(addr); - lookup_data.asn = asid; - lookup_data.ignoreAsn = false; - lookup_data.vmid = vmid; - lookup_data.hyp = targetEL == EL2; - lookup_data.secure = secureLookup; - lookup_data.functional = true; - lookup_data.targetEL = targetEL; - lookup_data.inHost = inHost; - lookup_data.mode = BaseMMU::Read; + TlbEntry::Lookup lookup_data = lookupGen(vmid); return te->match(lookup_data) && (!lastLevel || !te->partial); } @@ -305,5 +320,37 @@ TLBIIPA::operator()(ThreadContext* tc) } } +bool +TLBIRMVA::match(TlbEntry* te, vmid_t vmid) const +{ + TlbEntry::Lookup lookup_data = lookupGen(vmid); + lookup_data.size = rangeSize(); + + auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial); + if (addr_match) { + return tgMap[rangeData.tg] == te->tg && + (resTLBIttl(rangeData.tg, rangeData.ttl) || + rangeData.ttl == te->lookupLevel); + } else { + return false; + } +} + +bool +TLBIRMVAA::match(TlbEntry* te, vmid_t vmid) const +{ + TlbEntry::Lookup lookup_data = lookupGen(vmid); + lookup_data.size = rangeSize(); + + auto addr_match = te->match(lookup_data) && (!lastLevel || !te->partial); + if (addr_match) { + return tgMap[rangeData.tg] == te->tg && + (resTLBIttl(rangeData.tg, rangeData.ttl) || + rangeData.ttl == te->lookupLevel); + } else { + return false; + } +} + } // namespace ArmISA } // namespace gem5 diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh index 4f4ea09ec8..38e8252869 100644 --- a/src/arch/arm/tlbi_op.hh +++ b/src/arch/arm/tlbi_op.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, 2022 Arm Limited + * Copyright (c) 2018-2020, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -300,6 +300,8 @@ class TLBIALLN : public TLBIOp /** TLB Invalidate by VA, All ASID */ class TLBIMVAA : public TLBIOp { + protected: + TlbEntry::Lookup lookupGen(vmid_t vmid) const; public: TLBIMVAA(ExceptionLevel _targetEL, bool _secure, Addr _addr, bool last_level) @@ -319,6 +321,9 @@ class TLBIMVAA : public TLBIOp /** TLB Invalidate by VA */ class TLBIMVA : public TLBIOp { + protected: + TlbEntry::Lookup lookupGen(vmid_t vmid) const; + public: TLBIMVA(ExceptionLevel _targetEL, bool _secure, Addr _addr, uint16_t _asid, bool last_level) @@ -368,6 +373,61 @@ class DTLBIMVA : public TLBIMVA bool match(TlbEntry *entry, vmid_t curr_vmid) const override; }; +class TLBIRange +{ + public: + /** + * Is the range valid? This mainly depends on the specified + * translation granule. + */ + bool valid() const { return granule != ReservedGrain; } + + protected: + BitUnion64(RangeData) + Bitfield<47, 46> tg; + Bitfield<45, 44> scale; + Bitfield<43, 39> num; + Bitfield<38, 37> ttl; + Bitfield<36, 0> baseAddr; + EndBitUnion(RangeData) + + static constexpr std::array tgMap = { + ReservedGrain, + Grain4KB, + Grain16KB, + Grain64KB + }; + + TLBIRange(RegVal val) + : rangeData(val), granule(tgMap[rangeData.tg]) + {} + + Addr + startAddress() const + { + return sext<37>(rangeData.baseAddr) << granule; + } + + Addr + rangeSize() const + { + return (rangeData.num + 1) << (5 * rangeData.scale + 1 + granule); + } + + bool + resTLBIttl(uint8_t tg, uint8_t ttl) const + { + switch (ttl) { + case 0: return true; + case 1: return tgMap[tg] == Grain16KB; + default: return false; + } + } + + RangeData rangeData; + GrainSize granule; +}; + /** TLB Invalidate by Intermediate Physical Address */ class TLBIIPA : public TLBIOp { @@ -392,7 +452,7 @@ class TLBIIPA : public TLBIOp } /** TLBIIPA is basically a TLBIMVAA for stage2 TLBs */ - TLBIMVAA + virtual TLBIMVAA makeStage2() const { return TLBIMVAA(EL1, secureLookup, addr, lastLevel); @@ -402,6 +462,49 @@ class TLBIIPA : public TLBIOp bool lastLevel; }; +/** TLB Range Invalidate by VA */ +class TLBIRMVA : public TLBIRange, public TLBIMVA +{ + public: + TLBIRMVA(ExceptionLevel _targetEL, bool _secure, + RegVal val, uint16_t _asid, bool last_level) + : TLBIRange(val), + TLBIMVA(_targetEL, _secure, startAddress(), _asid, last_level) + {} + + bool match(TlbEntry *entry, vmid_t curr_vmid) const override; +}; + +/** TLB Range Invalidate by VA, All ASIDs */ +class TLBIRMVAA : public TLBIRange, public TLBIMVAA +{ + public: + TLBIRMVAA(ExceptionLevel _targetEL, bool _secure, + RegVal val, bool last_level) + : TLBIRange(val), + TLBIMVAA(_targetEL, _secure, startAddress(), last_level) + {} + + bool match(TlbEntry *entry, vmid_t curr_vmid) const override; +}; + +/** TLB Range Invalidate by VA, All ASIDs */ +class TLBIRIPA : public TLBIRange, public TLBIIPA +{ + public: + TLBIRIPA(ExceptionLevel _targetEL, bool _secure, + RegVal val, bool last_level) + : TLBIRange(val), + TLBIIPA(_targetEL, _secure, startAddress(), last_level) + {} + + virtual TLBIMVAA + makeStage2() const + { + return TLBIRMVAA(EL1, secureLookup, rangeData, lastLevel); + } +}; + } // namespace ArmISA } // namespace gem5 From edf9092feeb8b92c605fb1fc7a6e7f5486327509 Mon Sep 17 00:00:00 2001 From: David Schall Date: Sat, 7 Oct 2023 17:26:16 +0000 Subject: [PATCH 402/693] cpu: Restructure BTB - A new abstract BTB class is created to enable different BTB implementations. The new BTB class gets its own parameter and stats. - An enum is added to differentiate branch instruction types. This enum is used to enhance statistics and BPU management. - The existing BTB is moved into `simple_btb` as default. - An additional function is added to store the static instruction in the BTB. This function is used for the decoupled front-end. - Update configs to match new BTB parameters. Change-Id: I99b29a19a1b57e59ea2b188ed7d62a8b79426529 Signed-off-by: David Schall --- configs/common/cores/arm/HPI.py | 8 +- configs/common/cores/arm/O3_ARM_v7a.py | 8 +- configs/common/cores/arm/ex5_big.py | 8 +- src/cpu/pred/BranchPredictor.py | 57 +++++- src/cpu/pred/SConscript | 31 ++- src/cpu/pred/bpred_unit.cc | 17 +- src/cpu/pred/bpred_unit.hh | 22 ++- src/cpu/pred/branch_type.hh | 91 +++++++++ src/cpu/pred/btb.cc | 160 ++++++---------- src/cpu/pred/btb.hh | 136 +++++++------- src/cpu/pred/simple_btb.cc | 176 ++++++++++++++++++ src/cpu/pred/simple_btb.hh | 136 ++++++++++++++ .../riscvmatched/riscvmatched_core.py | 2 +- 13 files changed, 646 insertions(+), 206 deletions(-) create mode 100644 src/cpu/pred/branch_type.hh create mode 100644 src/cpu/pred/simple_btb.cc create mode 100644 src/cpu/pred/simple_btb.hh diff --git a/configs/common/cores/arm/HPI.py b/configs/common/cores/arm/HPI.py index d3d46054f1..cebd91cc72 100644 --- a/configs/common/cores/arm/HPI.py +++ b/configs/common/cores/arm/HPI.py @@ -1679,7 +1679,13 @@ class HPI_MMU(ArmMMU): dtb = ArmTLB(entry_type="data", size=256) +class HPI_BTB(SimpleBTB): + numEntries = 128 + tagBits = 18 + + class HPI_BP(TournamentBP): + btb = HPI_BTB() localPredictorSize = 64 localCtrBits = 2 localHistoryTableSize = 64 @@ -1687,8 +1693,6 @@ class HPI_BP(TournamentBP): globalCtrBits = 2 choicePredictorSize = 1024 choiceCtrBits = 2 - BTBEntries = 128 - BTBTagSize = 18 RASSize = 8 instShiftAmt = 2 diff --git a/configs/common/cores/arm/O3_ARM_v7a.py b/configs/common/cores/arm/O3_ARM_v7a.py index 6a1734235a..8c25b82496 100644 --- a/configs/common/cores/arm/O3_ARM_v7a.py +++ b/configs/common/cores/arm/O3_ARM_v7a.py @@ -107,14 +107,18 @@ class O3_ARM_v7a_FUP(FUPool): ] +class O3_ARM_v7a_BTB(SimpleBTB): + numEntries = 2048 + tagBits = 18 + + # Bi-Mode Branch Predictor class O3_ARM_v7a_BP(BiModeBP): + btb = O3_ARM_v7a_BTB() globalPredictorSize = 8192 globalCtrBits = 2 choicePredictorSize = 8192 choiceCtrBits = 2 - BTBEntries = 2048 - BTBTagSize = 18 RASSize = 16 instShiftAmt = 2 diff --git a/configs/common/cores/arm/ex5_big.py b/configs/common/cores/arm/ex5_big.py index 0d4d4903cf..3272ca4676 100644 --- a/configs/common/cores/arm/ex5_big.py +++ b/configs/common/cores/arm/ex5_big.py @@ -104,14 +104,18 @@ class ex5_big_FUP(FUPool): ] +class ex5_big_BTB(SimpleBTB): + numEntries = 4096 + tagBits = 18 + + # Bi-Mode Branch Predictor class ex5_big_BP(BiModeBP): + btb = ex5_big_BTB() globalPredictorSize = 4096 globalCtrBits = 2 choicePredictorSize = 1024 choiceCtrBits = 3 - BTBEntries = 4096 - BTBTagSize = 18 RASSize = 48 instShiftAmt = 2 diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index d18ca3f821..3bf5e52ae0 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -1,3 +1,15 @@ +# Copyright (c) 2022-2023 The University of Edinburgh +# 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) 2012 Mark D. Hill and David A. Wood # Copyright (c) 2015 The University of Wisconsin # All rights reserved. @@ -25,10 +37,46 @@ # (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.SimObject import SimObject +from m5.SimObject import * from m5.params import * from m5.proxy import * +from m5.objects.ClockedObject import ClockedObject + + +class BranchType(Enum): + vals = [ + "NoBranch", + "Return", + "CallDirect", + "CallIndirect", # 'Call', + "DirectCond", + "DirectUncond", # 'Direct', + "IndirectCond", + "IndirectUncond", #'Indirect', + ] + + +class BranchTargetBuffer(ClockedObject): + type = "BranchTargetBuffer" + cxx_class = "gem5::branch_prediction::BranchTargetBuffer" + cxx_header = "cpu/pred/btb.hh" + abstract = True + + numThreads = Param.Unsigned(Parent.numThreads, "Number of threads") + + +class SimpleBTB(BranchTargetBuffer): + type = "SimpleBTB" + cxx_class = "gem5::branch_prediction::SimpleBTB" + cxx_header = "cpu/pred/simple_btb.hh" + + numEntries = Param.Unsigned(4096, "Number of BTB entries") + tagBits = Param.Unsigned(16, "Size of the BTB tags, in bits") + instShiftAmt = Param.Unsigned( + Parent.instShiftAmt, "Number of bits to shift instructions by" + ) + class IndirectPredictor(SimObject): type = "IndirectPredictor" @@ -63,11 +111,12 @@ class BranchPredictor(SimObject): abstract = True numThreads = Param.Unsigned(Parent.numThreads, "Number of threads") - BTBEntries = Param.Unsigned(4096, "Number of BTB entries") - BTBTagSize = Param.Unsigned(16, "Size of the BTB tags, in bits") - RASSize = Param.Unsigned(16, "RAS size") instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") + RASSize = Param.Unsigned(16, "RAS size") + + btb = Param.BranchTargetBuffer(SimpleBTB(), "Branch target buffer (BTB)") + indirectBranchPred = Param.IndirectPredictor( SimpleIndirectPredictor(), "Indirect branch predictor, set to NULL to disable indirect predictions", diff --git a/src/cpu/pred/SConscript b/src/cpu/pred/SConscript index f4b6870ec5..89054ba8e8 100644 --- a/src/cpu/pred/SConscript +++ b/src/cpu/pred/SConscript @@ -1,5 +1,17 @@ # -*- mode:python -*- +# Copyright (c) 2022-2023 The University of Edinburgh +# 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) 2006 The Regents of The University of Michigan # All rights reserved. # @@ -28,8 +40,12 @@ Import('*') -SimObject('BranchPredictor.py', sim_objects=[ - 'IndirectPredictor', 'SimpleIndirectPredictor', 'BranchPredictor', + +SimObject('BranchPredictor.py', + sim_objects=[ + 'BranchPredictor', + 'IndirectPredictor', 'SimpleIndirectPredictor', + 'BranchTargetBuffer', 'SimpleBTB', 'LocalBP', 'TournamentBP', 'BiModeBP', 'TAGEBase', 'TAGE', 'LoopPredictor', 'TAGE_SC_L_TAGE', 'TAGE_SC_L_TAGE_64KB', 'TAGE_SC_L_TAGE_8KB', 'LTAGE', 'TAGE_SC_L_LoopPredictor', 'StatisticalCorrector', 'TAGE_SC_L', @@ -41,17 +57,16 @@ SimObject('BranchPredictor.py', sim_objects=[ 'MultiperspectivePerceptronTAGE', 'MPP_StatisticalCorrector_64KB', 'MultiperspectivePerceptronTAGE64KB', 'MPP_TAGE_8KB', 'MPP_LoopPredictor_8KB', 'MPP_StatisticalCorrector_8KB', - 'MultiperspectivePerceptronTAGE8KB']) + 'MultiperspectivePerceptronTAGE8KB'], + enums=['BranchType']) -DebugFlag('Indirect') Source('bpred_unit.cc') Source('2bit_local.cc') -Source('btb.cc') Source('simple_indirect.cc') Source('indirect.cc') Source('ras.cc') Source('tournament.cc') -Source ('bi_mode.cc') +Source('bi_mode.cc') Source('tage_base.cc') Source('tage.cc') Source('loop_predictor.cc') @@ -66,6 +81,10 @@ Source('statistical_corrector.cc') Source('tage_sc_l.cc') Source('tage_sc_l_8KB.cc') Source('tage_sc_l_64KB.cc') +Source('btb.cc') +Source('simple_btb.cc') +DebugFlag('Indirect') +DebugFlag('BTB') DebugFlag('FreeList') DebugFlag('Branch') DebugFlag('Tage') diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index ed8d6c8b08..85cb7c9e2f 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2012, 2014 ARM Limited - * Copyright (c) 2010 The University of Edinburgh + * Copyright (c) 2010,2022-2023 The University of Edinburgh * Copyright (c) 2012 Mark D. Hill and David A. Wood * All rights reserved * @@ -59,10 +59,7 @@ BPredUnit::BPredUnit(const Params ¶ms) : SimObject(params), numThreads(params.numThreads), predHist(numThreads), - BTB(params.BTBEntries, - params.BTBTagSize, - params.instShiftAmt, - params.numThreads), + btb(params.btb), RAS(numThreads), iPred(params.indirectBranchPred), stats(this), @@ -218,10 +215,13 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, if (inst->isDirectCtrl() || !iPred) { ++stats.BTBLookups; // Check BTB on direct branches - if (BTB.valid(pc.instAddr(), tid)) { + const PCStateBase * btb_target = btb->lookup(tid, + pc.instAddr(), + getBranchType(inst)); + if (btb_target) { ++stats.BTBHits; // If it's not a return, use the BTB to get target addr. - set(target, BTB.lookup(pc.instAddr(), tid)); + set(target, btb_target); DPRINTF(Branch, "[tid:%i] [sn:%llu] Instruction %s predicted " "target is %s\n", @@ -482,7 +482,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, hist_it->seqNum, hist_it->pc); ++stats.BTBUpdates; - BTB.update(hist_it->pc, corr_target, tid); + btb->update(tid, hist_it->pc, corr_target, + getBranchType(hist_it->inst)); } } else { //Actually not Taken diff --git a/src/cpu/pred/bpred_unit.hh b/src/cpu/pred/bpred_unit.hh index 4af1d876a8..1b10d44a7c 100644 --- a/src/cpu/pred/bpred_unit.hh +++ b/src/cpu/pred/bpred_unit.hh @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2012, 2014 ARM Limited - * Copyright (c) 2010 The University of Edinburgh + * Copyright (c) 2010,2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -46,6 +46,7 @@ #include "base/statistics.hh" #include "base/types.hh" +#include "cpu/pred/branch_type.hh" #include "cpu/pred/btb.hh" #include "cpu/pred/indirect.hh" #include "cpu/pred/ras.hh" @@ -152,7 +153,14 @@ class BPredUnit : public SimObject * @param inst_PC The PC to look up. * @return Whether the BTB contains the given PC. */ - bool BTBValid(Addr instPC) { return BTB.valid(instPC, 0); } + bool BTBValid(ThreadID tid, Addr instPC) + { + return btb->valid(tid, instPC); + } + bool BTBValid(ThreadID tid, PCStateBase &instPC) + { + return BTBValid(tid, instPC.instAddr()); + } /** * Looks up a given PC in the BTB to get the predicted target. The PC may @@ -162,9 +170,9 @@ class BPredUnit : public SimObject * @return The address of the target of the branch. */ const PCStateBase * - BTBLookup(Addr inst_pc) + BTBLookup(ThreadID tid, PCStateBase &instPC) { - return BTB.lookup(inst_pc, 0); + return btb->lookup(tid, instPC.instAddr()); } /** @@ -189,10 +197,10 @@ class BPredUnit : public SimObject * @param target_PC The branch's target that will be added to the BTB. */ void - BTBUpdate(Addr instPC, const PCStateBase &target) + BTBUpdate(ThreadID tid, Addr instPC, const PCStateBase &target) { ++stats.BTBUpdates; - BTB.update(instPC, target, 0); + return btb->update(tid, instPC, target); } @@ -295,7 +303,7 @@ class BPredUnit : public SimObject std::vector predHist; /** The BTB. */ - DefaultBTB BTB; + BranchTargetBuffer* btb; /** The per-thread return address stack. */ std::vector RAS; diff --git a/src/cpu/pred/branch_type.hh b/src/cpu/pred/branch_type.hh new file mode 100644 index 0000000000..dcc6149a9b --- /dev/null +++ b/src/cpu/pred/branch_type.hh @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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. + * + * 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. + */ + +/* @file + * A helper for branch type information + */ + +#ifndef __CPU_PRED_BRANCH_TYPE_HH__ +#define __CPU_PRED_BRANCH_TYPE_HH__ + +#include "cpu/static_inst.hh" +#include "enums/BranchType.hh" + +namespace gem5 +{ + +namespace branch_prediction +{ + +typedef enums::BranchType BranchType; + +inline BranchType getBranchType(StaticInstPtr inst) +{ + if (inst->isReturn()) { + return BranchType::Return; + } + + if (inst->isCall()) { + return inst->isDirectCtrl() + ? BranchType::CallDirect + : BranchType::CallIndirect; + } + + if (inst->isDirectCtrl()) { + return inst->isCondCtrl() + ? BranchType::DirectCond + : BranchType::DirectUncond; + } + + if (inst->isIndirectCtrl()) { + return inst->isCondCtrl() + ? BranchType::IndirectCond + : BranchType::IndirectUncond; + } + return BranchType::NoBranch; +} + +inline std::string toString(BranchType type) +{ + return std::string(enums::BranchTypeStrings[type]); +} + + +} // namespace branch_prediction +} // namespace gem5 + +#endif // __CPU_PRED_BRANCH_TYPE_HH__ diff --git a/src/cpu/pred/btb.cc b/src/cpu/pred/btb.cc index 71afd45b9f..85d3e2c9bb 100644 --- a/src/cpu/pred/btb.cc +++ b/src/cpu/pred/btb.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -28,119 +40,59 @@ #include "cpu/pred/btb.hh" -#include "base/intmath.hh" -#include "base/trace.hh" -#include "debug/Fetch.hh" - namespace gem5 { namespace branch_prediction { -DefaultBTB::DefaultBTB(unsigned _numEntries, - unsigned _tagBits, - unsigned _instShiftAmt, - unsigned _num_threads) - : numEntries(_numEntries), - tagBits(_tagBits), - instShiftAmt(_instShiftAmt), - log2NumThreads(floorLog2(_num_threads)) +BranchTargetBuffer::BranchTargetBuffer(const Params ¶ms) + : ClockedObject(params), + numThreads(params.numThreads), + stats(this) { - DPRINTF(Fetch, "BTB: Creating BTB object.\n"); +} - if (!isPowerOf2(numEntries)) { - fatal("BTB entries is not a power of 2!"); +BranchTargetBuffer::BranchTargetBufferStats::BranchTargetBufferStats( + statistics::Group *parent) + : statistics::Group(parent), + ADD_STAT(lookups, statistics::units::Count::get(), + "Number of BTB lookups"), + ADD_STAT(misses, statistics::units::Count::get(), + "Number of BTB misses"), + ADD_STAT(updates, statistics::units::Count::get(), + "Number of BTB updates"), + ADD_STAT(mispredict, statistics::units::Count::get(), + "Number of BTB mispredictions. " + "No target found or target wrong."), + ADD_STAT(evictions, statistics::units::Count::get(), + "Number of BTB evictions") +{ + using namespace statistics; + lookups + .init(enums::Num_BranchType) + .flags(total | pdf); + + misses + .init(enums::Num_BranchType) + .flags(total | pdf); + + updates + .init(enums::Num_BranchType) + .flags(total | pdf); + + mispredict + .init(enums::Num_BranchType) + .flags(total | pdf); + + evictions.flags(nozero); + + for (int i = 0; i < enums::Num_BranchType; i++) { + lookups.subname(i, enums::BranchTypeStrings[i]); + misses.subname(i, enums::BranchTypeStrings[i]); + updates.subname(i, enums::BranchTypeStrings[i]); + mispredict.subname(i, enums::BranchTypeStrings[i]); } - - btb.resize(numEntries); - - for (unsigned i = 0; i < numEntries; ++i) { - btb[i].valid = false; - } - - idxMask = numEntries - 1; - - tagMask = (1 << tagBits) - 1; - - tagShiftAmt = instShiftAmt + floorLog2(numEntries); -} - -void -DefaultBTB::reset() -{ - for (unsigned i = 0; i < numEntries; ++i) { - btb[i].valid = false; - } -} - -inline -unsigned -DefaultBTB::getIndex(Addr instPC, ThreadID tid) -{ - // Need to shift PC over by the word offset. - return ((instPC >> instShiftAmt) - ^ (tid << (tagShiftAmt - instShiftAmt - log2NumThreads))) - & idxMask; -} - -inline -Addr -DefaultBTB::getTag(Addr instPC) -{ - return (instPC >> tagShiftAmt) & tagMask; -} - -bool -DefaultBTB::valid(Addr instPC, ThreadID tid) -{ - unsigned btb_idx = getIndex(instPC, tid); - - Addr inst_tag = getTag(instPC); - - assert(btb_idx < numEntries); - - if (btb[btb_idx].valid - && inst_tag == btb[btb_idx].tag - && btb[btb_idx].tid == tid) { - return true; - } else { - return false; - } -} - -// @todo Create some sort of return struct that has both whether or not the -// address is valid, and also the address. For now will just use addr = 0 to -// represent invalid entry. -const PCStateBase * -DefaultBTB::lookup(Addr inst_pc, ThreadID tid) -{ - unsigned btb_idx = getIndex(inst_pc, tid); - - Addr inst_tag = getTag(inst_pc); - - assert(btb_idx < numEntries); - - if (btb[btb_idx].valid - && inst_tag == btb[btb_idx].tag - && btb[btb_idx].tid == tid) { - return btb[btb_idx].target.get(); - } else { - return nullptr; - } -} - -void -DefaultBTB::update(Addr inst_pc, const PCStateBase &target, ThreadID tid) -{ - unsigned btb_idx = getIndex(inst_pc, tid); - - assert(btb_idx < numEntries); - - btb[btb_idx].tid = tid; - btb[btb_idx].valid = true; - set(btb[btb_idx].target, target); - btb[btb_idx].tag = getTag(inst_pc); } } // namespace branch_prediction diff --git a/src/cpu/pred/btb.hh b/src/cpu/pred/btb.hh index 9213053d77..dd3e56a20f 100644 --- a/src/cpu/pred/btb.hh +++ b/src/cpu/pred/btb.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -29,9 +41,13 @@ #ifndef __CPU_PRED_BTB_HH__ #define __CPU_PRED_BTB_HH__ + #include "arch/generic/pcstate.hh" -#include "base/logging.hh" -#include "base/types.hh" +#include "base/statistics.hh" +#include "cpu/pred/branch_type.hh" +#include "cpu/static_inst.hh" +#include "params/BranchTargetBuffer.hh" +#include "sim/clocked_object.hh" namespace gem5 { @@ -39,93 +55,73 @@ namespace gem5 namespace branch_prediction { -class DefaultBTB +class BranchTargetBuffer : public ClockedObject { - private: - struct BTBEntry - { - /** The entry's tag. */ - Addr tag = 0; - - /** The entry's target. */ - std::unique_ptr target; - - /** The entry's thread id. */ - ThreadID tid; - - /** Whether or not the entry is valid. */ - bool valid = false; - }; - public: - /** Creates a BTB with the given number of entries, number of bits per - * tag, and instruction offset amount. - * @param numEntries Number of entries for the BTB. - * @param tagBits Number of bits for each tag in the BTB. - * @param instShiftAmt Offset amount for instructions to ignore alignment. - */ - DefaultBTB(unsigned numEntries, unsigned tagBits, - unsigned instShiftAmt, unsigned numThreads); + typedef BranchTargetBufferParams Params; + typedef enums::BranchType BranchType; - void reset(); + BranchTargetBuffer(const Params ¶ms); - /** Looks up an address in the BTB. Must call valid() first on the address. + virtual void memInvalidate() override = 0; + + /** Checks if a branch address is in the BTB. Intended as a quick check + * before calling lookup. Does not update statistics. * @param inst_PC The address of the branch to look up. - * @param tid The thread id. - * @return Returns the target of the branch. - */ - const PCStateBase *lookup(Addr instPC, ThreadID tid); - - /** Checks if a branch is in the BTB. - * @param inst_PC The address of the branch to look up. - * @param tid The thread id. * @return Whether or not the branch exists in the BTB. */ - bool valid(Addr instPC, ThreadID tid); + virtual bool valid(ThreadID tid, Addr instPC) = 0; + + /** Looks up an address in the BTB to get the target of the branch. + * @param inst_PC The address of the branch to look up. + * @param type Optional type of the branch to look up. + * @return The target of the branch or nullptr if the branch is not + * in the BTB. + */ + virtual const PCStateBase *lookup(ThreadID tid, Addr instPC, + BranchType type = BranchType::NoBranch) = 0; + + /** Looks up an address in the BTB and return the instruction + * information if existant. Does not update statistics. + * @param inst_PC The address of the branch to look up. + * @return Returns the target of the branch. + */ + virtual const StaticInstPtr getInst(ThreadID tid, Addr instPC) = 0; + /** Updates the BTB with the target of a branch. * @param inst_pc The address of the branch being updated. * @param target_pc The target address of the branch. - * @param tid The thread id. */ - void update(Addr inst_pc, const PCStateBase &target_pc, ThreadID tid); + virtual void update(ThreadID tid, Addr inst_pc, + const PCStateBase &target_pc, + BranchType type = BranchType::NoBranch, + StaticInstPtr inst = nullptr) = 0; - private: - /** Returns the index into the BTB, based on the branch's PC. - * @param inst_PC The branch to look up. - * @return Returns the index into the BTB. + /** Update BTB statistics */ - inline unsigned getIndex(Addr instPC, ThreadID tid); + virtual void incorrectTarget(Addr inst_pc, + BranchType type = BranchType::NoBranch) + { + stats.mispredict[type]++; + } - /** Returns the tag bits of a given address. - * @param inst_PC The branch's address. - * @return Returns the tag bits. - */ - inline Addr getTag(Addr instPC); + protected: + /** Number of the threads for which the branch history is maintained. */ + const unsigned numThreads; - /** The actual BTB. */ - std::vector btb; + struct BranchTargetBufferStats : public statistics::Group + { + BranchTargetBufferStats(statistics::Group *parent); - /** The number of entries in the BTB. */ - unsigned numEntries; + statistics::Vector lookups; + statistics::Vector misses; + statistics::Vector updates; + statistics::Vector mispredict; + statistics::Scalar evictions; - /** The index mask. */ - unsigned idxMask; + } stats; - /** The number of tag bits per entry. */ - unsigned tagBits; - - /** The tag mask. */ - unsigned tagMask; - - /** Number of bits to shift PC when calculating index. */ - unsigned instShiftAmt; - - /** Number of bits to shift PC when calculating tag. */ - unsigned tagShiftAmt; - - /** Log2 NumThreads used for hashing threadid */ - unsigned log2NumThreads; }; } // namespace branch_prediction diff --git a/src/cpu/pred/simple_btb.cc b/src/cpu/pred/simple_btb.cc new file mode 100644 index 0000000000..c78caac7a8 --- /dev/null +++ b/src/cpu/pred/simple_btb.cc @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2005 The Regents of The University of Michigan + * 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. + */ + +#include "cpu/pred/simple_btb.hh" + +#include "base/intmath.hh" +#include "base/trace.hh" +#include "debug/BTB.hh" + +namespace gem5 +{ + +namespace branch_prediction +{ + +SimpleBTB::SimpleBTB(const SimpleBTBParams &p) + : BranchTargetBuffer(p), + numEntries(p.numEntries), + tagBits(p.tagBits), + instShiftAmt(p.instShiftAmt), + log2NumThreads(floorLog2(p.numThreads)) +{ + DPRINTF(BTB, "BTB: Creating BTB object.\n"); + + if (!isPowerOf2(numEntries)) { + fatal("BTB entries is not a power of 2!"); + } + + btb.resize(numEntries); + + for (unsigned i = 0; i < numEntries; ++i) { + btb[i].valid = false; + } + + idxMask = numEntries - 1; + + tagMask = (1 << tagBits) - 1; + + tagShiftAmt = instShiftAmt + floorLog2(numEntries); +} + +void +SimpleBTB::memInvalidate() +{ + for (unsigned i = 0; i < numEntries; ++i) { + btb[i].valid = false; + } +} + +inline +unsigned +SimpleBTB::getIndex(Addr instPC, ThreadID tid) +{ + // Need to shift PC over by the word offset. + return ((instPC >> instShiftAmt) + ^ (tid << (tagShiftAmt - instShiftAmt - log2NumThreads))) + & idxMask; +} + +inline +Addr +SimpleBTB::getTag(Addr instPC) +{ + return (instPC >> tagShiftAmt) & tagMask; +} + +SimpleBTB::BTBEntry * +SimpleBTB::findEntry(Addr instPC, ThreadID tid) +{ + unsigned btb_idx = getIndex(instPC, tid); + Addr inst_tag = getTag(instPC); + + assert(btb_idx < numEntries); + + if (btb[btb_idx].valid + && inst_tag == btb[btb_idx].tag + && btb[btb_idx].tid == tid) { + return &btb[btb_idx]; + } + + return nullptr; +} + +bool +SimpleBTB::valid(ThreadID tid, Addr instPC) +{ + BTBEntry *entry = findEntry(instPC, tid); + + return entry != nullptr; +} + +// @todo Create some sort of return struct that has both whether or not the +// address is valid, and also the address. For now will just use addr = 0 to +// represent invalid entry. +const PCStateBase * +SimpleBTB::lookup(ThreadID tid, Addr instPC, BranchType type) +{ + stats.lookups[type]++; + + BTBEntry *entry = findEntry(instPC, tid); + + if (entry) { + return entry->target.get(); + } + stats.misses[type]++; + return nullptr; +} + +const StaticInstPtr +SimpleBTB::getInst(ThreadID tid, Addr instPC) +{ + BTBEntry *entry = findEntry(instPC, tid); + + if (entry) { + return entry->inst; + } + return nullptr; +} + +void +SimpleBTB::update(ThreadID tid, Addr instPC, + const PCStateBase &target, + BranchType type, StaticInstPtr inst) +{ + unsigned btb_idx = getIndex(instPC, tid); + + assert(btb_idx < numEntries); + + stats.updates[type]++; + + btb[btb_idx].tid = tid; + btb[btb_idx].valid = true; + set(btb[btb_idx].target, target); + btb[btb_idx].tag = getTag(instPC); + btb[btb_idx].inst = inst; +} + +} // namespace branch_prediction +} // namespace gem5 diff --git a/src/cpu/pred/simple_btb.hh b/src/cpu/pred/simple_btb.hh new file mode 100644 index 0000000000..3c76890348 --- /dev/null +++ b/src/cpu/pred/simple_btb.hh @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2005 The Regents of The University of Michigan + * 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. + */ + +#ifndef __CPU_PRED_SIMPLE_BTB_HH__ +#define __CPU_PRED_SIMPLE_BTB_HH__ + +#include "base/logging.hh" +#include "base/types.hh" +#include "cpu/pred/btb.hh" +#include "params/SimpleBTB.hh" + +namespace gem5 +{ + +namespace branch_prediction +{ + +class SimpleBTB : public BranchTargetBuffer +{ + public: + SimpleBTB(const SimpleBTBParams ¶ms); + + void memInvalidate() override; + bool valid(ThreadID tid, Addr instPC) override; + const PCStateBase *lookup(ThreadID tid, Addr instPC, + BranchType type = BranchType::NoBranch) override; + void update(ThreadID tid, Addr instPC, const PCStateBase &target_pc, + BranchType type = BranchType::NoBranch, + StaticInstPtr inst = nullptr) override; + const StaticInstPtr getInst(ThreadID tid, Addr instPC) override; + + + private: + struct BTBEntry + { + /** The entry's tag. */ + Addr tag = 0; + + /** The entry's target. */ + std::unique_ptr target; + + /** The entry's thread id. */ + ThreadID tid; + + /** Whether or not the entry is valid. */ + bool valid = false; + + /** Pointer to the static branch instruction at this address */ + StaticInstPtr inst = nullptr; + }; + + + /** Returns the index into the BTB, based on the branch's PC. + * @param inst_PC The branch to look up. + * @return Returns the index into the BTB. + */ + inline unsigned getIndex(Addr instPC, ThreadID tid); + + /** Returns the tag bits of a given address. + * @param inst_PC The branch's address. + * @return Returns the tag bits. + */ + inline Addr getTag(Addr instPC); + + /** Internal call to find an address in the BTB + * @param instPC The branch's address. + * @return Returns a pointer to the BTB entry if found, nullptr otherwise. + */ + BTBEntry *findEntry(Addr instPC, ThreadID tid); + + /** The actual BTB. */ + std::vector btb; + + /** The number of entries in the BTB. */ + unsigned numEntries; + + /** The index mask. */ + unsigned idxMask; + + /** The number of tag bits per entry. */ + unsigned tagBits; + + /** The tag mask. */ + unsigned tagMask; + + /** Number of bits to shift PC when calculating index. */ + unsigned instShiftAmt; + + /** Number of bits to shift PC when calculating tag. */ + unsigned tagShiftAmt; + + /** Log2 NumThreads used for hashing threadid */ + unsigned log2NumThreads; +}; + +} // namespace branch_prediction +} // namespace gem5 + +#endif // __CPU_PRED_SIMPLE_BTB_HH__ diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py index 4b8d2c1d32..ce265449c9 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py @@ -95,7 +95,7 @@ class U74FUPool(MinorFUPool): class U74BP(TournamentBP): - BTBEntries = 32 + btb = SimpleBTB(numEntries=32) RASSize = 12 localHistoryTableSize = 4096 # is 3.6 KiB but gem5 requires power of 2 localPredictorSize = 16384 From 3b8c974456a8fe3a85687c56c31175b394e9dbbb Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 18 Sep 2023 09:50:32 +0100 Subject: [PATCH 403/693] configs: Refactor BaseSimpleSystem in devices.py We define a new parent (ClusterSystem) to model a system with one or more cpu clusters within it. The idea is to make this new base class reusable by SE systems/scripts as well (like starter_se.py) Change-Id: I1398d773813db565f6ad5ce62cb4c022cb12a55a Signed-off-by: Giacomo Travaglini Reviewed-by: Richard Cooper --- configs/example/arm/devices.py | 103 ++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py index 6c6474ca2b..03d0a84799 100644 --- a/configs/example/arm/devices.py +++ b/configs/example/arm/devices.py @@ -338,56 +338,15 @@ class FastmodelCluster(CpuCluster): pass -class BaseSimpleSystem(ArmSystem): - cache_line_size = 64 - - def __init__(self, mem_size, platform, **kwargs): - super(BaseSimpleSystem, self).__init__(**kwargs) - - self.voltage_domain = VoltageDomain(voltage="1.0V") - self.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=Parent.voltage_domain - ) - - if platform is None: - self.realview = VExpress_GEM5_V1() - else: - self.realview = platform - - if hasattr(self.realview.gic, "cpu_addr"): - self.gic_cpu_addr = self.realview.gic.cpu_addr - - self.terminal = Terminal() - self.vncserver = VncServer() - - self.iobus = IOXBar() - # Device DMA -> MEM - self.mem_ranges = self.getMemRanges(int(Addr(mem_size))) +class ClusterSystem: + """ + Base class providing cpu clusters generation/handling methods to + SE/FS systems + """ + def __init__(self, **kwargs): self._clusters = [] - def getMemRanges(self, mem_size): - """ - Define system memory ranges. This depends on the physical - memory map provided by the realview platform and by the memory - size provided by the user (mem_size argument). - The method is iterating over all platform ranges until they cover - the entire user's memory requirements. - """ - mem_ranges = [] - for mem_range in self.realview._mem_regions: - size_in_range = min(mem_size, mem_range.size()) - - mem_ranges.append( - AddrRange(start=mem_range.start, size=size_in_range) - ) - - mem_size -= size_in_range - if mem_size == 0: - return mem_ranges - - raise ValueError("memory size too big for platform capabilities") - def numCpuClusters(self): return len(self._clusters) @@ -423,6 +382,56 @@ class BaseSimpleSystem(ArmSystem): cluster.connectMemSide(cluster_mem_bus) +class BaseSimpleSystem(ArmSystem, ClusterSystem): + cache_line_size = 64 + + def __init__(self, mem_size, platform, **kwargs): + ArmSystem.__init__(self, **kwargs) + ClusterSystem.__init__(self, **kwargs) + + self.voltage_domain = VoltageDomain(voltage="1.0V") + self.clk_domain = SrcClockDomain( + clock="1GHz", voltage_domain=Parent.voltage_domain + ) + + if platform is None: + self.realview = VExpress_GEM5_V1() + else: + self.realview = platform + + if hasattr(self.realview.gic, "cpu_addr"): + self.gic_cpu_addr = self.realview.gic.cpu_addr + + self.terminal = Terminal() + self.vncserver = VncServer() + + self.iobus = IOXBar() + # Device DMA -> MEM + self.mem_ranges = self.getMemRanges(int(Addr(mem_size))) + + def getMemRanges(self, mem_size): + """ + Define system memory ranges. This depends on the physical + memory map provided by the realview platform and by the memory + size provided by the user (mem_size argument). + The method is iterating over all platform ranges until they cover + the entire user's memory requirements. + """ + mem_ranges = [] + for mem_range in self.realview._mem_regions: + size_in_range = min(mem_size, mem_range.size()) + + mem_ranges.append( + AddrRange(start=mem_range.start, size=size_in_range) + ) + + mem_size -= size_in_range + if mem_size == 0: + return mem_ranges + + raise ValueError("memory size too big for platform capabilities") + + class SimpleSystem(BaseSimpleSystem): """ Meant to be used with the classic memory model From 7395b94c40a1b291e29f96b375448f799b969791 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 18 Sep 2023 09:51:47 +0100 Subject: [PATCH 404/693] configs: Add a SimpleSeSystem class to devices.py Change-Id: I9d120fbaf0c61c5a053163ec1e5f4f93c583df52 Signed-off-by: Giacomo Travaglini Reviewed-by: Richard Cooper --- configs/example/arm/devices.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py index 03d0a84799..7ceb3cd3bf 100644 --- a/configs/example/arm/devices.py +++ b/configs/example/arm/devices.py @@ -382,6 +382,30 @@ class ClusterSystem: cluster.connectMemSide(cluster_mem_bus) +class SimpleSeSystem(System, ClusterSystem): + """ + Example system class for syscall emulation mode + """ + + # Use a fixed cache line size of 64 bytes + cache_line_size = 64 + + def __init__(self, **kwargs): + System.__init__(self, **kwargs) + ClusterSystem.__init__(self, **kwargs) + # Create a voltage and clock domain for system components + self.voltage_domain = VoltageDomain(voltage="3.3V") + self.clk_domain = SrcClockDomain( + clock="1GHz", voltage_domain=self.voltage_domain + ) + + # Create the off-chip memory bus. + self.membus = SystemXBar() + + def connect(self): + self.system_port = self.membus.cpu_side_ports + + class BaseSimpleSystem(ArmSystem, ClusterSystem): cache_line_size = 64 From e35e2966c04f971326b76a630bef5c321cabcb57 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 18 Sep 2023 09:52:05 +0100 Subject: [PATCH 405/693] configs: Use devices.SimpleSeSystem in starter_se.py Change-Id: I742e280e7a2a4047ac4bb3d783a28ee97f461480 Signed-off-by: Giacomo Travaglini Reviewed-by: Richard Cooper --- configs/example/arm/starter_se.py | 95 +++++++++---------------------- 1 file changed, 28 insertions(+), 67 deletions(-) diff --git a/configs/example/arm/starter_se.py b/configs/example/arm/starter_se.py index f21f399675..9834487155 100644 --- a/configs/example/arm/starter_se.py +++ b/configs/example/arm/starter_se.py @@ -64,72 +64,6 @@ cpu_types = { } -class SimpleSeSystem(System): - """ - Example system class for syscall emulation mode - """ - - # Use a fixed cache line size of 64 bytes - cache_line_size = 64 - - def __init__(self, args, **kwargs): - super(SimpleSeSystem, self).__init__(**kwargs) - - # Setup book keeping to be able to use CpuClusters from the - # devices module. - self._clusters = [] - self._num_cpus = 0 - - # Create a voltage and clock domain for system components - self.voltage_domain = VoltageDomain(voltage="3.3V") - self.clk_domain = SrcClockDomain( - clock="1GHz", voltage_domain=self.voltage_domain - ) - - # Create the off-chip memory bus. - self.membus = SystemXBar() - - # Wire up the system port that gem5 uses to load the kernel - # and to perform debug accesses. - self.system_port = self.membus.cpu_side_ports - - # Add CPUs to the system. A cluster of CPUs typically have - # private L1 caches and a shared L2 cache. - self.cpu_cluster = devices.ArmCpuCluster( - self, - args.num_cores, - args.cpu_freq, - "1.2V", - *cpu_types[args.cpu], - tarmac_gen=args.tarmac_gen, - tarmac_dest=args.tarmac_dest, - ) - - # Create a cache hierarchy (unless we are simulating a - # functional CPU in atomic memory mode) for the CPU cluster - # and connect it to the shared memory bus. - if self.cpu_cluster.memory_mode() == "timing": - self.cpu_cluster.addL1() - self.cpu_cluster.addL2(self.cpu_cluster.clk_domain) - self.cpu_cluster.connectMemSide(self.membus) - - # Tell gem5 about the memory mode used by the CPUs we are - # simulating. - self.mem_mode = self.cpu_cluster.memory_mode() - - def numCpuClusters(self): - return len(self._clusters) - - def addCpuCluster(self, cpu_cluster): - assert cpu_cluster not in self._clusters - assert len(cpu_cluster) > 0 - self._clusters.append(cpu_cluster) - self._num_cpus += len(cpu_cluster) - - def numCpus(self): - return self._num_cpus - - def get_processes(cmd): """Interprets commands to run and returns a list of processes""" @@ -150,7 +84,31 @@ def get_processes(cmd): def create(args): """Create and configure the system object.""" - system = SimpleSeSystem(args) + cpu_class = cpu_types[args.cpu][0] + mem_mode = cpu_class.memory_mode() + # Only simulate caches when using a timing CPU (e.g., the HPI model) + want_caches = True if mem_mode == "timing" else False + + system = devices.SimpleSeSystem( + mem_mode=mem_mode, + ) + + # Add CPUs to the system. A cluster of CPUs typically have + # private L1 caches and a shared L2 cache. + system.cpu_cluster = devices.ArmCpuCluster( + system, + args.num_cores, + args.cpu_freq, + "1.2V", + *cpu_types[args.cpu], + tarmac_gen=args.tarmac_gen, + tarmac_dest=args.tarmac_dest, + ) + + # Create a cache hierarchy for the cluster. We are assuming that + # clusters have core-private L1 caches and an L2 that's shared + # within the cluster. + system.addCaches(want_caches, last_cache_level=2) # Tell components about the expected physical memory ranges. This # is, for example, used by the MemConfig helper to determine where @@ -160,6 +118,9 @@ def create(args): # Configure the off-chip memory system. MemConfig.config_mem(args, system) + # Wire up the system's memory system + system.connect() + # Parse the command line and get a list of Processes instances # that we can pass to gem5. processes = get_processes(args.commands_to_run) From 1a5dee0f0f9839f6c47f99d77a9fab823fd94fe4 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 13 Sep 2023 20:24:02 +0100 Subject: [PATCH 406/693] configs: Add an elastic-trace-generating CPU According to the original paper [1] the elastic trace generation process requires a cpu with a big number of entries in the ROB, LQ and SQ, so that there are no stalls due to resource limitation. At the moment these numbers are copy pasted from the CpuConfig.config_etrace method [2]. [1]: https://ieeexplore.ieee.org/document/7818336 [2]: https://github.com/gem5/gem5/blob/stable/\ configs/common/CpuConfig.py#L40 Change-Id: I00fde49e5420e420a4eddb7b49de4b74360348c9 Signed-off-by: Giacomo Travaglini Reviewed-by: Richard Cooper --- configs/common/cores/arm/O3_ARM_Etrace.py | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 configs/common/cores/arm/O3_ARM_Etrace.py diff --git a/configs/common/cores/arm/O3_ARM_Etrace.py b/configs/common/cores/arm/O3_ARM_Etrace.py new file mode 100644 index 0000000000..20870a0b7a --- /dev/null +++ b/configs/common/cores/arm/O3_ARM_Etrace.py @@ -0,0 +1,58 @@ +# Copyright (c) 2012, 2017-2018, 2023 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. +# +# 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 * +from .O3_ARM_v7a import O3_ARM_v7a_3 + +# O3_ARM_v7a_3 adapted to generate elastic traces +class O3_ARM_v7a_3_Etrace(O3_ARM_v7a_3): + # Make the number of entries in the ROB, LQ and SQ very + # large so that there are no stalls due to resource + # limitation as such stalls will get captured in the trace + # as compute delay. For replay, ROB, LQ and SQ sizes are + # modelled in the Trace CPU. + numROBEntries = 512 + LQEntries = 128 + SQEntries = 128 + + def attach_probe_listener(self, inst_trace_file, data_trace_file): + # Attach the elastic trace probe listener. Set the protobuf trace + # file names. Set the dependency window size equal to the cpu it + # is attached to. + self.traceListener = m5.objects.ElasticTrace( + instFetchTraceFile=inst_trace_file, + dataDepTraceFile=data_trace_file, + depWindowSize=3 * self.numROBEntries, + ) From 4c4615523f1367bef4ea143072f202c5c0b48b81 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 13 Sep 2023 20:27:58 +0100 Subject: [PATCH 407/693] configs: Add an example elastic-trace-generating script The new script will automatically use the newly defined O3_ARM_v7a_3_Etrace CPU to run a simple SE simulation while generating elastic trace files. The script is based on starter_se.py, but contains the following limitations: 1) No L2 cache as it might affect computational delay calculations 2) Supporting SimpleMemory only with minimal memory latency There restrictions were imported by the existing elastic trace generation logic in the common library (collected by grepping elastic_trace_en) [1][2][3] Example usage: build/ARM/gem5.opt configs/example/arm/etrace_se.py \ --inst-trace-file [INSTRUCTION TRACE] \ --data-trace-file [DATA TRACE] \ [WORKLOAD] [1]: https://github.com/gem5/gem5/blob/stable/\ configs/common/MemConfig.py#L191 [2]: https://github.com/gem5/gem5/blob/stable/\ configs/common/MemConfig.py#L232 [3]: https://github.com/gem5/gem5/blob/stable/\ configs/common/CacheConfig.py#L130 Change-Id: I021fc84fa101113c5c2f0737d50a930bb4750f76 Signed-off-by: Giacomo Travaglini Reviewed-by: Richard Cooper --- configs/example/arm/etrace_se.py | 191 +++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 configs/example/arm/etrace_se.py diff --git a/configs/example/arm/etrace_se.py b/configs/example/arm/etrace_se.py new file mode 100644 index 0000000000..8fa971ff84 --- /dev/null +++ b/configs/example/arm/etrace_se.py @@ -0,0 +1,191 @@ +# Copyright (c) 2016-2017, 2022-2023 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. +# +# 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. + + +import os +import m5 +from m5.util import addToPath +from m5.objects import * +import argparse +import shlex + +m5.util.addToPath("../..") + +from common import ObjectList + +import devices + + +def get_processes(cmd): + """Interprets commands to run and returns a list of processes""" + + cwd = os.getcwd() + multiprocesses = [] + for idx, c in enumerate(cmd): + argv = shlex.split(c) + + process = Process(pid=100 + idx, cwd=cwd, cmd=argv, executable=argv[0]) + process.gid = os.getgid() + + print("info: %d. command and arguments: %s" % (idx + 1, process.cmd)) + multiprocesses.append(process) + + return multiprocesses + + +def create(args): + """Create and configure the system object.""" + + system = devices.SimpleSeSystem( + mem_mode="timing", + ) + + # Add CPUs to the system. A cluster of CPUs typically have + # private L1 caches and a shared L2 cache. + system.cpu_cluster = devices.ArmCpuCluster( + system, + args.num_cores, + args.cpu_freq, + "1.2V", + ObjectList.cpu_list.get("O3_ARM_v7a_3_Etrace"), + devices.L1I, + devices.L1D, + devices.L2, + ) + + # Attach the elastic trace probe listener to every CPU in the cluster + for cpu in system.cpu_cluster: + cpu.attach_probe_listener(args.inst_trace_file, args.data_trace_file) + + # As elastic trace generation is enabled, make sure the memory system is + # minimal so that compute delays do not include memory access latencies. + # Configure the compulsory L1 caches for the O3CPU, do not configure + # any more caches. + system.addCaches(True, last_cache_level=1) + + # For elastic trace, over-riding Simple Memory latency to 1ns." + system.memory = SimpleMemory( + range=AddrRange(start=0, size=args.mem_size), + latency="1ns", + port=system.membus.mem_side_ports, + ) + + # Parse the command line and get a list of Processes instances + # that we can pass to gem5. + processes = get_processes(args.commands_to_run) + if len(processes) != args.num_cores: + print( + "Error: Cannot map %d command(s) onto %d CPU(s)" + % (len(processes), args.num_cores) + ) + sys.exit(1) + + system.workload = SEWorkload.init_compatible(processes[0].executable) + + # Assign one workload to each CPU + for cpu, workload in zip(system.cpu_cluster.cpus, processes): + cpu.workload = workload + + return system + + +def main(): + parser = argparse.ArgumentParser(epilog=__doc__) + + parser.add_argument( + "commands_to_run", + metavar="command(s)", + nargs="+", + help="Command(s) to run", + ) + parser.add_argument( + "--inst-trace-file", + action="store", + type=str, + help="""Instruction fetch trace file input to + Elastic Trace probe in a capture simulation and + Trace CPU in a replay simulation""", + default="fetchtrace.proto.gz", + ) + parser.add_argument( + "--data-trace-file", + action="store", + type=str, + help="""Data dependency trace file input to + Elastic Trace probe in a capture simulation and + Trace CPU in a replay simulation""", + default="deptrace.proto.gz", + ) + parser.add_argument("--cpu-freq", type=str, default="4GHz") + parser.add_argument( + "--num-cores", type=int, default=1, help="Number of CPU cores" + ) + parser.add_argument( + "--mem-size", + action="store", + type=str, + default="2GB", + help="Specify the physical memory size", + ) + + args = parser.parse_args() + + # Create a single root node for gem5's object hierarchy. There can + # only exist one root node in the simulator at any given + # time. Tell gem5 that we want to use syscall emulation mode + # instead of full system mode. + root = Root(full_system=False) + + # Populate the root node with a system. A system corresponds to a + # single node with shared memory. + root.system = create(args) + + # Instantiate the C++ object hierarchy. After this point, + # SimObjects can't be instantiated anymore. + m5.instantiate() + + # Start the simulator. This gives control to the C++ world and + # starts the simulator. The returned event tells the simulation + # script why the simulator exited. + event = m5.simulate() + + # Print the reason for the simulation exit. Some exit codes are + # requests for service (e.g., checkpoints) from the simulation + # script. We'll just ignore them here and exit. + print(f"{event.getCause()} ({event.getCode()}) @ {m5.curTick()}") + + +if __name__ == "__m5_main__": + main() From c4c5d2e17239d972e9808cae6c0567d26e920dba Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 23 May 2023 16:49:04 +0100 Subject: [PATCH 408/693] arch-arm: Implement ID_AA64MMFR3_EL1 register Change-Id: If8c37bdccf35a070870900c06dc4640348f0f063 Signed-off-by: Giacomo Travaglini --- src/arch/arm/regs/misc.cc | 10 +++++++++- src/arch/arm/regs/misc.hh | 2 ++ src/arch/arm/regs/misc_types.hh | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 57d0de1686..9a01c1c89f 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -981,7 +981,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 0, 0, 7, 0), MISCREG_ID_AA64MMFR0_EL1 }, { MiscRegNum64(3, 0, 0, 7, 1), MISCREG_ID_AA64MMFR1_EL1 }, { MiscRegNum64(3, 0, 0, 7, 2), MISCREG_ID_AA64MMFR2_EL1 }, - { MiscRegNum64(3, 0, 0, 7, 3), MISCREG_RAZ }, + { MiscRegNum64(3, 0, 0, 7, 3), MISCREG_ID_AA64MMFR3_EL1 }, { MiscRegNum64(3, 0, 0, 7, 4), MISCREG_RAZ }, { MiscRegNum64(3, 0, 0, 7, 5), MISCREG_RAZ }, { MiscRegNum64(3, 0, 0, 7, 6), MISCREG_RAZ }, @@ -4366,6 +4366,14 @@ ISA::initializeMiscRegMetadata() .faultRead(EL0, faultIdst) .faultRead(EL1, faultHcrEL1<&HCR::tid3>) .allPrivileges().writes(0); + InitReg(MISCREG_ID_AA64MMFR3_EL1) + .reset([p,release=release](){ + AA64MMFR3 mmfr3_el1 = 0; + return mmfr3_el1; + }()) + .faultRead(EL0, faultIdst) + .faultRead(EL1, faultHcrEL1<&HCR::tid3>) + .allPrivileges().writes(0); InitReg(MISCREG_APDAKeyHi_EL1) .faultRead(EL1, faultPauthEL1) diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index b6aaee0d2f..11d5188435 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -872,6 +872,7 @@ namespace ArmISA MISCREG_TTBR1_EL2, MISCREG_ID_AA64MMFR2_EL1, + MISCREG_ID_AA64MMFR3_EL1, //PAuth Key Regsiters MISCREG_APDAKeyHi_EL1, @@ -2585,6 +2586,7 @@ namespace ArmISA "ttbr1_el2", "id_aa64mmfr2_el1", + "id_aa64mmfr3_el1", "apdakeyhi_el1", "apdakeylo_el1", diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index f9a16c297a..befee2a4de 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -187,6 +187,21 @@ namespace ArmISA Bitfield<3, 0> cnp; EndBitUnion(AA64MMFR2) + BitUnion64(AA64MMFR3) + Bitfield<47, 44> anerr; + Bitfield<43, 40> snerr; + Bitfield<39, 36> d128_2; + Bitfield<35, 32> d128; + Bitfield<31, 28> mec; + Bitfield<27, 24> aie; + Bitfield<23, 20> s2poe; + Bitfield<19, 16> s1poe; + Bitfield<15, 12> s2pie; + Bitfield<11, 8> s1pie; + Bitfield<7, 4> sctlrx; + Bitfield<3, 0> tcrx; + EndBitUnion(AA64MMFR3) + BitUnion64(AA64PFR0) Bitfield<63, 60> csv3; Bitfield<59, 56> csv2; From 49cbb24351dbca9d81fc50f34ea74b7e182e51a5 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 10 May 2023 15:18:53 +0100 Subject: [PATCH 409/693] arch-arm: Implement FEAT_SCTLR2 Change-Id: Ifb8c8dc1729cc21007842b950273fe38129d9539 Signed-off-by: Giacomo Travaglini --- src/arch/arm/ArmSystem.py | 12 ++++- src/arch/arm/isa.cc | 2 + src/arch/arm/regs/misc.cc | 79 +++++++++++++++++++++++++++++++++ src/arch/arm/regs/misc.hh | 8 ++++ src/arch/arm/regs/misc_types.hh | 5 +++ src/arch/arm/utility.cc | 11 +++++ src/arch/arm/utility.hh | 1 + 7 files changed, 116 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index e220f92168..febebda50e 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -101,6 +101,8 @@ class ArmExtension(ScopedEnum): "FEAT_FGT", # Armv8.7 "FEAT_HCX", + # Armv8.9 + "FEAT_SCTLR2", # Armv9.2 "FEAT_SME", # Optional in Armv9.2 # Others @@ -258,8 +260,14 @@ class Armv87(Armv86): ] -class Armv92(Armv87): - extensions = Armv87.extensions + ["FEAT_SME"] +class Armv89(Armv87): + extensions = Armv87.extensions + [ + "FEAT_SCTLR2", + ] + + +class Armv92(Armv89): + extensions = Armv89.extensions + ["FEAT_SME"] class ArmAllRelease(ArmRelease): diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 02129266cf..67031a1a9c 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -320,6 +320,8 @@ ISA::redirectRegVHE(int misc_reg) return ELIsInHost(tc, currEL()) ? MISCREG_CNTPCT_EL0 : misc_reg; case MISCREG_SCTLR_EL12: return MISCREG_SCTLR_EL1; + case MISCREG_SCTLR2_EL12: + return MISCREG_SCTLR2_EL1; case MISCREG_CPACR_EL12: return MISCREG_CPACR_EL1; case MISCREG_ZCR_EL12: diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 9a01c1c89f..5d971f3e20 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -989,6 +989,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 0, 1, 0, 0), MISCREG_SCTLR_EL1 }, { MiscRegNum64(3, 0, 1, 0, 1), MISCREG_ACTLR_EL1 }, { MiscRegNum64(3, 0, 1, 0, 2), MISCREG_CPACR_EL1 }, + { MiscRegNum64(3, 0, 1, 0, 3), MISCREG_SCTLR2_EL1 }, { MiscRegNum64(3, 0, 1, 2, 0), MISCREG_ZCR_EL1 }, { MiscRegNum64(3, 0, 1, 2, 4), MISCREG_SMPRI_EL1 }, { MiscRegNum64(3, 0, 1, 2, 6), MISCREG_SMCR_EL1 }, @@ -1138,6 +1139,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 4, 0, 0, 5), MISCREG_VMPIDR_EL2 }, { MiscRegNum64(3, 4, 1, 0, 0), MISCREG_SCTLR_EL2 }, { MiscRegNum64(3, 4, 1, 0, 1), MISCREG_ACTLR_EL2 }, + { MiscRegNum64(3, 4, 1, 0, 3), MISCREG_SCTLR2_EL2 }, { MiscRegNum64(3, 4, 1, 1, 0), MISCREG_HCR_EL2 }, { MiscRegNum64(3, 4, 1, 1, 1), MISCREG_MDCR_EL2 }, { MiscRegNum64(3, 4, 1, 1, 2), MISCREG_CPTR_EL2 }, @@ -1227,6 +1229,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 4, 14, 5, 2), MISCREG_CNTHPS_CVAL_EL2 }, { MiscRegNum64(3, 5, 1, 0, 0), MISCREG_SCTLR_EL12 }, { MiscRegNum64(3, 5, 1, 0, 2), MISCREG_CPACR_EL12 }, + { MiscRegNum64(3, 5, 1, 0, 3), MISCREG_SCTLR2_EL12 }, { MiscRegNum64(3, 5, 1, 2, 0), MISCREG_ZCR_EL12 }, { MiscRegNum64(3, 5, 1, 2, 6), MISCREG_SMCR_EL12 }, { MiscRegNum64(3, 5, 2, 0, 0), MISCREG_TTBR0_EL12 }, @@ -1251,6 +1254,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 5, 14, 3, 2), MISCREG_CNTV_CVAL_EL02 }, { MiscRegNum64(3, 6, 1, 0, 0), MISCREG_SCTLR_EL3 }, { MiscRegNum64(3, 6, 1, 0, 1), MISCREG_ACTLR_EL3 }, + { MiscRegNum64(3, 6, 1, 0, 3), MISCREG_SCTLR2_EL3 }, { MiscRegNum64(3, 6, 1, 1, 0), MISCREG_SCR_EL3 }, { MiscRegNum64(3, 6, 1, 1, 1), MISCREG_SDER32_EL3 }, { MiscRegNum64(3, 6, 1, 1, 2), MISCREG_CPTR_EL3 }, @@ -1913,6 +1917,66 @@ faultIccSgiEL2(const MiscRegLUTEntry &entry, } } +template +Fault +faultSctlr2EL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_SCTLR2)) { + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + const HCRX hcrx = tc->readMiscReg(MISCREG_HCRX_EL2); + if (auto fault = faultHcrFgtEL1(entry, tc, inst); + fault != NoFault) { + return fault; + } else if (EL2Enabled(tc) && (!isHcrxEL2Enabled(tc) || !hcrx.sctlr2En)) { + return inst.generateTrap(EL2); + } else if (ArmSystem::haveEL(tc, EL3) && !scr.sctlr2En) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } +} + +Fault +faultSctlr2EL2(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_SCTLR2)) { + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + if (ArmSystem::haveEL(tc, EL3) && !scr.sctlr2En) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } +} + +Fault +faultSctlr2VheEL2(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_SCTLR2)) { + const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + if (hcr.e2h) { + if (ArmSystem::haveEL(tc, EL3) && !scr.sctlr2En) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } + } else { + return inst.undefined(); + } +} + template Fault faultCpacrEL1(const MiscRegLUTEntry &entry, @@ -4369,6 +4433,7 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_ID_AA64MMFR3_EL1) .reset([p,release=release](){ AA64MMFR3 mmfr3_el1 = 0; + mmfr3_el1.sctlrx = release->has(ArmExtension::FEAT_SCTLR2) ? 0x1 : 0x0; return mmfr3_el1; }()) .faultRead(EL0, faultIdst) @@ -4486,6 +4551,15 @@ ISA::initializeMiscRegMetadata() | (nTLSMD ? 0 : 0x8000000) | (LSMAOE ? 0 : 0x10000000)) .mapsTo(MISCREG_SCTLR_EL1); + InitReg(MISCREG_SCTLR2_EL1) + .allPrivileges().exceptUserMode() + .faultRead(EL1, faultSctlr2EL1) + .faultWrite(EL1, faultSctlr2EL1) + .fault(EL2,faultSctlr2EL2); + InitReg(MISCREG_SCTLR2_EL12) + .fault(EL2, faultSctlr2VheEL2) + .fault(EL3, defaultFaultE2H_EL3) + .mapsTo(MISCREG_SCTLR2_EL1); InitReg(MISCREG_ACTLR_EL1) .allPrivileges().exceptUserMode() .fault(EL1, faultHcrEL1<&HCR::tacr>) @@ -4509,6 +4583,9 @@ ISA::initializeMiscRegMetadata() | (EnIA ? 0 : 0x80000000)) .res1(0x30c50830) .mapsTo(MISCREG_HSCTLR); + InitReg(MISCREG_SCTLR2_EL2) + .hyp().mon() + .fault(EL2, faultSctlr2EL2); InitReg(MISCREG_ACTLR_EL2) .hyp().mon() .mapsTo(MISCREG_HACTLR); @@ -4541,6 +4618,8 @@ ISA::initializeMiscRegMetadata() | (EnIB ? 0 : 0x40000000) | (EnIA ? 0 : 0x80000000)) .res1(0x30c50830); + InitReg(MISCREG_SCTLR2_EL3) + .mon(); InitReg(MISCREG_ACTLR_EL3) .mon(); InitReg(MISCREG_SCR_EL3) diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index 11d5188435..9e4d1cab84 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -583,10 +583,13 @@ namespace ArmISA MISCREG_VMPIDR_EL2, MISCREG_SCTLR_EL1, MISCREG_SCTLR_EL12, + MISCREG_SCTLR2_EL1, + MISCREG_SCTLR2_EL12, MISCREG_ACTLR_EL1, MISCREG_CPACR_EL1, MISCREG_CPACR_EL12, MISCREG_SCTLR_EL2, + MISCREG_SCTLR2_EL2, MISCREG_ACTLR_EL2, MISCREG_HCR_EL2, MISCREG_HCRX_EL2, @@ -595,6 +598,7 @@ namespace ArmISA MISCREG_HSTR_EL2, MISCREG_HACR_EL2, MISCREG_SCTLR_EL3, + MISCREG_SCTLR2_EL3, MISCREG_ACTLR_EL3, MISCREG_SCR_EL3, MISCREG_SDER32_EL3, @@ -2303,10 +2307,13 @@ namespace ArmISA "vmpidr_el2", "sctlr_el1", "sctlr_el12", + "sctlr2_el1", + "sctlr2_el12", "actlr_el1", "cpacr_el1", "cpacr_el12", "sctlr_el2", + "sctlr2_el2", "actlr_el2", "hcr_el2", "hcrx_el2", @@ -2315,6 +2322,7 @@ namespace ArmISA "hstr_el2", "hacr_el2", "sctlr_el3", + "sctlr2_el3", "actlr_el3", "scr_el3", "sder32_el3", diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index befee2a4de..c2cf5356ac 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -376,6 +376,7 @@ namespace ArmISA EndBitUnion(NSACR) BitUnion64(SCR) + Bitfield<44> sctlr2En; Bitfield<40> trndr; Bitfield<38> hxen; Bitfield<27> fgten; @@ -1058,6 +1059,10 @@ namespace ArmISA Bitfield<0> afsr0EL1; EndBitUnion(HFGTR) + BitUnion64(HCRX) + Bitfield<15> sctlr2En; + EndBitUnion(HCRX) + } // namespace ArmISA } // namespace gem5 diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 9051eaa151..926a7e3343 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -1355,5 +1355,16 @@ fgtEnabled(ThreadContext *tc) static_cast(tc->readMiscReg(MISCREG_SCR_EL3)).fgten); } +bool +isHcrxEL2Enabled(ThreadContext *tc) +{ + if (!ArmSystem::has(ArmExtension::FEAT_HCX, tc)) + return false; + if (ArmSystem::haveEL(tc, EL3) && + !static_cast(tc->readMiscReg(MISCREG_SCR_EL3)).hxen) + return false; + return EL2Enabled(tc); +} + } // namespace ArmISA } // namespace gem5 diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index c231b93bdb..8ccb251fa5 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -365,6 +365,7 @@ void syncVecRegsToElems(ThreadContext *tc); void syncVecElemsToRegs(ThreadContext *tc); bool fgtEnabled(ThreadContext *tc); +bool isHcrxEL2Enabled(ThreadContext *tc); static inline bool useVMID(ExceptionLevel el, bool in_host) From eac5a8b215f97d1f3bc6e750d90ac36f3a9b2fbf Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 11 May 2023 09:53:52 +0100 Subject: [PATCH 410/693] arch-arm: Implement FEAT_TCR2 Change-Id: I0396f5938c09b68fcc3303a6fdda1e4dde290869 Signed-off-by: Giacomo Travaglini --- src/arch/arm/ArmSystem.py | 5 +- src/arch/arm/isa.cc | 2 + src/arch/arm/regs/misc.cc | 93 +++++++++++++++++++++++++++++++++ src/arch/arm/regs/misc.hh | 6 +++ src/arch/arm/regs/misc_types.hh | 2 + 5 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index febebda50e..f66c9c83d2 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -103,6 +103,7 @@ class ArmExtension(ScopedEnum): "FEAT_HCX", # Armv8.9 "FEAT_SCTLR2", + "FEAT_TCR2", # Armv9.2 "FEAT_SME", # Optional in Armv9.2 # Others @@ -261,9 +262,7 @@ class Armv87(Armv86): class Armv89(Armv87): - extensions = Armv87.extensions + [ - "FEAT_SCTLR2", - ] + extensions = Armv87.extensions + ["FEAT_SCTLR2", "FEAT_TCR2"] class Armv92(Armv89): diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 67031a1a9c..a395d1a35f 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -332,6 +332,8 @@ ISA::redirectRegVHE(int misc_reg) return MISCREG_TTBR1_EL1; case MISCREG_TCR_EL12: return MISCREG_TCR_EL1; + case MISCREG_TCR2_EL12: + return MISCREG_TCR2_EL1; case MISCREG_SPSR_EL12: return MISCREG_SPSR_EL1; case MISCREG_ELR_EL12: diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 5d971f3e20..039717a8b7 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -996,6 +996,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 0, 2, 0, 0), MISCREG_TTBR0_EL1 }, { MiscRegNum64(3, 0, 2, 0, 1), MISCREG_TTBR1_EL1 }, { MiscRegNum64(3, 0, 2, 0, 2), MISCREG_TCR_EL1 }, + { MiscRegNum64(3, 0, 2, 0, 3), MISCREG_TCR2_EL1 }, { MiscRegNum64(3, 0, 2, 1, 0), MISCREG_APIAKeyLo_EL1 }, { MiscRegNum64(3, 0, 2, 1, 1), MISCREG_APIAKeyHi_EL1 }, { MiscRegNum64(3, 0, 2, 1, 2), MISCREG_APIBKeyLo_EL1 }, @@ -1155,6 +1156,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 4, 2, 0, 0), MISCREG_TTBR0_EL2 }, { MiscRegNum64(3, 4, 2, 0, 1), MISCREG_TTBR1_EL2 }, { MiscRegNum64(3, 4, 2, 0, 2), MISCREG_TCR_EL2 }, + { MiscRegNum64(3, 4, 2, 0, 3), MISCREG_TCR2_EL2 }, { MiscRegNum64(3, 4, 2, 1, 0), MISCREG_VTTBR_EL2 }, { MiscRegNum64(3, 4, 2, 1, 2), MISCREG_VTCR_EL2 }, { MiscRegNum64(3, 4, 2, 6, 0), MISCREG_VSTTBR_EL2 }, @@ -1235,6 +1237,7 @@ std::unordered_map miscRegNumToIdx{ { MiscRegNum64(3, 5, 2, 0, 0), MISCREG_TTBR0_EL12 }, { MiscRegNum64(3, 5, 2, 0, 1), MISCREG_TTBR1_EL12 }, { MiscRegNum64(3, 5, 2, 0, 2), MISCREG_TCR_EL12 }, + { MiscRegNum64(3, 5, 2, 0, 3), MISCREG_TCR2_EL12 }, { MiscRegNum64(3, 5, 4, 0, 0), MISCREG_SPSR_EL12 }, { MiscRegNum64(3, 5, 4, 0, 1), MISCREG_ELR_EL12 }, { MiscRegNum64(3, 5, 5, 1, 0), MISCREG_AFSR0_EL12 }, @@ -1977,6 +1980,83 @@ faultSctlr2VheEL2(const MiscRegLUTEntry &entry, } } +template +Fault +faultTcr2EL1(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_TCR2)) { + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + const HCRX hcrx = tc->readMiscReg(MISCREG_HCRX_EL2); + if (auto fault = faultHcrFgtEL1(entry, tc, inst); + fault != NoFault) { + return fault; + } else if (EL2Enabled(tc) && (!isHcrxEL2Enabled(tc) || !hcrx.tcr2En)) { + return inst.generateTrap(EL2); + } else if (ArmSystem::haveEL(tc, EL3) && !scr.tcr2En) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } +} + +Fault +faultTcr2EL2(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_TCR2)) { + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + if (ArmSystem::haveEL(tc, EL3) && !scr.tcr2En) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } +} + +Fault +faultTcr2VheEL2(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_TCR2)) { + const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); + const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + if (hcr.e2h) { + if (ArmSystem::haveEL(tc, EL3) && !scr.tcr2En) { + return inst.generateTrap(EL3); + } else { + return NoFault; + } + } else { + return inst.undefined(); + } + } else { + return inst.undefined(); + } +} + +Fault +faultTcr2VheEL3(const MiscRegLUTEntry &entry, + ThreadContext *tc, const MiscRegOp64 &inst) +{ + if (HaveExt(tc, ArmExtension::FEAT_TCR2)) { + const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); + const bool el2_host = EL2Enabled(tc) && hcr.e2h; + if (el2_host) { + return NoFault; + } else { + return inst.undefined(); + } + } else { + return inst.undefined(); + } +} + template Fault faultCpacrEL1(const MiscRegLUTEntry &entry, @@ -4434,6 +4514,7 @@ ISA::initializeMiscRegMetadata() .reset([p,release=release](){ AA64MMFR3 mmfr3_el1 = 0; mmfr3_el1.sctlrx = release->has(ArmExtension::FEAT_SCTLR2) ? 0x1 : 0x0; + mmfr3_el1.tcrx = release->has(ArmExtension::FEAT_TCR2) ? 0x1 : 0x0; return mmfr3_el1; }()) .faultRead(EL0, faultIdst) @@ -4660,6 +4741,15 @@ ISA::initializeMiscRegMetadata() .fault(EL2, defaultFaultE2H_EL2) .fault(EL3, defaultFaultE2H_EL3) .mapsTo(MISCREG_TTBCR_NS); + InitReg(MISCREG_TCR2_EL1) + .allPrivileges().exceptUserMode() + .faultRead(EL1, faultTcr2EL1) + .faultWrite(EL1, faultTcr2EL1) + .fault(EL2, faultTcr2EL2); + InitReg(MISCREG_TCR2_EL12) + .fault(EL2, faultTcr2VheEL2) + .fault(EL3, faultTcr2VheEL3) + .mapsTo(MISCREG_TCR2_EL1); InitReg(MISCREG_TTBR0_EL2) .hyp().mon() .mapsTo(MISCREG_HTTBR); @@ -4668,6 +4758,9 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_TCR_EL2) .hyp().mon() .mapsTo(MISCREG_HTCR); + InitReg(MISCREG_TCR2_EL2) + .hyp().mon() + .fault(EL2, faultTcr2EL2); InitReg(MISCREG_VTTBR_EL2) .hyp().mon() .mapsTo(MISCREG_VTTBR); diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index 9e4d1cab84..6a4933c5d6 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -610,8 +610,11 @@ namespace ArmISA MISCREG_TTBR1_EL12, MISCREG_TCR_EL1, MISCREG_TCR_EL12, + MISCREG_TCR2_EL1, + MISCREG_TCR2_EL12, MISCREG_TTBR0_EL2, MISCREG_TCR_EL2, + MISCREG_TCR2_EL2, MISCREG_VTTBR_EL2, MISCREG_VTCR_EL2, MISCREG_VSTTBR_EL2, @@ -2334,8 +2337,11 @@ namespace ArmISA "ttbr1_el12", "tcr_el1", "tcr_el12", + "tcr2_el1", + "tcr2_el12", "ttbr0_el2", "tcr_el2", + "tcr2_el2", "vttbr_el2", "vtcr_el2", "vsttbr_el2", diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index c2cf5356ac..abbe2afa98 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -377,6 +377,7 @@ namespace ArmISA BitUnion64(SCR) Bitfield<44> sctlr2En; + Bitfield<43> tcr2En; Bitfield<40> trndr; Bitfield<38> hxen; Bitfield<27> fgten; @@ -1061,6 +1062,7 @@ namespace ArmISA BitUnion64(HCRX) Bitfield<15> sctlr2En; + Bitfield<14> tcr2En; EndBitUnion(HCRX) } // namespace ArmISA From 70f8c49e8b2bd54565166eaa96d120e549eaa446 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 6 Oct 2023 01:17:41 -0700 Subject: [PATCH 411/693] tests,misc: Remove 'run' and 'build' labels All runners are now equal, these labels are pointless. Change-Id: I9d5fb31e20e95d30e9726d4bf0353dc87af614d7 --- .github/workflows/ci-tests.yaml | 10 +++++----- .github/workflows/compiler-tests.yaml | 4 ++-- .github/workflows/daily-tests.yaml | 14 +++++++------- .github/workflows/docker-build.yaml | 4 ++-- .github/workflows/gpu-tests.yaml | 4 ++-- .github/workflows/weekly-tests.yaml | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 5a92422e79..103de52b31 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -47,7 +47,7 @@ jobs: exit 1 unittests-all-opt: - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] if: github.event.pull_request.draft == false container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes @@ -60,7 +60,7 @@ jobs: - run: echo "This job's status is ${{ job.status }}." testlib-quick-matrix: - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] if: github.event.pull_request.draft == false # In order to make sure the environment is exactly the same, we run in # the same container we use to build gem5 and run the testlib tests. This @@ -89,7 +89,7 @@ jobs: test-dirs-matrix: ${{ steps.dir-matrix.outputs.test-dirs-matrix }} testlib-quick-gem5-builds: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] if: github.event.pull_request.draft == false container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id, testlib-quick-matrix] @@ -119,7 +119,7 @@ jobs: retention-days: 7 testlib-quick-execution: - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] if: github.event.pull_request.draft == false container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [pre-commit, check-for-change-id, testlib-quick-matrix, testlib-quick-gem5-builds] @@ -174,7 +174,7 @@ jobs: # merged. The 'testlib-quick-execution' is a matrix job which runs all the # the testlib quick tests. This job is therefore a stub which will pass if # all the testlib-quick-execution jobs pass. - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] needs: testlib-quick-execution steps: - run: echo "This job's status is ${{ job.status }}." diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 595e231323..5bd6a8d165 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -17,7 +17,7 @@ jobs: matrix: image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-16, clang-version-15, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: @@ -38,7 +38,7 @@ jobs: gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, GCN3_X86] image: [gcc-version-12, clang-version-16] opts: [.opt] - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] timeout-minutes: 2880 # 48 hours container: gcr.io/gem5-test/${{ matrix.image }}:latest steps: diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 06d37c86a8..86dba0c139 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -36,7 +36,7 @@ jobs: command-line: --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) - image: NULL_MI_example command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] needs: name-artifacts container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest steps: @@ -59,7 +59,7 @@ jobs: strategy: matrix: type: [fast, debug] - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest timeout-minutes: 60 steps: @@ -77,7 +77,7 @@ jobs: fail-fast: false matrix: test-type: [arm_boot_tests, fs, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours for entire matrix to run @@ -164,7 +164,7 @@ jobs: # split library example tests into runs based on Suite UID # so that they don't hog the runners for too long testlib-long-gem5_library_example_tests: - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] strategy: fail-fast: false matrix: @@ -210,7 +210,7 @@ jobs: # This runs the SST-gem5 integration compilation and tests it with # ext/sst/sst/example.py. sst-test: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/sst-env:latest timeout-minutes: 180 @@ -232,7 +232,7 @@ jobs: # This runs the gem5 within SystemC ingration and runs a simple hello-world # simulation with it. systemc-test: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/systemc-env:latest timeout-minutes: 180 @@ -256,7 +256,7 @@ jobs: # Runs the gem5 Nighyly GPU tests. gpu-tests: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/gcn-gpu:latest timeout-minutes: 720 # 12 hours diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 19cf02c582..c0dc7bcb36 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -4,7 +4,7 @@ on: workflow_dispatch: jobs: obtain-dockerfiles: - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest steps: @@ -20,7 +20,7 @@ jobs: # This builds and pushes the docker image. build-and-push: - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] needs: obtain-dockerfiles permissions: packages: write diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index c6e0155ecf..98f2529b92 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -11,7 +11,7 @@ on: jobs: build-gem5: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/gcn-gpu:latest steps: - uses: actions/checkout@v3 @@ -29,7 +29,7 @@ jobs: - run: echo "This job's status is ${{ job.status }}." HACC-tests: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/gcn-gpu:latest needs: build-gem5 timeout-minutes: 120 # 2 hours diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 782647cb81..875bff12f7 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -11,7 +11,7 @@ on: jobs: build-gem5: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest outputs: build-name: ${{ steps.artifact-name.outputs.name }} @@ -39,7 +39,7 @@ jobs: fail-fast: false matrix: test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] - runs-on: [self-hosted, linux, x64, run] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest needs: [build-gem5] timeout-minutes: 4320 # 3 days @@ -79,7 +79,7 @@ jobs: - run: echo "This job's status is ${{ job.status }}." dramsys-tests: - runs-on: [self-hosted, linux, x64, build] + runs-on: [self-hosted, linux, x64] container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest timeout-minutes: 4320 # 3 days steps: From 243a2614917620fa5ed4905723bc8311c8be47a8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 6 Oct 2023 01:24:28 -0700 Subject: [PATCH 412/693] tests: Update Testlib CI tests to use multiheading These were previously only running on single-threaded machines. Now they'll be running on 4-core VMs so may as well run tests in parallel. Change-Id: I7ee86512dc72851cea307dfd800dcf9a02f2f738 --- .github/workflows/ci-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 103de52b31..b9016219ae 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -152,7 +152,7 @@ jobs: - name: Run "tests/${{ matrix.test-dir }}" TestLib quick tests id: run-tests working-directory: ${{ github.workspace }}/tests - run: ./main.py run --skip-build -vv ${{ matrix.test-dir }} + run: ./main.py run --skip-build -t $(nproc) -vv ${{ matrix.test-dir }} # Get the basename of the matrix.test-dir path (to name the artifact). - name: Sanatize test-dir for artifact name From d5e454138af1f31dfd0381ec3c52654b51983728 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 09:55:36 -0700 Subject: [PATCH 413/693] util: Remove 'run' and 'build' tags from runners Change-Id: Ib7b2eba5f08a1d8a311dc20cb55f540a5cd7dc7b --- util/github-runners-vagrant/Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 7743c3e6a4..3446f703dd 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -59,7 +59,7 @@ Vagrant.configure("2") do |config| runner.vm.provision "file", source: "./action-run.sh", destination: "/tmp/action-run.sh" runner.vm.provision :shell, privileged: false, inline: "cp /tmp/action-run.sh ." # Execute the actions-run.sh script on every boot. This configures the and starts the runner. - runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} "run,build" >> action-run.log 2>&1 &" + runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} >> action-run.log 2>&1 &" end end end From c53529783b03d2d01eab2cae94e256df11997ccc Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 13:09:21 -0700 Subject: [PATCH 414/693] misc,python: Add `requirements-txt-fixer` to pre-commit This sorts entries in requirements.txt files. Change-Id: I7ee6e31f3cbe5078f24d13471a6aa9edc482cecd --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 37b1acbbea..e3088b08be 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,6 +61,7 @@ repos: - id: check-added-large-files - id: mixed-line-ending args: [--fix=lf] + - id: requirements-txt-fixer - id: check-case-conflict - repo: https://github.com/psf/black rev: 22.6.0 From 402ec3a57cfe486844fadce9a1c085e2fea979b0 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 13:10:23 -0700 Subject: [PATCH 415/693] misc,python: Run `pre-commit run --all-files` This applies the `requirement-txt-fixer` to the repo. Change-Id: I23b1d26ad8deb49ec0019095efc6d253ac1c817c --- requirements.txt | 2 +- util/gem5-resources-manager/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index c057a43b97..4b820f51ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pre-commit==2.20.0 mypy==1.5.1 +pre-commit==2.20.0 diff --git a/util/gem5-resources-manager/requirements.txt b/util/gem5-resources-manager/requirements.txt index 72771183ed..5ffd51deb2 100644 --- a/util/gem5-resources-manager/requirements.txt +++ b/util/gem5-resources-manager/requirements.txt @@ -21,9 +21,9 @@ packaging==23.1 pycparser==2.21 pymongo==4.3.3 pyrsistent==0.19.3 +python-dotenv==1.0.0 requests==2.31.0 sentinels==1.0.0 urllib3==2.0.2 Werkzeug==2.3.4 zipp==3.15.0 -python-dotenv==1.0.0 From 5b09777011dd03a17431397b98adc321f1f366bb Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 13:16:52 -0700 Subject: [PATCH 416/693] misc,python: Add `pre-commit-hook-yamlfmt` to pre-commit This automatically formats .yaml files. By deault has the following parameters: * `mapping`: 4 spaces. * `sequence`: 6 spaces. * `offset`: 4 spaces. * `colons`: do not align top-level colons. * `width`: None. Change-Id: Iee5194cd57b7b162fd7e33aa6852b64c5578a3d2 --- .pre-commit-config.yaml | 97 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 37b1acbbea..367a7c09d6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +--- # Copyright (c) 2022 Arm Limited # All rights reserved. # @@ -33,57 +34,61 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -minimum_pre_commit_version: "2.18" +minimum_pre_commit_version: '2.18' default_language_version: - python: python3 + python: python3 exclude: | - (?x)^( - ext/(?!testlib/).*| - build/.*| - src/systemc/ext/.*| - src/systemc/tests/.*/.*| - src/python/m5/ext/pyfdt/.*| - tests/.*/ref/.* - )$ + (?x)^( + ext/(?!testlib/).*| + build/.*| + src/systemc/ext/.*| + src/systemc/tests/.*/.*| + src/python/m5/ext/pyfdt/.*| + tests/.*/ref/.* + )$ default_stages: [commit] repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-json - - id: check-yaml - - id: check-added-large-files - - id: mixed-line-ending - args: [--fix=lf] - - id: check-case-conflict -- repo: https://github.com/psf/black - rev: 22.6.0 - hooks: - - id: black -- repo: local - hooks: - - id: gem5-style-checker - name: gem5 style checker - entry: util/git-pre-commit.py - always_run: true - exclude: ".*" - language: system - description: 'The gem5 style checker hook.' - - id: gem5-commit-msg-checker - name: gem5 commit msg checker - entry: ext/git-commit-msg - language: system - stages: [commit-msg] - description: 'The gem5 commit message checker hook.' - - id: gerrit-commit-msg-job - name: gerrit commit message job - entry: util/gerrit-commit-msg-hook - language: system - stages: [commit-msg] - description: 'Adds Change-ID to the commit message. Needed by Gerrit.' + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-json + - id: check-yaml + - id: check-added-large-files + - id: mixed-line-ending + args: [--fix=lf] + - id: check-case-conflict + - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt + rev: 0.2.3 + hooks: + - id: yamlfmt + - repo: https://github.com/psf/black + rev: 22.6.0 + hooks: + - id: black + - repo: local + hooks: + - id: gem5-style-checker + name: gem5 style checker + entry: util/git-pre-commit.py + always_run: true + exclude: .* + language: system + description: The gem5 style checker hook. + - id: gem5-commit-msg-checker + name: gem5 commit msg checker + entry: ext/git-commit-msg + language: system + stages: [commit-msg] + description: The gem5 commit message checker hook. + - id: gerrit-commit-msg-job + name: gerrit commit message job + entry: util/gerrit-commit-msg-hook + language: system + stages: [commit-msg] + description: Adds Change-ID to the commit message. Needed by Gerrit. From fa8c9414b282832b2c963f8c6eafba42f05a264b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 13:20:25 -0700 Subject: [PATCH 417/693] misc,python: Run `pre-commit run --all-files` This applies the automatical formatting to the .yaml files. Change-Id: I10d067ba65722aca8aaf64a62b42ae57de468e75 --- .github/workflows/ci-tests.yaml | 261 +++++++------- .github/workflows/compiler-tests.yaml | 77 +++-- .github/workflows/daily-tests.yaml | 472 +++++++++++++------------- .github/workflows/docker-build.yaml | 79 ++--- .github/workflows/gpu-tests.yaml | 93 ++--- .github/workflows/utils.yaml | 26 +- .github/workflows/weekly-tests.yaml | 174 +++++----- MAINTAINERS.yaml | 299 ++++++++-------- util/dockerfiles/docker-compose.yaml | 1 + 9 files changed, 745 insertions(+), 737 deletions(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 5a92422e79..2a61c17209 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -1,105 +1,106 @@ +--- # This workflow runs after a pull-request has been approved by a reviewer. name: CI Tests on: - pull_request: - types: [opened, edited, synchronize, ready_for_review] + pull_request: + types: [opened, edited, synchronize, ready_for_review] concurrency: - group: ${{ github.workflow }}-${{ github.ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: - pre-commit: + pre-commit: # runs on github hosted runner - runs-on: ubuntu-22.04 - if: github.event.pull_request.draft == false - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v3.0.0 + runs-on: ubuntu-22.04 + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.0 # ensures we have a change-id in every commit, needed for gerrit - check-for-change-id: + check-for-change-id: # runs on github hosted runner - runs-on: ubuntu-22.04 - if: github.event.pull_request.draft == false - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Check for Change-Id - run: | - # loop through all the commits in the pull request - for commit in $(git rev-list ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}); do - git checkout $commit - if (git log -1 --pretty=format:"%B" | grep -q "Change-Id: ") - then - # passes as long as at least one change-id exists in the pull request - exit 0 - fi - done - # if we reach this part, none of the commits had a change-id - echo "None of the commits in this pull request contains a Change-ID, which we require for any changes made to gem5. "\ - "To automatically insert one, run the following:\n f=`git rev-parse --git-dir`/hooks/commit-msg ; mkdir -p $(dirname $f) ; "\ - "curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f\n Then amend the commit with git commit --amend --no-edit, and update your pull request." - exit 1 + runs-on: ubuntu-22.04 + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Check for Change-Id + run: | + # loop through all the commits in the pull request + for commit in $(git rev-list ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}); do + git checkout $commit + if (git log -1 --pretty=format:"%B" | grep -q "Change-Id: ") + then + # passes as long as at least one change-id exists in the pull request + exit 0 + fi + done + # if we reach this part, none of the commits had a change-id + echo "None of the commits in this pull request contains a Change-ID, which we require for any changes made to gem5. "\ + "To automatically insert one, run the following:\n f=`git rev-parse --git-dir`/hooks/commit-msg ; mkdir -p $(dirname $f) ; "\ + "curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f\n Then amend the commit with git commit --amend --no-edit, and update your pull request." + exit 1 - unittests-all-opt: - runs-on: [self-hosted, linux, x64, run] - if: github.event.pull_request.draft == false - container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes - timeout-minutes: 60 - steps: - - uses: actions/checkout@v3 - - name: CI Unittests - working-directory: ${{ github.workspace }} - run: scons build/ALL/unittests.opt -j $(nproc) - - run: echo "This job's status is ${{ job.status }}." + unittests-all-opt: + runs-on: [self-hosted, linux, x64, run] + if: github.event.pull_request.draft == false + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, check-for-change-id] # only runs if pre-commit and change-id passes + timeout-minutes: 60 + steps: + - uses: actions/checkout@v3 + - name: CI Unittests + working-directory: ${{ github.workspace }} + run: scons build/ALL/unittests.opt -j $(nproc) + - run: echo "This job's status is ${{ job.status }}." - testlib-quick-matrix: - runs-on: [self-hosted, linux, x64, run] - if: github.event.pull_request.draft == false + testlib-quick-matrix: + runs-on: [self-hosted, linux, x64, run] + if: github.event.pull_request.draft == false # In order to make sure the environment is exactly the same, we run in # the same container we use to build gem5 and run the testlib tests. This - container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, check-for-change-id] - steps: - - uses: actions/checkout@v3 + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, check-for-change-id] + steps: + - uses: actions/checkout@v3 # Unfortunately the 'ubunutu-latest' image doesn't have jq installed. # We therefore need to install it as a step here. - - name: Install jq - run: apt install -y jq + - name: Install jq + run: apt install -y jq - - name: Get directories for testlib-quick - working-directory: "${{ github.workspace }}/tests" - id: dir-matrix - run: echo "test-dirs-matrix=$(find gem5/* -type d -maxdepth 0 | jq -ncR '[inputs]')" >>$GITHUB_OUTPUT + - name: Get directories for testlib-quick + working-directory: ${{ github.workspace }}/tests + id: dir-matrix + run: echo "test-dirs-matrix=$(find gem5/* -type d -maxdepth 0 | jq -ncR '[inputs]')" >>$GITHUB_OUTPUT - - name: Get the build targets for testlib-quick-gem5-builds - working-directory: "${{ github.workspace }}/tests" - id: build-matrix - run: echo "build-matrix=$(./main.py list --build-targets -q | jq -ncR '[inputs]')" >>$GITHUB_OUTPUT + - name: Get the build targets for testlib-quick-gem5-builds + working-directory: ${{ github.workspace }}/tests + id: build-matrix + run: echo "build-matrix=$(./main.py list --build-targets -q | jq -ncR '[inputs]')" >>$GITHUB_OUTPUT - outputs: - build-matrix: ${{ steps.build-matrix.outputs.build-matrix }} - test-dirs-matrix: ${{ steps.dir-matrix.outputs.test-dirs-matrix }} + outputs: + build-matrix: ${{ steps.build-matrix.outputs.build-matrix }} + test-dirs-matrix: ${{ steps.dir-matrix.outputs.test-dirs-matrix }} - testlib-quick-gem5-builds: - runs-on: [self-hosted, linux, x64, build] - if: github.event.pull_request.draft == false - container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, check-for-change-id, testlib-quick-matrix] - strategy: - matrix: - build-target: ${{ fromJson(needs.testlib-quick-matrix.outputs.build-matrix) }} - steps: - - uses: actions/checkout@v3 - - name: Build gem5 - run: scons ${{ matrix.build-target }} -j $(nproc) + testlib-quick-gem5-builds: + runs-on: [self-hosted, linux, x64, build] + if: github.event.pull_request.draft == false + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, check-for-change-id, testlib-quick-matrix] + strategy: + matrix: + build-target: ${{ fromJson(needs.testlib-quick-matrix.outputs.build-matrix) }} + steps: + - uses: actions/checkout@v3 + - name: Build gem5 + run: scons ${{ matrix.build-target }} -j $(nproc) # Upload the gem5 binary as an artifact. # Note: the "achor.txt" file is a hack to make sure the paths are @@ -109,72 +110,70 @@ jobs: # Then upload-artifact will upload "ARM/gem5.opt" and "RISCV/gem5.opt", # stripping the "build" directory. By adding the "anchor.txt" file, we # ensure the "build" directory is preserved. - - run: echo "anchor" > anchor.txt - - uses: actions/upload-artifact@v3 - with: - name: ci-tests-${{ github.run_number }}-testlib-quick-all-gem5-builds - path: | - build/*/gem5.* - anchor.txt - retention-days: 7 + - run: echo "anchor" > anchor.txt + - uses: actions/upload-artifact@v3 + with: + name: ci-tests-${{ github.run_number }}-testlib-quick-all-gem5-builds + path: | + build/*/gem5.* + anchor.txt + retention-days: 7 - testlib-quick-execution: - runs-on: [self-hosted, linux, x64, run] - if: github.event.pull_request.draft == false - container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - needs: [pre-commit, check-for-change-id, testlib-quick-matrix, testlib-quick-gem5-builds] - timeout-minutes: 360 # 6 hours - strategy: - fail-fast: false - matrix: - test-dir: ${{ fromJson(needs.testlib-quick-matrix.outputs.test-dirs-matrix) }} - steps: - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true + testlib-quick-execution: + runs-on: [self-hosted, linux, x64, run] + if: github.event.pull_request.draft == false + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + needs: [pre-commit, check-for-change-id, testlib-quick-matrix, testlib-quick-gem5-builds] + timeout-minutes: 360 # 6 hours + strategy: + fail-fast: false + matrix: + test-dir: ${{ fromJson(needs.testlib-quick-matrix.outputs.test-dirs-matrix) }} + steps: + - name: Clean runner + run: rm -rf ./* || true rm -rf ./.??* || true rm -rf ~/.cache || true # Checkout the repository then download the gem5.opt artifact. - - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 - with: - name: ci-tests-${{ github.run_number }}-testlib-quick-all-gem5-builds + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 + with: + name: ci-tests-${{ github.run_number }}-testlib-quick-all-gem5-builds # Check that the gem5.opt artifact exists and is executable. - - name: Chmod gem5.{opt,debug,fast} to be executable - run: | - find . -name "gem5.opt" -exec chmod u+x {} \; - find . -name "gem5.debug" -exec chmod u+x {} \; - find . -name "gem5.fast" -exec chmod u+x {} \; + - name: Chmod gem5.{opt,debug,fast} to be executable + run: | + find . -name "gem5.opt" -exec chmod u+x {} \; + find . -name "gem5.debug" -exec chmod u+x {} \; + find . -name "gem5.fast" -exec chmod u+x {} \; # Run the testlib quick tests in the given directory. - - name: Run "tests/${{ matrix.test-dir }}" TestLib quick tests - id: run-tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --skip-build -vv ${{ matrix.test-dir }} + - name: Run "tests/${{ matrix.test-dir }}" TestLib quick tests + id: run-tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --skip-build -vv ${{ matrix.test-dir }} # Get the basename of the matrix.test-dir path (to name the artifact). - - name: Sanatize test-dir for artifact name - id: sanitize-test-dir - if: success() || failure() - run: echo "sanatized-test-dir=$(echo '${{ matrix.test-dir }}' | sed 's/\//-/g')" >> $GITHUB_OUTPUT + - name: Sanatize test-dir for artifact name + id: sanitize-test-dir + if: success() || failure() + run: echo "sanatized-test-dir=$(echo '${{ matrix.test-dir }}' | sed 's/\//-/g')" >> $GITHUB_OUTPUT # Upload the tests/testing-results directory as an artifact. - - name: Upload test results - if: success() || failure() - uses: actions/upload-artifact@v3 - with: - name: ci-tests-run-${{ github.run_number }}-attempt-${{ github.run_attempt }}-testlib-quick-${{ steps.sanitize-test-dir.outputs.sanatized-test-dir }}-status-${{ steps.run-tests.outcome }}-output - path: tests/testing-results - retention-days: 30 + - name: Upload test results + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: ci-tests-run-${{ github.run_number }}-attempt-${{ github.run_attempt }}-testlib-quick-${{ steps.sanitize-test-dir.outputs.sanatized-test-dir + }}-status-${{ steps.run-tests.outcome }}-output + path: tests/testing-results + retention-days: 30 - testlib-quick: + testlib-quick: # It is 'testlib-quick' which needs to pass for the pull request to be # merged. The 'testlib-quick-execution' is a matrix job which runs all the # the testlib quick tests. This job is therefore a stub which will pass if # all the testlib-quick-execution jobs pass. - runs-on: [self-hosted, linux, x64, run] - needs: testlib-quick-execution - steps: - - run: echo "This job's status is ${{ job.status }}." + runs-on: [self-hosted, linux, x64, run] + needs: testlib-quick-execution + steps: + - run: echo "This job's status is ${{ job.status }}." diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 595e231323..00c9482e3b 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -1,52 +1,57 @@ +--- # This workflow runs all of the compiler tests name: Compiler Tests on: # Runs every Friday from 7AM UTC - schedule: - - cron: '00 7 * * 5' + schedule: + - cron: 00 7 * * 5 # Allows us to manually start workflow for testing - workflow_dispatch: + workflow_dispatch: jobs: # replication of compiler-tests.sh - all-compilers: - strategy: - fail-fast: false - matrix: - image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-16, clang-version-15, clang-version-14, clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] - opts: [.opt, .fast] - runs-on: [self-hosted, linux, x64, build] - timeout-minutes: 2880 # 48 hours - container: gcr.io/gem5-test/${{ matrix.image }}:latest - steps: - - uses: actions/checkout@v3 - with: + all-compilers: + strategy: + fail-fast: false + matrix: + image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-16, clang-version-15, clang-version-14, + clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, + ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] + opts: [.opt, .fast] + runs-on: [self-hosted, linux, x64, build] + timeout-minutes: 2880 # 48 hours + container: gcr.io/gem5-test/${{ matrix.image }}:latest + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Compile build/ALL/gem5${{ matrix.opts }} with ${{ matrix.image }} - run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/ALL/gem5${{ matrix.opts }} -j$(nproc) - timeout-minutes: 600 # 10 hours + ref: develop + - name: Compile build/ALL/gem5${{ matrix.opts }} with ${{ matrix.image }} + run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/ALL/gem5${{ matrix.opts }} -j$(nproc) + timeout-minutes: 600 # 10 hours # Tests the two latest gcc and clang supported compilers against all gem5 compilations. - latest-compilers-all-gem5-builds: - strategy: - fail-fast: false - matrix: - gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, GCN3_X86] - image: [gcc-version-12, clang-version-16] - opts: [.opt] - runs-on: [self-hosted, linux, x64, build] - timeout-minutes: 2880 # 48 hours - container: gcr.io/gem5-test/${{ matrix.image }}:latest - steps: - - uses: actions/checkout@v3 - with: + latest-compilers-all-gem5-builds: + strategy: + fail-fast: false + matrix: + gem5-compilation: [ARM, ARM_MESI_Three_Level, ARM_MESI_Three_Level_HTM, ARM_MOESI_hammer, Garnet_standalone, GCN3_X86, MIPS, 'NULL', NULL_MESI_Two_Level, + NULL_MOESI_CMP_directory, NULL_MOESI_CMP_token, NULL_MOESI_hammer, POWER, RISCV, SPARC, X86, X86_MI_example, X86_MOESI_AMD_Base, VEGA_X86, + GCN3_X86] + image: [gcc-version-12, clang-version-16] + opts: [.opt] + runs-on: [self-hosted, linux, x64, build] + timeout-minutes: 2880 # 48 hours + container: gcr.io/gem5-test/${{ matrix.image }}:latest + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Compile build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} with ${{ matrix.image }} - run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} -j$(nproc) - timeout-minutes: 600 # 10 hours + ref: develop + - name: Compile build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} with ${{ matrix.image }} + run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} -j$(nproc) + timeout-minutes: 600 # 10 hours diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 06d37c86a8..13fca4cd92 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -1,286 +1,286 @@ +--- # This workflow runs all of the long tests within main.py, extra tests in nightly.sh, and unittests name: Daily Tests on: # Runs every day from 7AM UTC - schedule: - - cron: '0 7 * * *' + schedule: + - cron: 0 7 * * * jobs: - name-artifacts: - runs-on: ubuntu-latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v2 - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S-")" >> $GITHUB_OUTPUT + name-artifacts: + runs-on: ubuntu-latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v2 + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S-")" >> $GITHUB_OUTPUT - build-gem5: - strategy: - fail-fast: false - matrix: + build-gem5: + strategy: + fail-fast: false + matrix: # NULL is in quotes since it is considered a keyword in yaml files - image: [ALL, ALL_CHI, ARM, ALL_MSI, ALL_MESI_Two_Level, "NULL", NULL_MI_example, RISCV, VEGA_X86] + image: [ALL, ALL_CHI, ARM, ALL_MSI, ALL_MESI_Two_Level, 'NULL', NULL_MI_example, RISCV, VEGA_X86] # this allows us to pass additional command line parameters # the default is to add -j $(nproc), but some images # require more specifications when built - include: - - command-line: -j $(nproc) - - image: ALL_CHI - command-line: --default=ALL PROTOCOL=CHI -j $(nproc) - - image: ALL_MSI - command-line: --default=ALL PROTOCOL=MSI -j $(nproc) - - image: ALL_MESI_Two_Level - command-line: --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) - - image: NULL_MI_example - command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) - runs-on: [self-hosted, linux, x64, build] - needs: name-artifacts - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - steps: - - uses: actions/checkout@v3 - with: + include: + - command-line: -j $(nproc) + - image: ALL_CHI + command-line: --default=ALL PROTOCOL=CHI -j $(nproc) + - image: ALL_MSI + command-line: --default=ALL PROTOCOL=MSI -j $(nproc) + - image: ALL_MESI_Two_Level + command-line: --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) + - image: NULL_MI_example + command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) + runs-on: [self-hosted, linux, x64, build] + needs: name-artifacts + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Build gem5 - run: scons build/${{ matrix.image }}/gem5.opt ${{ matrix.command-line }} - - uses: actions/upload-artifact@v3 - with: - name: ${{ needs.name-artifacts.outputs.build-name }}${{ matrix.image }} - path: build/${{ matrix.image }}/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." + ref: develop + - name: Build gem5 + run: scons build/${{ matrix.image }}/gem5.opt ${{ matrix.command-line }} + - uses: actions/upload-artifact@v3 + with: + name: ${{ needs.name-artifacts.outputs.build-name }}${{ matrix.image }} + path: build/${{ matrix.image }}/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." # this builds both unittests.fast and unittests.debug - unittests-fast-debug: - strategy: - matrix: - type: [fast, debug] - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - timeout-minutes: 60 - steps: - - uses: actions/checkout@v3 - with: + unittests-fast-debug: + strategy: + matrix: + type: [fast, debug] + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: ALL/unittests.${{ matrix.type }} UnitTests - run: scons build/ALL/unittests.${{ matrix.type }} -j $(nproc) + ref: develop + - name: ALL/unittests.${{ matrix.type }} UnitTests + run: scons build/ALL/unittests.${{ matrix.type }} -j $(nproc) # start running all of the long tests - testlib-long-tests: - strategy: - fail-fast: false - matrix: - test-type: [arm_boot_tests, fs, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [name-artifacts, build-gem5] - timeout-minutes: 1440 # 24 hours for entire matrix to run - steps: - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - uses: actions/checkout@v3 - with: + testlib-long-tests: + strategy: + fail-fast: false + matrix: + test-type: [arm_boot_tests, fs, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, + stdlib, x86_boot_tests] + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [name-artifacts, build-gem5] + timeout-minutes: 1440 # 24 hours for entire matrix to run + steps: + - name: Clean runner + run: rm -rf ./* || true rm -rf ./.??* || true rm -rf ~/.cache || true + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop + ref: develop # download all artifacts for each test # since long tests can't start until the build matrix completes, # we download all artifacts from the build for each test # in this matrix - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}ALL - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}ALL_CHI - path: build/ALL_CHI - - run: chmod u+x build/ALL_CHI/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}ARM - path: build/ARM - - run: chmod u+x build/ARM/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}ALL_MSI - path: build/ALL_MSI - - run: chmod u+x build/ALL_MSI/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}ALL_MESI_Two_Level - path: build/ALL_MESI_Two_Level - - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}NULL - path: build/NULL - - run: chmod u+x build/NULL/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}NULL_MI_example - path: build/NULL_MI_example - - run: chmod u+x build/NULL_MI_example/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}RISCV - path: build/RISCV - - run: chmod u+x build/RISCV/gem5.opt - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}VEGA_X86 - path: build/VEGA_X86 - - run: chmod u+x build/VEGA_X86/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ALL + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ALL_CHI + path: build/ALL_CHI + - run: chmod u+x build/ALL_CHI/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ARM + path: build/ARM + - run: chmod u+x build/ARM/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ALL_MSI + path: build/ALL_MSI + - run: chmod u+x build/ALL_MSI/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ALL_MESI_Two_Level + path: build/ALL_MESI_Two_Level + - run: chmod u+x build/ALL_MESI_Two_Level/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}NULL + path: build/NULL + - run: chmod u+x build/NULL/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}NULL_MI_example + path: build/NULL_MI_example + - run: chmod u+x build/NULL_MI_example/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}RISCV + path: build/RISCV + - run: chmod u+x build/RISCV/gem5.opt + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}VEGA_X86 + path: build/VEGA_X86 + - run: chmod u+x build/VEGA_X86/gem5.opt # run test - - name: long ${{ matrix.test-type }} tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/${{ matrix.test-type }} --length=long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - run: echo "This job's status is ${{ job.status }}." + - name: long ${{ matrix.test-type }} tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/${{ matrix.test-type }} --length=long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." # split library example tests into runs based on Suite UID # so that they don't hog the runners for too long - testlib-long-gem5_library_example_tests: - runs-on: [self-hosted, linux, x64, run] - strategy: - fail-fast: false - matrix: - test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [name-artifacts, build-gem5] - timeout-minutes: 1440 # 24 hours - steps: - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - uses: actions/checkout@v3 - with: + testlib-long-gem5_library_example_tests: + runs-on: [self-hosted, linux, x64, run] + strategy: + fail-fast: false + matrix: + test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, + gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [name-artifacts, build-gem5] + timeout-minutes: 1440 # 24 hours + steps: + - name: Clean runner + run: rm -rf ./* || true rm -rf ./.??* || true rm -rf ~/.cache || true + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.name-artifacts.outputs.build-name}}ALL - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: long ${{ matrix.test-type }} gem5_library_example_tests - working-directory: ${{ github.workspace }}/tests - run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-${{ matrix.test-type }} --length=long --skip-build -vv - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - run: echo "This job's status is ${{ job.status }}." + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.name-artifacts.outputs.build-name}}ALL + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: long ${{ matrix.test-type }} gem5_library_example_tests + working-directory: ${{ github.workspace }}/tests + run: ./main.py run --uid SuiteUID:tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py:test-${{ matrix.test-type }} --length=long + --skip-build -vv + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." # This runs the SST-gem5 integration compilation and tests it with # ext/sst/sst/example.py. - sst-test: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/sst-env:latest - timeout-minutes: 180 + sst-test: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/sst-env:latest + timeout-minutes: 180 - steps: - - uses: actions/checkout@v3 - with: + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Build RISCV/libgem5_opt.so with SST - run: scons build/RISCV/libgem5_opt.so --without-tcmalloc --duplicate-sources --ignore-style -j $(nproc) - - name: Compile ext/sst - working-directory: ${{ github.workspace }}/ext/sst - run: make -j $(nproc) - - name: Run SST test - working-directory: ${{ github.workspace }}/ext/sst - run: sst --add-lib-path=./ sst/example.py + ref: develop + - name: Build RISCV/libgem5_opt.so with SST + run: scons build/RISCV/libgem5_opt.so --without-tcmalloc --duplicate-sources --ignore-style -j $(nproc) + - name: Compile ext/sst + working-directory: ${{ github.workspace }}/ext/sst + run: make -j $(nproc) + - name: Run SST test + working-directory: ${{ github.workspace }}/ext/sst + run: sst --add-lib-path=./ sst/example.py # This runs the gem5 within SystemC ingration and runs a simple hello-world # simulation with it. - systemc-test: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/systemc-env:latest - timeout-minutes: 180 + systemc-test: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/systemc-env:latest + timeout-minutes: 180 - steps: - - uses: actions/checkout@v3 - with: + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Build ARM/gem5.opt - run: scons build/ARM/gem5.opt --ignore-style --duplicate-sources -j$(nproc) - - name: Build ARM/libgem5_opt.so - run: scons build/ARM/libgem5_opt.so --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 -j$(nproc) --duplicate-sources - - name: Compile gem5 withing SystemC - working-directory: ${{ github.workspace }}/util/systemc/gem5_within_systemc - run: make - - name: Run gem5 within SystemC test - run: ./build/ARM/gem5.opt configs/deprecated/example/se.py -c tests/test-progs/hello/bin/arm/linux/hello - - name: Continue gem5 within SystemC test - run: LD_LIBRARY_PATH=build/ARM/:/opt/systemc/lib-linux64/ ./util/systemc/gem5_within_systemc/gem5.opt.sc m5out/config.ini + ref: develop + - name: Build ARM/gem5.opt + run: scons build/ARM/gem5.opt --ignore-style --duplicate-sources -j$(nproc) + - name: Build ARM/libgem5_opt.so + run: scons build/ARM/libgem5_opt.so --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 -j$(nproc) --duplicate-sources + - name: Compile gem5 withing SystemC + working-directory: ${{ github.workspace }}/util/systemc/gem5_within_systemc + run: make + - name: Run gem5 within SystemC test + run: ./build/ARM/gem5.opt configs/deprecated/example/se.py -c tests/test-progs/hello/bin/arm/linux/hello + - name: Continue gem5 within SystemC test + run: LD_LIBRARY_PATH=build/ARM/:/opt/systemc/lib-linux64/ ./util/systemc/gem5_within_systemc/gem5.opt.sc m5out/config.ini # Runs the gem5 Nighyly GPU tests. - gpu-tests: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/gcn-gpu:latest - timeout-minutes: 720 # 12 hours + gpu-tests: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/gcn-gpu:latest + timeout-minutes: 720 # 12 hours - steps: - - uses: actions/checkout@v3 - with: + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Compile build/GCN3_X86/gem5.opt - run: scons build/GCN3_X86/gem5.opt -j $(nproc) - - name: Get Square test-prog from gem5-resources - uses: wei/wget@v1 - with: - args: -q http://dist.gem5.org/dist/develop/test-progs/square/square # Removed -N bc it wasn't available within actions, should be okay bc workspace is clean every time: https://github.com/coder/sshcode/issues/102 - - name: Run Square test with GCN3_X86/gem5.opt (SE mode) - run: | - mkdir -p tests/testing-results - ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c square - - name: Get allSyncPrims-1kernel from gem5-resources - uses: wei/wget@v1 - with: - args: -q http://dist.gem5.org/dist/develop/test-progs/heterosync/gcn3/allSyncPrims-1kernel # Removed -N bc it wasn't available within actions, should be okay bc workspace is clean every time - - name: Run allSyncPrims-1kernel sleepMutex test with GCN3_X86/gem5.opt (SE mode) - run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="sleepMutex 10 16 4" - - name: Run allSyncPrims-1kernel lfTreeBarrUsing test with GCN3_X86/gem5.opt (SE mode) - run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="lfTreeBarrUniq 10 16 4" + ref: develop + - name: Compile build/GCN3_X86/gem5.opt + run: scons build/GCN3_X86/gem5.opt -j $(nproc) + - name: Get Square test-prog from gem5-resources + uses: wei/wget@v1 + with: + args: -q http://dist.gem5.org/dist/develop/test-progs/square/square # Removed -N bc it wasn't available within actions, should be okay bc workspace is clean every time: https://github.com/coder/sshcode/issues/102 + - name: Run Square test with GCN3_X86/gem5.opt (SE mode) + run: | + mkdir -p tests/testing-results + ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c square + - name: Get allSyncPrims-1kernel from gem5-resources + uses: wei/wget@v1 + with: + args: -q http://dist.gem5.org/dist/develop/test-progs/heterosync/gcn3/allSyncPrims-1kernel # Removed -N bc it wasn't available within actions, should be okay bc workspace is clean every time + - name: Run allSyncPrims-1kernel sleepMutex test with GCN3_X86/gem5.opt (SE mode) + run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="sleepMutex 10 16 + 4" + - name: Run allSyncPrims-1kernel lfTreeBarrUsing test with GCN3_X86/gem5.opt (SE mode) + run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="lfTreeBarrUniq + 10 16 4" diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 19cf02c582..1db41ca339 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -1,53 +1,54 @@ +--- name: Docker images build and push on: - workflow_dispatch: + workflow_dispatch: jobs: - obtain-dockerfiles: - runs-on: [self-hosted, linux, x64, run] - container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest + obtain-dockerfiles: + runs-on: [self-hosted, linux, x64, run] + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest - steps: - - uses: actions/checkout@v3 - with: + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/upload-artifact@v3 - with: - name: dockerfiles - path: util/dockerfiles + ref: develop + - uses: actions/upload-artifact@v3 + with: + name: dockerfiles + path: util/dockerfiles # This builds and pushes the docker image. - build-and-push: - runs-on: [self-hosted, linux, x64, run] - needs: obtain-dockerfiles - permissions: - packages: write - contents: read + build-and-push: + runs-on: [self-hosted, linux, x64, run] + needs: obtain-dockerfiles + permissions: + packages: write + contents: read - steps: - - uses: actions/download-artifact@v3 - with: - name: dockerfiles - path: dockerfiles-docker-build + steps: + - uses: actions/download-artifact@v3 + with: + name: dockerfiles + path: dockerfiles-docker-build - - uses: docker/setup-qemu-action@v2 - name: Setup QEMU + - uses: docker/setup-qemu-action@v2 + name: Setup QEMU - - uses: docker/setup-buildx-action@v2 - name: Set up Docker Buildx + - uses: docker/setup-buildx-action@v2 + name: Set up Docker Buildx - - uses: docker/login-action@v2 - name: Login to the GitHub Container Registry - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/login-action@v2 + name: Login to the GitHub Container Registry + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push with bake - uses: docker/bake-action@v4 - with: - workdir: ./dockerfiles-docker-build - files: docker-bake.hcl - push: true + - name: Build and push with bake + uses: docker/bake-action@v4 + with: + workdir: ./dockerfiles-docker-build + files: docker-bake.hcl + push: true diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index c6e0155ecf..298d655b7d 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -1,60 +1,61 @@ +--- # This workflow runs all of the very-long tests within main.py name: Weekly Tests on: # Runs every Sunday from 7AM UTC - schedule: - - cron: '00 7 * * 6' + schedule: + - cron: 00 7 * * 6 # Allows us to manually start workflow for testing - workflow_dispatch: + workflow_dispatch: jobs: - build-gem5: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/gcn-gpu:latest - steps: - - uses: actions/checkout@v3 - with: + build-gem5: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/gcn-gpu:latest + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Build gem5 - run: scons build/GCN3_X86/gem5.opt -j $(nproc) --ignore-style - - uses: actions/upload-artifact@v3 - with: - name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 - path: build/GCN3_X86/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." + ref: develop + - name: Build gem5 + run: scons build/GCN3_X86/gem5.opt -j $(nproc) --ignore-style + - uses: actions/upload-artifact@v3 + with: + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 + path: build/GCN3_X86/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." - HACC-tests: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/gcn-gpu:latest - needs: build-gem5 - timeout-minutes: 120 # 2 hours - steps: - - uses: actions/checkout@v3 - with: + HACC-tests: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/gcn-gpu:latest + needs: build-gem5 + timeout-minutes: 120 # 2 hours + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 - path: build/GCN3_X86 - - run: chmod u+x build/GCN3_X86/gem5.opt - - name: make hip directory - run: mkdir hip - - name: Compile m5ops and x86 - working-directory: ${{ github.workspace }}/util/m5 - run: | - export TERM=xterm-256color - scons build/x86/out/m5 - - name: Download tests - working-directory: ${{ github.workspace }}/hip - run: wget http://dist.gem5.org/dist/v22-1/test-progs/halo-finder/ForceTreeTest - - name: Run HACC tests - working-directory: ${{ github.workspace }} - run: | - build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --reg-alloc-policy=dynamic --benchmark-root=hip -c ForceTreeTest --options="0.5 0.1 64 0.1 1 N 12 rcb" + ref: develop + - uses: actions/download-artifact@v3 + with: + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 + path: build/GCN3_X86 + - run: chmod u+x build/GCN3_X86/gem5.opt + - name: make hip directory + run: mkdir hip + - name: Compile m5ops and x86 + working-directory: ${{ github.workspace }}/util/m5 + run: | + export TERM=xterm-256color + scons build/x86/out/m5 + - name: Download tests + working-directory: ${{ github.workspace }}/hip + run: wget http://dist.gem5.org/dist/v22-1/test-progs/halo-finder/ForceTreeTest + - name: Run HACC tests + working-directory: ${{ github.workspace }} + run: | + build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --reg-alloc-policy=dynamic --benchmark-root=hip -c ForceTreeTest --options="0.5 0.1 64 0.1 1 N 12 rcb" diff --git a/.github/workflows/utils.yaml b/.github/workflows/utils.yaml index 91d0bf1722..ccbd87c82f 100644 --- a/.github/workflows/utils.yaml +++ b/.github/workflows/utils.yaml @@ -1,19 +1,21 @@ +--- # This workflow file contains miscellaneous tasks to manage the repository. name: Utils for Repository on: - schedule: - - cron: '30 1 * * *' - workflow_dispatch: + schedule: + - cron: 30 1 * * * + workflow_dispatch: jobs: # This job runs the stale action to close issues that have been inactive for 30 days. # It is scheduled to run every day at 1:30 AM UTC. - close-stale-issues: - runs-on: ubuntu-latest - steps: - - uses: actions/stale@v8.0.0 - with: - close-issue-message: 'This issue is being closed because it has been inactive waiting for response for 30 days. If this is still an issue, please open a new issue and reference this one.' - days-before-stale: 21 - days-before-close: 7 - any-of-labels: 'needs details' + close-stale-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v8.0.0 + with: + close-issue-message: This issue is being closed because it has been inactive waiting for response for 30 days. If this is still an issue, + please open a new issue and reference this one. + days-before-stale: 21 + days-before-close: 7 + any-of-labels: needs details diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 782647cb81..6a6dcc6812 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -1,110 +1,108 @@ +--- # This workflow runs all of the very-long tests within main.py name: Weekly Tests on: # Runs every Sunday from 7AM UTC - schedule: - - cron: '00 7 * * 6' + schedule: + - cron: 00 7 * * 6 # Allows us to manually start workflow for testing - workflow_dispatch: + workflow_dispatch: jobs: - build-gem5: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - outputs: - build-name: ${{ steps.artifact-name.outputs.name }} - steps: - - uses: actions/checkout@v3 - with: + build-gem5: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + outputs: + build-name: ${{ steps.artifact-name.outputs.name }} + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - id: artifact-name - run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL" >> $GITHUB_OUTPUT - - name: Build gem5 - run: | - scons build/ALL/gem5.opt -j $(nproc) - - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.artifact-name.outputs.name }} - path: build/ALL/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." + ref: develop + - id: artifact-name + run: echo "name=$(date +"%Y-%m-%d_%H.%M.%S")-ALL" >> $GITHUB_OUTPUT + - name: Build gem5 + run: | + scons build/ALL/gem5.opt -j $(nproc) + - uses: actions/upload-artifact@v3 + with: + name: ${{ steps.artifact-name.outputs.name }} + path: build/ALL/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." # start running the very-long tests - testlib-very-long-tests: - strategy: - fail-fast: false - matrix: - test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] - runs-on: [self-hosted, linux, x64, run] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - needs: [build-gem5] - timeout-minutes: 4320 # 3 days - steps: - - name: Clean runner - run: - rm -rf ./* || true - rm -rf ./.??* || true - rm -rf ~/.cache || true - - uses: actions/checkout@v3 - with: + testlib-very-long-tests: + strategy: + fail-fast: false + matrix: + test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] + runs-on: [self-hosted, linux, x64, run] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + needs: [build-gem5] + timeout-minutes: 4320 # 3 days + steps: + - name: Clean runner + run: rm -rf ./* || true rm -rf ./.??* || true rm -rf ~/.cache || true + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop - - uses: actions/download-artifact@v3 - with: - name: ${{needs.build-gem5.outputs.build-name}} - path: build/ALL - - run: chmod u+x build/ALL/gem5.opt - - name: very-long ${{ matrix.test-type }} - working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/${{ matrix.test-type }} --length very-long --skip-build -vv -t $(nproc) - - name: create zip of results - if: success() || failure() - run: | - apt-get -y install zip - zip -r output.zip tests/testing-results - - name: upload zip - if: success() || failure() - uses: actions/upload-artifact@v3 - env: - MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} - with: - name: ${{ env.MY_STEP_VAR }} - path: output.zip - retention-days: 7 - - run: echo "This job's status is ${{ job.status }}." + ref: develop + - uses: actions/download-artifact@v3 + with: + name: ${{needs.build-gem5.outputs.build-name}} + path: build/ALL + - run: chmod u+x build/ALL/gem5.opt + - name: very-long ${{ matrix.test-type }} + working-directory: ${{ github.workspace }}/tests + run: ./main.py run gem5/${{ matrix.test-type }} --length very-long --skip-build -vv -t $(nproc) + - name: create zip of results + if: success() || failure() + run: | + apt-get -y install zip + zip -r output.zip tests/testing-results + - name: upload zip + if: success() || failure() + uses: actions/upload-artifact@v3 + env: + MY_STEP_VAR: ${{ matrix.test-type }}_COMMIT.${{github.sha}}_RUN.${{github.run_id}}_ATTEMPT.${{github.run_attempt}} + with: + name: ${{ env.MY_STEP_VAR }} + path: output.zip + retention-days: 7 + - run: echo "This job's status is ${{ job.status }}." - dramsys-tests: - runs-on: [self-hosted, linux, x64, build] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest - timeout-minutes: 4320 # 3 days - steps: - - uses: actions/checkout@v3 - with: + dramsys-tests: + runs-on: [self-hosted, linux, x64, build] + container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + timeout-minutes: 4320 # 3 days + steps: + - uses: actions/checkout@v3 + with: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. - ref: develop + ref: develop - - name: Checkout DRAMSys - working-directory: ${{ github.workspace }}/ext/dramsys - run: | - git clone https://github.com/tukl-msd/DRAMSys DRAMSys - cd DRAMSys - git checkout -b gem5 09f6dcbb91351e6ee7cadfc7bc8b29d97625db8f - git submodule update --init --recursive + - name: Checkout DRAMSys + working-directory: ${{ github.workspace }}/ext/dramsys + run: | + git clone https://github.com/tukl-msd/DRAMSys DRAMSys + cd DRAMSys + git checkout -b gem5 09f6dcbb91351e6ee7cadfc7bc8b29d97625db8f + git submodule update --init --recursive # gem5 is built separately because it depends on the DRAMSys library - - name: Build gem5 - working-directory: ${{ github.workspace }} - run: scons build/ALL/gem5.opt -j $(nproc) + - name: Build gem5 + working-directory: ${{ github.workspace }} + run: scons build/ALL/gem5.opt -j $(nproc) - - name: Run DRAMSys Checks - working-directory: ${{ github.workspace }} - run: | - ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/arm-hello-dramsys.py - ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/dramsys-traffic.py - ./build/ALL/gem5.opt configs/example/dramsys.py + - name: Run DRAMSys Checks + working-directory: ${{ github.workspace }} + run: | + ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/arm-hello-dramsys.py + ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/dramsys-traffic.py + ./build/ALL/gem5.opt configs/example/dramsys.py diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index 02a8b3eb7b..6636f11e26 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -1,3 +1,4 @@ +--- # See CONTRIBUTING.md for details of gem5's contribution process. # # This file contains a list of gem5's subsystems and their @@ -40,246 +41,246 @@ # targeting that subsystem. arch: - desc: >- - General architecture-specific components - status: orphaned + desc: >- + General architecture-specific components + status: orphaned arch-arm: - status: maintained - maintainers: - - Giacomo Travaglini - - Andreas Sandberg + status: maintained + maintainers: + - Giacomo Travaglini + - Andreas Sandberg arch-gcn3: - status: maintained - maintainers: - - Matt Sinclair - - Matt Porema + status: maintained + maintainers: + - Matt Sinclair + - Matt Porema arch-vega: - status: maintained - maintainers: - - Matt Sinclair - - Matt Porema + status: maintained + maintainers: + - Matt Sinclair + - Matt Porema arch-mips: - status: orphaned + status: orphaned arch-power: - status: orphaned + status: orphaned arch-riscv: - status: orphaned + status: orphaned arch-sparc: - status: orphaned + status: orphaned arch-x86: - status: orphaned + status: orphaned base: - status: orphaned + status: orphaned base-stats: - status: orphaned + status: orphaned configs: - status: orphaned - experts: - - Jason Lowe-Power + status: orphaned + experts: + - Jason Lowe-Power cpu: - desc: >- - General changes to all CPU models (e.g., BaseCPU) - status: orphaned - experts: - - Jason Lowe-Power + desc: >- + General changes to all CPU models (e.g., BaseCPU) + status: orphaned + experts: + - Jason Lowe-Power cpu-kvm: - status: maintained - maintainers: - - Andreas Sandberg + status: maintained + maintainers: + - Andreas Sandberg cpu-minor: - status: orphaned + status: orphaned cpu-o3: - status: orphaned + status: orphaned cpu-simple: - status: orphaned - experts: - - Jason Lowe-Power + status: orphaned + experts: + - Jason Lowe-Power dev: - status: orphaned + status: orphaned dev-hsa: - status: maintained - maintainers: - - Matt Poremba + status: maintained + maintainers: + - Matt Poremba dev-amdgpu: - status: maintained - maintainers: - - Matt Poremba + status: maintained + maintainers: + - Matt Poremba dev-virtio: - status: maintained - maintainers: - - Andreas Sandberg + status: maintained + maintainers: + - Andreas Sandberg dev-arm: - status: maintained - maintainers: - - Giacomo Travaglini - - Andreas Sandberg + status: maintained + maintainers: + - Giacomo Travaglini + - Andreas Sandberg doc: - status: orphaned + status: orphaned ext: - desc: >- - Components external to gem5 - status: orphaned - experts: - - Jason Lowe-Power + desc: >- + Components external to gem5 + status: orphaned + experts: + - Jason Lowe-Power ext-testlib: - status: orphaned - experts: - - Bobby R. Bruce + status: orphaned + experts: + - Bobby R. Bruce fastmodel: - desc: >- - Changes relating to ARM Fast Models - status: orphaned + desc: >- + Changes relating to ARM Fast Models + status: orphaned gpu-compute: - status: maintained - maintainers: - - Matt Poremba + status: maintained + maintainers: + - Matt Poremba learning-gem5: - desc: >- - The code and configs for the Learning gem5 book - status: orphaned - experts: - - Jason Lowe-Power - - Bobby R. Bruce + desc: >- + The code and configs for the Learning gem5 book + status: orphaned + experts: + - Jason Lowe-Power + - Bobby R. Bruce stdlib: - desc: >- - The gem5 standard library found under `src/python/gem5` - status: maintained - maintainers: - - Bobby R. Bruce + desc: >- + The gem5 standard library found under `src/python/gem5` + status: maintained + maintainers: + - Bobby R. Bruce mem: - desc: >- - General memory system (e.g., XBar, Packet) - status: orphaned + desc: >- + General memory system (e.g., XBar, Packet) + status: orphaned mem-cache: - desc: >- - Classic caches and coherence - status: orphaned + desc: >- + Classic caches and coherence + status: orphaned mem-dram: - status: orphaned + status: orphaned mem-garnet: - desc: >- - Garnet subcomponent of Ruby - status: orphaned + desc: >- + Garnet subcomponent of Ruby + status: orphaned mem-ruby: - desc: >- - Ruby structures and protocols - status: maintained - maintainers: - - Matt Sinclair - experts: - - Jason Lowe-Power + desc: >- + Ruby structures and protocols + status: maintained + maintainers: + - Matt Sinclair + experts: + - Jason Lowe-Power misc: - desc: >- - Anything outside of the other categories - status: orphaned - experts: - - Jason Lowe-Power + desc: >- + Anything outside of the other categories + status: orphaned + experts: + - Jason Lowe-Power python: - desc: >- - Python SimObject wrapping and infrastructure - status: orphaned - experts: - - Jason Lowe-Power - - Andreas Sandberg + desc: >- + Python SimObject wrapping and infrastructure + status: orphaned + experts: + - Jason Lowe-Power + - Andreas Sandberg resources: - desc: >- - The gem5-resources repo with auxiliary resources for simulation - status: maintained - maintainers: - - Bobby R. Bruce - experts: - - Jason Lowe-Power + desc: >- + The gem5-resources repo with auxiliary resources for simulation + status: maintained + maintainers: + - Bobby R. Bruce + experts: + - Jason Lowe-Power scons: - desc: >- - Build system - status: orphaned + desc: >- + Build system + status: orphaned sim: - desc: >- - General simulation components - status: orphaned - experts: - - Jason Lowe-Power + desc: >- + General simulation components + status: orphaned + experts: + - Jason Lowe-Power sim-se: - desc: >- - Syscall emulation - status: orphaned + desc: >- + Syscall emulation + status: orphaned system-arm: - status: maintained - maintainers: - - Giacomo Travaglini - - Andreas Sandberg + status: maintained + maintainers: + - Giacomo Travaglini + - Andreas Sandberg systemc: - desc: >- - Code for the gem5 SystemC implementation and interface - status: orphaned + desc: >- + Code for the gem5 SystemC implementation and interface + status: orphaned tests: - desc: >- - testing changes - status: maintained - maintainers: - - Bobby R. Bruce + desc: >- + testing changes + status: maintained + maintainers: + - Bobby R. Bruce util: - status: orphaned + status: orphaned util-docker: - status: maintained - maintainers: - - Bobby R. Bruce + status: maintained + maintainers: + - Bobby R. Bruce util-m5: - status: orphaned + status: orphaned util-gem5art: - status: orphaned + status: orphaned website: - desc: >- - The gem5-website repo which contains the gem5.org site - status: maintained - maintainers: - - Bobby R. Bruce - experts: - - Jason Lowe-Power + desc: >- + The gem5-website repo which contains the gem5.org site + status: maintained + maintainers: + - Bobby R. Bruce + experts: + - Jason Lowe-Power diff --git a/util/dockerfiles/docker-compose.yaml b/util/dockerfiles/docker-compose.yaml index fcbc3e9f70..a4f585f6d7 100644 --- a/util/dockerfiles/docker-compose.yaml +++ b/util/dockerfiles/docker-compose.yaml @@ -1,3 +1,4 @@ +--- version: '2' services: From 1fe0056d3b9b5a3d185e63b86afe7798165451a7 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 14:00:21 -0700 Subject: [PATCH 418/693] configs,tests: Remove `mkdir` in simpoint-se-checkpoint.py This `mkdir` is problematic as it doesn't create the directory recursively. This casues errors if `dir` is `X/Y/Z` and both `Y` and `Z` has not been created. An error will be returned (`No such file or directory`). This issue was fixed with: https://github.com/gem5/gem5/pull/263. The checkpointing code already recursively creates directories as needed. Ergo was can remove this `mkdir` statement. Change-Id: Ibae38267c8ee1eba76d7834367aa1c54013365bc --- .../example/gem5_library/checkpoints/simpoints-se-checkpoint.py | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py b/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py index b5eb7e9912..5787bf4bfc 100644 --- a/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py @@ -128,7 +128,6 @@ board.set_se_simpoint_workload( ) dir = Path(args.checkpoint_path) -dir.mkdir(exist_ok=True) simulator = Simulator( board=board, From 51c881d0f1967db677892e1d25f21afa3adec5b0 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 13:06:36 -0700 Subject: [PATCH 419/693] stdlib: Improve handing of errors in Atlas request failures Now: * The Atlas Client will attempt a connection 4 times, using an exponential backoff approach between attempts. * When a failure does arise a rich output is given so problems can be easily diagnosed. Change-Id: I3df332277c33a040c0ed734b9f3e28f38606af44 --- .../resources/client_api/abstract_client.py | 20 --- .../gem5/resources/client_api/atlasclient.py | 114 ++++++++++++++---- .../resources/client_api/client_wrapper.py | 8 +- 3 files changed, 99 insertions(+), 43 deletions(-) diff --git a/src/python/gem5/resources/client_api/abstract_client.py b/src/python/gem5/resources/client_api/abstract_client.py index 7f8ad6166e..0365b5ca60 100644 --- a/src/python/gem5/resources/client_api/abstract_client.py +++ b/src/python/gem5/resources/client_api/abstract_client.py @@ -30,26 +30,6 @@ import urllib.parse class AbstractClient(ABC): - def verify_status_code(self, status_code: int) -> None: - """ - Verifies that the status code is 200. - :param status_code: The status code to verify. - """ - if status_code == 200: - return - if status_code == 429: - raise Exception("Panic: Too many requests") - if status_code == 401: - raise Exception("Panic: Unauthorized") - if status_code == 404: - raise Exception("Panic: Not found") - if status_code == 400: - raise Exception("Panic: Bad request") - if status_code == 500: - raise Exception("Panic: Internal server error") - - raise Exception(f"Panic: Unknown status code {status_code}") - def _url_validator(self, url: str) -> bool: """ Validates the provided URL. diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py index 7d2a27c3f7..a39f478458 100644 --- a/src/python/gem5/resources/client_api/atlasclient.py +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -25,11 +25,40 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from urllib import request, parse -from urllib.error import HTTPError, URLError from typing import Optional, Dict, Union, Type, Tuple, List, Any import json +import time +import itertools from .abstract_client import AbstractClient +from m5.util import warn + + +class AtlasClientHttpJsonRequestError(Exception): + def __init__( + self, + client: "AtlasClient", + data: Dict[str, Any], + purpose_of_request: Optional[str], + ): + """An exception raised when an HTTP request to Atlas MongoDB fails. + :param client: The AtlasClient instance that raised the exception. + :param purpose_of_request: A string describing the purpose of the + request. + """ + error_str = ( + f"Http Request to Atlas MongoDB failed.\n" + f"Atlas URL: {client.url}\n" + f"Auth URL: {client.authUrl}\n" + f"Database: {client.database}\n" + f"Collection: {client.collection}\n\n" + f"Data sent:\n\n{json.dumps(data,indent=4)}\n\n" + ) + + if purpose_of_request: + error_str += f"Purpose of Request: {purpose_of_request}\n\n" + super().__init__(error_str) + class AtlasClient(AbstractClient): def __init__(self, config: Dict[str, str]): @@ -47,22 +76,69 @@ class AtlasClient(AbstractClient): self.authUrl = config["authUrl"] def get_token(self): - data = {"key": self.apiKey} - data = json.dumps(data).encode("utf-8") + return self._atlas_http_json_req( + self.url, + data_json={"key": self.apiKey}, + headers={"Content-Type": "application/json"}, + purpose_of_request="Get Access Token with API key", + )["access_token"] + + def _atlas_http_json_req( + self, + url: str, + data_json: Dict[str, Any], + headers: Dict[str, str], + purpose_of_request: Optional[str], + max_failed_attempts: int = 4, + reattempt_pause_base: int = 2, + ) -> Dict[str, Any]: + """Sends a JSON object over HTTP to a given Atlas MongoDB server and + returns the response. This function will attempt to reconnect to the + server if the connection fails a set number of times before raising an + exception. + + :param url: The URL to open the connection. + :param data_json: The JSON object to send. + :param headers: The headers to send with the request. + :param purpose_of_request: A string describing the purpose of the + request. This is optional. It's used to give context to the user if an + exception is raised. + :param max_failed_attempts: The maximum number of times to an attempt + at making a request should be done before throwing an exception. + :param reattempt_pause_base: The base of the exponential backoff -- the + time between each attempt. + + **Warning**: This function assumes a JSON response. + """ + data = json.dumps(data_json).encode("utf-8") req = request.Request( - self.authUrl, + url, data=data, - headers={"Content-Type": "application/json"}, + headers=headers, ) - try: - response = request.urlopen(req) - except HTTPError as e: - self.verify_status_code(e.status) - return None - result = json.loads(response.read().decode("utf-8")) - token = result["access_token"] - return token + + for attempt in itertools.count(start=1): + try: + response = request.urlopen(req) + break + except Exception as e: + if attempt >= max_failed_attempts: + raise AtlasClientHttpJsonRequestError( + client=self, + data=data_json, + purpose_of_request=purpose_of_request, + ) + pause = reattempt_pause_base**attempt + warn( + f"Attempt {attempt} of Atlas HTTP Request failed.\n" + f"Purpose of Request: {purpose_of_request}.\n\n" + f"Failed with Exception:\n{e}\n\n" + f"Retrying after {pause} seconds..." + ) + time.sleep(pause) + + return json.loads(response.read().decode("utf-8")) def get_resources( self, @@ -84,21 +160,15 @@ class AtlasClient(AbstractClient): if filter: data["filter"] = filter - data = json.dumps(data).encode("utf-8") headers = { "Authorization": f"Bearer {self.get_token()}", "Content-Type": "application/json", } - req = request.Request(url, data=data, headers=headers) - try: - response = request.urlopen(req) - except HTTPError as e: - self.verify_status_code(e.status) - return None - result = json.loads(response.read().decode("utf-8")) - resources = result["documents"] + resources = self._atlas_http_json_req( + url, data=data, headers=headers, purpose_of_request="Get Resources" + )["documents"] # I do this as a lazy post-processing step because I can't figure out # how to do this via an Atlas query, which may be more efficient. diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index ccb92cfb20..12030e1649 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -30,6 +30,7 @@ from _m5 import core from typing import Optional, Dict, List, Tuple import itertools from m5.util import warn +import sys class ClientWrapper: @@ -114,7 +115,12 @@ class ClientWrapper: self.clients[client].get_resources_by_id(resource_id) ) except Exception as e: - warn(f"Error getting resources from client {client}: {str(e)}") + print( + f"Exception thrown while getting resource '{resource_id}' " + f"from client '{client}'\n", + file=sys.stderr, + ) + raise e # check if no 2 resources have the same id and version for res1, res2 in itertools.combinations(resources, 2): if res1["resource_version"] == res2["resource_version"]: From 05ebbd2184adf491d2deb7e3213b83072b4de0c9 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 10 Oct 2023 05:25:26 +0000 Subject: [PATCH 420/693] stdlib: Fix use internal _hashlib in md5_utils.py Removes the use of the internal _hashlib, which is an internal Python API Change-Id: Id4541a143adb767ca7d942c0fd8a1cf1a08a04ab --- src/python/gem5/resources/md5_utils.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/python/gem5/resources/md5_utils.py b/src/python/gem5/resources/md5_utils.py index f4a1a87df5..a371274fef 100644 --- a/src/python/gem5/resources/md5_utils.py +++ b/src/python/gem5/resources/md5_utils.py @@ -1,4 +1,5 @@ # Copyright (c) 2022-2023 The Regents of the University of California +# Copyright (c) 2023 COSEDA Technologies GmbH # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,11 +26,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from pathlib import Path +from typing import Type import hashlib -from _hashlib import HASH as Hash -def _md5_update_from_file(filename: Path, hash: Hash) -> Hash: +def _md5_update_from_file( + filename: Path, hash: Type[hashlib.md5] +) -> Type[hashlib.md5]: assert filename.is_file() if filename.stat().st_size < 1024 * 1024 * 100: @@ -52,7 +55,9 @@ def _md5_update_from_file(filename: Path, hash: Hash) -> Hash: return hash -def _md5_update_from_dir(directory: Path, hash: Hash) -> Hash: +def _md5_update_from_dir( + directory: Path, hash: Type[hashlib.md5] +) -> Type[hashlib.md5]: assert directory.is_dir() for path in sorted(directory.iterdir(), key=lambda p: str(p).lower()): hash.update(path.name.encode()) From e412ddddbd717487adc35dddd5655cb729f3e515 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 1 Jun 2023 14:16:59 +0100 Subject: [PATCH 421/693] arch-arm: Split takeInt into AArch64/32 versions We pay a small duplication cost but we make the code more readable and we enable further modifications to the AArch64 code without forcing the same code on the AArch32 method Signed-off-by: Giacomo Travaglini Change-Id: I1efa33cf19f91094fd33bd48b6a0a57d8df8f89f --- src/arch/arm/interrupts.cc | 166 +++++++++++++++++++++++-------------- src/arch/arm/interrupts.hh | 2 + 2 files changed, 105 insertions(+), 63 deletions(-) diff --git a/src/arch/arm/interrupts.cc b/src/arch/arm/interrupts.cc index 57b1334b77..80ae481cfd 100644 --- a/src/arch/arm/interrupts.cc +++ b/src/arch/arm/interrupts.cc @@ -43,12 +43,9 @@ namespace gem5 { bool -ArmISA::Interrupts::takeInt(InterruptTypes int_type) const +ArmISA::Interrupts::takeInt32(InterruptTypes int_type) const { - // Table G1-17~19 of ARM V8 ARM InterruptMask mask; - bool highest_el_is_64 = ArmSystem::highestELIs64(tc); - CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);; HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); @@ -82,74 +79,117 @@ ArmISA::Interrupts::takeInt(InterruptTypes int_type) const if (hcr.tge) hcr_mask_override_bit = 1; - if (!highest_el_is_64) { - // AArch32 - if (!scr_routing_bit) { - // SCR IRQ == 0 - if (!hcr_mask_override_bit) - mask = INT_MASK_M; - else { - if (!is_secure && (el == EL0 || el == EL1)) - mask = INT_MASK_T; - else - mask = INT_MASK_M; - } - } else { - // SCR IRQ == 1 - if ((!is_secure) && - (hcr_mask_override_bit || - (!scr_fwaw_bit && !hcr_mask_override_bit))) + if (!scr_routing_bit) { + // SCR IRQ == 0 + if (!hcr_mask_override_bit) + mask = INT_MASK_M; + else { + if (!is_secure && (el == EL0 || el == EL1)) mask = INT_MASK_T; else mask = INT_MASK_M; } } else { - // AArch64 - if (!scr_routing_bit) { - // SCR IRQ == 0 - if (!scr.rw) { - // SCR RW == 0 - if (!hcr_mask_override_bit) { - if (el == EL3) - mask = INT_MASK_P; - else - mask = INT_MASK_M; - } else { - if (el == EL3) - mask = INT_MASK_T; - else if (is_secure || el == EL2) - mask = INT_MASK_M; - else - mask = INT_MASK_T; - } - } else { - // SCR RW == 1 - if (!hcr_mask_override_bit) { - if (el == EL3 || el == EL2) - mask = INT_MASK_P; - else - mask = INT_MASK_M; - } else { - if (el == EL3) - mask = INT_MASK_P; - else if (is_secure || el == EL2) - mask = INT_MASK_M; - else - mask = INT_MASK_T; - } - } - } else { - // SCR IRQ == 1 - if (el == EL3) - mask = INT_MASK_M; - else - mask = INT_MASK_T; - } + // SCR IRQ == 1 + if ((!is_secure) && + (hcr_mask_override_bit || + (!scr_fwaw_bit && !hcr_mask_override_bit))) + mask = INT_MASK_T; + else + mask = INT_MASK_M; } - return ((mask == INT_MASK_T) || ((mask == INT_MASK_M) && !cpsr_mask_bit)) && (mask != INT_MASK_P); } + +bool +ArmISA::Interrupts::takeInt64(InterruptTypes int_type) const +{ + InterruptMask mask; + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);; + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + ExceptionLevel el = currEL(tc); + bool cpsr_mask_bit, scr_routing_bit, hcr_mask_override_bit; + bool is_secure = isSecure(tc); + + switch(int_type) { + case INT_FIQ: + cpsr_mask_bit = cpsr.f; + scr_routing_bit = scr.fiq; + hcr_mask_override_bit = hcr.fmo; + break; + case INT_IRQ: + cpsr_mask_bit = cpsr.i; + scr_routing_bit = scr.irq; + hcr_mask_override_bit = hcr.imo; + break; + case INT_ABT: + cpsr_mask_bit = cpsr.a; + scr_routing_bit = scr.ea; + hcr_mask_override_bit = hcr.amo; + break; + default: + panic("Unhandled interrupt type!"); + } + + if (hcr.tge) + hcr_mask_override_bit = 1; + + if (!scr_routing_bit) { + // SCR IRQ == 0 + if (!scr.rw) { + // SCR RW == 0 + if (!hcr_mask_override_bit) { + if (el == EL3) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } else { + if (el == EL3) + mask = INT_MASK_T; + else if (is_secure || el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + } else { + // SCR RW == 1 + if (!hcr_mask_override_bit) { + if (el == EL3 || el == EL2) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } else { + if (el == EL3) + mask = INT_MASK_P; + else if (is_secure || el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + } + } else { + // SCR IRQ == 1 + if (el == EL3) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + return ((mask == INT_MASK_T) || + ((mask == INT_MASK_M) && !cpsr_mask_bit)) && + (mask != INT_MASK_P); +} + +bool +ArmISA::Interrupts::takeInt(InterruptTypes int_type) const +{ + // Table G1-17~19 of ARM V8 ARM + return ArmSystem::highestELIs64(tc) ? takeInt64(int_type) : + takeInt32(int_type); + +} + } // namespace gem5 diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index 178ee6cea5..c2a2d13a8d 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -129,6 +129,8 @@ class Interrupts : public BaseInterrupts }; bool takeInt(InterruptTypes int_type) const; + bool takeInt32(InterruptTypes int_type) const; + bool takeInt64(InterruptTypes int_type) const; bool checkInterrupts() const override From 8acf49b6fad29937ea88246b913f1375d54aa977 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 1 Jun 2023 15:20:50 +0100 Subject: [PATCH 422/693] arch-arm: Revamp takeInt to take VHE/SEL2 into account The new implementation matches the table in the ARM Architecture Reference Manual (version DDI 0487J.a, section D1.3.6, table R_SXLWJ) It takes into consideration features like FEAT_SEL2 (scr.eel2 bit) and FEAT_VHE (hcr.e2h bit) which affect the masking of interrupts under certain circumstances Signed-off-by: Giacomo Travaglini Change-Id: I07ebd8d859651475bd32fd201eea0f4e64a7dd5f --- src/arch/arm/interrupts.cc | 151 ++++++++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 29 deletions(-) diff --git a/src/arch/arm/interrupts.cc b/src/arch/arm/interrupts.cc index 80ae481cfd..c2f1009147 100644 --- a/src/arch/arm/interrupts.cc +++ b/src/arch/arm/interrupts.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012-2013, 2016, 2019 ARM Limited + * Copyright (c) 2009, 2012-2013, 2016, 2019, 2023 Arm Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -113,7 +113,7 @@ ArmISA::Interrupts::takeInt64(InterruptTypes int_type) const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); ExceptionLevel el = currEL(tc); bool cpsr_mask_bit, scr_routing_bit, hcr_mask_override_bit; - bool is_secure = isSecure(tc); + bool is_secure = isSecureBelowEL3(tc); switch(int_type) { case INT_FIQ: @@ -135,48 +135,141 @@ ArmISA::Interrupts::takeInt64(InterruptTypes int_type) const panic("Unhandled interrupt type!"); } - if (hcr.tge) - hcr_mask_override_bit = 1; - - if (!scr_routing_bit) { - // SCR IRQ == 0 - if (!scr.rw) { - // SCR RW == 0 - if (!hcr_mask_override_bit) { + if (is_secure) { + if (!scr.eel2) { + if (!scr_routing_bit) { + // NS=0,EEL2=0,EAI/IRQ/FIQ=0 if (el == EL3) mask = INT_MASK_P; else mask = INT_MASK_M; } else { + // NS=0,EEL2=0,EAI/IRQ/FIQ=1 if (el == EL3) - mask = INT_MASK_T; - else if (is_secure || el == EL2) mask = INT_MASK_M; else mask = INT_MASK_T; } } else { - // SCR RW == 1 - if (!hcr_mask_override_bit) { - if (el == EL3 || el == EL2) - mask = INT_MASK_P; - else - mask = INT_MASK_M; + if (!scr_routing_bit) { + if (!hcr.tge) { + if (!hcr_mask_override_bit) { + // NS=0,EEL2=1,EAI/IRQ/FIQ=0,TGE=0,AMO/IMO/FMO=0 + if (el == EL3 || el == EL2) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } else { + // NS=0,EEL2=1,EAI/IRQ/FIQ=0,TGE=0,AMO/IMO/FMO=1 + if (el == EL3) + mask = INT_MASK_P; + else if (el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + } else { + if (!hcr.e2h) { + // NS=0,EEL2=1,EAI/IRQ/FIQ=0,TGE=1,E2H=0 + if (el == EL3) + mask = INT_MASK_P; + else if (el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } else { + // NS=0,EEL2=1,EAI/IRQ/FIQ=0,TGE=1,E2H=1 + if (el == EL3) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } + } } else { - if (el == EL3) - mask = INT_MASK_P; - else if (is_secure || el == EL2) - mask = INT_MASK_M; - else - mask = INT_MASK_T; + if (!hcr.tge) { + // NS=0,EEL2=1,EAI/IRQ/FIQ=1,TGE=0 + if (el == EL3) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } else { + // NS=0,EEL2=1,EAI/IRQ/FIQ=1,TGE=1 + if (el == EL3) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } } } } else { - // SCR IRQ == 1 - if (el == EL3) - mask = INT_MASK_M; - else - mask = INT_MASK_T; + if (!scr_routing_bit) { + if (!scr.rw) { + if (!hcr.tge) { + if (!hcr_mask_override_bit) { + // NS=1,EAI/IRQ/FIQ=0,RW=0,TGE=0,AMO/IMO?/FMO=0 + if (el == EL3) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } else { + // NS=1,EAI/IRQ/FIQ=0,RW=0,TGE=0,AMO/IMO?/FMO=1 + if (el == EL3) + mask = INT_MASK_P; + else if (el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + } else { + // NS=1,EAI/IRQ/FIQ=0,RW=0,TGE=1 + if (el == EL3) + mask = INT_MASK_P; + else if (el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + } else { + if (!hcr.tge) { + if (!hcr_mask_override_bit) { + // NS=1,EAI/IRQ/FIQ=0,RW=1,TGE=0,AMO/IMO/FMO=0 + if (el == EL3 || el == EL2) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } else { + // NS=1,EAI/IRQ/FIQ=0,RW=1,TGE=0,AMO/IMO/FMO=1 + if (el == EL3) + mask = INT_MASK_P; + else if (el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } + } else { + if (!hcr.e2h) { + // NS=1,EAI/IRQ/FIQ=0,RW=1,TGE=1,E2H=0 + if (el == EL3) + mask = INT_MASK_P; + else if (el == EL2) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } else { + // NS=1,EAI/IRQ/FIQ=0,RW=1,TGE=1,E2H=1 + if (el == EL3) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } + } + } + } else { + if (el == EL3) + mask = INT_MASK_M; + else + mask = INT_MASK_T; + } } return ((mask == INT_MASK_T) || ((mask == INT_MASK_M) && !cpsr_mask_bit)) && From 9f4d334644ea8eb552e25dc12252bd9eb8d605ed Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 6 Oct 2023 10:30:45 -0500 Subject: [PATCH 423/693] gpu-compute: Update tokens for flat global/scratch Memory instructions acquire coalescer tokens in the schedule stage. Currently this is only done for buffer and flat instructions, but not flat global or flat scratch. This change now acquires tokens for flat global and flat scratch instructions. This provides back-pressure to the CUs and helps to avoid deadlocks in Ruby. The change also handles returning tokens for buffer, flat global, and flat scratch instructions. This was previously only being done for normal flat instructions leading to deadlocks in some applications when the tokens were exhausted. To simplify the logic, added a needsToken() method to GPUDynInst which return if the instruction is buffer or any flat segment. The waitcnts were also incorrect for flat global and flat scratch. We should always decrement vmem and exp count for stores and only normal flat instructions should decrement lgkm. Currently vmem/exp are not decremented for flat global and flat scratch which can lead to deadlock. This change set fixes this by always decrementing vmem/exp and lgkm only for normal flat instructions. Change-Id: I673f4ac6121e4b5a5e8491bc9130c6d825d95fc5 --- src/arch/amdgpu/vega/insts/instructions.cc | 102 ++++++++++++++------- src/gpu-compute/gpu_dyn_inst.cc | 6 ++ src/gpu-compute/gpu_dyn_inst.hh | 1 + src/gpu-compute/schedule_stage.cc | 2 +- src/gpu-compute/wavefront.cc | 2 +- 5 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index b0f8c908ed..bb6a2233cd 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -43894,9 +43894,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -43978,9 +43980,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44063,9 +44067,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44118,9 +44124,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44173,9 +44181,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44237,9 +44247,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44304,9 +44316,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } wf->decExpInstsIssued(); return; } @@ -44361,9 +44375,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } wf->decExpInstsIssued(); return; } @@ -44418,9 +44434,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } wf->decExpInstsIssued(); return; } @@ -44476,9 +44494,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } wf->decExpInstsIssued(); return; } @@ -44534,9 +44554,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } wf->decExpInstsIssued(); return; } @@ -44600,9 +44622,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } wf->decExpInstsIssued(); return; } @@ -44677,9 +44701,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44757,9 +44783,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -44837,9 +44865,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -45370,9 +45400,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } @@ -45451,9 +45483,11 @@ namespace VegaISA { Wavefront *wf = gpuDynInst->wavefront(); - if (gpuDynInst->exec_mask.none() && isFlat()) { + if (gpuDynInst->exec_mask.none()) { wf->decVMemInstsIssued(); - wf->decLGKMInstsIssued(); + if (isFlat()) { + wf->decLGKMInstsIssued(); + } return; } diff --git a/src/gpu-compute/gpu_dyn_inst.cc b/src/gpu-compute/gpu_dyn_inst.cc index 0b394e7e36..c59317d2c4 100644 --- a/src/gpu-compute/gpu_dyn_inst.cc +++ b/src/gpu-compute/gpu_dyn_inst.cc @@ -582,6 +582,12 @@ GPUDynInst::readsFlatScratch() const return false; } +bool +GPUDynInst::needsToken() const +{ + return isGlobalMem() || isFlat() || isFlatGlobal() || isFlatScratch(); +} + bool GPUDynInst::isAtomicAnd() const { diff --git a/src/gpu-compute/gpu_dyn_inst.hh b/src/gpu-compute/gpu_dyn_inst.hh index 558cce8431..6551fa417a 100644 --- a/src/gpu-compute/gpu_dyn_inst.hh +++ b/src/gpu-compute/gpu_dyn_inst.hh @@ -257,6 +257,7 @@ class GPUDynInst : public GPUExecContext bool writesFlatScratch() const; bool readsExecMask() const; bool writesExecMask() const; + bool needsToken() const; bool isAtomicAnd() const; bool isAtomicOr() const; diff --git a/src/gpu-compute/schedule_stage.cc b/src/gpu-compute/schedule_stage.cc index 4c4028b152..0d475c577e 100644 --- a/src/gpu-compute/schedule_stage.cc +++ b/src/gpu-compute/schedule_stage.cc @@ -579,7 +579,7 @@ ScheduleStage::fillDispatchList() // operation. GPUDynInstPtr mp = schIter->first; if (!mp->isMemSync() && !mp->isScalar() && - (mp->isGlobalMem() || mp->isFlat())) { + mp->needsToken()) { computeUnit.globalMemoryPipe.acqCoalescerToken(mp); } diff --git a/src/gpu-compute/wavefront.cc b/src/gpu-compute/wavefront.cc index 8a1adfe802..0bca152e08 100644 --- a/src/gpu-compute/wavefront.cc +++ b/src/gpu-compute/wavefront.cc @@ -1082,7 +1082,7 @@ Wavefront::exec() * we return here to avoid spurious errors related to flat insts * and their address segment resolution. */ - if (execMask().none() && ii->isFlat()) { + if (execMask().none() && ii->needsToken()) { computeUnit->getTokenManager()->recvTokens(1); return; } From 141b06d335adce2ea6594a0059b020164ea0e148 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Tue, 10 Oct 2023 23:00:10 +0800 Subject: [PATCH 424/693] arch,arch-riscv: Remove setRegOperand in VecRegOperand (#341) The RISC-V vector instructions still work without setRegOperand. We should fix the register statistic issue by https://github.com/gem5/gem5/pull/360 to avoid duplicate statistic register write count Change-Id: Ib6a52935e00c3e557b366abfcf60450dca05614d --- src/arch/isa_parser/operand_types.py | 1 - src/arch/riscv/insts/vector.hh | 1 - 2 files changed, 2 deletions(-) diff --git a/src/arch/isa_parser/operand_types.py b/src/arch/isa_parser/operand_types.py index 113cc2f982..174a54cd4c 100755 --- a/src/arch/isa_parser/operand_types.py +++ b/src/arch/isa_parser/operand_types.py @@ -372,7 +372,6 @@ class VecRegOperand(RegOperand): def makeWrite(self): return f""" - xc->setRegOperand(this, {self.dest_reg_idx}, &tmp_d{self.dest_reg_idx}); if (traceData) {{ traceData->setData({self.reg_class}, &tmp_d{self.dest_reg_idx}); }} diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index 8098c98b78..fb6c7821b5 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -579,7 +579,6 @@ class VMaskMergeMicroInst : public VectorArithMicroInst memcpy(Vd + i * byte_offset, s + i * byte_offset, byte_offset); } } - xc->setRegOperand(this, 0, &tmp_d0); if (traceData) traceData->setData(vecRegClass, &tmp_d0); return NoFault; From 486763b6712591b6bd37ebab2d087aaa77277f41 Mon Sep 17 00:00:00 2001 From: ivanaamit Date: Wed, 4 Oct 2023 17:07:03 -0700 Subject: [PATCH 425/693] learning-gem5: use f-string for print Change-Id: If27af6524af4e4a6a59e914e9e40ba10de24adf4 --- configs/learning_gem5/part1/simple-arm.py | 4 ++-- configs/learning_gem5/part1/simple-riscv.py | 4 ++-- configs/learning_gem5/part1/simple.py | 4 ++-- configs/learning_gem5/part1/two_level.py | 4 ++-- configs/learning_gem5/part2/hello_goodbye.py | 4 ++-- configs/learning_gem5/part2/run_simple.py | 4 ++-- configs/learning_gem5/part2/simple_cache.py | 4 ++-- configs/learning_gem5/part2/simple_memobj.py | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/configs/learning_gem5/part1/simple-arm.py b/configs/learning_gem5/part1/simple-arm.py index 62f7645c5a..fac53a78af 100644 --- a/configs/learning_gem5/part1/simple-arm.py +++ b/configs/learning_gem5/part1/simple-arm.py @@ -73,6 +73,6 @@ system.cpu.createThreads() root = Root(full_system=False, system=system) m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part1/simple-riscv.py b/configs/learning_gem5/part1/simple-riscv.py index f05ca4ab50..6e296d5fc0 100644 --- a/configs/learning_gem5/part1/simple-riscv.py +++ b/configs/learning_gem5/part1/simple-riscv.py @@ -73,6 +73,6 @@ system.cpu.createThreads() root = Root(full_system=False, system=system) m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part1/simple.py b/configs/learning_gem5/part1/simple.py index e36cd78c8e..3792fddc4d 100644 --- a/configs/learning_gem5/part1/simple.py +++ b/configs/learning_gem5/part1/simple.py @@ -113,6 +113,6 @@ root = Root(full_system=False, system=system) # instantiate all of the objects we've created above m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part1/two_level.py b/configs/learning_gem5/part1/two_level.py index 8aa7dd7e83..1daf36a4f0 100644 --- a/configs/learning_gem5/part1/two_level.py +++ b/configs/learning_gem5/part1/two_level.py @@ -140,6 +140,6 @@ root = Root(full_system=False, system=system) # instantiate all of the objects we've created above m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part2/hello_goodbye.py b/configs/learning_gem5/part2/hello_goodbye.py index e4b70ba3ae..eeb76f708f 100644 --- a/configs/learning_gem5/part2/hello_goodbye.py +++ b/configs/learning_gem5/part2/hello_goodbye.py @@ -50,6 +50,6 @@ root.hello.goodbye_object = GoodbyeObject(buffer_size="100B") # instantiate all of the objects we've created above m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part2/run_simple.py b/configs/learning_gem5/part2/run_simple.py index be5f6ee7b8..ba91e5c36c 100644 --- a/configs/learning_gem5/part2/run_simple.py +++ b/configs/learning_gem5/part2/run_simple.py @@ -48,6 +48,6 @@ root.hello = SimpleObject() # instantiate all of the objects we've created above m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part2/simple_cache.py b/configs/learning_gem5/part2/simple_cache.py index 4228956126..2cdebc218a 100644 --- a/configs/learning_gem5/part2/simple_cache.py +++ b/configs/learning_gem5/part2/simple_cache.py @@ -103,6 +103,6 @@ root = Root(full_system=False, system=system) # instantiate all of the objects we've created above m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") diff --git a/configs/learning_gem5/part2/simple_memobj.py b/configs/learning_gem5/part2/simple_memobj.py index 20f4362b81..aef3a700e5 100644 --- a/configs/learning_gem5/part2/simple_memobj.py +++ b/configs/learning_gem5/part2/simple_memobj.py @@ -101,6 +101,6 @@ root = Root(full_system=False, system=system) # instantiate all of the objects we've created above m5.instantiate() -print("Beginning simulation!") +print(f"Beginning simulation!") exit_event = m5.simulate() -print("Exiting @ tick %i because %s" % (m5.curTick(), exit_event.getCause())) +print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}") From 317d2fb5b8d95318e247e3d20b2f627f5f162e9b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 12:38:27 -0700 Subject: [PATCH 426/693] misc: Run `pre-commit autoupdate` This updates the pre-commit utility from v4.3.0 to v4.5.0 and updates black from 22.6.0 to 23.9.1. Change-Id: I7ebb551f30e617059ce49f89a30207f739b1cb14 --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 367a7c09d6..d25f2a81c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ default_stages: [commit] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -68,7 +68,7 @@ repos: hooks: - id: yamlfmt - repo: https://github.com/psf/black - rev: 22.6.0 + rev: 23.9.1 hooks: - id: black - repo: local From ddf6cb88e48df4ac7de4a9e4b612daf2e7e635c8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 12:40:48 -0700 Subject: [PATCH 427/693] misc: Run `pre-commit run --all-files` This is reflect the updates made to black when running `pre-commit autoupdate`. Change-Id: Ifb7fea117f354c7f02f26926a5afdf7d67bc5919 --- build_tools/enum_cc.py | 1 - build_tools/sim_object_param_struct_cc.py | 1 - configs/common/GPUTLBConfig.py | 2 -- configs/common/GPUTLBOptions.py | 1 - configs/common/HMC.py | 2 -- configs/common/ObjectList.py | 2 +- configs/common/Simulation.py | 1 - configs/common/cores/arm/HPI.py | 1 + configs/common/cores/arm/O3_ARM_Etrace.py | 1 + configs/common/cores/arm/O3_ARM_v7a.py | 1 + configs/common/cores/arm/ex5_LITTLE.py | 1 + configs/common/cores/arm/ex5_big.py | 1 + configs/deprecated/example/fs.py | 2 +- configs/dist/sw.py | 2 +- configs/dram/lat_mem_rd.py | 3 +++ configs/example/apu_se.py | 3 ++- .../looppoints/restore-looppoint-checkpoint.py | 1 + configs/example/gem5_library/x86-npb-benchmarks.py | 2 ++ .../example/gem5_library/x86-parsec-benchmarks.py | 1 + configs/example/gpufs/DisjointNetwork.py | 5 ----- configs/example/gpufs/Disjoint_VIPER.py | 2 -- configs/example/gpufs/system/system.py | 2 +- configs/example/memcheck.py | 1 + configs/example/memtest.py | 2 ++ configs/example/noc_config/2x4.py | 1 + configs/example/read_config.py | 1 - configs/learning_gem5/part3/msi_caches.py | 2 -- .../learning_gem5/part3/ruby_caches_MI_example.py | 2 -- configs/network/Network.py | 2 -- configs/ruby/AMD_Base_Constructor.py | 2 +- configs/ruby/CHI.py | 1 - configs/ruby/GPU_VIPER.py | 13 ------------- configs/ruby/Garnet_standalone.py | 1 + configs/ruby/MESI_Three_Level.py | 2 +- configs/ruby/MESI_Three_Level_HTM.py | 2 +- configs/ruby/MESI_Two_Level.py | 2 +- configs/ruby/MI_example.py | 2 +- configs/ruby/MOESI_AMD_Base.py | 1 - configs/ruby/MOESI_CMP_directory.py | 2 +- configs/ruby/MOESI_CMP_token.py | 2 +- configs/ruby/MOESI_hammer.py | 2 +- configs/ruby/Ruby.py | 1 - configs/splash2/cluster.py | 1 + configs/splash2/run.py | 1 + configs/topologies/Crossbar.py | 1 - configs/topologies/CustomMesh.py | 1 - configs/topologies/MeshDirCorners_XY.py | 4 ++-- configs/topologies/Mesh_XY.py | 4 ++-- configs/topologies/Mesh_westfirst.py | 4 ++-- ext/testlib/helper.py | 1 + ext/testlib/query.py | 1 + src/arch/arm/ArmISA.py | 1 + src/arch/arm/ArmMMU.py | 1 + src/arch/isa_parser/isa_parser.py | 1 + src/arch/isa_parser/operand_types.py | 1 - src/arch/isa_parser/util.py | 1 + src/arch/micro_asm.py | 3 +++ src/arch/x86/bios/ACPI.py | 1 + src/base/Graphics.py | 1 + src/cpu/testers/traffic_gen/BaseTrafficGen.py | 1 + src/cpu/testers/traffic_gen/TrafficGen.py | 1 + src/dev/IntPin.py | 1 + src/dev/ResetPort.py | 1 + src/dev/amdgpu/AMDGPU.py | 1 + src/dev/arm/FlashDevice.py | 1 + src/dev/lupio/LupioBLK.py | 1 - src/dev/lupio/LupioPIC.py | 1 - src/dev/lupio/LupioRNG.py | 1 - src/dev/pci/PciHost.py | 1 - src/dev/sparc/T1000.py | 1 + src/mem/AddrMapper.py | 1 + src/mem/CommMonitor.py | 1 + src/mem/DRAMSim2.py | 1 + src/mem/DRAMsim3.py | 1 + src/mem/MemCtrl.py | 1 + src/mem/MemInterface.py | 1 + src/mem/NVMInterface.py | 1 + src/mem/cache/Cache.py | 1 + src/mem/qos/QoSMemCtrl.py | 1 + src/mem/qos/QoSPolicy.py | 1 + src/mem/qos/QoSTurnaround.py | 1 + src/mem/ruby/network/MessageBuffer.py | 1 + src/mem/slicc/ast/FuncCallExprAST.py | 2 +- src/mem/slicc/ast/MethodCallExprAST.py | 1 - src/python/gem5/components/boards/arm_board.py | 5 ----- .../components/boards/experimental/lupv_board.py | 2 -- src/python/gem5/components/boards/x86_board.py | 1 - .../chi/private_l1_cache_hierarchy.py | 1 - .../components/cachehierarchies/classic/no_cache.py | 2 -- .../classic/private_l1_cache_hierarchy.py | 2 -- .../private_l1_private_l2_cache_hierarchy.py | 2 -- .../classic/private_l1_shared_l2_cache_hierarchy.py | 2 -- .../ruby/caches/abstract_directory.py | 1 - .../ruby/caches/abstract_dma_controller.py | 1 - .../ruby/caches/abstract_l1_cache.py | 1 - .../ruby/caches/abstract_l2_cache.py | 1 - .../ruby/caches/mesi_three_level/directory.py | 1 - .../ruby/caches/mesi_three_level/l1_cache.py | 2 +- .../ruby/caches/mesi_three_level/l2_cache.py | 2 +- .../ruby/caches/mesi_three_level/l3_cache.py | 2 +- .../ruby/caches/mesi_two_level/directory.py | 1 - .../ruby/caches/mi_example/directory.py | 1 - .../ruby/caches/prebuilt/octopi_cache/octopi.py | 2 +- .../caches/prebuilt/octopi_cache/octopi_network.py | 1 + .../ruby/mesi_three_level_cache_hierarchy.py | 1 - .../ruby/mesi_two_level_cache_hierarchy.py | 1 - .../ruby/mi_example_cache_hierarchy.py | 1 - .../gem5/components/memory/dram_interfaces/hbm.py | 1 - src/python/gem5/components/memory/hbm.py | 1 - .../gem5/components/processors/base_cpu_core.py | 3 --- .../components/processors/base_cpu_processor.py | 1 - .../gem5/components/processors/simple_core.py | 1 - .../components/processors/switchable_processor.py | 3 --- .../prebuilt/riscvmatched/riscvmatched_cache.py | 2 -- .../gem5/resources/client_api/client_wrapper.py | 1 - src/python/gem5/resources/downloader.py | 2 -- src/python/gem5/resources/looppoint.py | 1 - src/python/gem5/resources/resource.py | 1 - src/python/gem5/simulate/simulator.py | 6 ++---- src/python/gem5/utils/multiprocessing/context.py | 1 + src/python/gem5/utils/progress_bar.py | 1 + src/python/m5/SimObject.py | 4 ++-- src/python/m5/params.py | 7 ++++++- src/python/m5/simulate.py | 1 + src/python/m5/ticks.py | 1 + src/python/m5/util/__init__.py | 1 + src/python/m5/util/terminal_formatter.py | 1 - src/sim/ClockDomain.py | 1 + src/sim/DVFSHandler.py | 1 + src/sim/PowerDomain.py | 1 + src/sim/PowerState.py | 1 + src/sim/Root.py | 1 - src/sim/SubSystem.py | 1 + src/sim/power/MathExprPowerModel.py | 1 + src/sim/power/PowerModel.py | 1 + src/sim/power/PowerModelState.py | 1 + src/sim/power/ThermalDomain.py | 1 + src/systemc/core/SystemC.py | 1 + tests/gem5/arm_boot_tests/test_linux_boot.py | 1 - tests/gem5/fixture.py | 2 -- tests/gem5/fs/linux/arm/configs/switcheroo.py | 3 +-- .../test_gem5_library_examples.py | 1 - tests/gem5/kvm_fork_tests/test_kvm_fork_run.py | 1 - tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py | 1 - .../parsec_benchmarks/configs/parsec_disk_run.py | 2 +- tests/gem5/parsec_benchmarks/test_parsec.py | 1 - .../replacement_policies/traces/rrip_test2_ld.py | 1 - .../replacement_policies/traces/rrip_test2_st.py | 1 - .../traces/second_chance_test2_ld.py | 1 - .../traces/second_chance_test3_st.py | 1 - tests/gem5/riscv_boot_tests/test_linux_boot.py | 1 - tests/gem5/se_mode/hello_se/test_hello_se.py | 1 - tests/gem5/suite.py | 1 - tests/gem5/traffic_gen/test_memory_traffic_gen.py | 1 - tests/gem5/verifier.py | 1 - tests/gem5/x86_boot_tests/test_linux_boot.py | 1 - tests/pyunit/stdlib/pyunit_looppoint.py | 1 - .../stdlib/resources/pyunit_md5_utils_check.py | 1 - tests/run.py | 2 ++ util/checkpoint_aggregator.py | 2 +- util/cpt_upgraders/arm-ccregs.py | 2 +- util/cpt_upgraders/arm-gicv2-banked-regs.py | 1 + util/cpt_upgraders/arm-sve.py | 1 - util/cpt_upgraders/arm-sysreg-mapping-ns.py | 1 + util/cpt_upgraders/isa-is-simobject.py | 8 ++++---- util/cpt_upgraders/mempool-sections.py | 1 - util/cpt_upgraders/riscv-pcstate.py | 2 -- util/cpt_upgraders/riscv-vext.py | 2 -- util/gem5art/artifact/gem5art/artifact/artifact.py | 1 - util/gem5art/artifact/tests/test_artifact.py | 1 - util/gem5art/run/bin/gem5art-getruns | 1 - util/gem5art/run/gem5art/run.py | 1 - util/gem5img.py | 1 + util/logroll.py | 4 ---- util/maint/lib/maintainers.py | 1 - util/on-chip-network-power-area.py | 2 +- util/plot_dram/PlotPowerStates.py | 2 -- util/plot_dram/dram_lat_mem_rd_plot.py | 4 ++-- util/plot_dram/dram_sweep_plot.py | 2 +- util/plot_dram/lowp_dram_sweep_plot.py | 2 -- util/streamline/m5stats2streamline.py | 2 +- .../systemc_gem5_tlm/SystemC_Example.py | 1 + .../systemc_simple_object/SystemC_Example.py | 1 + 183 files changed, 120 insertions(+), 175 deletions(-) diff --git a/build_tools/enum_cc.py b/build_tools/enum_cc.py index 173143fc38..504a1b9883 100644 --- a/build_tools/enum_cc.py +++ b/build_tools/enum_cc.py @@ -118,7 +118,6 @@ code("} // namespace gem5") if use_python: - name = enum.__name__ enum_name = enum.__name__ if enum.enum_name is None else enum.enum_name wrapper_name = enum_name if enum.is_class else enum.wrapper_name diff --git a/build_tools/sim_object_param_struct_cc.py b/build_tools/sim_object_param_struct_cc.py index 0384809456..2ef90c7420 100644 --- a/build_tools/sim_object_param_struct_cc.py +++ b/build_tools/sim_object_param_struct_cc.py @@ -88,7 +88,6 @@ ports = sim_object._ports.local # only include pybind if python is enabled in the build if use_python: - code( """#include "pybind11/pybind11.h" #include "pybind11/stl.h" diff --git a/configs/common/GPUTLBConfig.py b/configs/common/GPUTLBConfig.py index e59cd00da4..5b34ddbfcd 100644 --- a/configs/common/GPUTLBConfig.py +++ b/configs/common/GPUTLBConfig.py @@ -36,7 +36,6 @@ from m5.objects import * def TLB_constructor(options, level, gpu_ctrl=None, full_system=False): - if full_system: constructor_call = ( "VegaGPUTLB(\ @@ -71,7 +70,6 @@ def TLB_constructor(options, level, gpu_ctrl=None, full_system=False): def Coalescer_constructor(options, level, full_system): - if full_system: constructor_call = ( "VegaTLBCoalescer(probesPerCycle = \ diff --git a/configs/common/GPUTLBOptions.py b/configs/common/GPUTLBOptions.py index 1a77a2c192..6f232e2d0d 100644 --- a/configs/common/GPUTLBOptions.py +++ b/configs/common/GPUTLBOptions.py @@ -29,7 +29,6 @@ def tlb_options(parser): - # =================================================================== # TLB Configuration # =================================================================== diff --git a/configs/common/HMC.py b/configs/common/HMC.py index f8321f356b..eef1e793fb 100644 --- a/configs/common/HMC.py +++ b/configs/common/HMC.py @@ -430,7 +430,6 @@ def add_options(parser): # configure HMC host controller def config_hmc_host_ctrl(opt, system): - # create HMC host controller system.hmc_host = SubSystem() @@ -533,7 +532,6 @@ def config_hmc_host_ctrl(opt, system): # Create an HMC device def config_hmc_dev(opt, system, hmc_host): - # create HMC device system.hmc_dev = SubSystem() diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index 4b862db9e8..5dd420e872 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -164,7 +164,7 @@ class EnumList(ObjectList): def _add_objects(self): """Add all enum values to the ObjectList""" self._sub_classes = {} - for (key, value) in list(self.base_cls.__members__.items()): + for key, value in list(self.base_cls.__members__.items()): # All Enums have a value Num_NAME at the end which we # do not want to include if not key.startswith("Num_"): diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 4377b65e64..2afb10ca2d 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -771,7 +771,6 @@ def run(options, root, testsys, cpu_class): if ( options.take_checkpoints or options.take_simpoint_checkpoints ) and options.checkpoint_restore: - if m5.options.outdir: cptdir = m5.options.outdir else: diff --git a/configs/common/cores/arm/HPI.py b/configs/common/cores/arm/HPI.py index cebd91cc72..f7e9348622 100644 --- a/configs/common/cores/arm/HPI.py +++ b/configs/common/cores/arm/HPI.py @@ -44,6 +44,7 @@ at: http://www.arm.com/ResearchEnablement/SystemModeling from m5.objects import * + # Simple function to allow a string of [01x_] to be converted into a # mask and value for use with MinorFUTiming def make_implicant(implicant_string): diff --git a/configs/common/cores/arm/O3_ARM_Etrace.py b/configs/common/cores/arm/O3_ARM_Etrace.py index 20870a0b7a..3315664cec 100644 --- a/configs/common/cores/arm/O3_ARM_Etrace.py +++ b/configs/common/cores/arm/O3_ARM_Etrace.py @@ -36,6 +36,7 @@ from m5.objects import * from .O3_ARM_v7a import O3_ARM_v7a_3 + # O3_ARM_v7a_3 adapted to generate elastic traces class O3_ARM_v7a_3_Etrace(O3_ARM_v7a_3): # Make the number of entries in the ROB, LQ and SQ very diff --git a/configs/common/cores/arm/O3_ARM_v7a.py b/configs/common/cores/arm/O3_ARM_v7a.py index 8c25b82496..e8a7826372 100644 --- a/configs/common/cores/arm/O3_ARM_v7a.py +++ b/configs/common/cores/arm/O3_ARM_v7a.py @@ -26,6 +26,7 @@ from m5.objects import * + # Simple ALU Instructions have a latency of 1 class O3_ARM_v7a_Simple_Int(FUDesc): opList = [OpDesc(opClass="IntAlu", opLat=1)] diff --git a/configs/common/cores/arm/ex5_LITTLE.py b/configs/common/cores/arm/ex5_LITTLE.py index 982792d2d2..a89881436d 100644 --- a/configs/common/cores/arm/ex5_LITTLE.py +++ b/configs/common/cores/arm/ex5_LITTLE.py @@ -31,6 +31,7 @@ from m5.objects import * # ex5 LITTLE core (based on the ARM Cortex-A7) # ----------------------------------------------------------------------- + # Simple ALU Instructions have a latency of 3 class ex5_LITTLE_Simple_Int(MinorDefaultIntFU): opList = [OpDesc(opClass="IntAlu", opLat=4)] diff --git a/configs/common/cores/arm/ex5_big.py b/configs/common/cores/arm/ex5_big.py index 3272ca4676..daf5102e28 100644 --- a/configs/common/cores/arm/ex5_big.py +++ b/configs/common/cores/arm/ex5_big.py @@ -31,6 +31,7 @@ from m5.objects import * # ex5 big core (based on the ARM Cortex-A15) # ----------------------------------------------------------------------- + # Simple ALU Instructions have a latency of 1 class ex5_big_Simple_Int(FUDesc): opList = [OpDesc(opClass="IntAlu", opLat=1)] diff --git a/configs/deprecated/example/fs.py b/configs/deprecated/example/fs.py index c50e3ac4cc..ce6eea7623 100644 --- a/configs/deprecated/example/fs.py +++ b/configs/deprecated/example/fs.py @@ -164,7 +164,7 @@ def build_test_system(np): # assuming that there is just one such port. test_sys.iobus.mem_side_ports = test_sys.ruby._io_port.in_ports - for (i, cpu) in enumerate(test_sys.cpu): + for i, cpu in enumerate(test_sys.cpu): # # Tie the cpu ports to the correct ruby system ports # diff --git a/configs/dist/sw.py b/configs/dist/sw.py index 726735773e..701e986707 100644 --- a/configs/dist/sw.py +++ b/configs/dist/sw.py @@ -62,7 +62,7 @@ def build_switch(args): for i in range(args.dist_size) ] - for (i, link) in enumerate(switch.portlink): + for i, link in enumerate(switch.portlink): link.int0 = switch.interface[i] return switch diff --git a/configs/dram/lat_mem_rd.py b/configs/dram/lat_mem_rd.py index 74a94997bb..93ca372e93 100644 --- a/configs/dram/lat_mem_rd.py +++ b/configs/dram/lat_mem_rd.py @@ -150,6 +150,7 @@ cfg_file = open(cfg_file_name, "w") burst_size = 64 system.cache_line_size = burst_size + # lazy version to check if an integer is a power of two def is_pow2(num): return num != 0 and ((num & (num - 1)) == 0) @@ -177,6 +178,7 @@ iterations = 2 # do not pile up in the system, adjust if needed itt = 150 * 1000 + # for every data point, we create a trace containing a random address # sequence, so that we can play back the same sequence for warming and # the actual measurement @@ -276,6 +278,7 @@ system.tgen.port = system.monitor.cpu_side_port # basic to explore some of the options from common.Caches import * + # a starting point for an L3 cache class L3Cache(Cache): assoc = 16 diff --git a/configs/example/apu_se.py b/configs/example/apu_se.py index 287135fd62..4e70454348 100644 --- a/configs/example/apu_se.py +++ b/configs/example/apu_se.py @@ -673,6 +673,7 @@ gpu_driver.device = gpu_cmd_proc shader.dispatcher = dispatcher shader.gpu_cmd_proc = gpu_cmd_proc + # Create and assign the workload Check for rel_path in elements of # base_list using test, returning the first full path that satisfies test def find_path(base_list, rel_path, test): @@ -756,7 +757,7 @@ if fast_forward: ] # Other CPU strings cause bad addresses in ROCm. Revert back to M5 Simulator. -for (i, cpu) in enumerate(cpu_list): +for i, cpu in enumerate(cpu_list): for j in range(len(cpu)): cpu.isa[j].vendor_string = "M5 Simulator" diff --git a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py index 5224c6e6ea..4ca6ad495e 100644 --- a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py +++ b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py @@ -117,6 +117,7 @@ board.set_workload( ) ) + # This generator will dump the stats and exit the simulation loop when the # simulation region reaches its end. In the case there is a warmup interval, # the simulation stats are reset after the warmup is complete. diff --git a/configs/example/gem5_library/x86-npb-benchmarks.py b/configs/example/gem5_library/x86-npb-benchmarks.py index 47a62b9fa5..bcc48382ac 100644 --- a/configs/example/gem5_library/x86-npb-benchmarks.py +++ b/configs/example/gem5_library/x86-npb-benchmarks.py @@ -211,6 +211,7 @@ board.set_kernel_disk_workload( readfile_contents=command, ) + # The first exit_event ends with a `workbegin` cause. This means that the # system started successfully and the execution on the program started. def handle_workbegin(): @@ -236,6 +237,7 @@ def handle_workbegin(): # The next exit_event is to simulate the ROI. It should be exited with a cause # marked by `workend`. + # We exepect that ROI ends with `workend` or `simulate() limit reached`. def handle_workend(): print("Dump stats at the end of the ROI!") diff --git a/configs/example/gem5_library/x86-parsec-benchmarks.py b/configs/example/gem5_library/x86-parsec-benchmarks.py index 15f063be92..cc33103183 100644 --- a/configs/example/gem5_library/x86-parsec-benchmarks.py +++ b/configs/example/gem5_library/x86-parsec-benchmarks.py @@ -192,6 +192,7 @@ board.set_kernel_disk_workload( readfile_contents=command, ) + # functions to handle different exit events during the simuation def handle_workbegin(): print("Done booting Linux") diff --git a/configs/example/gpufs/DisjointNetwork.py b/configs/example/gpufs/DisjointNetwork.py index 1fbd0dcb15..bfacabc3b3 100644 --- a/configs/example/gpufs/DisjointNetwork.py +++ b/configs/example/gpufs/DisjointNetwork.py @@ -46,7 +46,6 @@ class DisjointSimple(SimpleNetwork): self.ruby_system = ruby_system def connectCPU(self, opts, controllers): - # Setup parameters for makeTopology call for CPU network topo_module = import_module(f"topologies.{opts.cpu_topology}") topo_class = getattr(topo_module, opts.cpu_topology) @@ -56,7 +55,6 @@ class DisjointSimple(SimpleNetwork): self.initSimple(opts, self.int_links, self.ext_links) def connectGPU(self, opts, controllers): - # Setup parameters for makeTopology call for GPU network topo_module = import_module(f"topologies.{opts.gpu_topology}") topo_class = getattr(topo_module, opts.gpu_topology) @@ -66,7 +64,6 @@ class DisjointSimple(SimpleNetwork): self.initSimple(opts, self.int_links, self.ext_links) def initSimple(self, opts, int_links, ext_links): - # Attach links to network self.int_links = int_links self.ext_links = ext_links @@ -82,7 +79,6 @@ class DisjointGarnet(GarnetNetwork): self.ruby_system = ruby_system def connectCPU(self, opts, controllers): - # Setup parameters for makeTopology call for CPU network topo_module = import_module(f"topologies.{opts.cpu_topology}") topo_class = getattr(topo_module, opts.cpu_topology) @@ -94,7 +90,6 @@ class DisjointGarnet(GarnetNetwork): Network.init_network(opts, self, GarnetNetworkInterface) def connectGPU(self, opts, controllers): - # Setup parameters for makeTopology call topo_module = import_module(f"topologies.{opts.gpu_topology}") topo_class = getattr(topo_module, opts.gpu_topology) diff --git a/configs/example/gpufs/Disjoint_VIPER.py b/configs/example/gpufs/Disjoint_VIPER.py index 14b47d8cf0..b9577182e3 100644 --- a/configs/example/gpufs/Disjoint_VIPER.py +++ b/configs/example/gpufs/Disjoint_VIPER.py @@ -38,7 +38,6 @@ from ruby import Ruby class DummySystem: def __init__(self, mem_ranges): - self.mem_ctrls = [] self.mem_ranges = mem_ranges @@ -51,7 +50,6 @@ class Disjoint_VIPER(RubySystem): super(Disjoint_VIPER, self).__init__() def create(self, options, system, piobus, dma_devices): - # Disjoint network topology if "garnet" in options.network: self.network_cpu = DisjointGarnet(self) diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index 7cb0ce1aa5..241b68c2b9 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -267,7 +267,7 @@ def makeGpuFSSystem(args): # and FMA. avx_cpu_features = [0x00020F51, 0x00000805, 0xEFDBFBFF, 0x1C983209] - for (i, cpu) in enumerate(system.cpu): + for i, cpu in enumerate(system.cpu): # Break once we reach the shader "CPU" if i == args.num_cpus: break diff --git a/configs/example/memcheck.py b/configs/example/memcheck.py index aee2ef74d0..f26eabcacd 100644 --- a/configs/example/memcheck.py +++ b/configs/example/memcheck.py @@ -260,6 +260,7 @@ system.memchecker = MemChecker() # For each level, track the next subsys index to use next_subsys_index = [0] * (len(cachespec) + 1) + # Recursive function to create a sub-tree of the cache and tester # hierarchy def make_cache_level(ncaches, prototypes, level, next_cache): diff --git a/configs/example/memtest.py b/configs/example/memtest.py index 0cbbab5b4f..96ee11c107 100644 --- a/configs/example/memtest.py +++ b/configs/example/memtest.py @@ -145,6 +145,7 @@ parser.add_argument( args = parser.parse_args() + # Get the total number of testers def numtesters(cachespec, testerspec): # Determine the tester multiplier for each level as the @@ -278,6 +279,7 @@ system.clk_domain = SrcClockDomain( # For each level, track the next subsys index to use next_subsys_index = [0] * (len(cachespec) + 1) + # Recursive function to create a sub-tree of the cache and tester # hierarchy def make_cache_level(ncaches, prototypes, level, next_cache): diff --git a/configs/example/noc_config/2x4.py b/configs/example/noc_config/2x4.py index 3dd2403799..b6c1e80fc5 100644 --- a/configs/example/noc_config/2x4.py +++ b/configs/example/noc_config/2x4.py @@ -35,6 +35,7 @@ from ruby import CHI_config + # CustomMesh parameters for a 2x4 mesh. Routers will have the following layout: # # 0 --- 1 --- 2 --- 3 diff --git a/configs/example/read_config.py b/configs/example/read_config.py index 40c20ef501..b8f1d0d401 100644 --- a/configs/example/read_config.py +++ b/configs/example/read_config.py @@ -366,7 +366,6 @@ class ConfigManager(object): if port_has_correct_index(from_port) and port_has_correct_index( to_port ): - connections_to_make.append((from_port, to_port)) increment_port_index(from_port) diff --git a/configs/learning_gem5/part3/msi_caches.py b/configs/learning_gem5/part3/msi_caches.py index 13b2a11b1a..de1d8c185f 100644 --- a/configs/learning_gem5/part3/msi_caches.py +++ b/configs/learning_gem5/part3/msi_caches.py @@ -110,7 +110,6 @@ class MyCacheSystem(RubySystem): class L1Cache(L1Cache_Controller): - _version = 0 @classmethod @@ -174,7 +173,6 @@ class L1Cache(L1Cache_Controller): class DirController(Directory_Controller): - _version = 0 @classmethod diff --git a/configs/learning_gem5/part3/ruby_caches_MI_example.py b/configs/learning_gem5/part3/ruby_caches_MI_example.py index 8c25a9b2d9..f929cb224d 100644 --- a/configs/learning_gem5/part3/ruby_caches_MI_example.py +++ b/configs/learning_gem5/part3/ruby_caches_MI_example.py @@ -108,7 +108,6 @@ class MyCacheSystem(RubySystem): class L1Cache(L1Cache_Controller): - _version = 0 @classmethod @@ -163,7 +162,6 @@ class L1Cache(L1Cache_Controller): class DirController(Directory_Controller): - _version = 0 @classmethod diff --git a/configs/network/Network.py b/configs/network/Network.py index a5334741c0..dbac88c246 100644 --- a/configs/network/Network.py +++ b/configs/network/Network.py @@ -121,7 +121,6 @@ def define_options(parser): def create_network(options, ruby): - # Allow legacy users to use garnet through garnet2.0 option # until next gem5 release. if options.network == "garnet2.0": @@ -162,7 +161,6 @@ def create_network(options, ruby): def init_network(options, network, InterfaceClass): - if options.network == "garnet": network.num_rows = options.mesh_rows network.vcs_per_vnet = options.vcs_per_vnet diff --git a/configs/ruby/AMD_Base_Constructor.py b/configs/ruby/AMD_Base_Constructor.py index 030b45cbb6..ec06fbad34 100644 --- a/configs/ruby/AMD_Base_Constructor.py +++ b/configs/ruby/AMD_Base_Constructor.py @@ -38,6 +38,7 @@ addToPath("../") from topologies.Cluster import Cluster + # # Note: the L1 Cache latency is only used by the sequencer on fast path hits # @@ -115,7 +116,6 @@ def construct(options, system, ruby_system): cpuCluster = None cpuCluster = Cluster(name="CPU Cluster", extBW=8, intBW=8) # 16 GB/s for i in range((options.num_cpus + 1) // 2): - cp_cntrl = CPCntrl() cp_cntrl.create(options, ruby_system, system) diff --git a/configs/ruby/CHI.py b/configs/ruby/CHI.py index 96537e558a..2487f696fd 100644 --- a/configs/ruby/CHI.py +++ b/configs/ruby/CHI.py @@ -65,7 +65,6 @@ def read_config_file(file): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "CHI": m5.panic("This script requires the CHI build") diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index 2948b6eeda..b8757c273d 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -524,7 +524,6 @@ def define_options(parser): def construct_dirs(options, system, ruby_system, network): - dir_cntrl_nodes = [] # For an odd number of CPUs, still create the right number of controllers @@ -592,7 +591,6 @@ def construct_dirs(options, system, ruby_system, network): def construct_gpudirs(options, system, ruby_system, network): - dir_cntrl_nodes = [] mem_ctrls = [] @@ -681,12 +679,10 @@ def construct_gpudirs(options, system, ruby_system, network): def construct_corepairs(options, system, ruby_system, network): - cpu_sequencers = [] cp_cntrl_nodes = [] for i in range((options.num_cpus + 1) // 2): - cp_cntrl = CPCntrl() cp_cntrl.create(options, ruby_system, system) @@ -721,7 +717,6 @@ def construct_corepairs(options, system, ruby_system, network): def construct_tcps(options, system, ruby_system, network): - tcp_sequencers = [] tcp_cntrl_nodes = [] @@ -729,7 +724,6 @@ def construct_tcps(options, system, ruby_system, network): TCC_bits = int(math.log(options.num_tccs, 2)) for i in range(options.num_compute_units): - tcp_cntrl = TCPCntrl( TCC_select_num_bits=TCC_bits, issue_latency=1, number_of_TBEs=2560 ) @@ -769,7 +763,6 @@ def construct_tcps(options, system, ruby_system, network): def construct_sqcs(options, system, ruby_system, network): - sqc_sequencers = [] sqc_cntrl_nodes = [] @@ -777,7 +770,6 @@ def construct_sqcs(options, system, ruby_system, network): TCC_bits = int(math.log(options.num_tccs, 2)) for i in range(options.num_sqc): - sqc_cntrl = SQCCntrl(TCC_select_num_bits=TCC_bits) sqc_cntrl.create(options, ruby_system, system) @@ -804,7 +796,6 @@ def construct_sqcs(options, system, ruby_system, network): def construct_scalars(options, system, ruby_system, network): - scalar_sequencers = [] scalar_cntrl_nodes = [] @@ -837,7 +828,6 @@ def construct_scalars(options, system, ruby_system, network): def construct_cmdprocs(options, system, ruby_system, network): - cmdproc_sequencers = [] cmdproc_cntrl_nodes = [] @@ -845,7 +835,6 @@ def construct_cmdprocs(options, system, ruby_system, network): TCC_bits = int(math.log(options.num_tccs, 2)) for i in range(options.num_cp): - tcp_ID = options.num_compute_units + i sqc_ID = options.num_sqc + i @@ -898,11 +887,9 @@ def construct_cmdprocs(options, system, ruby_system, network): def construct_tccs(options, system, ruby_system, network): - tcc_cntrl_nodes = [] for i in range(options.num_tccs): - tcc_cntrl = TCCCntrl(l2_response_latency=options.TCC_latency) tcc_cntrl.create(options, ruby_system, system) tcc_cntrl.l2_request_latency = options.gpu_to_dir_latency diff --git a/configs/ruby/Garnet_standalone.py b/configs/ruby/Garnet_standalone.py index ba5216eb24..eb481bb4ad 100644 --- a/configs/ruby/Garnet_standalone.py +++ b/configs/ruby/Garnet_standalone.py @@ -31,6 +31,7 @@ from m5.defines import buildEnv from m5.util import addToPath from .Ruby import create_topology, create_directories + # # Declare caches used by the protocol # diff --git a/configs/ruby/MESI_Three_Level.py b/configs/ruby/MESI_Three_Level.py index 70f9c82723..077c461b69 100644 --- a/configs/ruby/MESI_Three_Level.py +++ b/configs/ruby/MESI_Three_Level.py @@ -35,6 +35,7 @@ from .Ruby import create_topology, create_directories from .Ruby import send_evicts from common import FileSystemConfig + # # Declare caches used by the protocol # @@ -77,7 +78,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MESI_Three_Level": fatal( "This script requires the MESI_Three_Level protocol to be\ diff --git a/configs/ruby/MESI_Three_Level_HTM.py b/configs/ruby/MESI_Three_Level_HTM.py index 883db9800e..f2c2ecfd9f 100644 --- a/configs/ruby/MESI_Three_Level_HTM.py +++ b/configs/ruby/MESI_Three_Level_HTM.py @@ -35,6 +35,7 @@ from .Ruby import create_topology, create_directories from .Ruby import send_evicts from common import FileSystemConfig + # # Declare caches used by the protocol # @@ -77,7 +78,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MESI_Three_Level_HTM": fatal( "This script requires the MESI_Three_Level protocol to be\ diff --git a/configs/ruby/MESI_Two_Level.py b/configs/ruby/MESI_Two_Level.py index 80a823bc52..7326a6cab8 100644 --- a/configs/ruby/MESI_Two_Level.py +++ b/configs/ruby/MESI_Two_Level.py @@ -32,6 +32,7 @@ from m5.defines import buildEnv from .Ruby import create_topology, create_directories from .Ruby import send_evicts + # # Declare caches used by the protocol # @@ -50,7 +51,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MESI_Two_Level": fatal("This script requires the MESI_Two_Level protocol to be built.") diff --git a/configs/ruby/MI_example.py b/configs/ruby/MI_example.py index 0ccfd75506..7adf5b8ebd 100644 --- a/configs/ruby/MI_example.py +++ b/configs/ruby/MI_example.py @@ -32,6 +32,7 @@ from m5.defines import buildEnv from .Ruby import create_topology, create_directories from .Ruby import send_evicts + # # Declare caches used by the protocol # @@ -46,7 +47,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MI_example": panic("This script requires the MI_example protocol to be built.") diff --git a/configs/ruby/MOESI_AMD_Base.py b/configs/ruby/MOESI_AMD_Base.py index 30c7678f08..2c7d743ede 100644 --- a/configs/ruby/MOESI_AMD_Base.py +++ b/configs/ruby/MOESI_AMD_Base.py @@ -327,7 +327,6 @@ def create_system( # For an odd number of CPUs, still create the right number of controllers cpuCluster = Cluster(extBW=512, intBW=512) # 1 TB/s for i in range((options.num_cpus + 1) // 2): - cp_cntrl = CPCntrl() cp_cntrl.create(options, ruby_system, system) diff --git a/configs/ruby/MOESI_CMP_directory.py b/configs/ruby/MOESI_CMP_directory.py index ead03c1693..ecee4a464e 100644 --- a/configs/ruby/MOESI_CMP_directory.py +++ b/configs/ruby/MOESI_CMP_directory.py @@ -44,6 +44,7 @@ from m5.defines import buildEnv from .Ruby import create_topology, create_directories from .Ruby import send_evicts + # # Declare caches used by the protocol # @@ -64,7 +65,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MOESI_CMP_directory": panic( "This script requires the MOESI_CMP_directory protocol to be built." diff --git a/configs/ruby/MOESI_CMP_token.py b/configs/ruby/MOESI_CMP_token.py index a610db5076..89852e07c3 100644 --- a/configs/ruby/MOESI_CMP_token.py +++ b/configs/ruby/MOESI_CMP_token.py @@ -32,6 +32,7 @@ from m5.defines import buildEnv from .Ruby import create_topology, create_directories from .Ruby import send_evicts + # # Declare caches used by the protocol # @@ -71,7 +72,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MOESI_CMP_token": panic("This script requires the MOESI_CMP_token protocol to be built.") diff --git a/configs/ruby/MOESI_hammer.py b/configs/ruby/MOESI_hammer.py index 65ec11a1ad..6ed6a2d50f 100644 --- a/configs/ruby/MOESI_hammer.py +++ b/configs/ruby/MOESI_hammer.py @@ -33,6 +33,7 @@ from .Ruby import create_topology, create_directories from .Ruby import send_evicts from common import FileSystemConfig + # # Declare caches used by the protocol # @@ -70,7 +71,6 @@ def define_options(parser): def create_system( options, full_system, system, dma_ports, bootmem, ruby_system, cpus ): - if buildEnv["PROTOCOL"] != "MOESI_hammer": panic("This script requires the MOESI_hammer protocol to be built.") diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index d3c2efbb3f..a7aeb6b16f 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -221,7 +221,6 @@ def create_system( bootmem=None, cpus=None, ): - system.ruby = RubySystem() ruby = system.ruby diff --git a/configs/splash2/cluster.py b/configs/splash2/cluster.py index 4c09eee8f8..f7157d98c2 100644 --- a/configs/splash2/cluster.py +++ b/configs/splash2/cluster.py @@ -64,6 +64,7 @@ parser.add_argument("-b", "--benchmark", help="Splash 2 benchmark to run") args = parser.parse_args() + # -------------------- # Define Splash2 Benchmarks # ==================== diff --git a/configs/splash2/run.py b/configs/splash2/run.py index 08c11e0f5a..4bc2cf653d 100644 --- a/configs/splash2/run.py +++ b/configs/splash2/run.py @@ -66,6 +66,7 @@ if not args.numcpus: print("Specify the number of cpus with -n") sys.exit(1) + # -------------------- # Define Splash2 Benchmarks # ==================== diff --git a/configs/topologies/Crossbar.py b/configs/topologies/Crossbar.py index e0d220a0fd..45929b18ed 100644 --- a/configs/topologies/Crossbar.py +++ b/configs/topologies/Crossbar.py @@ -34,7 +34,6 @@ class Crossbar(SimpleTopology): description = "Crossbar" def makeTopology(self, options, network, IntLink, ExtLink, Router): - # default values for link latency and router latency. # Can be over-ridden on a per link/router basis link_latency = options.link_latency # used by simple and garnet diff --git a/configs/topologies/CustomMesh.py b/configs/topologies/CustomMesh.py index 21fa2dcc13..0f0d6765cf 100644 --- a/configs/topologies/CustomMesh.py +++ b/configs/topologies/CustomMesh.py @@ -67,7 +67,6 @@ class CustomMesh(SimpleTopology): cross_links, cross_link_latency, ): - # East->West, West->East, North->South, South->North # XY routing weights link_weights = [1, 1, 2, 2] diff --git a/configs/topologies/MeshDirCorners_XY.py b/configs/topologies/MeshDirCorners_XY.py index 6faf340c5b..1f6eb4297b 100644 --- a/configs/topologies/MeshDirCorners_XY.py +++ b/configs/topologies/MeshDirCorners_XY.py @@ -91,7 +91,7 @@ class MeshDirCorners_XY(SimpleTopology): # Connect each cache controller to the appropriate router ext_links = [] - for (i, n) in enumerate(cache_nodes): + for i, n in enumerate(cache_nodes): cntrl_level, router_id = divmod(i, num_routers) assert cntrl_level < caches_per_router ext_links.append( @@ -161,7 +161,7 @@ class MeshDirCorners_XY(SimpleTopology): link_count += 1 # Connect the dma nodes to router 0. These should only be DMA nodes. - for (i, node) in enumerate(dma_nodes): + for i, node in enumerate(dma_nodes): assert node.type == "DMA_Controller" ext_links.append( ExtLink( diff --git a/configs/topologies/Mesh_XY.py b/configs/topologies/Mesh_XY.py index 94cb770750..e5402d3d83 100644 --- a/configs/topologies/Mesh_XY.py +++ b/configs/topologies/Mesh_XY.py @@ -87,7 +87,7 @@ class Mesh_XY(SimpleTopology): # Connect each node to the appropriate router ext_links = [] - for (i, n) in enumerate(network_nodes): + for i, n in enumerate(network_nodes): cntrl_level, router_id = divmod(i, num_routers) assert cntrl_level < cntrls_per_router ext_links.append( @@ -102,7 +102,7 @@ class Mesh_XY(SimpleTopology): # Connect the remainding nodes to router 0. These should only be # DMA nodes. - for (i, node) in enumerate(remainder_nodes): + for i, node in enumerate(remainder_nodes): assert node.type == "DMA_Controller" assert i < remainder ext_links.append( diff --git a/configs/topologies/Mesh_westfirst.py b/configs/topologies/Mesh_westfirst.py index 663c31e2cf..45702b759a 100644 --- a/configs/topologies/Mesh_westfirst.py +++ b/configs/topologies/Mesh_westfirst.py @@ -90,7 +90,7 @@ class Mesh_westfirst(SimpleTopology): # Connect each node to the appropriate router ext_links = [] - for (i, n) in enumerate(network_nodes): + for i, n in enumerate(network_nodes): cntrl_level, router_id = divmod(i, num_routers) assert cntrl_level < cntrls_per_router ext_links.append( @@ -105,7 +105,7 @@ class Mesh_westfirst(SimpleTopology): # Connect the remainding nodes to router 0. These should only be # DMA nodes. - for (i, node) in enumerate(remainder_nodes): + for i, node in enumerate(remainder_nodes): assert node.type == "DMA_Controller" assert i < remainder ext_links.append( diff --git a/ext/testlib/helper.py b/ext/testlib/helper.py index 6b5194bd97..c8680e6948 100644 --- a/ext/testlib/helper.py +++ b/ext/testlib/helper.py @@ -132,6 +132,7 @@ class TimedWaitPID(object): # Patch os.waitpid() TimedWaitPID.install() + # TODO Tear out duplicate logic from the sandbox IOManager def log_call(logger, command, time, *popenargs, **kwargs): """ diff --git a/ext/testlib/query.py b/ext/testlib/query.py index be1c5a6792..6b49bc2b00 100644 --- a/ext/testlib/query.py +++ b/ext/testlib/query.py @@ -29,6 +29,7 @@ import testlib.terminal as terminal import testlib.log as log + # TODO Refactor print logic out of this so the objects # created are separate from print logic. class QueryRunner(object): diff --git a/src/arch/arm/ArmISA.py b/src/arch/arm/ArmISA.py index 8c1ee5ae42..97c2609f50 100644 --- a/src/arch/arm/ArmISA.py +++ b/src/arch/arm/ArmISA.py @@ -41,6 +41,7 @@ from m5.objects.ArmPMU import ArmPMU from m5.objects.ArmSystem import SveVectorLength, SmeVectorLength, ArmRelease from m5.objects.BaseISA import BaseISA + # Enum for DecoderFlavor class DecoderFlavor(Enum): vals = ["Generic"] diff --git a/src/arch/arm/ArmMMU.py b/src/arch/arm/ArmMMU.py index dba6618567..e2e548b1b3 100644 --- a/src/arch/arm/ArmMMU.py +++ b/src/arch/arm/ArmMMU.py @@ -42,6 +42,7 @@ from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * + # Basic stage 1 translation objects class ArmTableWalker(ClockedObject): type = "ArmTableWalker" diff --git a/src/arch/isa_parser/isa_parser.py b/src/arch/isa_parser/isa_parser.py index ef035c5fcb..9199c7ca73 100755 --- a/src/arch/isa_parser/isa_parser.py +++ b/src/arch/isa_parser/isa_parser.py @@ -374,6 +374,7 @@ def substBitOps(code): # ##################################################################### + # Force the argument to be a list. Useful for flags, where a caller # can specify a singleton flag or a list of flags. Also usful for # converting tuples to lists so they can be modified. diff --git a/src/arch/isa_parser/operand_types.py b/src/arch/isa_parser/operand_types.py index 174a54cd4c..fb38376f3a 100755 --- a/src/arch/isa_parser/operand_types.py +++ b/src/arch/isa_parser/operand_types.py @@ -50,7 +50,6 @@ class OperandDesc(object): def __init__( self, base_cls, dflt_ext, reg_spec, flags=None, sort_pri=None ): - from .isa_parser import makeList # Canonical flag structure is a triple of lists, where each list diff --git a/src/arch/isa_parser/util.py b/src/arch/isa_parser/util.py index 2cf0d82a7a..e036a4c2e2 100755 --- a/src/arch/isa_parser/util.py +++ b/src/arch/isa_parser/util.py @@ -42,6 +42,7 @@ import re ################### # Utility functions + # # Indent every line in string 's' by two spaces # (except preprocessor directives). diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index 1c2183c07a..4f04f3977d 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -187,6 +187,7 @@ def handle_statement(parser, container, statement): # ########################################################################## + # Error handler. Just call exit. Output formatted to work under # Emacs compile-mode. Optional 'print_traceback' arg, if set to True, # prints a Python stack backtrace too (can be handy when trying to @@ -231,6 +232,7 @@ reserved_map = {} for r in reserved: reserved_map[r.lower()] = r + # Ignore comments def t_ANY_COMMENT(t): r"\#[^\n]*(?=\n)" @@ -360,6 +362,7 @@ def t_ANY_error(t): # ########################################################################## + # Start symbol for a file which may have more than one macroop or rom # specification. def p_file(t): diff --git a/src/arch/x86/bios/ACPI.py b/src/arch/x86/bios/ACPI.py index fbbeda015c..90d0ce094c 100644 --- a/src/arch/x86/bios/ACPI.py +++ b/src/arch/x86/bios/ACPI.py @@ -36,6 +36,7 @@ from m5.params import * from m5.SimObject import SimObject + # ACPI description table header. Subclasses contain and handle the actual # contents as appropriate for that type of table. class X86ACPISysDescTable(SimObject): diff --git a/src/base/Graphics.py b/src/base/Graphics.py index b0bec3b137..b58e287129 100644 --- a/src/base/Graphics.py +++ b/src/base/Graphics.py @@ -36,6 +36,7 @@ from m5.SimObject import SimObject from m5.params import * + # Image Formats: # Auto option will let gem5 to choose the image format it prefers. class ImageFormat(Enum): diff --git a/src/cpu/testers/traffic_gen/BaseTrafficGen.py b/src/cpu/testers/traffic_gen/BaseTrafficGen.py index b5df83e779..7fdfda22e5 100644 --- a/src/cpu/testers/traffic_gen/BaseTrafficGen.py +++ b/src/cpu/testers/traffic_gen/BaseTrafficGen.py @@ -37,6 +37,7 @@ from m5.params import * from m5.proxy import * from m5.objects.ClockedObject import ClockedObject + # Types of Stream Generators. # Those are orthogonal to the other generators in the TrafficGen # and are meant to initialize the stream and substream IDs for diff --git a/src/cpu/testers/traffic_gen/TrafficGen.py b/src/cpu/testers/traffic_gen/TrafficGen.py index 6f1aa67bfd..15190120cc 100644 --- a/src/cpu/testers/traffic_gen/TrafficGen.py +++ b/src/cpu/testers/traffic_gen/TrafficGen.py @@ -36,6 +36,7 @@ from m5.params import * from m5.objects.BaseTrafficGen import * + # The behaviour of this traffic generator is specified in a # configuration file, and this file describes a state transition graph # where each state is a specific generator behaviour. Examples include diff --git a/src/dev/IntPin.py b/src/dev/IntPin.py index 9336a89900..61c645af2f 100644 --- a/src/dev/IntPin.py +++ b/src/dev/IntPin.py @@ -29,6 +29,7 @@ INT_SOURCE_ROLE = "Int Source Pin" INT_SINK_ROLE = "Int Sink Pin" Port.compat(INT_SOURCE_ROLE, INT_SINK_ROLE) + # A source pin generally represents a single pin which might connect to # multiple sinks. class IntSourcePin(VectorPort): diff --git a/src/dev/ResetPort.py b/src/dev/ResetPort.py index 15caa476ec..467771a258 100644 --- a/src/dev/ResetPort.py +++ b/src/dev/ResetPort.py @@ -29,6 +29,7 @@ RESET_REQUEST_ROLE = "Reset Request" RESET_RESPONSE_ROLE = "Reset Response" Port.compat(RESET_REQUEST_ROLE, RESET_RESPONSE_ROLE) + # ResetRequestPort is an artifact request port for reset purpose. class ResetRequestPort(Port): def __init__(self, desc): diff --git a/src/dev/amdgpu/AMDGPU.py b/src/dev/amdgpu/AMDGPU.py index 616c501c63..7873794109 100644 --- a/src/dev/amdgpu/AMDGPU.py +++ b/src/dev/amdgpu/AMDGPU.py @@ -34,6 +34,7 @@ from m5.objects.PciDevice import PciMemBar, PciMemUpperBar, PciLegacyIoBar from m5.objects.Device import DmaDevice, DmaVirtDevice from m5.objects.ClockedObject import ClockedObject + # PCI device model for an AMD Vega 10 based GPU. The PCI codes and BARs # correspond to a Vega Frontier Edition hardware device. None of the PCI # related values in this class should be changed. diff --git a/src/dev/arm/FlashDevice.py b/src/dev/arm/FlashDevice.py index d5069d94ac..7bd365a2ba 100644 --- a/src/dev/arm/FlashDevice.py +++ b/src/dev/arm/FlashDevice.py @@ -38,6 +38,7 @@ from m5.proxy import * from m5.objects.AbstractNVM import * + # Distribution of the data. # sequential: sequential (address n+1 is likely to be on the same plane as n) # Random: @TODO Not yet implemented diff --git a/src/dev/lupio/LupioBLK.py b/src/dev/lupio/LupioBLK.py index 786c2ccbc5..e230e23fed 100644 --- a/src/dev/lupio/LupioBLK.py +++ b/src/dev/lupio/LupioBLK.py @@ -31,7 +31,6 @@ from m5.proxy import Parent class LupioBLK(DmaDevice): - type = "LupioBLK" cxx_class = "gem5::LupioBLK" cxx_header = "dev/lupio/lupio_blk.hh" diff --git a/src/dev/lupio/LupioPIC.py b/src/dev/lupio/LupioPIC.py index 7afa727e4b..40ea7c7f89 100644 --- a/src/dev/lupio/LupioPIC.py +++ b/src/dev/lupio/LupioPIC.py @@ -29,7 +29,6 @@ from m5.params import Param class LupioPIC(BasicPioDevice): - type = "LupioPIC" cxx_class = "gem5::LupioPIC" cxx_header = "dev/lupio/lupio_pic.hh" diff --git a/src/dev/lupio/LupioRNG.py b/src/dev/lupio/LupioRNG.py index d6b7b8a199..a1b93446a0 100644 --- a/src/dev/lupio/LupioRNG.py +++ b/src/dev/lupio/LupioRNG.py @@ -30,7 +30,6 @@ from m5.proxy import Parent class LupioRNG(BasicPioDevice): - type = "LupioRNG" cxx_class = "gem5::LupioRNG" cxx_header = "dev/lupio/lupio_rng.hh" diff --git a/src/dev/pci/PciHost.py b/src/dev/pci/PciHost.py index 007b17a30c..58f8eb5a78 100644 --- a/src/dev/pci/PciHost.py +++ b/src/dev/pci/PciHost.py @@ -76,7 +76,6 @@ class GenericPciHost(PciHost): relocatable=0, addr=0, ): - busf = bus & 0xFF devicef = device & 0x1F functionf = function & 0x7 diff --git a/src/dev/sparc/T1000.py b/src/dev/sparc/T1000.py index 9e473a395d..d797c5fc13 100644 --- a/src/dev/sparc/T1000.py +++ b/src/dev/sparc/T1000.py @@ -151,6 +151,7 @@ class T1000(Platform): puart0 = Uart8250(pio_addr=0x1F10000000) iob = Iob() + # Attach I/O devices that are on chip def attachOnChipIO(self, bus): self.iob.pio = bus.mem_side_ports diff --git a/src/mem/AddrMapper.py b/src/mem/AddrMapper.py index 932fbf14e1..f1f3fbd6f5 100644 --- a/src/mem/AddrMapper.py +++ b/src/mem/AddrMapper.py @@ -36,6 +36,7 @@ from m5.params import * from m5.SimObject import SimObject + # An address mapper changes the packet addresses in going from the # response port side of the mapper to the request port side. When the # response port is queried for the address ranges, it also performs the diff --git a/src/mem/CommMonitor.py b/src/mem/CommMonitor.py index ab946f1e91..e0040b74e0 100644 --- a/src/mem/CommMonitor.py +++ b/src/mem/CommMonitor.py @@ -38,6 +38,7 @@ from m5.proxy import * from m5.objects.System import System from m5.SimObject import SimObject + # The communication monitor will most typically be used in combination # with periodic dumping and resetting of stats using schedStatEvent class CommMonitor(SimObject): diff --git a/src/mem/DRAMSim2.py b/src/mem/DRAMSim2.py index 14c85312fe..037baaa8b5 100644 --- a/src/mem/DRAMSim2.py +++ b/src/mem/DRAMSim2.py @@ -38,6 +38,7 @@ from citations import add_citation from m5.params import * from m5.objects.AbstractMemory import * + # A wrapper for DRAMSim2 multi-channel memory controller class DRAMSim2(AbstractMemory): type = "DRAMSim2" diff --git a/src/mem/DRAMsim3.py b/src/mem/DRAMsim3.py index 0ca0077a85..de70293258 100644 --- a/src/mem/DRAMsim3.py +++ b/src/mem/DRAMsim3.py @@ -38,6 +38,7 @@ from m5.citations import add_citation from m5.params import * from m5.objects.AbstractMemory import * + # A wrapper for DRAMSim3 multi-channel memory controller class DRAMsim3(AbstractMemory): type = "DRAMsim3" diff --git a/src/mem/MemCtrl.py b/src/mem/MemCtrl.py index 62e4d97b26..eca15877e5 100644 --- a/src/mem/MemCtrl.py +++ b/src/mem/MemCtrl.py @@ -43,6 +43,7 @@ from m5.proxy import * from m5.objects.QoSMemCtrl import * from m5.citations import add_citation + # Enum for memory scheduling algorithms, currently First-Come # First-Served and a First-Row Hit then First-Come First-Served class MemSched(Enum): diff --git a/src/mem/MemInterface.py b/src/mem/MemInterface.py index 60bf99bf47..424e6320ac 100644 --- a/src/mem/MemInterface.py +++ b/src/mem/MemInterface.py @@ -43,6 +43,7 @@ from m5.proxy import * from m5.objects.AbstractMemory import AbstractMemory + # Enum for the address mapping. With Ch, Ra, Ba, Ro and Co denoting # channel, rank, bank, row and column, respectively, and going from # MSB to LSB. Available are RoRaBaChCo and RoRaBaCoCh, that are diff --git a/src/mem/NVMInterface.py b/src/mem/NVMInterface.py index 841dc0c047..66b1f9401e 100644 --- a/src/mem/NVMInterface.py +++ b/src/mem/NVMInterface.py @@ -39,6 +39,7 @@ from m5.objects.MemCtrl import MemCtrl from m5.objects.MemInterface import MemInterface from m5.objects.DRAMInterface import AddrMap + # The following interface aims to model byte-addressable NVM # The most important system-level performance effects of a NVM # are modeled without getting into too much detail of the media itself. diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py index 49665dde91..d853a08cd9 100644 --- a/src/mem/cache/Cache.py +++ b/src/mem/cache/Cache.py @@ -46,6 +46,7 @@ from m5.objects.Prefetcher import BasePrefetcher from m5.objects.ReplacementPolicies import * from m5.objects.Tags import * + # Enum for cache clusivity, currently mostly inclusive or mostly # exclusive. class Clusivity(Enum): diff --git a/src/mem/qos/QoSMemCtrl.py b/src/mem/qos/QoSMemCtrl.py index 3028b439d5..86ed03196f 100644 --- a/src/mem/qos/QoSMemCtrl.py +++ b/src/mem/qos/QoSMemCtrl.py @@ -38,6 +38,7 @@ from m5.proxy import * from m5.objects.ClockedObject import ClockedObject from m5.objects.QoSTurnaround import * + # QoS Queue Selection policy used to select packets among same-QoS queues class QoSQPolicy(Enum): vals = ["fifo", "lifo", "lrg"] diff --git a/src/mem/qos/QoSPolicy.py b/src/mem/qos/QoSPolicy.py index 2dfc974f43..ef44121567 100644 --- a/src/mem/qos/QoSPolicy.py +++ b/src/mem/qos/QoSPolicy.py @@ -36,6 +36,7 @@ from m5.SimObject import * from m5.params import * + # QoS scheduler policy used to serve incoming transaction class QoSPolicy(SimObject): type = "QoSPolicy" diff --git a/src/mem/qos/QoSTurnaround.py b/src/mem/qos/QoSTurnaround.py index f356635a57..26794c3f49 100644 --- a/src/mem/qos/QoSTurnaround.py +++ b/src/mem/qos/QoSTurnaround.py @@ -35,6 +35,7 @@ from m5.SimObject import SimObject + # QoS Turnaround policy used to select bus state - READ or WRITE class QoSTurnaroundPolicy(SimObject): type = "QoSTurnaroundPolicy" diff --git a/src/mem/ruby/network/MessageBuffer.py b/src/mem/ruby/network/MessageBuffer.py index bd20239cea..270dbb1ba1 100644 --- a/src/mem/ruby/network/MessageBuffer.py +++ b/src/mem/ruby/network/MessageBuffer.py @@ -40,6 +40,7 @@ from m5.params import * from m5.proxy import * from m5.SimObject import SimObject + # A MessageBuffer inserts random delays to enqueued messages when the # randomization param is set to 'enabled' or when globally enabled for the # RubySystem and the param is set to 'ruby_system' (default). 'disabled' diff --git a/src/mem/slicc/ast/FuncCallExprAST.py b/src/mem/slicc/ast/FuncCallExprAST.py index 6ccca6650a..01b604c8bf 100644 --- a/src/mem/slicc/ast/FuncCallExprAST.py +++ b/src/mem/slicc/ast/FuncCallExprAST.py @@ -282,7 +282,7 @@ if (!(${{cvec[0]}})) { params = "" first_param = True - for (param_code, type) in zip(cvec, type_vec): + for param_code, type in zip(cvec, type_vec): if first_param: params = str(param_code) first_param = False diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py index 7bdf0c7dd9..e5bf3e29f9 100644 --- a/src/mem/slicc/ast/MethodCallExprAST.py +++ b/src/mem/slicc/ast/MethodCallExprAST.py @@ -189,7 +189,6 @@ class ClassMethodCallExprAST(MethodCallExprAST): return f"[MethodCallExpr: {self.proc_name!r} {self.expr_ast_vec!r}]" def generate_prefix(self, paramTypes): - # class method call prefix = f"({self.type_ast}::" obj_type = self.type_ast.type diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index db215bd029..032a863fd3 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -88,7 +88,6 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): platform: VExpress_GEM5_Base = VExpress_GEM5_Foundation(), release: ArmRelease = ArmDefaultRelease(), ) -> None: - # The platform and the clk has to be set before calling the super class self._platform = platform self._clk_freq = clk_freq @@ -117,7 +116,6 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): @overrides(AbstractBoard) def _setup_board(self) -> None: - # This board is expected to run full-system simulation. # Loading ArmFsLinux() from `src/arch/arm/ArmFsWorkload.py` self.workload = ArmFsLinux() @@ -213,7 +211,6 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): # created. The IO device has to be attached first. This is done in the # realview class. if self.get_cache_hierarchy().is_ruby(): - # All the on-chip devices are attached in this method. self.realview.attachOnChipIO( self.iobus, @@ -359,7 +356,6 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): @overrides(KernelDiskWorkload) def _add_disk_to_board(self, disk_image: AbstractResource): - self._image = CowDiskImage( child=RawDiskImage( read_only=True, image_file=disk_image.get_local_path() @@ -379,7 +375,6 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): @overrides(KernelDiskWorkload) def get_default_kernel_args(self) -> List[str]: - # The default kernel string is taken from the devices.py file. return [ "console=ttyAMA0", diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index 51db66913a..4ba81c258b 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -90,7 +90,6 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): memory: AbstractMemorySystem, cache_hierarchy: AbstractCacheHierarchy, ) -> None: - if cache_hierarchy.is_ruby(): raise EnvironmentError("RiscvBoard is not compatible with Ruby") @@ -105,7 +104,6 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): @overrides(AbstractSystemBoard) def _setup_board(self) -> None: - self.workload = RiscvLinux() # Initialize all the devices that we want to use on this board diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index 01a0ac1f6b..e7e65ecf71 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -202,7 +202,6 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): base_entries.append(pci_dev4_inta) def assignISAInt(irq, apicPin): - assign_8259_to_apic = X86IntelMPIOIntAssignment( interrupt_type="ExtInt", polarity="ConformPolarity", 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 index 9c91e05ac1..7be9239331 100644 --- a/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py @@ -75,7 +75,6 @@ class PrivateL1CacheHierarchy(AbstractRubyCacheHierarchy): @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - requires(coherence_protocol_required=CoherenceProtocol.CHI) self.ruby_system = RubySystem() diff --git a/src/python/gem5/components/cachehierarchies/classic/no_cache.py b/src/python/gem5/components/cachehierarchies/classic/no_cache.py index 51b5d30eb4..b7af6ed02f 100644 --- a/src/python/gem5/components/cachehierarchies/classic/no_cache.py +++ b/src/python/gem5/components/cachehierarchies/classic/no_cache.py @@ -97,12 +97,10 @@ class NoCache(AbstractClassicCacheHierarchy): @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - if board.has_coherent_io(): self._setup_coherent_io_bridge(board) for core in board.get_processor().get_cores(): - core.connect_icache(self.membus.cpu_side_ports) core.connect_dcache(self.membus.cpu_side_ports) core.connect_walker_ports( diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py index 42ff183a1d..9a40c39550 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py @@ -86,7 +86,6 @@ class PrivateL1CacheHierarchy(AbstractClassicCacheHierarchy): @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - # Set up the system port for functional access from the simulator. board.connect_system_port(self.membus.cpu_side_ports) @@ -117,7 +116,6 @@ class PrivateL1CacheHierarchy(AbstractClassicCacheHierarchy): self._setup_io_cache(board) for i, cpu in enumerate(board.get_processor().get_cores()): - cpu.connect_icache(self.l1icaches[i].cpu_side) cpu.connect_dcache(self.l1dcaches[i].cpu_side) 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 8b60aef7f6..b27ced916c 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 @@ -111,7 +111,6 @@ class PrivateL1PrivateL2CacheHierarchy( @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - # Set up the system port for functional access from the simulator. board.connect_system_port(self.membus.cpu_side_ports) @@ -148,7 +147,6 @@ class PrivateL1PrivateL2CacheHierarchy( self._setup_io_cache(board) for i, cpu in enumerate(board.get_processor().get_cores()): - cpu.connect_icache(self.l1icaches[i].cpu_side) cpu.connect_dcache(self.l1dcaches[i].cpu_side) diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py index 72df1a53de..be2dfbe79c 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py @@ -107,7 +107,6 @@ class PrivateL1SharedL2CacheHierarchy( @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - # Set up the system port for functional access from the simulator. board.connect_system_port(self.membus.cpu_side_ports) @@ -143,7 +142,6 @@ class PrivateL1SharedL2CacheHierarchy( self._setup_io_cache(board) for i, cpu in enumerate(board.get_processor().get_cores()): - cpu.connect_icache(self.l1icaches[i].cpu_side) cpu.connect_dcache(self.l1dcaches[i].cpu_side) diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_directory.py index e39a38ccc9..8552b975e1 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_directory.py @@ -30,7 +30,6 @@ from m5.objects import Directory_Controller class AbstractDirectory(Directory_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_dma_controller.py b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_dma_controller.py index 8d36736017..dad1f7cd72 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_dma_controller.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_dma_controller.py @@ -30,7 +30,6 @@ from m5.objects import DMA_Controller class AbstractDMAController(DMA_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py index 683d69584c..237cd606df 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py @@ -35,7 +35,6 @@ import math class AbstractL1Cache(L1Cache_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l2_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l2_cache.py index 88b41228c4..41929f4e42 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l2_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l2_cache.py @@ -30,7 +30,6 @@ from m5.objects import L2Cache_Controller class AbstractL2Cache(L2Cache_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py index cd4f166fed..58676daaf0 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py @@ -32,7 +32,6 @@ from m5.objects import MessageBuffer, RubyDirectoryMemory class Directory(AbstractDirectory): def __init__(self, network, cache_line_size, mem_range, port): - super().__init__(network, cache_line_size) self.addr_ranges = [mem_range] self.directory = RubyDirectoryMemory() diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py index e746579834..0d7f436193 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py @@ -39,10 +39,10 @@ from m5.objects import ( import math + # L0Cache_Controller is the ruby backend's terminology corresponding to # L1 cache in stdlib terms. class L1Cache(L0Cache_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py index dfc1304a87..280c2e4110 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py @@ -38,10 +38,10 @@ from m5.objects import ( import math + # L1Cache_Controller is ruby backend's terminology corresponding to # L2Cache in stdlib's terms class L2Cache(L1Cache_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py index 0a93d9b0c8..4b05166752 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py @@ -28,10 +28,10 @@ from m5.objects import MessageBuffer, RubyCache, L2Cache_Controller import math + # L2Cache_Controller is ruby backend's terminology corresponding to # L3 cache in stdlib. class L3Cache(L2Cache_Controller): - _version = 0 @classmethod diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py index cd4f166fed..58676daaf0 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py @@ -32,7 +32,6 @@ from m5.objects import MessageBuffer, RubyDirectoryMemory class Directory(AbstractDirectory): def __init__(self, network, cache_line_size, mem_range, port): - super().__init__(network, cache_line_size) self.addr_ranges = [mem_range] self.directory = RubyDirectoryMemory() diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py index e74772cc18..0e7cddf6fe 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py @@ -37,7 +37,6 @@ class Directory(AbstractDirectory): """ def __init__(self, network, cache_line_size, mem_range, port): - super().__init__(network, cache_line_size) self.addr_ranges = [mem_range] self.directory = RubyDirectoryMemory() 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 index 9c8b93d812..09ee69e011 100644 --- 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 @@ -45,6 +45,7 @@ from .core_complex import CoreComplex from .octopi_network import OctopiNetwork from .ruby_network_components import RubyRouter, RubyExtLink, RubyIntLink + # CoreComplex sub-systems own the L1, L2, L3 controllers # OctopiCache owns the directory controllers # RubySystem owns the DMA Controllers @@ -85,7 +86,6 @@ class OctopiCache( self._is_fullsystem = is_fullsystem def incorporate_cache(self, board: AbstractBoard) -> None: - requires( coherence_protocol_required=CoherenceProtocol.MESI_THREE_LEVEL ) 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 index 745ef826c7..8e5befabf7 100644 --- 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 @@ -32,6 +32,7 @@ from .ruby_network_components import ( RubyIntLink, ) + # . The Network owns all routers, all int links and all ext links that are not in CCD's. # . The CCD subsystems are not of type RubyNetwork, so we need to copy the references of # routers and links to OctopiNetwork._routers, ._int_links, and ._ext_links; which will 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 3646418572..2a8ce30cda 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 @@ -80,7 +80,6 @@ class MESIThreeLevelCacheHierarchy( self._num_l3_banks = num_l3_banks def incorporate_cache(self, board: AbstractBoard) -> None: - requires( coherence_protocol_required=CoherenceProtocol.MESI_THREE_LEVEL ) diff --git a/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py index 79c8b0ada3..8c7bba4ed4 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py @@ -76,7 +76,6 @@ class MESITwoLevelCacheHierarchy( self._num_l2_banks = num_l2_banks def incorporate_cache(self, board: AbstractBoard) -> None: - requires(coherence_protocol_required=CoherenceProtocol.MESI_TWO_LEVEL) cache_line_size = board.get_cache_line_size() diff --git a/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py index 5955ad3b20..93b19591cc 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py @@ -58,7 +58,6 @@ class MIExampleCacheHierarchy(AbstractRubyCacheHierarchy): @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - requires(coherence_protocol_required=CoherenceProtocol.MI_EXAMPLE) self.ruby_system = RubySystem() diff --git a/src/python/gem5/components/memory/dram_interfaces/hbm.py b/src/python/gem5/components/memory/dram_interfaces/hbm.py index 5063c4d9e1..50578a04c8 100644 --- a/src/python/gem5/components/memory/dram_interfaces/hbm.py +++ b/src/python/gem5/components/memory/dram_interfaces/hbm.py @@ -201,7 +201,6 @@ class HBM_1000_4H_1x64(HBM_1000_4H_1x128): # on HBM gen2 specifications. 4H stack, 8Gb per die and total capacity # of 4GiB. class HBM_2000_4H_1x64(DRAMInterface): - # 64-bit interface for a single pseudo channel device_bus_width = 64 diff --git a/src/python/gem5/components/memory/hbm.py b/src/python/gem5/components/memory/hbm.py index 75db1f9fde..3f0716c14b 100644 --- a/src/python/gem5/components/memory/hbm.py +++ b/src/python/gem5/components/memory/hbm.py @@ -137,7 +137,6 @@ class HighBandwidthMemory(ChanneledMemory): @overrides(ChanneledMemory) def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]: - intlv_bits = log(self._num_channels, 2) mask_list = [] diff --git a/src/python/gem5/components/processors/base_cpu_core.py b/src/python/gem5/components/processors/base_cpu_core.py index c75c0029cf..58d06024bc 100644 --- a/src/python/gem5/components/processors/base_cpu_core.py +++ b/src/python/gem5/components/processors/base_cpu_core.py @@ -93,7 +93,6 @@ class BaseCPUCore(AbstractCore): @overrides(AbstractCore) def is_kvm_core(self) -> bool: - try: from m5.objects import BaseKvmCPU @@ -118,7 +117,6 @@ class BaseCPUCore(AbstractCore): @overrides(AbstractCore) def connect_walker_ports(self, port1: Port, port2: Port) -> None: if self.get_isa() == ISA.ARM: - # Unlike X86 and RISCV MMU, the ARM MMU has two L1 TLB walker ports # named `walker` and `stage2_walker` for both data and instruction. # The gem5 standard library currently supports one TLB walker port @@ -144,7 +142,6 @@ class BaseCPUCore(AbstractCore): interrupt_requestor: Optional[Port] = None, interrupt_responce: Optional[Port] = None, ) -> None: - # TODO: This model assumes that we will only create an interrupt # controller as we require it. Not sure how true this is in all cases. self.core.createInterruptController() diff --git a/src/python/gem5/components/processors/base_cpu_processor.py b/src/python/gem5/components/processors/base_cpu_processor.py index 9a7561587a..d097682d26 100644 --- a/src/python/gem5/components/processors/base_cpu_processor.py +++ b/src/python/gem5/components/processors/base_cpu_processor.py @@ -71,7 +71,6 @@ class BaseCPUProcessor(AbstractProcessor): @overrides(AbstractProcessor) def incorporate_processor(self, board: AbstractBoard) -> None: - if any(core.is_kvm_core() for core in self.get_cores()): board.kvm_vm = self.kvm_vm # To get the KVM CPUs to run on different host CPUs diff --git a/src/python/gem5/components/processors/simple_core.py b/src/python/gem5/components/processors/simple_core.py index 15e15dc0cf..65c0f0ec83 100644 --- a/src/python/gem5/components/processors/simple_core.py +++ b/src/python/gem5/components/processors/simple_core.py @@ -44,7 +44,6 @@ class SimpleCore(BaseCPUCore): def __init__( self, cpu_type: CPUTypes, core_id: int, isa: Optional[ISA] = None ): - # If the ISA is not specified, we infer it via the `get_runtime_isa` # function. if isa: diff --git a/src/python/gem5/components/processors/switchable_processor.py b/src/python/gem5/components/processors/switchable_processor.py index 20754fbf73..1160c2749a 100644 --- a/src/python/gem5/components/processors/switchable_processor.py +++ b/src/python/gem5/components/processors/switchable_processor.py @@ -52,7 +52,6 @@ class SwitchableProcessor(AbstractProcessor): switchable_cores: Dict[str, List[SimpleCore]], starting_cores: str, ) -> None: - if starting_cores not in switchable_cores.keys(): raise AssertionError( f"Key {starting_cores} cannot be found in the " @@ -85,7 +84,6 @@ class SwitchableProcessor(AbstractProcessor): @overrides(AbstractProcessor) def incorporate_processor(self, board: AbstractBoard) -> None: - # This is a bit of a hack. The `m5.switchCpus` function, used in the # "switch_to_processor" function, requires the System simobject as an # argument. We therefore need to store the board when incorporating the @@ -119,7 +117,6 @@ class SwitchableProcessor(AbstractProcessor): yield core def switch_to_processor(self, switchable_core_key: str): - # Run various checks. if not hasattr(self, "_board"): raise AssertionError("The processor has not been incorporated.") diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py index 25e55ef310..dce1c5a964 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py @@ -97,7 +97,6 @@ class RISCVMatchedCacheHierarchy( @overrides(AbstractCacheHierarchy) def incorporate_cache(self, board: AbstractBoard) -> None: - # Set up the system port for functional access from the simulator. board.connect_system_port(self.membus.cpu_side_ports) @@ -135,7 +134,6 @@ class RISCVMatchedCacheHierarchy( self._setup_io_cache(board) for i, cpu in enumerate(board.get_processor().get_cores()): - cpu.connect_icache(self.l1icaches[i].cpu_side) cpu.connect_dcache(self.l1dcaches[i].cpu_side) diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index ccb92cfb20..4ae1057566 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -63,7 +63,6 @@ class ClientWrapper: clients: Optional[List[str]] = None, gem5_version: Optional[str] = core.gem5Version, ) -> Dict[str, List[str]]: - clients_to_search = ( list(self.clients.keys()) if clients is None else clients ) diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index 3260c97a4b..e9b4980b53 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -369,7 +369,6 @@ def get_resource( with tarfile.open(download_dest) as f: def is_within_directory(directory, target): - abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) @@ -380,7 +379,6 @@ def get_resource( def safe_extract( tar, path=".", members=None, *, numeric_owner=False ): - for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): diff --git a/src/python/gem5/resources/looppoint.py b/src/python/gem5/resources/looppoint.py index 684faef37d..6e26efefdc 100644 --- a/src/python/gem5/resources/looppoint.py +++ b/src/python/gem5/resources/looppoint.py @@ -491,7 +491,6 @@ class LooppointJsonLoader(Looppoint): with open(_path) as file: json_contents = json.load(file) for rid in json_contents: - start_pc = int(json_contents[rid]["simulation"]["start"]["pc"]) start_globl = int( json_contents[rid]["simulation"]["start"]["global"] diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index af8a8d9acd..695ea79986 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -863,7 +863,6 @@ def obtain_resource( # If the "url" field is specified, the resoruce must be downloaded. if "url" in resource_json and resource_json["url"]: - # If the `to_path` parameter is set, we use that as the path to which # the resource is to be downloaded. Otherwise, default to the # `resource_directory` parameter plus the resource ID. diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index e355d200ad..5470202830 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -464,7 +464,7 @@ class Simulator: """ start = 0 to_return = [] - for (exit_event, tick) in self._tick_stopwatch: + for exit_event, tick in self._tick_stopwatch: if exit_event == ExitEvent.WORKBEGIN: start = tick elif exit_event == ExitEvent.WORKEND: @@ -480,7 +480,6 @@ class Simulator: """ if not self._instantiated: - # Before anything else we run the AbstractBoard's # `_pre_instantiate` function. self._board._pre_instantiate() @@ -557,7 +556,6 @@ class Simulator: # This while loop will continue until an a generator yields True. while True: - self._last_exit_event = m5.simulate(max_ticks) # Translate the exit event cause to the exit event enum. @@ -584,7 +582,7 @@ class Simulator: # If the user has specified their own generator for this exit # event, use it. exit_on_completion = next(self._on_exit_event[exit_enum]) - except (StopIteration): + except StopIteration: # If the user's generator has ended, throw a warning and use # the default generator for this exit event. warn( diff --git a/src/python/gem5/utils/multiprocessing/context.py b/src/python/gem5/utils/multiprocessing/context.py index 87917d1bfb..0fc48e2789 100644 --- a/src/python/gem5/utils/multiprocessing/context.py +++ b/src/python/gem5/utils/multiprocessing/context.py @@ -33,6 +33,7 @@ multiprocessing module (i.e., cpython/Lib/multiprocessing/). from multiprocessing import context, process from multiprocessing.context import DefaultContext + # The `_start_method` must be `None` for the `Spawn_gem5Process` class. # Otherwise, in `_bootstrap` in the `BaseProcess` it will try to force the # `_start_method` to be gem5-specific, which the `multiprocessing` module diff --git a/src/python/gem5/utils/progress_bar.py b/src/python/gem5/utils/progress_bar.py index 0ac13200b9..43d3a3dec8 100644 --- a/src/python/gem5/utils/progress_bar.py +++ b/src/python/gem5/utils/progress_bar.py @@ -55,6 +55,7 @@ except ImportError: tqdm = FakeTQDM() _have_tqdm = False + # Hook for the progress bar def progress_hook(t): if not _have_tqdm: diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index f2c1b30def..e601544b68 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -1252,7 +1252,7 @@ class SimObject(object, metaclass=MetaSimObject): # The order of the dict is implementation dependent, so sort # it based on the key (name) to ensure the order is the same # on all hosts - for (name, child) in sorted(self._children.items()): + for name, child in sorted(self._children.items()): for obj in child.descendants(): yield obj @@ -1275,7 +1275,7 @@ class SimObject(object, metaclass=MetaSimObject): def connectPorts(self): # Sort the ports based on their attribute name to ensure the # order is the same on all hosts - for (attr, portRef) in sorted(self._port_refs.items()): + for attr, portRef in sorted(self._port_refs.items()): portRef.ccConnect() # Default function for generating the device structure. diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 2559b553d2..37af0b6c5c 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -453,6 +453,7 @@ VectorParam = ParamFactory(VectorParamDesc) # ##################################################################### + # String-valued parameter. Just mixin the ParamValue class with the # built-in str class. class String(ParamValue, str): @@ -1524,10 +1525,11 @@ class Time(ParamValue): # derive the new type from the appropriate base class on the fly. allEnums = {} + + # Metaclass for Enum types class MetaEnum(MetaParamValue): def __new__(mcls, name, bases, dict): - cls = super().__new__(mcls, name, bases, dict) allEnums[name] = cls return cls @@ -1963,6 +1965,7 @@ class MemoryBandwidth(float, ParamValue): # "Constants"... handy aliases for various values. # + # Special class for NULL pointers. Note the special check in # make_param_value() above that lets these be assigned where a # SimObject is required. @@ -2030,6 +2033,7 @@ AllMemory = AddrRange(0, MaxAddr) # ##################################################################### + # Port reference: encapsulates a reference to a particular port on a # particular SimObject. class PortRef(object): @@ -2371,6 +2375,7 @@ SlavePort = ResponsePort VectorMasterPort = VectorRequestPort VectorSlavePort = VectorResponsePort + # 'Fake' ParamDesc for Port references to assign to the _pdesc slot of # proxy objects (via set_param_desc()) so that proxy error messages # make sense. diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 19d5604568..d619697247 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -65,6 +65,7 @@ _drain_manager = _m5.drain.DrainManager.instance() _instantiated = False # Has m5.instantiate() been called? + # The final call to instantiate the SimObject graph and initialize the # system. def instantiate(ckpt_dir=None): diff --git a/src/python/m5/ticks.py b/src/python/m5/ticks.py index 47b033cfb4..7ec84c3709 100644 --- a/src/python/m5/ticks.py +++ b/src/python/m5/ticks.py @@ -29,6 +29,7 @@ import decimal import sys from m5.util import warn + # fix the global frequency def fixGlobalFrequency(): import _m5.core diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py index 34c5ee8a49..e1c9bd226a 100644 --- a/src/python/m5/util/__init__.py +++ b/src/python/m5/util/__init__.py @@ -48,6 +48,7 @@ from . import convert from .attrdict import attrdict, multiattrdict, optiondict from .multidict import multidict + # panic() should be called when something happens that should never # ever happen regardless of what the user does (i.e., an acutal m5 # bug). diff --git a/src/python/m5/util/terminal_formatter.py b/src/python/m5/util/terminal_formatter.py index 8d533f8bb7..da441b1188 100644 --- a/src/python/m5/util/terminal_formatter.py +++ b/src/python/m5/util/terminal_formatter.py @@ -45,7 +45,6 @@ class TerminalFormatter: return w, h def __get_paragraphs(self, text, flatten=False): - """ This function takes a text and returns a list of constituent paragraphs, defining a paragraph as a block of text separated from diff --git a/src/sim/ClockDomain.py b/src/sim/ClockDomain.py index d71252e1bc..34380f916b 100644 --- a/src/sim/ClockDomain.py +++ b/src/sim/ClockDomain.py @@ -37,6 +37,7 @@ from m5.params import * from m5.SimObject import SimObject from m5.proxy import * + # Abstract clock domain class ClockDomain(SimObject): type = "ClockDomain" diff --git a/src/sim/DVFSHandler.py b/src/sim/DVFSHandler.py index f7064221e1..13c649dbb0 100644 --- a/src/sim/DVFSHandler.py +++ b/src/sim/DVFSHandler.py @@ -37,6 +37,7 @@ from m5.params import * from m5.SimObject import SimObject from m5.proxy import * + # The handler in its current form is design to be centeralized, one per system # and manages all the source clock domains (SrcClockDomain) it is configured to # handle. The specific voltage and frequency points are configured per clock diff --git a/src/sim/PowerDomain.py b/src/sim/PowerDomain.py index 2f42343870..64018e6d15 100644 --- a/src/sim/PowerDomain.py +++ b/src/sim/PowerDomain.py @@ -39,6 +39,7 @@ import sys from m5.params import * from m5.objects.PowerState import PowerState + # A power domain groups multiple ClockedObjects and creates a # hierarchy in which follower ClockedObjects (caches for example) can # change power state depeding on what the leader objects (CPUs for diff --git a/src/sim/PowerState.py b/src/sim/PowerState.py index ca285fc68b..9c9fe03a5a 100644 --- a/src/sim/PowerState.py +++ b/src/sim/PowerState.py @@ -38,6 +38,7 @@ from m5.SimObject import SimObject from m5.params import * from m5.proxy import * + # Enumerate set of allowed power states that can be used by a clocked object. # The list is kept generic to express a base minimal set. # State definition :- diff --git a/src/sim/Root.py b/src/sim/Root.py index 5002cdcf81..5ad42da668 100644 --- a/src/sim/Root.py +++ b/src/sim/Root.py @@ -32,7 +32,6 @@ from m5.util import fatal class Root(SimObject): - _the_instance = None def __new__(cls, **kwargs): diff --git a/src/sim/SubSystem.py b/src/sim/SubSystem.py index fa0063ba1f..49f70d5b8a 100644 --- a/src/sim/SubSystem.py +++ b/src/sim/SubSystem.py @@ -36,6 +36,7 @@ from m5.SimObject import SimObject from m5.params import * + # An empty simobject. Used for organizing simobjects # into logical groups as subsystems of a larger # system. For example, if we wanted to build a cpu cluster diff --git a/src/sim/power/MathExprPowerModel.py b/src/sim/power/MathExprPowerModel.py index 755b3953ee..6f335980a4 100644 --- a/src/sim/power/MathExprPowerModel.py +++ b/src/sim/power/MathExprPowerModel.py @@ -37,6 +37,7 @@ from m5.SimObject import SimObject from m5.params import * from m5.objects.PowerModelState import PowerModelState + # Represents a power model for a simobj class MathExprPowerModel(PowerModelState): type = "MathExprPowerModel" diff --git a/src/sim/power/PowerModel.py b/src/sim/power/PowerModel.py index 8dba29795d..f45f24a3cc 100644 --- a/src/sim/power/PowerModel.py +++ b/src/sim/power/PowerModel.py @@ -37,6 +37,7 @@ from m5.SimObject import * from m5.params import * from m5.proxy import Parent + # Enum for a type of power model class PMType(Enum): vals = ["All", "Static", "Dynamic"] diff --git a/src/sim/power/PowerModelState.py b/src/sim/power/PowerModelState.py index 081cd652d2..ba7bd44915 100644 --- a/src/sim/power/PowerModelState.py +++ b/src/sim/power/PowerModelState.py @@ -36,6 +36,7 @@ from m5.SimObject import * from m5.params import * + # Represents a power model for a simobj class PowerModelState(SimObject): type = "PowerModelState" diff --git a/src/sim/power/ThermalDomain.py b/src/sim/power/ThermalDomain.py index ddb8d4455b..ff5fdaff3f 100644 --- a/src/sim/power/ThermalDomain.py +++ b/src/sim/power/ThermalDomain.py @@ -36,6 +36,7 @@ from m5.SimObject import * from m5.params import * + # Represents a group of simobj which produce heat class ThermalDomain(SimObject): type = "ThermalDomain" diff --git a/src/systemc/core/SystemC.py b/src/systemc/core/SystemC.py index f1f87a0583..a51c33f86f 100644 --- a/src/systemc/core/SystemC.py +++ b/src/systemc/core/SystemC.py @@ -25,6 +25,7 @@ from m5.SimObject import SimObject, cxxMethod + # This class represents the systemc kernel. There should be exactly one in the # simulation. It receives gem5 SimObject lifecycle callbacks (init, regStats, # etc.) and manages the lifecycle of the systemc simulation accordingly. diff --git a/tests/gem5/arm_boot_tests/test_linux_boot.py b/tests/gem5/arm_boot_tests/test_linux_boot.py index b7c0fa86b0..23921ef403 100644 --- a/tests/gem5/arm_boot_tests/test_linux_boot.py +++ b/tests/gem5/arm_boot_tests/test_linux_boot.py @@ -44,7 +44,6 @@ def test_boot( length: str, to_tick: Optional[int] = None, ): - name = f"{cpu}-cpu_{num_cpus}-cores_{mem_system}_{memory_class}_\ arm_boot_test" diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index 05b599dd80..48e2a2540b 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -370,7 +370,6 @@ class DownloadedArchive(DownloadedProgram): with tarfile.open(self.filename) as tf: def is_within_directory(directory, target): - abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) @@ -381,7 +380,6 @@ class DownloadedArchive(DownloadedProgram): def safe_extract( tar, path=".", members=None, *, numeric_owner=False ): - for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): diff --git a/tests/gem5/fs/linux/arm/configs/switcheroo.py b/tests/gem5/fs/linux/arm/configs/switcheroo.py index 72736a9d87..3c39fbf96a 100644 --- a/tests/gem5/fs/linux/arm/configs/switcheroo.py +++ b/tests/gem5/fs/linux/arm/configs/switcheroo.py @@ -53,7 +53,7 @@ class Sequential: def __init__(self, cpus): self.first_cpu = None - for (cpuno, cpu) in enumerate(cpus): + for cpuno, cpu in enumerate(cpus): if not cpu.switched_out: if self.first_cpu != None: fatal("More than one CPU is switched in") @@ -141,7 +141,6 @@ def run_test(root, switcher=None, freq=1000, verbose=False): exit_cause == "target called exit()" or exit_cause == "m5_exit instruction encountered" ): - sys.exit(0) else: print(f"Test failed: Unknown exit cause: {exit_cause}") diff --git a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py index 1967560d99..512e2c7cc2 100644 --- a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py +++ b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py @@ -180,7 +180,6 @@ log.test_log.message( ) # 'False' is used to disable the tests. if False: # os.access("/dev/kvm", mode=os.R_OK | os.W_OK): - # The x86-parsec-benchmarks uses KVM cores, this test will therefore only # be run on systems that support KVM. gem5_verify_config( diff --git a/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py b/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py index f5d407330e..be6821d6ef 100644 --- a/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py +++ b/tests/gem5/kvm_fork_tests/test_kvm_fork_run.py @@ -41,7 +41,6 @@ else: def test_kvm_fork_run(cpu: str, num_cpus: int, mem_system: str, length: str): - if not os.access("/dev/kvm", mode=os.R_OK | os.W_OK): # Don't run the tests if KVM is unavailable. return diff --git a/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py b/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py index 4beb60de64..6cc53e6134 100644 --- a/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py +++ b/tests/gem5/kvm_switch_tests/test_kvm_cpu_switch.py @@ -41,7 +41,6 @@ else: def test_kvm_switch(cpu: str, num_cpus: int, mem_system: str, length: str): - if not os.access("/dev/kvm", mode=os.R_OK | os.W_OK): # Don't run the tests if KVM is unavailable. return diff --git a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py index a0911d46e3..341548729b 100644 --- a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py +++ b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py @@ -147,7 +147,6 @@ 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, ) @@ -214,6 +213,7 @@ board.set_kernel_disk_workload( readfile_contents=command, ) + # Here we define some custom workbegin/workend exit event generators. Here we # want to switch to detailed CPUs at the beginning of the ROI, then continue to # the end of of the ROI. Then we exit the simulation. diff --git a/tests/gem5/parsec_benchmarks/test_parsec.py b/tests/gem5/parsec_benchmarks/test_parsec.py index fee8e7134a..60aae0736d 100644 --- a/tests/gem5/parsec_benchmarks/test_parsec.py +++ b/tests/gem5/parsec_benchmarks/test_parsec.py @@ -43,7 +43,6 @@ def test_parsec( size: str, length: str, ): - if (boot_cpu == "kvm" or detailed_cpu == "kvm") and not os.access( "/dev/kvm", mode=os.R_OK | os.W_OK ): diff --git a/tests/gem5/replacement_policies/traces/rrip_test2_ld.py b/tests/gem5/replacement_policies/traces/rrip_test2_ld.py index b9f2ee026e..dcc8df90ee 100644 --- a/tests/gem5/replacement_policies/traces/rrip_test2_ld.py +++ b/tests/gem5/replacement_policies/traces/rrip_test2_ld.py @@ -52,7 +52,6 @@ from m5.objects.ReplacementPolicies import RRIPRP as rp def python_generator(generator): - yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 100, 0) yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 100, 0) yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 100, 0) diff --git a/tests/gem5/replacement_policies/traces/rrip_test2_st.py b/tests/gem5/replacement_policies/traces/rrip_test2_st.py index be23756a95..b53ec4a076 100644 --- a/tests/gem5/replacement_policies/traces/rrip_test2_st.py +++ b/tests/gem5/replacement_policies/traces/rrip_test2_st.py @@ -52,7 +52,6 @@ from m5.objects.ReplacementPolicies import RRIPRP as rp def python_generator(generator): - yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 0, 0) yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 0, 0) yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 0, 0) diff --git a/tests/gem5/replacement_policies/traces/second_chance_test2_ld.py b/tests/gem5/replacement_policies/traces/second_chance_test2_ld.py index d187cbec3f..88c8e462a2 100644 --- a/tests/gem5/replacement_policies/traces/second_chance_test2_ld.py +++ b/tests/gem5/replacement_policies/traces/second_chance_test2_ld.py @@ -52,7 +52,6 @@ from m5.objects.ReplacementPolicies import SecondChanceRP as rp def python_generator(generator): - yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 100, 0) yield generator.createLinear(60000, 128, 191, 64, 30000, 30000, 100, 0) yield generator.createLinear(60000, 256, 319, 64, 30000, 30000, 100, 0) diff --git a/tests/gem5/replacement_policies/traces/second_chance_test3_st.py b/tests/gem5/replacement_policies/traces/second_chance_test3_st.py index 53dcbffe89..d40383e8fc 100644 --- a/tests/gem5/replacement_policies/traces/second_chance_test3_st.py +++ b/tests/gem5/replacement_policies/traces/second_chance_test3_st.py @@ -54,7 +54,6 @@ from m5.objects.ReplacementPolicies import SecondChanceRP as rp def python_generator(generator): - yield generator.createLinear(60000, 0, 63, 64, 30000, 30000, 0, 0) yield generator.createLinear(60000, 128, 191, 64, 30000, 30000, 0, 0) yield generator.createLinear(60000, 256, 319, 64, 30000, 30000, 0, 0) diff --git a/tests/gem5/riscv_boot_tests/test_linux_boot.py b/tests/gem5/riscv_boot_tests/test_linux_boot.py index 42ae27730f..43d1c6d69f 100644 --- a/tests/gem5/riscv_boot_tests/test_linux_boot.py +++ b/tests/gem5/riscv_boot_tests/test_linux_boot.py @@ -44,7 +44,6 @@ def test_boot( length: str, to_tick: Optional[int] = None, ): - name = "{}-cpu_{}-cores_{}_{}_riscv-boot-test".format( cpu, str(num_cpus), cache_type, memory_class ) diff --git a/tests/gem5/se_mode/hello_se/test_hello_se.py b/tests/gem5/se_mode/hello_se/test_hello_se.py index 5c6ab4ea07..ebcef719a8 100644 --- a/tests/gem5/se_mode/hello_se/test_hello_se.py +++ b/tests/gem5/se_mode/hello_se/test_hello_se.py @@ -90,7 +90,6 @@ stdout_verifier = verifier.MatchRegex(regex) def verify_config(isa, binary, cpu, hosts, verifier, input): - gem5_verify_config( name="test-" + binary + "-" + cpu, fixtures=(), diff --git a/tests/gem5/suite.py b/tests/gem5/suite.py index 7e0935d9eb..939ecdd8fa 100644 --- a/tests/gem5/suite.py +++ b/tests/gem5/suite.py @@ -98,7 +98,6 @@ def gem5_verify_config( for host in valid_hosts: for opt in valid_variants: for isa in valid_isas: - # Create a tempdir fixture to be shared throughout the test. tempdir = TempdirFixture() gem5_returncode = VariableFixture( diff --git a/tests/gem5/traffic_gen/test_memory_traffic_gen.py b/tests/gem5/traffic_gen/test_memory_traffic_gen.py index 0dc5103011..74b31105b7 100644 --- a/tests/gem5/traffic_gen/test_memory_traffic_gen.py +++ b/tests/gem5/traffic_gen/test_memory_traffic_gen.py @@ -44,7 +44,6 @@ def test_memory( memory: str, *args, ) -> None: - name = ( "test-memory-" + f"{generator}-{generator_cores}-{cache}-{module}-{memory}" diff --git a/tests/gem5/verifier.py b/tests/gem5/verifier.py index 9bc5e8f8b5..2cebf24d5f 100644 --- a/tests/gem5/verifier.py +++ b/tests/gem5/verifier.py @@ -139,7 +139,6 @@ class DerivedGoldStandard(MatchGoldStandard): def __init__( self, standard_filename, ignore_regex=__ignore_regex_sentinel, **kwargs ): - if ignore_regex == self.__ignore_regex_sentinel: ignore_regex = self._default_ignore_regex diff --git a/tests/gem5/x86_boot_tests/test_linux_boot.py b/tests/gem5/x86_boot_tests/test_linux_boot.py index 3418e839ab..d4b744a0b1 100644 --- a/tests/gem5/x86_boot_tests/test_linux_boot.py +++ b/tests/gem5/x86_boot_tests/test_linux_boot.py @@ -44,7 +44,6 @@ def test_boot( boot_type: str = "init", to_tick: Optional[int] = None, ): - name = "{}-cpu_{}-cores_{}_{}_{}_x86-boot-test".format( cpu, str(num_cpus), mem_system, memory_class, boot_type ) diff --git a/tests/pyunit/stdlib/pyunit_looppoint.py b/tests/pyunit/stdlib/pyunit_looppoint.py index 0cb708e8ac..0b7acbd3f8 100644 --- a/tests/pyunit/stdlib/pyunit_looppoint.py +++ b/tests/pyunit/stdlib/pyunit_looppoint.py @@ -318,7 +318,6 @@ class LooppointTestSuite(unittest.TestCase): self.assertEquals(PcCountPair(101, 202), targets[5]) def test_get_region_start_id_map(self): - region1 = LooppointRegion( simulation=LooppointSimulation( start=LooppointRegionPC(pc=56, globl=2345, relative=344), diff --git a/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py b/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py index 65bf33544e..826d2ae2fa 100644 --- a/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py @@ -75,7 +75,6 @@ class MD5DirTestSuite(unittest.TestCase): """Test cases for gem5.resources.md5_utils.md5_dir()""" def _create_temp_directory(self) -> Path: - dir = tempfile.mkdtemp() with open(os.path.join(dir, "file1"), "w") as f: diff --git a/tests/run.py b/tests/run.py index dde8f70749..d72a6ceba4 100644 --- a/tests/run.py +++ b/tests/run.py @@ -161,6 +161,7 @@ test_progs = os.environ.get("M5_TEST_PROGS", "/dist/m5/regression/test-progs") if not os.path.isdir(test_progs): test_progs = joinpath(tests_root, "test-progs") + # generate path to binary file def binpath(app, file=None): # executable has same name as app unless specified otherwise @@ -234,6 +235,7 @@ exec( ) ) + # Initialize all CPUs in a system def initCPUs(sys): def initCPU(cpu): diff --git a/util/checkpoint_aggregator.py b/util/checkpoint_aggregator.py index 86892c87b1..069557a2ef 100755 --- a/util/checkpoint_aggregator.py +++ b/util/checkpoint_aggregator.py @@ -57,7 +57,7 @@ def aggregate(output_dir, cpts, no_compress, memory_size): max_curtick = 0 num_digits = len(str(len(cpts) - 1)) - for (i, arg) in enumerate(cpts): + for i, arg in enumerate(cpts): print(arg) merged_config = myCP() config = myCP() diff --git a/util/cpt_upgraders/arm-ccregs.py b/util/cpt_upgraders/arm-ccregs.py index 435be7b0cb..fb17fd5886 100644 --- a/util/cpt_upgraders/arm-ccregs.py +++ b/util/cpt_upgraders/arm-ccregs.py @@ -11,7 +11,7 @@ def upgrader(cpt): continue items = [] - for (item, value) in cpt.items(sec): + for item, value in cpt.items(sec): items.append(item) if "ccRegs" not in items: intRegs = cpt.get(sec, "intRegs").split() diff --git a/util/cpt_upgraders/arm-gicv2-banked-regs.py b/util/cpt_upgraders/arm-gicv2-banked-regs.py index 44a6146b58..3e8fa3c60c 100644 --- a/util/cpt_upgraders/arm-gicv2-banked-regs.py +++ b/util/cpt_upgraders/arm-gicv2-banked-regs.py @@ -33,6 +33,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # duplicate banked registers into new per-cpu arrays. def upgrader(cpt): if cpt.get("root", "isa", fallback="") == "arm": diff --git a/util/cpt_upgraders/arm-sve.py b/util/cpt_upgraders/arm-sve.py index 45d2949aa8..ac93b9f24a 100644 --- a/util/cpt_upgraders/arm-sve.py +++ b/util/cpt_upgraders/arm-sve.py @@ -13,7 +13,6 @@ def upgrader(cpt): # Search for all ISA sections if re.search(".*sys.*\.cpu.*\.isa$", sec): - # haveSVE = false cpt.set(sec, "haveSVE", "false") diff --git a/util/cpt_upgraders/arm-sysreg-mapping-ns.py b/util/cpt_upgraders/arm-sysreg-mapping-ns.py index fd02062039..5551b301da 100644 --- a/util/cpt_upgraders/arm-sysreg-mapping-ns.py +++ b/util/cpt_upgraders/arm-sysreg-mapping-ns.py @@ -33,6 +33,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # reflect updated register mappings for ARM ISA def upgrader(cpt): if cpt.get("root", "isa", fallback="") == "arm": diff --git a/util/cpt_upgraders/isa-is-simobject.py b/util/cpt_upgraders/isa-is-simobject.py index 0fd33f733e..6305eeba5c 100644 --- a/util/cpt_upgraders/isa-is-simobject.py +++ b/util/cpt_upgraders/isa-is-simobject.py @@ -75,17 +75,17 @@ def upgrader(cpt): isa_section = [] for fspec in isa_fields: - for (key, value) in cpt.items(sec, raw=True): + for key, value in cpt.items(sec, raw=True): if key in isa_fields: isa_section.append((key, value)) name = f"{re_cpu_match.group(1)}.isa" isa_sections.append((name, isa_section)) - for (key, value) in isa_section: + for key, value in isa_section: cpt.remove_option(sec, key) - for (sec, options) in isa_sections: + for sec, options in isa_sections: # Some intermediate versions of gem5 have empty ISA sections # (after we made the ISA a SimObject, but before we started to # serialize into a separate ISA section). @@ -97,7 +97,7 @@ def upgrader(cpt): "Unexpected populated ISA section in old checkpoint" ) - for (key, value) in options: + for key, value in options: cpt.set(sec, key, value) diff --git a/util/cpt_upgraders/mempool-sections.py b/util/cpt_upgraders/mempool-sections.py index dec2e02799..55f1d591dc 100644 --- a/util/cpt_upgraders/mempool-sections.py +++ b/util/cpt_upgraders/mempool-sections.py @@ -12,7 +12,6 @@ def upgrader(cpt): systems[sec] = ptrs, limits for sec, (ptrs, limits) in systems.items(): - ptrs = list(map(int, ptrs.split())) limits = list(map(int, limits.split())) diff --git a/util/cpt_upgraders/riscv-pcstate.py b/util/cpt_upgraders/riscv-pcstate.py index b8c6baf729..c8220ddbb8 100644 --- a/util/cpt_upgraders/riscv-pcstate.py +++ b/util/cpt_upgraders/riscv-pcstate.py @@ -26,7 +26,6 @@ def upgrader(cpt): - # Update the RISC-V pcstate to match the new version of # PCState @@ -34,7 +33,6 @@ def upgrader(cpt): import re if re.search(".*processor.*\.core.*\.xc.*", sec): - if cpt.get(sec, "_rvType", fallback="") == "": cpt.set(sec, "_rvType", "1") diff --git a/util/cpt_upgraders/riscv-vext.py b/util/cpt_upgraders/riscv-vext.py index ada492fe1e..8b340ac3d7 100644 --- a/util/cpt_upgraders/riscv-vext.py +++ b/util/cpt_upgraders/riscv-vext.py @@ -40,7 +40,6 @@ def upgrader(cpt): # Search for all XC sections if re.search(".*processor.*\.core.*\.xc.*", sec): - # Updating RVV vector registers (dummy values) # Assuming VLEN = 256 bits (32 bytes) mr = cpt.get(sec, "regs.vector").split() @@ -58,7 +57,6 @@ def upgrader(cpt): # Search for all ISA sections if re.search(".*processor.*\.core.*\.isa$", sec): - # Updating RVV misc registers (dummy values) mr = cpt.get(sec, "miscRegFile").split() if len(mr) == 164: diff --git a/util/gem5art/artifact/gem5art/artifact/artifact.py b/util/gem5art/artifact/gem5art/artifact/artifact.py index b71369c689..d178b218dd 100644 --- a/util/gem5art/artifact/gem5art/artifact/artifact.py +++ b/util/gem5art/artifact/gem5art/artifact/artifact.py @@ -166,7 +166,6 @@ class Artifact: version: str = "", **kwargs: str, ) -> "Artifact": - """Constructs a new artifact without using the database. Different from registerArtifact(), this method won't use database. diff --git a/util/gem5art/artifact/tests/test_artifact.py b/util/gem5art/artifact/tests/test_artifact.py index af6f8ae75b..548409c8c9 100644 --- a/util/gem5art/artifact/tests/test_artifact.py +++ b/util/gem5art/artifact/tests/test_artifact.py @@ -205,7 +205,6 @@ class TestArtifactSimilarity(unittest.TestCase): class TestRegisterArtifact(unittest.TestCase): def setUp(self): - # Create and register an artifact self.testArtifactA = artifact.Artifact.registerArtifact( name="artifact-A", diff --git a/util/gem5art/run/bin/gem5art-getruns b/util/gem5art/run/bin/gem5art-getruns index 5474dd68d7..da8d2f0835 100755 --- a/util/gem5art/run/bin/gem5art-getruns +++ b/util/gem5art/run/bin/gem5art-getruns @@ -71,7 +71,6 @@ def parseArgs(): if __name__ == "__main__": - args = parseArgs() db = getDBConnection(args.db_uri) diff --git a/util/gem5art/run/gem5art/run.py b/util/gem5art/run/gem5art/run.py index 12e4b3e208..7b7b823200 100644 --- a/util/gem5art/run/gem5art/run.py +++ b/util/gem5art/run/gem5art/run.py @@ -672,7 +672,6 @@ def getRunsByNameLike( def getRerunnableRunsByNameLike( db: ArtifactDB, name: str, fs_only: bool = False, limit: int = 0 ) -> Iterable[gem5Run]: - """Returns a generator of gem5Run objects having rerunnable as true and the object "name" containing the name parameter as a substring. The parameter is case sensitive. diff --git a/util/gem5img.py b/util/gem5img.py index 8eb0965c9e..298c43c1c3 100755 --- a/util/gem5img.py +++ b/util/gem5img.py @@ -65,6 +65,7 @@ env["PATH"] += ":/sbin:/usr/sbin" # Whether to print debug output. debug = False + # Figure out cylinders, heads and sectors from a size in blocks. def chsFromSize(sizeInBlocks): if sizeInBlocks >= MaxLBABlocks: diff --git a/util/logroll.py b/util/logroll.py index 02ca309e87..e3dfb7d78c 100755 --- a/util/logroll.py +++ b/util/logroll.py @@ -214,7 +214,6 @@ class TestLogroll(unittest.TestCase): ) as mock_signal, unittest.mock.patch( __name__ + ".dump_lines", new_callable=CopyingMock ) as mock_dump_lines: - signal_dict = self.mock_signal_dict(mock_signal) main( @@ -237,7 +236,6 @@ class TestLogroll(unittest.TestCase): ) as mock_signal, unittest.mock.patch( __name__ + ".dump_lines", new_callable=CopyingMock ) as mock_dump_lines: - signal_dict = self.mock_signal_dict(mock_signal) with self.assertRaises(SystemExit): @@ -258,7 +256,6 @@ class TestLogroll(unittest.TestCase): ) as mock_signal, unittest.mock.patch( __name__ + ".dump_lines", new_callable=CopyingMock ) as mock_dump_lines: - signal_dict = self.mock_signal_dict(mock_signal) main( @@ -283,7 +280,6 @@ class TestLogroll(unittest.TestCase): ) as mock_signal, unittest.mock.patch( __name__ + ".dump_lines", new_callable=CopyingMock ) as mock_dump_lines: - signal_dict = self.mock_signal_dict(mock_signal) with self.assertRaises(SystemExit): diff --git a/util/maint/lib/maintainers.py b/util/maint/lib/maintainers.py index 93ea1a17bf..947e268112 100644 --- a/util/maint/lib/maintainers.py +++ b/util/maint/lib/maintainers.py @@ -118,7 +118,6 @@ class Maintainers(object): def from_file( cls, path_or_file: Optional[PathOrFile] = None ) -> "Maintainers": - return cls(Maintainers._load_maintainers_file(path_or_file)) @classmethod diff --git a/util/on-chip-network-power-area.py b/util/on-chip-network-power-area.py index 61a316a99c..1dfc434be8 100644 --- a/util/on-chip-network-power-area.py +++ b/util/on-chip-network-power-area.py @@ -55,6 +55,7 @@ os.chdir("../../../") sys.path.append("build/ext/dsent") import dsent + # Parse gem5 config.ini file for the configuration parameters related to # the on-chip network. def parseConfig(config_file): @@ -182,7 +183,6 @@ def parseStats( buffers_per_control_vc, ni_flit_size_bits, ): - # Open the stats.txt file and parse it to for the required numbers # and the number of routers. try: diff --git a/util/plot_dram/PlotPowerStates.py b/util/plot_dram/PlotPowerStates.py index b476a24da1..395c48184f 100755 --- a/util/plot_dram/PlotPowerStates.py +++ b/util/plot_dram/PlotPowerStates.py @@ -150,7 +150,6 @@ def plotLowPStates( for delay in delayValues: for bank_util in bankUtilValues: for seq_bytes in seqBytesValues: - for line in stats_file: if "Begin" in line: break @@ -261,7 +260,6 @@ def plotStackedStates(delay, states_list, bottom_state, plot_name, ylabel_str): ind = np.arange(N) for sub_idx, bank_util in enumerate(bankUtilValues): - l_states = {} p_states = {} diff --git a/util/plot_dram/dram_lat_mem_rd_plot.py b/util/plot_dram/dram_lat_mem_rd_plot.py index 541fa9808c..d8f2e90470 100755 --- a/util/plot_dram/dram_lat_mem_rd_plot.py +++ b/util/plot_dram/dram_lat_mem_rd_plot.py @@ -46,11 +46,11 @@ except ImportError: import sys import re + # This script is intended to post process and plot the output from # running configs/dram/lat_mem_rd.py, as such it parses the simout.txt and # stats.txt to get the relevant data points. def main(): - if len(sys.argv) != 2: print("Usage: ", sys.argv[0], "") exit(-1) @@ -122,7 +122,7 @@ def main(): ) exit(-1) - for (r, l) in zip(ranges, final_rd_lat): + for r, l in zip(ranges, final_rd_lat): print(r, round(l, 2)) # lazy version to check if an integer is a power of two diff --git a/util/plot_dram/dram_sweep_plot.py b/util/plot_dram/dram_sweep_plot.py index 89c0dda7da..50efc424f1 100755 --- a/util/plot_dram/dram_sweep_plot.py +++ b/util/plot_dram/dram_sweep_plot.py @@ -47,12 +47,12 @@ except ImportError: import sys import re + # Determine the parameters of the sweep from the simout output, and # then parse the stats and plot the 3D surface corresponding to the # different combinations of parallel banks, and stride size, as # generated by the config/dram/sweep.py script def main(): - if len(sys.argv) != 3: print("Usage: ", sys.argv[0], "-u|p|e ") exit(-1) diff --git a/util/plot_dram/lowp_dram_sweep_plot.py b/util/plot_dram/lowp_dram_sweep_plot.py index dedd1e0c0d..053d7d0bc6 100755 --- a/util/plot_dram/lowp_dram_sweep_plot.py +++ b/util/plot_dram/lowp_dram_sweep_plot.py @@ -140,7 +140,6 @@ def wrapForGraphic(filename, width="1.0"): def startDocText(outfile): - start_stuff = """ \\documentclass[a4paper,landscape,twocolumn]{article} @@ -152,7 +151,6 @@ def startDocText(outfile): def endDocText(outfile): - end_stuff = """ \\end{document} diff --git a/util/streamline/m5stats2streamline.py b/util/streamline/m5stats2streamline.py index 7e82744d0b..5b91cb648d 100755 --- a/util/streamline/m5stats2streamline.py +++ b/util/streamline/m5stats2streamline.py @@ -143,6 +143,7 @@ num_events = args.num_events start_tick = -1 end_tick = -1 + # Parse gem5 config.ini file to determine some system configurations. # Number of CPUs, L2s, etc. def parseConfig(config_file): @@ -814,7 +815,6 @@ def writeXmlFile(xml, filename): # StatsEntry that contains individual statistics class StatsEntry(object): def __init__(self, name, group, group_index, per_cpu, key): - # Full name of statistics self.name = name diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py index f2bee1653a..d23b6764c7 100644 --- a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py +++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py @@ -31,6 +31,7 @@ from m5.proxy import * from m5.objects.SystemC import SystemC_ScModule from m5.objects.Tlm import TlmTargetSocket + # This class is a subclass of sc_module, and all the special magic which makes # that work is handled in the base classes. class TLM_Target(SystemC_ScModule): diff --git a/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py b/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py index 66b05bf79f..e4535d2c12 100644 --- a/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py +++ b/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py @@ -28,6 +28,7 @@ from m5.SimObject import SimObject from m5.objects.SystemC import SystemC_ScModule + # This class is a subclass of sc_module, and all the special magic which makes # that work is handled in the base classes. class SystemC_Printer(SystemC_ScModule): From 1502f7c09fcb81e7452cc3e16567710100a087a3 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 12:42:29 -0700 Subject: [PATCH 428/693] misc: Add black update change to .git-blame-ignore-rev Change-Id: Ief04aec128bc48e66b79fc2f5c474948dd5eb9eb --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index da2f5c07bc..2605198ccf 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -32,3 +32,6 @@ e73655d038cdfa68964109044e33c9a6e7d85ac9 # A commit which ran pre-commit on ext/testlib 9e1afdecefaf910fa6e266f29dc480a32b0fa83e + +# Updated black from 22.6.0 to 23.9.1 +ddf6cb88e48df4ac7de4a9e4b612daf2e7e635c8 From 937b829e8fc45f4ee94f884375f2822799d41506 Mon Sep 17 00:00:00 2001 From: Kaustav Goswami Date: Wed, 4 Oct 2023 17:11:05 -0700 Subject: [PATCH 429/693] configs,ext: Updated the gem5 SST Bridge to use SST 13.0.0 This change updates the gem5 SST Bridge to use SST 13.0.0. Changes are made to replace SimpleMem class to StandardMem class as SimpleMem will be deprecated in SST 14 and above. In addition, the translator.hh is updated to translate more types of gem5 packets. A new parameter `ports` was added on SST's side when invoking the gem5 component which does not require recompiling the gem5 component whenever a new outgoing bridge is added in a gem5 config. Change-Id: I45f0013bc35d088df0aa5a71951422cabab4d7f7 Signed-off-by: Kaustav Goswami --- configs/example/sst/riscv_fs.py | 20 ++-- ext/sst/INSTALL.md | 46 +++++---- ext/sst/Makefile.linux | 21 +++++ ext/sst/Makefile.mac | 21 +++++ ext/sst/gem5.cc | 65 +++++++++---- ext/sst/gem5.hh | 13 ++- ext/sst/sst/arm_example.py | 37 +++++--- ext/sst/sst/example.py | 41 ++++++--- ext/sst/sst_responder.hh | 5 +- ext/sst/sst_responder_subcomponent.cc | 93 ++++++++++--------- ext/sst/sst_responder_subcomponent.hh | 22 ++--- ext/sst/translator.hh | 128 +++++++++++++++++++------- 12 files changed, 354 insertions(+), 158 deletions(-) create mode 100644 ext/sst/Makefile.linux create mode 100644 ext/sst/Makefile.mac diff --git a/configs/example/sst/riscv_fs.py b/configs/example/sst/riscv_fs.py index 77db9e4dbe..46754debf5 100644 --- a/configs/example/sst/riscv_fs.py +++ b/configs/example/sst/riscv_fs.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2021-2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -104,16 +104,9 @@ def createHiFivePlatform(system): system.platform.pci_host.pio = system.membus.mem_side_ports - system.platform.rtc = RiscvRTC(frequency=Frequency("100MHz")) + system.platform.rtc = RiscvRTC(frequency=Frequency("10MHz")) system.platform.clint.int_pin = system.platform.rtc.int_pin - system.pma_checker = PMAChecker( - uncacheable=[ - *system.platform._on_chip_ranges(), - *system.platform._off_chip_ranges(), - ] - ) - system.iobus = IOXBar() system.bridge = Bridge(delay="50ns") system.bridge.mem_side_port = system.iobus.cpu_side_ports @@ -122,6 +115,15 @@ def createHiFivePlatform(system): system.platform.setNumCores(1) + for cpu in system.cpu: + # pma_checker has to be added for each of the system cpus. + cpu.mmu.pma_checker = PMAChecker( + uncacheable=[ + *system.platform._on_chip_ranges(), + *system.platform._off_chip_ranges(), + ] + ) + system.platform.attachOnChipIO(system.membus) system.platform.attachOffChipIO(system.iobus) diff --git a/ext/sst/INSTALL.md b/ext/sst/INSTALL.md index 91f92eb7ff..ba61996b32 100644 --- a/ext/sst/INSTALL.md +++ b/ext/sst/INSTALL.md @@ -1,8 +1,8 @@ # Installing SST -The links to download SST source code are available here -[http://sst-simulator.org/SSTPages/SSTMainDownloads/]. -This guide is using the most recent SST version (11.0.0) as of September 2021. +The links to download SST source code are available at +. +This guide is using the most recent SST version (13.0.0) as of September 2023. The following guide assumes `$SST_CORE_HOME` as the location where SST will be installed. @@ -11,14 +11,14 @@ installed. ### Downloading the SST-Core Source Code ```sh -wget https://github.com/sstsimulator/sst-core/releases/download/v11.1.0_Final/sstcore-11.1.0.tar.gz -tar xf sstcore-11.1.0.tar.gz +wget https://github.com/sstsimulator/sst-core/releases/download/v13.0.0_Final/sstcore-13.0.0.tar.gz +tar xzf sstcore-13.0.0.tar.gz ``` ### Installing SST-Core ```sh -cd sstcore-11.1.0 +cd sstcore-13.0.0 ./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ --disable-mpi # optional, used when MPI is not available. make all -j$(nproc) @@ -36,14 +36,14 @@ export PATH=$SST_CORE_HOME/bin:$PATH ### Downloading the SST-Elements Source Code ```sh -wget https://github.com/sstsimulator/sst-elements/releases/download/v11.1.0_Final/sstelements-11.1.0.tar.gz -tar xf sstelements-11.1.0.tar.gz +wget https://github.com/sstsimulator/sst-elements/releases/download/v13.0.0_Final/sstelements-13.0.0.tar.gz +tar xzf sstelements-13.0.0.tar.gz ``` ### Installing SST-Elements ```sh -cd sst-elements-library-11.1.0 +cd sst-elements-library-13.0.0 ./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ --with-sst-core=$SST_CORE_HOME make all -j$(nproc) @@ -58,24 +58,36 @@ echo "export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$SST_CORE_HOME/lib/pkgconfig/" >> ### Building gem5 library -At the root of gem5 folder, - +At the root of the gem5 folder, you need to compile gem5 as a library. This +varies dependent on which OS you are using. If you're using Linux, then +execute the following: ```sh scons build/RISCV/libgem5_opt.so -j $(nproc) --without-tcmalloc --duplicate-sources ``` +In case you're using Mac, then type the following: +```sh +scons build/RISCV/libgem5_opt.dylib -j $(nproc) --without-tcmalloc --duplicate-sources +``` -**Note:** `--without-tcmalloc` is required to avoid a conflict with SST's malloc. -`--duplicate-sources` is required as the compilation of SST depends on sources to be present in the "build" directory. +**Note:** +* `--without-tcmalloc` is required to avoid a conflict with SST's malloc. +* `--duplicate-sources` is required as the compilation of SST depends on sources to be present in the "build" directory. +* The Mac version was tested on a Macbook Air with M2 processor. ### Compiling the SST integration -At the root of gem5 folder, - +Go to the SST directory in the gem5 repo. ```sh cd ext/sst -make ``` - +Depending on your OS, you need to copy the correct `Makefile.xxx` file to +`Makefile`. +```sh +cp Makefile.xxx Makefile # linux or mac +make -j4 +``` +The make file is hardcoded to RISC-V. IN the case you wish to compile to ARM, +edit the Makefile or pass `ARCH=RISCV` to `ARCH=ARM` while compiling. ### Running an example simulation See `README.md` diff --git a/ext/sst/Makefile.linux b/ext/sst/Makefile.linux new file mode 100644 index 0000000000..f44ecd46d9 --- /dev/null +++ b/ext/sst/Makefile.linux @@ -0,0 +1,21 @@ +SST_VERSION=SST-13.0.0 # Name of the .pc file in lib/pkgconfig where SST is installed +GEM5_LIB=gem5_opt +ARCH=RISCV +OFLAG=3 + +LDFLAGS=-shared -fno-common ${shell pkg-config ${SST_VERSION} --libs} -L../../build/${ARCH}/ -Wl,-rpath ../../build/${ARCH} +CXXFLAGS=-std=c++17 -g -O${OFLAG} -fPIC ${shell pkg-config ${SST_VERSION} --cflags} ${shell python3-config --includes} -I../../build/${ARCH}/ -I../../ext/pybind11/include/ -I../../build/softfloat/ -I../../ext +CPPFLAGS+=-MMD -MP +SRC=$(wildcard *.cc) + +.PHONY: clean all + +all: libgem5.so + +libgem5.so: $(SRC:%.cc=%.o) + ${CXX} ${CPPFLAGS} ${LDFLAGS} $? -o $@ -l${GEM5_LIB} + +-include $(SRC:%.cc=%.d) + +clean: + ${RM} *.[do] libgem5.so diff --git a/ext/sst/Makefile.mac b/ext/sst/Makefile.mac new file mode 100644 index 0000000000..4a67570a44 --- /dev/null +++ b/ext/sst/Makefile.mac @@ -0,0 +1,21 @@ +SST_VERSION=SST-13.0.0 # Name of the .pc file in lib/pkgconfig where SST is installed +GEM5_LIB=gem5_opt +ARCH=RISCV +OFLAG=3 + +LDFLAGS=-shared -fno-common ${shell pkg-config ${SST_VERSION} --libs} -L../../build/${ARCH}/ -Wl,-rpath ../../build/${ARCH} +CXXFLAGS=-std=c++17 -g -O${OFLAG} -fPIC ${shell pkg-config ${SST_VERSION} --cflags} ${shell python3-config --includes} -I../../build/${ARCH}/ -I../../ext/pybind11/include/ -I../../build/softfloat/ -I../../ext +CPPFLAGS+=-MMD -MP +SRC=$(wildcard *.cc) + +.PHONY: clean all + +all: libgem5.dylib + +libgem5.dylib: $(SRC:%.cc=%.o) + ${CXX} ${CPPFLAGS} ${LDFLAGS} $? -o $@ -l${GEM5_LIB} + +-include $(SRC:%.cc=%.d) + +clean: + ${RM} *.[do] libgem5.dylib diff --git a/ext/sst/gem5.cc b/ext/sst/gem5.cc index 7af0eed7b7..8c845f329e 100644 --- a/ext/sst/gem5.cc +++ b/ext/sst/gem5.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Regents of the University of California +// Copyright (c) 2021-2023 The Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -70,7 +70,6 @@ #include #include -#include #include #include #include @@ -169,16 +168,29 @@ gem5Component::gem5Component(SST::ComponentId_t id, SST::Params& params): registerAsPrimaryComponent(); primaryComponentDoNotEndSim(); - systemPort = \ - loadUserSubComponent("system_port",0); - cachePort = \ - loadUserSubComponent("cache_port", 0); - - systemPort->setTimeConverter(timeConverter); - systemPort->setOutputStream(&(output)); - cachePort->setTimeConverter(timeConverter); - cachePort->setOutputStream(&(output)); - + // We need to add another parameter when invoking gem5 scripts from SST to + // keep a track of all the OutgoingBridges. This will allow to add or + // remove OutgoingBridges from gem5 configs without the need to recompile + // the ext/sst source everytime. + std::string ports = params.find("ports", ""); + if (ports.empty()) { + output.fatal( + CALL_INFO, -1, "Component %s must have a 'ports' parameter.\n", + getName().c_str() + ); + } + // Split the port names using the util method defined. + splitPortNames(ports); + for (int i = 0 ; i < sstPortCount ; i++) { + std::cout << sstPortNames[i] << std::endl; + sstPorts.push_back( + loadUserSubComponent(sstPortNames[i], 0) + ); + // If the name defined in the `ports` is incorrect, then the program + // will crash when calling `setTimeConverter`. + sstPorts[i]->setTimeConverter(timeConverter); + sstPorts[i]->setOutputStream(&(output)); + } } gem5Component::~gem5Component() @@ -216,8 +228,9 @@ gem5Component::init(unsigned phase) // find the corresponding SimObject for each SSTResponderSubComponent gem5::Root* gem5_root = gem5::Root::root(); - systemPort->findCorrespondingSimObject(gem5_root); - cachePort->findCorrespondingSimObject(gem5_root); + for (auto &port : sstPorts) { + port->findCorrespondingSimObject(gem5_root); + } // initialize the gem5 event queue if (!(threadInitialized)) { @@ -230,17 +243,18 @@ gem5Component::init(unsigned phase) } } - - systemPort->init(phase); - cachePort->init(phase); + for (auto &port : sstPorts) { + port->init(phase); + } } void gem5Component::setup() { output.verbose(CALL_INFO, 1, 0, "Component is being setup.\n"); - systemPort->setup(); - cachePort->setup(); + for (auto &port : sstPorts) { + port->setup(); + } } void @@ -427,3 +441,16 @@ gem5Component::splitCommandArgs(std::string &cmd, std::vector &args) for (auto part: parsed_args) args.push_back(strdup(part.c_str())); } + +void +gem5Component::splitPortNames(std::string port_names) +{ + std::vector parsed_args = tokenizeString( + port_names, {'\\', ' ', '\'', '\"'} + ); + sstPortCount = 0; + for (auto part: parsed_args) { + sstPortNames.push_back(strdup(part.c_str())); + sstPortCount++; + } +} diff --git a/ext/sst/gem5.hh b/ext/sst/gem5.hh index 447c68c3b2..fd00b1504e 100644 --- a/ext/sst/gem5.hh +++ b/ext/sst/gem5.hh @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Regents of the University of California +// Copyright (c) 2021-2023 The Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -79,7 +79,6 @@ #include #include -#include #include #include @@ -108,15 +107,20 @@ class gem5Component: public SST::Component private: SST::Output output; - SSTResponderSubComponent* systemPort; - SSTResponderSubComponent* cachePort; uint64_t clocksProcessed; SST::TimeConverter* timeConverter; gem5::GlobalSimLoopExitEvent *simulateLimitEvent; std::vector args; + // We need a list of incoming port names so that we don't need to recompile + // everytime when we add a new OutgoingBridge from python. + std::vector sstPorts; + std::vector sstPortNames; + int sstPortCount; + void initPython(int argc, char **argv); void splitCommandArgs(std::string &cmd, std::vector &args); + void splitPortNames(std::string port_names); bool threadInitialized; @@ -139,6 +143,7 @@ class gem5Component: public SST::Component ) SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( + // These are the generally expected ports. {"system_port", "Connection to gem5 system_port", "gem5.gem5Bridge"}, {"cache_port", "Connection to gem5 CPU", "gem5.gem5Bridge"} ) diff --git a/ext/sst/sst/arm_example.py b/ext/sst/sst/arm_example.py index cdee3ca40a..4bc111cb86 100644 --- a/ext/sst/sst/arm_example.py +++ b/ext/sst/sst/arm_example.py @@ -10,7 +10,7 @@ # 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 +# Copyright (c) 2021-2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -46,9 +46,10 @@ cache_link_latency = "1ps" kernel = "vmlinux_exit.arm64" cpu_clock_rate = "3GHz" -# gem5 will send requests to physical addresses of range [0x80000000, inf) to memory -# currently, we do not subtract 0x80000000 from the request's address to get the "real" address -# so, the mem_size would always be 2GiB larger than the desired memory size +# gem5 will send requests to physical addresses of range [0x80000000, inf) to +# memory currently, we do not subtract 0x80000000 from the request's address to +# get the "real" address so, the mem_size would always be 2GiB larger than the +# desired memory size memory_size_gem5 = "4GiB" memory_size_sst = "16GiB" addr_range_end = UnitAlgebra(memory_size_sst).getRoundedValue() @@ -69,9 +70,22 @@ gem5_command = f" ../../configs/example/sst/arm_fs.py \ --cpu-clock-rate {cpu_clock_rate} \ --memory-size {memory_size_gem5}" +# We keep a track of all the memory ports that we have. +sst_ports = { + "system_port" : "system.system_outgoing_bridge", + "cache_port" : "system.memory_outgoing_bridge" +} + +# We need a list of ports. +port_list = [] +for port in sst_ports: + port_list.append(port) + cpu_params = { "frequency": cpu_clock_rate, "cmd": gem5_command, + "ports" : " ".join(port_list), + "debug_flags" : "" } gem5_node = sst.Component("gem5_node", "gem5.gem5Component") @@ -79,16 +93,16 @@ gem5_node.addParams(cpu_params) cache_bus = sst.Component("cache_bus", "memHierarchy.Bus") cache_bus.addParams( { "bus_frequency" : cpu_clock_rate } ) - -system_port = gem5_node.setSubComponent("system_port", "gem5.gem5Bridge", 0) # for initialization +# for initialization +system_port = gem5_node.setSubComponent("system_port", "gem5.gem5Bridge", 0) system_port.addParams({ - "response_receiver_name": "system.system_outgoing_bridge", + "response_receiver_name": sst_ports["system_port"], "mem_size": memory_size_sst }) - -cache_port = gem5_node.setSubComponent("cache_port", "gem5.gem5Bridge", 0) # SST -> gem5 +# SST -> gem5 +cache_port = gem5_node.setSubComponent("cache_port", "gem5.gem5Bridge", 0) cache_port.addParams({ - "response_receiver_name": "system.memory_outgoing_bridge", + "response_receiver_name": sst_ports["cache_port"], "mem_size": memory_size_sst }) @@ -98,11 +112,12 @@ l1_cache.addParams(l1_params) # Memory memctrl = sst.Component("memory", "memHierarchy.MemController") +# `addr_range_end` should be changed accordingly to memory_size_sst memctrl.addParams({ "debug" : "0", "clock" : "1GHz", "request_width" : "64", - "addr_range_end" : addr_range_end, # should be changed accordingly to memory_size_sst + "addr_range_end" : addr_range_end, }) memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams({ diff --git a/ext/sst/sst/example.py b/ext/sst/sst/example.py index 76cf8ad24e..1c35bc3f83 100644 --- a/ext/sst/sst/example.py +++ b/ext/sst/sst/example.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2021-2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,9 +34,10 @@ cache_link_latency = "1ps" bbl = "riscv-boot-exit-nodisk" cpu_clock_rate = "3GHz" -# gem5 will send requests to physical addresses of range [0x80000000, inf) to memory -# currently, we do not subtract 0x80000000 from the request's address to get the "real" address -# so, the mem_size would always be 2GiB larger than the desired memory size +# gem5 will send requests to physical addresses of range [0x80000000, inf) to +# memory currently, we do not subtract 0x80000000 from the request's address to +# get the "real" address so, the mem_size would always be 2GiB larger than the +# desired memory size memory_size_gem5 = "4GiB" memory_size_sst = "6GiB" addr_range_end = UnitAlgebra(memory_size_sst).getRoundedValue() @@ -52,10 +53,24 @@ l1_params = { "L1" : "1", } +# We keep a track of all the memory ports that we have. +sst_ports = { + "system_port" : "system.system_outgoing_bridge", + "cache_port" : "system.memory_outgoing_bridge" +} + +# We need a list of ports. +port_list = [] +for port in sst_ports: + port_list.append(port) + cpu_params = { "frequency": cpu_clock_rate, - "cmd": " ../../configs/example/sst/riscv_fs.py --cpu-clock-rate {} --memory-size {}".format(cpu_clock_rate, memory_size_gem5), - "debug_flags": "" + "cmd": " ../../configs/example/sst/riscv_fs.py" + + f" --cpu-clock-rate {cpu_clock_rate}" + + f" --memory-size {memory_size_gem5}", + "debug_flags": "", + "ports" : " ".join(port_list) } gem5_node = sst.Component("gem5_node", "gem5.gem5Component") @@ -64,11 +79,14 @@ gem5_node.addParams(cpu_params) cache_bus = sst.Component("cache_bus", "memHierarchy.Bus") cache_bus.addParams( { "bus_frequency" : cpu_clock_rate } ) -system_port = gem5_node.setSubComponent("system_port", "gem5.gem5Bridge", 0) # for initialization -system_port.addParams({ "response_receiver_name": "system.system_outgoing_bridge"}) # tell the SubComponent the name of the corresponding SimObject +# for initialization +system_port = gem5_node.setSubComponent(port_list[0], "gem5.gem5Bridge", 0) +# tell the SubComponent the name of the corresponding SimObject +system_port.addParams({ "response_receiver_name": sst_ports["system_port"]}) -cache_port = gem5_node.setSubComponent("cache_port", "gem5.gem5Bridge", 0) # SST -> gem5 -cache_port.addParams({ "response_receiver_name": "system.memory_outgoing_bridge"}) +# SST -> gem5 +cache_port = gem5_node.setSubComponent(port_list[1], "gem5.gem5Bridge", 0) +cache_port.addParams({ "response_receiver_name": sst_ports["cache_port"]}) # L1 cache l1_cache = sst.Component("l1_cache", "memHierarchy.Cache") @@ -76,11 +94,12 @@ l1_cache.addParams(l1_params) # Memory memctrl = sst.Component("memory", "memHierarchy.MemController") +# `addr_range_end` should be changed accordingly to memory_size_sst memctrl.addParams({ "debug" : "0", "clock" : "1GHz", "request_width" : "64", - "addr_range_end" : addr_range_end, # should be changed accordingly to memory_size_sst + "addr_range_end" : addr_range_end, }) memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams({ diff --git a/ext/sst/sst_responder.hh b/ext/sst/sst_responder.hh index a89d311064..5f483be845 100644 --- a/ext/sst/sst_responder.hh +++ b/ext/sst/sst_responder.hh @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Regents of the University of California +// Copyright (c) 2021-2023 The Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -35,9 +35,8 @@ #include #include -#include #include -#include +#include #include #include diff --git a/ext/sst/sst_responder_subcomponent.cc b/ext/sst/sst_responder_subcomponent.cc index 366f99aecf..8cd2c04628 100644 --- a/ext/sst/sst_responder_subcomponent.cc +++ b/ext/sst/sst_responder_subcomponent.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Regents of the University of California +// Copyright (c) 2021-2023 The Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -64,13 +64,12 @@ SSTResponderSubComponent::setTimeConverter(SST::TimeConverter* tc) // SHARE_PORTS means the interface can use our port as if it were its own // INSERT_STATS means the interface will inherit our statistic // configuration (e.g., if ours are enabled, the interface’s will be too) - memoryInterface = \ - loadAnonymousSubComponent( - "memHierarchy.memInterface", "memory", 0, - SST::ComponentInfo::SHARE_PORTS | SST::ComponentInfo::INSERT_STATS, - interface_params, timeConverter, - new SST::Interfaces::SimpleMem::Handler( - this, &SSTResponderSubComponent::portEventHandler) + memoryInterface = loadAnonymousSubComponent( + "memHierarchy.standardInterface", "memory", 0, + SST::ComponentInfo::SHARE_PORTS | SST::ComponentInfo::INSERT_STATS, + interface_params, timeConverter, + new SST::Interfaces::StandardMem::Handler( + this, &SSTResponderSubComponent::portEventHandler) ); assert(memoryInterface != NULL); } @@ -91,9 +90,9 @@ SSTResponderSubComponent::setResponseReceiver( bool SSTResponderSubComponent::handleTimingReq( - SST::Interfaces::SimpleMem::Request* request) + SST::Interfaces::StandardMem::Request* request) { - memoryInterface->sendRequest(request); + memoryInterface->send(request); return true; } @@ -104,12 +103,10 @@ SSTResponderSubComponent::init(unsigned phase) for (auto p: responseReceiver->getInitData()) { gem5::Addr addr = p.first; std::vector data = p.second; - SST::Interfaces::SimpleMem::Request* request = \ - new SST::Interfaces::SimpleMem::Request( - SST::Interfaces::SimpleMem::Request::Command::Write, addr, - data.size(), data - ); - memoryInterface->sendInitData(request); + SST::Interfaces::StandardMem::Request* request = \ + new SST::Interfaces::StandardMem::Write( + addr, data.size(), data); + memoryInterface->sendUntimedData(request); } } memoryInterface->init(phase); @@ -132,20 +129,24 @@ SSTResponderSubComponent::findCorrespondingSimObject(gem5::Root* gem5_root) void SSTResponderSubComponent::handleSwapReqResponse( - SST::Interfaces::SimpleMem::Request* request) + SST::Interfaces::StandardMem::Request* request) { // get the data, then, // 1. send a response to gem5 with the original data // 2. send a write to memory with atomic op applied - SST::Interfaces::SimpleMem::Request::id_t request_id = request->id; + SST::Interfaces::StandardMem::Request::id_t request_id = request->getID(); TPacketMap::iterator it = sstRequestIdToPacketMap.find(request_id); assert(it != sstRequestIdToPacketMap.end()); - std::vector data = request->data; + std::vector data = \ + dynamic_cast(request)->data; // step 1 gem5::PacketPtr pkt = it->second; - pkt->setData(request->data.data()); + pkt->setData( + dynamic_cast( + request)->data.data() + ); pkt->makeAtomicResponse(); pkt->headerDelay = pkt->payloadDelay = 0; if (blocked() || !responseReceiver->sendTimingResp(pkt)) @@ -153,27 +154,29 @@ SSTResponderSubComponent::handleSwapReqResponse( // step 2 (*(pkt->getAtomicOp()))(data.data()); // apply the atomic op - SST::Interfaces::SimpleMem::Request::Command cmd = \ - SST::Interfaces::SimpleMem::Request::Command::Write; - SST::Interfaces::SimpleMem::Addr addr = request->addr; + // This is a Write. Need to use the Write visitor class. But the original + // request is a read response. Therefore, we need to find the address and + // the data size and then call Write. + SST::Interfaces::StandardMem::Addr addr = \ + dynamic_cast(request)->pAddr; auto data_size = data.size(); - SST::Interfaces::SimpleMem::Request* write_request = \ - new SST::Interfaces::SimpleMem::Request( - cmd, addr, data_size, data - ); - write_request->setMemFlags( - SST::Interfaces::SimpleMem::Request::Flags::F_LOCKED); - memoryInterface->sendRequest(write_request); + // Create the Write request here. + SST::Interfaces::StandardMem::Request* write_request = \ + new SST::Interfaces::StandardMem::Write(addr, data_size, data); + // F_LOCKED flag in SimpleMem was changed to ReadLock and WriteUnlock + // visitor classes. This has to be addressed in the future. The boot test + // works without using ReadLock and WriteUnlock classes. + memoryInterface->send(write_request); delete request; } void SSTResponderSubComponent::portEventHandler( - SST::Interfaces::SimpleMem::Request* request) + SST::Interfaces::StandardMem::Request* request) { // Expect to handle an SST response - SST::Interfaces::SimpleMem::Request::id_t request_id = request->id; + SST::Interfaces::StandardMem::Request::id_t request_id = request->getID(); TPacketMap::iterator it = sstRequestIdToPacketMap.find(request_id); @@ -193,19 +196,27 @@ SSTResponderSubComponent::portEventHandler( Translator::inplaceSSTRequestToGem5PacketPtr(pkt, request); - if (blocked() || !(responseReceiver->sendTimingResp(pkt))) + if (blocked() || !(responseReceiver->sendTimingResp(pkt))) { responseQueue.push(pkt); - } else { // we can handle unexpected invalidates, but nothing else. - SST::Interfaces::SimpleMem::Request::Command cmd = request->cmd; - if (cmd == SST::Interfaces::SimpleMem::Request::Command::WriteResp) + } + } else { + // we can handle unexpected invalidates, but nothing else. + if (SST::Interfaces::StandardMem::Read* test = + dynamic_cast(request)) { return; - assert(cmd == SST::Interfaces::SimpleMem::Request::Command::Inv); - - // make Req/Pkt for Snoop/no response needed + } + else if (SST::Interfaces::StandardMem::WriteResp* test = + dynamic_cast( + request)) { + return; + } + // for Snoop/no response needed // presently no consideration for masterId, packet type, flags... gem5::RequestPtr req = std::make_shared( - request->addr, request->size, 0, 0 - ); + dynamic_cast( + request)->pAddr, + dynamic_cast( + request)->size, 0, 0); gem5::PacketPtr pkt = new gem5::Packet( req, gem5::MemCmd::InvalidateReq); diff --git a/ext/sst/sst_responder_subcomponent.hh b/ext/sst/sst_responder_subcomponent.hh index 51bc4f9318..ed9f09d6b8 100644 --- a/ext/sst/sst_responder_subcomponent.hh +++ b/ext/sst/sst_responder_subcomponent.hh @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Regents of the University of California +// Copyright (c) 2021-2023 The Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -36,10 +36,8 @@ #include #include - -#include #include -#include +#include #include #include @@ -59,12 +57,12 @@ class SSTResponderSubComponent: public SST::SubComponent gem5::OutgoingRequestBridge* responseReceiver; gem5::SSTResponderInterface* sstResponder; - SST::Interfaces::SimpleMem* memoryInterface; + SST::Interfaces::StandardMem* memoryInterface; SST::TimeConverter* timeConverter; SST::Output* output; std::queue responseQueue; - std::vector initRequests; + std::vector initRequests; std::string gem5SimObjectName; std::string memSize; @@ -78,7 +76,7 @@ class SSTResponderSubComponent: public SST::SubComponent void setOutputStream(SST::Output* output_); void setResponseReceiver(gem5::OutgoingRequestBridge* gem5_bridge); - void portEventHandler(SST::Interfaces::SimpleMem::Request* request); + void portEventHandler(SST::Interfaces::StandardMem::Request* request); bool blocked(); void setup(); @@ -86,18 +84,18 @@ class SSTResponderSubComponent: public SST::SubComponent // return true if the SimObject could be found bool findCorrespondingSimObject(gem5::Root* gem5_root); - bool handleTimingReq(SST::Interfaces::SimpleMem::Request* request); + bool handleTimingReq(SST::Interfaces::StandardMem::Request* request); void handleRecvRespRetry(); void handleRecvFunctional(gem5::PacketPtr pkt); - void handleSwapReqResponse(SST::Interfaces::SimpleMem::Request* request); + void handleSwapReqResponse(SST::Interfaces::StandardMem::Request* request); TPacketMap sstRequestIdToPacketMap; public: // register the component to SST SST_ELI_REGISTER_SUBCOMPONENT_API(SSTResponderSubComponent); - SST_ELI_REGISTER_SUBCOMPONENT_DERIVED( + SST_ELI_REGISTER_SUBCOMPONENT( SSTResponderSubComponent, - "gem5", // SST will look for libgem5.so + "gem5", // SST will look for libgem5.so or libgem5.dylib "gem5Bridge", SST_ELI_ELEMENT_VERSION(1, 0, 0), "Initialize gem5 and link SST's ports to gem5's ports", @@ -106,7 +104,7 @@ class SSTResponderSubComponent: public SST::SubComponent SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( {"memory", "Interface to the memory subsystem", \ - "SST::Interfaces::SimpleMem"} + "SST::Interfaces::StandardMem"} ) SST_ELI_DOCUMENT_PORTS( diff --git a/ext/sst/translator.hh b/ext/sst/translator.hh index 2d8c8b782a..bf6a168d9a 100644 --- a/ext/sst/translator.hh +++ b/ext/sst/translator.hh @@ -1,4 +1,4 @@ -// Copyright (c) 2021 The Regents of the University of California +// Copyright (c) 2021-2023 The Regents of the University of California // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -27,87 +27,143 @@ #ifndef __TRANSLATOR_H__ #define __TRANSLATOR_H__ -#include +#include #include -#include #include #include #include -typedef std::unordered_map TPacketMap; namespace Translator { -inline SST::Interfaces::SimpleMem::Request* +inline SST::Interfaces::StandardMem::Request* gem5RequestToSSTRequest(gem5::PacketPtr pkt, TPacketMap& sst_request_id_to_packet_map) { - SST::Interfaces::SimpleMem::Request::Command cmd; + // Listing all the different SST Memory commands. + enum sst_standard_mem_commands + { + Read, + ReadResp, + Write, + WriteResp, + FlushAddr, + FlushResp, + ReadLock, + WriteUnlock, + LoadLink, + StoreConditional, + MoveData, + CustomReq, + CustomResp, + InvNotify + + }; + // SST's standard memory class has visitor classes for all the different + // types of memory commands. Request class now does not have a command + // variable. Instead for different types of request, we now need to + // dynamically cast the class object. I'm using an extra variable to map + // the type of command for SST. + int sst_command_type = -1; + // StandardMem only has one cache flush class with an option to flush or + // flush and invalidate an address. By default, this is set to true so that + // it corresponds to ge,::MemCmd::InvalidateReq + bool flush_addr_flag = true; switch ((gem5::MemCmd::Command)pkt->cmd.toInt()) { case gem5::MemCmd::HardPFReq: case gem5::MemCmd::SoftPFReq: case gem5::MemCmd::SoftPFExReq: case gem5::MemCmd::LoadLockedReq: case gem5::MemCmd::ReadExReq: + case gem5::MemCmd::ReadCleanReq: + case gem5::MemCmd::ReadSharedReq: case gem5::MemCmd::ReadReq: case gem5::MemCmd::SwapReq: - cmd = SST::Interfaces::SimpleMem::Request::Command::Read; + sst_command_type = Read; break; case gem5::MemCmd::StoreCondReq: + case gem5::MemCmd::WritebackDirty: + case gem5::MemCmd::WritebackClean: case gem5::MemCmd::WriteReq: - cmd = SST::Interfaces::SimpleMem::Request::Command::Write; + sst_command_type = Write; break; case gem5::MemCmd::CleanInvalidReq: case gem5::MemCmd::InvalidateReq: - cmd = SST::Interfaces::SimpleMem::Request::Command::FlushLineInv; + sst_command_type = FlushAddr; break; case gem5::MemCmd::CleanSharedReq: - cmd = SST::Interfaces::SimpleMem::Request::Command::FlushLine; + sst_command_type = FlushAddr; + flush_addr_flag = false; break; default: panic("Unable to convert gem5 packet: %s\n", pkt->cmd.toString()); } - SST::Interfaces::SimpleMem::Addr addr = pkt->getAddr(); - - uint8_t* data_ptr = pkt->getPtr(); + SST::Interfaces::StandardMem::Addr addr = pkt->getAddr(); auto data_size = pkt->getSize(); - std::vector data = std::vector( - data_ptr, data_ptr + data_size - ); + std::vector data; + // Need to make sure that the command type is a Write to retrive the data + // data_ptr. + if (sst_command_type == Write) { + uint8_t* data_ptr = pkt->getPtr(); + data = std::vector(data_ptr, data_ptr + data_size); - SST::Interfaces::SimpleMem::Request* request = \ - new SST::Interfaces::SimpleMem::Request( - cmd, addr, data_size, data - ); + } + // Now convert a sst StandardMem request. + SST::Interfaces::StandardMem::Request* request = nullptr; + // find the corresponding memory command type. + switch(sst_command_type) { + case Read: + request = new SST::Interfaces::StandardMem::Read(addr, data_size); + break; + case Write: + request = + new SST::Interfaces::StandardMem::Write(addr, data_size, data); + break; + case FlushAddr: { + // StandardMem::FlushAddr has a invoking variable called `depth` + // which defines the number of cache levels to invalidate. Ideally + // this has to be input from the SST config, however in + // implementation I'm hardcoding this value to 2. + int cache_depth = 2; + request = + new SST::Interfaces::StandardMem::FlushAddr( + addr, data_size, flush_addr_flag, cache_depth); + break; + } + default: + panic("Unable to translate command %d to Request class!", + sst_command_type); + } if ((gem5::MemCmd::Command)pkt->cmd.toInt() == gem5::MemCmd::LoadLockedReq || (gem5::MemCmd::Command)pkt->cmd.toInt() == gem5::MemCmd::SwapReq || pkt->req->isLockedRMW()) { - request->setMemFlags( - SST::Interfaces::SimpleMem::Request::Flags::F_LOCKED); - } else if ((gem5::MemCmd::Command)pkt->cmd.toInt() == \ + // F_LOCKED is deprecated. Therefore I'm skipping this flag for the + // StandardMem request. + } else if ((gem5::MemCmd::Command)pkt->cmd.toInt() == gem5::MemCmd::StoreCondReq) { - request->setMemFlags( - SST::Interfaces::SimpleMem::Request::Flags::F_LLSC); + // F_LLSC is deprecated. Therefore I'm skipping this flag for the + // StandardMem request. } if (pkt->req->isUncacheable()) { - request->setFlags( - SST::Interfaces::SimpleMem::Request::Flags::F_NONCACHEABLE); + request->setFlag( + SST::Interfaces::StandardMem::Request::Flag::F_NONCACHEABLE); } if (pkt->needsResponse()) - sst_request_id_to_packet_map[request->id] = pkt; + sst_request_id_to_packet_map[request->getID()] = pkt; return request; } inline void inplaceSSTRequestToGem5PacketPtr(gem5::PacketPtr pkt, - SST::Interfaces::SimpleMem::Request* request) + SST::Interfaces::StandardMem::Request* request) { pkt->makeResponse(); @@ -116,8 +172,18 @@ inplaceSSTRequestToGem5PacketPtr(gem5::PacketPtr pkt, // SC interprets ExtraData == 1 as the store was successful pkt->req->setExtraData(1); } - - pkt->setData(request->data.data()); + // If there is data in the request, send it back. Only ReadResp requests + // have data associated with it. Other packets does not need to be casted. + if (!pkt->isWrite()) { + // Need to verify whether the packet is a ReadResp, otherwise the + // program will try to incorrectly cast the request object. + if (SST::Interfaces::StandardMem::ReadResp* test = + dynamic_cast(request)) { + pkt->setData(dynamic_cast( + request)->data.data() + ); + } + } // Clear out bus delay notifications pkt->headerDelay = pkt->payloadDelay = 0; From bbc301f2f027f10976c23ae4f64b81f48aade826 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 10 Oct 2023 15:54:20 -0700 Subject: [PATCH 430/693] stdlib, tests: Fixed bugs and tests - Fixed bugs rekated to retrying on request faliure. - Updated the pyunit tests. Change-Id: Ia484690267bf27018488324f3408f7e47c59bef3 --- .../gem5/resources/client_api/atlasclient.py | 11 ++-- .../resources/pyunit_client_wrapper_checks.py | 64 ++++++------------- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py index a39f478458..511ef71fed 100644 --- a/src/python/gem5/resources/client_api/atlasclient.py +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -30,7 +30,7 @@ import json import time import itertools from .abstract_client import AbstractClient - +from urllib.error import HTTPError from m5.util import warn @@ -77,7 +77,7 @@ class AtlasClient(AbstractClient): def get_token(self): return self._atlas_http_json_req( - self.url, + self.authUrl, data_json={"key": self.apiKey}, headers={"Content-Type": "application/json"}, purpose_of_request="Get Access Token with API key", @@ -122,7 +122,7 @@ class AtlasClient(AbstractClient): try: response = request.urlopen(req) break - except Exception as e: + except HTTPError as e: if attempt >= max_failed_attempts: raise AtlasClientHttpJsonRequestError( client=self, @@ -167,7 +167,10 @@ class AtlasClient(AbstractClient): } resources = self._atlas_http_json_req( - url, data=data, headers=headers, purpose_of_request="Get Resources" + url, + data_json=data, + headers=headers, + purpose_of_request="Get Resources", )["documents"] # I do this as a lazy post-processing step because I can't figure out diff --git a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py index f190b1ed5f..66b934a16f 100644 --- a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py @@ -34,6 +34,10 @@ import io import contextlib from pathlib import Path +from gem5.resources.client_api.atlasclient import ( + AtlasClientHttpJsonRequestError, +) + mock_json_path = Path(__file__).parent / "refs/resources.json" mock_config_json = { "sources": { @@ -419,21 +423,11 @@ class ClientWrapperTestSuite(unittest.TestCase): @patch("urllib.request.urlopen", side_effect=mocked_requests_post) def test_invalid_auth_url(self, mock_get): resource_id = "test-resource" - f = io.StringIO() - with self.assertRaises(Exception) as context: - with contextlib.redirect_stderr(f): - get_resource_json_obj( - resource_id, - gem5_version="develop", - ) - self.assertTrue( - "Error getting resources from client gem5-resources:" - " Panic: Not found" in str(f.getvalue()) - ) - self.assertTrue( - "Resource with ID 'test-resource' not found." - in str(context.exception) - ) + with self.assertRaises(AtlasClientHttpJsonRequestError) as context: + get_resource_json_obj( + resource_id, + gem5_version="develop", + ) @patch( "gem5.resources.client.clientwrapper", @@ -442,21 +436,11 @@ class ClientWrapperTestSuite(unittest.TestCase): @patch("urllib.request.urlopen", side_effect=mocked_requests_post) def test_invalid_url(self, mock_get): resource_id = "test-resource" - f = io.StringIO() - with self.assertRaises(Exception) as context: - with contextlib.redirect_stderr(f): - get_resource_json_obj( - resource_id, - gem5_version="develop", - ) - self.assertTrue( - "Error getting resources from client gem5-resources:" - " Panic: Not found" in str(f.getvalue()) - ) - self.assertTrue( - "Resource with ID 'test-resource' not found." - in str(context.exception) - ) + with self.assertRaises(AtlasClientHttpJsonRequestError) as context: + get_resource_json_obj( + resource_id, + gem5_version="develop", + ) @patch( "gem5.resources.client.clientwrapper", @@ -465,18 +449,8 @@ class ClientWrapperTestSuite(unittest.TestCase): @patch("urllib.request.urlopen", side_effect=mocked_requests_post) def test_invalid_url(self, mock_get): resource_id = "test-too-many" - f = io.StringIO() - with self.assertRaises(Exception) as context: - with contextlib.redirect_stderr(f): - get_resource_json_obj( - resource_id, - gem5_version="develop", - ) - self.assertTrue( - "Error getting resources from client gem5-resources:" - " Panic: Too many requests" in str(f.getvalue()) - ) - self.assertTrue( - "Resource with ID 'test-too-many' not found." - in str(context.exception) - ) + with self.assertRaises(AtlasClientHttpJsonRequestError) as context: + get_resource_json_obj( + resource_id, + gem5_version="develop", + ) From 132ec10818bac8cebc46b1ffd527d243fdf43a31 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 19:26:01 -0700 Subject: [PATCH 431/693] python,misc: Add `check-ast` hook to pre-commit This verifies all Python files have a AST indicating they valid Python. No file in the repo fails this test, so it triggered no changes. Change-Id: Ifd7998268df6be766d92c19cfc7f1cfdf8ed103e --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 040c81089f..c7faabcc60 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,6 +62,7 @@ repos: - id: check-added-large-files - id: mixed-line-ending args: [--fix=lf] + - id: check-ast - id: check-case-conflict - id: requirements-txt-fixer - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt From 5b5c5d09ddba06248a35b2df7fa5b815aafb9b92 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 19:34:07 -0700 Subject: [PATCH 432/693] python,misc: Add `check-merge-conflict` hook to pre-commit This hook will check to see if files have merge conflict strings and blocks commit if so. Change-Id: I8687e0a8367d3c43133890001023e0352954d90d --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c7faabcc60..4435b881dc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -64,6 +64,7 @@ repos: args: [--fix=lf] - id: check-ast - id: check-case-conflict + - id: check-merge-conflict - id: requirements-txt-fixer - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt rev: 0.2.3 From 768e488a6bb237394ccbf2903ea01ac063acf139 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 19:37:04 -0700 Subject: [PATCH 433/693] python,misc: Add `check-symlinks` hook to pre-commit This hook checks that symlinks in the repo still point to valid location. Change-Id: I350760800406d9c003e81236af8248c6fc0a7359 --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4435b881dc..ab2b8be79f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -65,6 +65,7 @@ repos: - id: check-ast - id: check-case-conflict - id: check-merge-conflict + - id: check-symlinks - id: requirements-txt-fixer - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt rev: 0.2.3 From 592fbae2f58d8cc75262711f04b7593cecc967fe Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Oct 2023 19:40:36 -0700 Subject: [PATCH 434/693] python,misc: Add `destroyed-symlinks` hook to pre-commit This hook detects which symlinks are changed to regular files with the content of a path which that symlink was pointing to. Change-Id: Ic925f02debc65c7c04e6d4cc3a25415b30858977 --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ab2b8be79f..d03de87ee1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -66,6 +66,7 @@ repos: - id: check-case-conflict - id: check-merge-conflict - id: check-symlinks + - id: destroyed-symlinks - id: requirements-txt-fixer - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt rev: 0.2.3 From 83af4525ce17a266ddf6d46bec2c2eea7cd51566 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 13:30:27 -0700 Subject: [PATCH 435/693] misc,python: Add `pyupgrade` hook to pre-commit This hook automatically upgrades the syntax to recommended standards for new versions of the language. These are numerous and are outlined here: https://github.com/asottile/pyupgrade Change-Id: I73fc58a08160ed9a21cfa3b3e023c259a84592ba --- .pre-commit-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 57f0d672a2..e472e48b19 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -72,6 +72,13 @@ repos: rev: 23.9.1 hooks: - id: black + - repo: https://github.com/asottile/pyupgrade + rev: v3.14.0 + hooks: + - id: pyupgrade + # Python 3.8 is the earliest version supported. + # We therefore conform to the standards compatible with 3.8+. + args: [--py38-plus] - repo: local hooks: - id: gem5-style-checker From 298119e4028a04d0f5fcae066c12026585212526 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 9 Oct 2023 13:40:03 -0700 Subject: [PATCH 436/693] misc,python: Run `pre-commit run --all-files` Applies the `pyupgrade` hook to all files in the repo. Change-Id: I9879c634a65c5fcaa9567c63bc5977ff97d5d3bf --- build_tools/code_formatter.py | 14 +- build_tools/enum_hh.py | 2 +- build_tools/grammar.py | 8 +- build_tools/infopy.py | 2 +- build_tools/marshal.py | 2 +- build_tools/sim_object_param_struct_hh.py | 2 +- configs/common/ObjectList.py | 8 +- configs/common/SimpleOpts.py | 1 - configs/common/Simulation.py | 10 +- configs/common/SysPaths.py | 6 +- configs/common/cpu2000.py | 4 +- configs/deprecated/example/se.py | 2 +- configs/dram/lat_mem_rd.py | 2 +- configs/example/apu_se.py | 2 +- configs/example/arm/baremetal.py | 7 +- configs/example/arm/devices.py | 4 +- configs/example/arm/fs_power.py | 8 +- configs/example/arm/workloads.py | 4 +- .../gem5_library/x86-parsec-benchmarks.py | 4 +- configs/example/gpufs/DisjointNetwork.py | 4 +- configs/example/gpufs/Disjoint_VIPER.py | 2 +- configs/example/gpufs/system/amdgpu.py | 2 +- configs/example/read_config.py | 14 +- configs/example/sst/arm_fs.py | 2 +- configs/learning_gem5/part1/caches.py | 9 +- configs/learning_gem5/part1/two_level.py | 1 - configs/learning_gem5/part2/hello_goodbye.py | 1 - configs/learning_gem5/part2/run_simple.py | 1 - configs/learning_gem5/part2/simple_cache.py | 1 - configs/learning_gem5/part2/simple_memobj.py | 1 - configs/learning_gem5/part3/msi_caches.py | 9 +- .../part3/ruby_caches_MI_example.py | 9 +- configs/learning_gem5/part3/ruby_test.py | 1 - configs/learning_gem5/part3/simple_ruby.py | 1 - configs/learning_gem5/part3/test_caches.py | 3 +- configs/ruby/CHI_config.py | 32 +-- configs/topologies/BaseTopology.py | 2 +- ext/testlib/configuration.py | 20 +- ext/testlib/fixture.py | 8 +- ext/testlib/handlers.py | 16 +- ext/testlib/helper.py | 24 +-- ext/testlib/loader.py | 4 +- ext/testlib/log.py | 8 +- ext/testlib/main.py | 6 +- ext/testlib/query.py | 2 +- ext/testlib/result.py | 12 +- ext/testlib/runner.py | 10 +- ext/testlib/suite.py | 4 +- ext/testlib/terminal.py | 4 +- ext/testlib/test_util.py | 4 +- ext/testlib/uid.py | 2 +- ext/testlib/wrappers.py | 2 +- site_scons/gem5_scons/__init__.py | 2 +- site_scons/gem5_scons/builders/config_file.py | 2 +- site_scons/gem5_scons/configure.py | 20 +- site_scons/gem5_scons/defaults.py | 50 +++-- site_scons/gem5_scons/sources.py | 6 +- site_scons/gem5_scons/util.py | 2 +- site_scons/site_init.py | 1 - src/arch/arm/ArmPMU.py | 4 +- src/arch/isa_parser/isa_parser.py | 38 ++-- src/arch/isa_parser/operand_list.py | 2 +- src/arch/isa_parser/operand_types.py | 4 +- src/arch/isa_parser/util.py | 2 +- src/arch/micro_asm.py | 8 +- src/arch/micro_asm_test.py | 8 +- src/cpu/BaseCPU.py | 3 +- src/learning_gem5/part2/HelloObject.py | 1 - src/learning_gem5/part2/SimpleCache.py | 1 - src/learning_gem5/part2/SimpleMemobj.py | 1 - src/learning_gem5/part2/SimpleObject.py | 1 - src/mem/DRAMSys.py | 2 +- src/mem/cache/prefetch/Prefetcher.py | 2 +- .../slicc/ast/DeferEnqueueingStatementAST.py | 2 +- src/mem/slicc/ast/EnqueueStatementAST.py | 2 +- src/mem/slicc/ast/EnumDeclAST.py | 2 +- src/mem/slicc/ast/MachineAST.py | 16 +- src/mem/slicc/ast/MethodCallExprAST.py | 2 +- src/mem/slicc/ast/OperatorExprAST.py | 4 +- src/mem/slicc/ast/PeekStatementAST.py | 12 +- src/mem/slicc/ast/StateDeclAST.py | 2 +- src/mem/slicc/ast/TypeDeclAST.py | 2 +- src/mem/slicc/parser.py | 4 +- src/mem/slicc/symbols/StateMachine.py | 20 +- src/mem/slicc/symbols/SymbolTable.py | 2 +- src/mem/slicc/symbols/Transition.py | 2 +- src/mem/slicc/util.py | 4 +- .../boards/experimental/lupv_board.py | 2 +- .../chi/nodes/abstract_node.py | 2 +- .../processors/abstract_processor.py | 2 +- .../gem5/components/processors/cpu_types.py | 2 +- .../processors/switchable_processor.py | 5 +- src/python/gem5/isas.py | 2 +- src/python/gem5/resources/client.py | 2 +- src/python/gem5/resources/resource.py | 3 +- .../gem5/simulate/exit_event_generators.py | 3 +- src/python/gem5/utils/filelock.py | 2 +- src/python/importer.py | 4 +- src/python/m5/SimObject.py | 14 +- src/python/m5/citations.py | 2 +- src/python/m5/main.py | 4 +- src/python/m5/options.py | 4 +- src/python/m5/params.py | 25 ++- src/python/m5/proxy.py | 4 +- src/python/m5/util/dot_writer.py | 14 +- src/python/m5/util/fdthelper.py | 6 +- src/python/m5/util/multidict.py | 5 +- src/python/m5/util/pybind.py | 2 +- src/python/m5/util/terminal.py | 2 +- src/sim/power/ThermalModel.py | 2 +- src/systemc/python/systemc.py | 2 +- tests/gem5/cpu_tests/run.py | 1 - tests/gem5/fixture.py | 26 ++- .../gem5/fs/linux/arm/configs/arm_generic.py | 4 +- .../gem5/fs/linux/arm/configs/base_config.py | 16 +- .../gem5_resources/configs/download_check.py | 2 +- tests/gem5/m5threads_test_atomic/caches.py | 8 +- tests/gem5/verifier.py | 30 +-- tests/pyunit/pyunit_jsonserializable_check.py | 20 +- tests/pyunit/stdlib/pyunit_looppoint.py | 186 +++++++++--------- .../resources/pyunit_client_wrapper_checks.py | 4 +- .../resources/pyunit_json_client_checks.py | 12 +- .../resources/pyunit_md5_utils_check.py | 8 +- .../pyunit_obtain_resources_check.py | 26 ++- .../pyunit_resource_specialization.py | 54 +++-- .../stdlib/resources/pyunit_suite_checks.py | 2 +- .../resources/pyunit_workload_checks.py | 18 +- tests/run.py | 2 +- util/checkpoint-tester.py | 2 +- util/cpt_upgrader.py | 8 +- util/cpt_upgraders/arm-ccregs.py | 2 +- util/cpt_upgraders/arm-contextidr-el2.py | 2 +- util/cpt_upgraders/arm-gem5-gic-ext.py | 2 +- util/cpt_upgraders/arm-gicv2-banked-regs.py | 2 +- util/cpt_upgraders/arm-hdlcd-upgrade.py | 2 +- util/cpt_upgraders/arm-miscreg-teehbr.py | 2 +- util/cpt_upgraders/arm-sve.py | 2 +- util/cpt_upgraders/arm-sysreg-mapping-ns.py | 2 +- util/cpt_upgraders/armv8.py | 12 +- util/cpt_upgraders/isa-is-simobject.py | 2 +- util/cpt_upgraders/memory-per-range.py | 4 +- .../remove-arm-cpsr-mode-miscreg.py | 2 +- util/cpt_upgraders/riscv-pcstate.py | 2 +- util/cpt_upgraders/riscv-vext.py | 4 +- util/cpt_upgraders/smt-interrupts.py | 2 +- util/cpt_upgraders/x86-add-tlb.py | 4 +- util/decode_inst_dep_trace.py | 2 +- util/decode_inst_trace.py | 6 +- util/decode_packet_trace.py | 2 +- util/encode_inst_dep_trace.py | 4 +- util/encode_packet_trace.py | 6 +- util/find_copyrights.py | 4 +- .../api/create_resources_json.py | 6 +- .../test/json_client_test.py | 4 +- .../artifact/gem5art/artifact/_artifactdb.py | 16 +- util/gem5art/artifact/tests/test_artifact.py | 2 +- util/gem5art/artifact/tests/test_filedb.py | 2 +- util/gem5img.py | 4 +- util/gerrit-bot/bot.py | 8 +- util/gerrit-bot/extract_gitcookies.py | 2 +- util/gerrit-bot/util.py | 6 +- util/git-commit-msg.py | 6 +- util/logroll.py | 11 +- util/maint/lib/maintainers.py | 6 +- util/maint/list_changes.py | 26 ++- util/maint/show_changes_by_file.py | 2 +- util/minorview/blobs.py | 8 +- util/minorview/model.py | 44 ++--- util/minorview/parse.py | 18 +- util/minorview/point.py | 2 +- util/minorview/view.py | 8 +- util/o3-pipeview.py | 2 +- util/on-chip-network-power-area.py | 4 +- util/oprofile-top.py | 2 +- util/plot_dram/PlotPowerStates.py | 2 +- util/plot_dram/dram_lat_mem_rd_plot.py | 12 +- util/plot_dram/dram_sweep_plot.py | 16 +- util/plot_dram/lowp_dram_sweep_plot.py | 2 +- util/protolib.py | 8 +- util/streamline/m5stats2streamline.py | 38 ++-- util/style.py | 2 +- util/style/file_types.py | 2 +- util/style/region.py | 6 +- util/style/repo.py | 4 +- util/style/sort_includes.py | 26 +-- util/style/style.py | 6 +- util/style/verifiers.py | 40 ++-- util/update_copyright/__init__.py | 2 +- 188 files changed, 741 insertions(+), 779 deletions(-) diff --git a/build_tools/code_formatter.py b/build_tools/code_formatter.py index a2651c9dd0..cb6ce8e5a9 100644 --- a/build_tools/code_formatter.py +++ b/build_tools/code_formatter.py @@ -46,7 +46,7 @@ import os import re -class lookup(object): +class lookup: def __init__(self, formatter, frame, *args, **kwargs): self.frame = frame self.formatter = formatter @@ -106,7 +106,7 @@ class code_formatter_meta(type): """ def __init__(cls, name, bases, dct): - super(code_formatter_meta, cls).__init__(name, bases, dct) + super().__init__(name, bases, dct) if "pattern" in dct: pat = cls.pattern else: @@ -125,7 +125,7 @@ class code_formatter_meta(type): cls.pattern = re.compile(pat, re.VERBOSE | re.DOTALL | re.MULTILINE) -class code_formatter(object, metaclass=code_formatter_meta): +class code_formatter(metaclass=code_formatter_meta): delim = r"$" ident = r"[_A-z]\w*" pos = r"[0-9]+" @@ -272,7 +272,7 @@ class code_formatter(object, metaclass=code_formatter_meta): # check for a lone identifier if ident: indent = match.group("indent") # must be spaces - lone = "%s" % (l[ident],) + lone = f"{l[ident]}" def indent_lines(gen): for line in gen: @@ -284,7 +284,7 @@ class code_formatter(object, metaclass=code_formatter_meta): # check for an identifier, braced or not ident = match.group("ident") or match.group("b_ident") if ident is not None: - return "%s" % (l[ident],) + return f"{l[ident]}" # check for a positional parameter, braced or not pos = match.group("pos") or match.group("b_pos") @@ -295,13 +295,13 @@ class code_formatter(object, metaclass=code_formatter_meta): "Positional parameter #%d not found in pattern" % pos, code_formatter.pattern, ) - return "%s" % (args[int(pos)],) + return f"{args[int(pos)]}" # check for a double braced expression eval_expr = match.group("eval") if eval_expr is not None: result = eval(eval_expr, {}, l) - return "%s" % (result,) + return f"{result}" # check for an escaped delimiter if match.group("escaped") is not None: diff --git a/build_tools/enum_hh.py b/build_tools/enum_hh.py index a5b9f42cba..f91ffef437 100644 --- a/build_tools/enum_hh.py +++ b/build_tools/enum_hh.py @@ -66,7 +66,7 @@ code = code_formatter() wrapper_name = enum.wrapper_name wrapper = "struct" if enum.wrapper_is_struct else "namespace" name = enum.__name__ if enum.enum_name is None else enum.enum_name -idem_macro = "__ENUM__%s__%s__" % (wrapper_name, name) +idem_macro = f"__ENUM__{wrapper_name}__{name}__" code( """\ diff --git a/build_tools/grammar.py b/build_tools/grammar.py index 6ac638bcd0..582ff8710b 100644 --- a/build_tools/grammar.py +++ b/build_tools/grammar.py @@ -36,7 +36,7 @@ class ParseError(Exception): self.token = token -class Grammar(object): +class Grammar: def setupLexerFactory(self, **kwargs): if "module" in kwargs: raise AttributeError("module is an illegal attribute") @@ -92,7 +92,7 @@ class Grammar(object): return self.current_lexer.lineno raise AttributeError( - "'%s' object has no attribute '%s'" % (type(self), attr) + f"'{type(self)}' object has no attribute '{attr}'" ) def parse_string(self, data, source="", debug=None, tracking=0): @@ -118,7 +118,7 @@ class Grammar(object): def parse_file(self, f, **kwargs): if isinstance(f, str): source = f - f = open(f, "r") + f = open(f) elif isinstance(f, file): source = f.name else: @@ -137,7 +137,7 @@ class Grammar(object): t.value, ) else: - msg = "Syntax error at end of %s" % (self.current_source,) + msg = f"Syntax error at end of {self.current_source}" raise ParseError(msg, t) def t_error(self, t): diff --git a/build_tools/infopy.py b/build_tools/infopy.py index 8a4e013388..1662094573 100644 --- a/build_tools/infopy.py +++ b/build_tools/infopy.py @@ -56,7 +56,7 @@ for source in args.files: # `README.md = "..."` which is not valid as `md` is not a property of # `README`. src = os.path.basename(source).replace(".", "_") - with open(source, "r") as f: + with open(source) as f: data = "".join(f) code("${src} = ${{repr(data)}}") diff --git a/build_tools/marshal.py b/build_tools/marshal.py index 58c78e1632..979c0eda6f 100644 --- a/build_tools/marshal.py +++ b/build_tools/marshal.py @@ -74,7 +74,7 @@ if "LC_CTYPE" in os.environ: _, cpp, python, modpath, abspath = sys.argv -with open(python, "r") as f: +with open(python) as f: src = f.read() compiled = compile(src, python, "exec") diff --git a/build_tools/sim_object_param_struct_hh.py b/build_tools/sim_object_param_struct_hh.py index bf37da2a07..45971669f8 100644 --- a/build_tools/sim_object_param_struct_hh.py +++ b/build_tools/sim_object_param_struct_hh.py @@ -81,7 +81,7 @@ except: warned_about_nested_templates = False -class CxxClass(object): +class CxxClass: def __init__(self, sig, template_params=[]): # Split the signature into its constituent parts. This could # potentially be done with regular expressions, but diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index 5dd420e872..7b926efaf5 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -42,7 +42,7 @@ import sys from textwrap import TextWrapper -class ObjectList(object): +class ObjectList: """Creates a list of objects that are sub-classes of a given class.""" def _is_obj_class(self, cls): @@ -86,7 +86,7 @@ class ObjectList(object): print(line) if self._aliases: - print("\Aliases:") + print(r"\Aliases:") for alias, target in list(self._aliases.items()): print(f"\t{alias} => {target}") @@ -127,14 +127,14 @@ class CPUList(ObjectList): # We can't use the normal inspect.isclass because the ParamFactory # and ProxyFactory classes have a tendency to confuse it. try: - return super(CPUList, self)._is_obj_class(cls) and not issubclass( + return super()._is_obj_class(cls) and not issubclass( cls, m5.objects.CheckerCPU ) except (TypeError, AttributeError): return False def _add_objects(self): - super(CPUList, self)._add_objects() + super()._add_objects() from importlib import import_module diff --git a/configs/common/SimpleOpts.py b/configs/common/SimpleOpts.py index 96c73f57b8..da78ec977d 100644 --- a/configs/common/SimpleOpts.py +++ b/configs/common/SimpleOpts.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015 Jason Power # All rights reserved. # diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 2afb10ca2d..a2a04c3610 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -153,8 +153,8 @@ def findCptDir(options, cptdir, testsys): # Assumes that the checkpoint dir names are formatted as follows: dirs = listdir(cptdir) expr = re.compile( - "cpt\.simpoint_(\d+)_inst_(\d+)" - + "_weight_([\d\.e\-]+)_interval_(\d+)_warmup_(\d+)" + r"cpt\.simpoint_(\d+)_inst_(\d+)" + + r"_weight_([\d\.e\-]+)_interval_(\d+)_warmup_(\d+)" ) cpts = [] for dir in dirs: @@ -190,7 +190,7 @@ def findCptDir(options, cptdir, testsys): else: dirs = listdir(cptdir) - expr = re.compile("cpt\.([0-9]+)") + expr = re.compile(r"cpt\.([0-9]+)") cpts = [] for dir in dirs: match = expr.match(dir) @@ -325,7 +325,7 @@ def parseSimpointAnalysisFile(options, testsys): line = simpoint_file.readline() if not line: break - m = re.match("(\d+)\s+(\d+)", line) + m = re.match(r"(\d+)\s+(\d+)", line) if m: interval = int(m.group(1)) else: @@ -334,7 +334,7 @@ def parseSimpointAnalysisFile(options, testsys): line = weight_file.readline() if not line: fatal("not enough lines in simpoint weight file!") - m = re.match("([0-9\.e\-]+)\s+(\d+)", line) + m = re.match(r"([0-9\.e\-]+)\s+(\d+)", line) if m: weight = float(m.group(1)) else: diff --git a/configs/common/SysPaths.py b/configs/common/SysPaths.py index 60375c30c5..382740e110 100644 --- a/configs/common/SysPaths.py +++ b/configs/common/SysPaths.py @@ -30,7 +30,7 @@ config_path = os.path.dirname(os.path.abspath(__file__)) config_root = os.path.dirname(config_path) -class PathSearchFunc(object): +class PathSearchFunc: _sys_paths = None environment_variable = "M5_PATH" @@ -58,7 +58,7 @@ class PathSearchFunc(object): paths = list(filter(os.path.isdir, paths)) if not paths: - raise IOError( + raise OSError( "Can't find system files directory, " "check your {} environment variable".format( self.environment_variable @@ -72,7 +72,7 @@ class PathSearchFunc(object): try: return next(p for p in paths if os.path.exists(p)) except StopIteration: - raise IOError( + raise OSError( f"Can't find file '{filepath}' on {self.environment_variable}." ) diff --git a/configs/common/cpu2000.py b/configs/common/cpu2000.py index 06f927cbcf..b928152939 100644 --- a/configs/common/cpu2000.py +++ b/configs/common/cpu2000.py @@ -71,7 +71,7 @@ def copyfiles(srcdir, dstdir): os.symlink(".", outlink) -class Benchmark(object): +class Benchmark: def __init__(self, isa, os, input_set): if not hasattr(self.__class__, "name"): self.name = self.__class__.__name__ @@ -877,7 +877,7 @@ class vortex(Benchmark): else: raise AttributeError(f"unknown ISA {isa}") - super(vortex, self).__init__(isa, os, input_set) + super().__init__(isa, os, input_set) def test(self, isa, os): self.args = [f"{self.endian}.raw"] diff --git a/configs/deprecated/example/se.py b/configs/deprecated/example/se.py index 8d6735903f..6e0aa5b919 100644 --- a/configs/deprecated/example/se.py +++ b/configs/deprecated/example/se.py @@ -94,7 +94,7 @@ def get_processes(args): process.gid = os.getgid() if args.env: - with open(args.env, "r") as f: + with open(args.env) as f: process.env = [line.rstrip() for line in f] if len(pargs) > idx: diff --git a/configs/dram/lat_mem_rd.py b/configs/dram/lat_mem_rd.py index 93ca372e93..639a93dbf6 100644 --- a/configs/dram/lat_mem_rd.py +++ b/configs/dram/lat_mem_rd.py @@ -185,7 +185,7 @@ itt = 150 * 1000 def create_trace(filename, max_addr, burst_size, itt): try: proto_out = gzip.open(filename, "wb") - except IOError: + except OSError: print("Failed to open ", filename, " for writing") exit(-1) diff --git a/configs/example/apu_se.py b/configs/example/apu_se.py index 4e70454348..b20779fcdb 100644 --- a/configs/example/apu_se.py +++ b/configs/example/apu_se.py @@ -699,7 +699,7 @@ if os.path.isdir(executable): executable = find_file(benchmark_path, args.cmd) if args.env: - with open(args.env, "r") as f: + with open(args.env) as f: env = [line.rstrip() for line in f] else: env = [ diff --git a/configs/example/arm/baremetal.py b/configs/example/arm/baremetal.py index 08af3ef435..fae85fa04b 100644 --- a/configs/example/arm/baremetal.py +++ b/configs/example/arm/baremetal.py @@ -171,9 +171,10 @@ def create(args): system.workload = workload_class(object_file, system) if args.with_pmu: - enabled_pmu_events = set( - (*args.pmu_dump_stats_on, *args.pmu_reset_stats_on) - ) + enabled_pmu_events = { + *args.pmu_dump_stats_on, + *args.pmu_reset_stats_on, + } exit_sim_on_control = bool( enabled_pmu_events & set(pmu_control_events.keys()) ) diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py index 7ceb3cd3bf..7d92f4ee36 100644 --- a/configs/example/arm/devices.py +++ b/configs/example/arm/devices.py @@ -462,7 +462,7 @@ class SimpleSystem(BaseSimpleSystem): """ def __init__(self, caches, mem_size, platform=None, **kwargs): - super(SimpleSystem, self).__init__(mem_size, platform, **kwargs) + super().__init__(mem_size, platform, **kwargs) self.membus = MemBus() # CPUs->PIO @@ -501,7 +501,7 @@ class ArmRubySystem(BaseSimpleSystem): """ def __init__(self, mem_size, platform=None, **kwargs): - super(ArmRubySystem, self).__init__(mem_size, platform, **kwargs) + super().__init__(mem_size, platform, **kwargs) self._dma_ports = [] self._mem_ports = [] diff --git a/configs/example/arm/fs_power.py b/configs/example/arm/fs_power.py index 671cf63f2f..0442682411 100644 --- a/configs/example/arm/fs_power.py +++ b/configs/example/arm/fs_power.py @@ -47,7 +47,7 @@ import fs_bigLITTLE as bL class CpuPowerOn(MathExprPowerModel): def __init__(self, cpu_path, **kwargs): - super(CpuPowerOn, self).__init__(**kwargs) + super().__init__(**kwargs) # 2A per IPC, 3pA per cache miss # and then convert to Watt self.dyn = ( @@ -64,7 +64,7 @@ class CpuPowerOff(MathExprPowerModel): class CpuPowerModel(PowerModel): def __init__(self, cpu_path, **kwargs): - super(CpuPowerModel, self).__init__(**kwargs) + super().__init__(**kwargs) self.pm = [ CpuPowerOn(cpu_path), # ON CpuPowerOff(), # CLK_GATED @@ -75,7 +75,7 @@ class CpuPowerModel(PowerModel): class L2PowerOn(MathExprPowerModel): def __init__(self, l2_path, **kwargs): - super(L2PowerOn, self).__init__(**kwargs) + super().__init__(**kwargs) # Example to report l2 Cache overallAccesses # The estimated power is converted to Watt and will vary based # on the size of the cache @@ -90,7 +90,7 @@ class L2PowerOff(MathExprPowerModel): class L2PowerModel(PowerModel): def __init__(self, l2_path, **kwargs): - super(L2PowerModel, self).__init__(**kwargs) + super().__init__(**kwargs) # Choose a power model for every power state self.pm = [ L2PowerOn(l2_path), # ON diff --git a/configs/example/arm/workloads.py b/configs/example/arm/workloads.py index 5c70dabfc2..d7aea2ca0a 100644 --- a/configs/example/arm/workloads.py +++ b/configs/example/arm/workloads.py @@ -49,7 +49,7 @@ class ArmBaremetal(ArmFsWorkload): dtb_addr = 0 def __init__(self, obj, system, **kwargs): - super(ArmBaremetal, self).__init__(**kwargs) + super().__init__(**kwargs) self.object_file = obj @@ -76,7 +76,7 @@ class ArmTrustedFirmware(ArmFsWorkload): dtb_addr = 0 def __init__(self, obj, system, **kwargs): - super(ArmTrustedFirmware, self).__init__(**kwargs) + super().__init__(**kwargs) self.extras = [binary("bl1.bin"), binary("fip.bin")] self.extras_addrs = [ diff --git a/configs/example/gem5_library/x86-parsec-benchmarks.py b/configs/example/gem5_library/x86-parsec-benchmarks.py index cc33103183..5e855b773f 100644 --- a/configs/example/gem5_library/x86-parsec-benchmarks.py +++ b/configs/example/gem5_library/x86-parsec-benchmarks.py @@ -175,7 +175,7 @@ board = X86Board( command = ( - "cd /home/gem5/parsec-benchmark;".format(args.benchmark) + f"cd /home/gem5/parsec-benchmark;" + "source env.sh;" + f"parsecmgmt -a run -p {args.benchmark} -c gcc-hooks -i {args.size} -n 2;" + "sleep 5;" @@ -236,7 +236,7 @@ print("Done with the simulation") print() print("Performance statistics:") -print("Simulated time in ROI: " + ((str(simulator.get_roi_ticks()[0])))) +print("Simulated time in ROI: " + (str(simulator.get_roi_ticks()[0]))) print( "Ran a total of", simulator.get_current_tick() / 1e12, "simulated seconds" ) diff --git a/configs/example/gpufs/DisjointNetwork.py b/configs/example/gpufs/DisjointNetwork.py index bfacabc3b3..9215691476 100644 --- a/configs/example/gpufs/DisjointNetwork.py +++ b/configs/example/gpufs/DisjointNetwork.py @@ -37,7 +37,7 @@ from network import Network class DisjointSimple(SimpleNetwork): def __init__(self, ruby_system): - super(DisjointSimple, self).__init__() + super().__init__() self.netifs = [] self.routers = [] @@ -73,7 +73,7 @@ class DisjointSimple(SimpleNetwork): class DisjointGarnet(GarnetNetwork): def __init__(self, ruby_system): - super(DisjointGarnet, self).__init__() + super().__init__() self.netifs = [] self.ruby_system = ruby_system diff --git a/configs/example/gpufs/Disjoint_VIPER.py b/configs/example/gpufs/Disjoint_VIPER.py index b9577182e3..d4619c01a0 100644 --- a/configs/example/gpufs/Disjoint_VIPER.py +++ b/configs/example/gpufs/Disjoint_VIPER.py @@ -47,7 +47,7 @@ class Disjoint_VIPER(RubySystem): if buildEnv["PROTOCOL"] != "GPU_VIPER": fatal("This ruby config only supports the GPU_VIPER protocol") - super(Disjoint_VIPER, self).__init__() + super().__init__() def create(self, options, system, piobus, dma_devices): # Disjoint network topology diff --git a/configs/example/gpufs/system/amdgpu.py b/configs/example/gpufs/system/amdgpu.py index 450a00bf93..4bca52c77e 100644 --- a/configs/example/gpufs/system/amdgpu.py +++ b/configs/example/gpufs/system/amdgpu.py @@ -184,7 +184,7 @@ def connectGPU(system, args): elif args.gpu_device == "Vega10": system.pc.south_bridge.gpu.DeviceID = 0x6863 else: - panic("Unknown GPU device: {}".format(args.gpu_device)) + panic(f"Unknown GPU device: {args.gpu_device}") # Use the gem5 default of 0x280 OR'd with 0x10 which tells Linux there is # a PCI capabilities list to travse. diff --git a/configs/example/read_config.py b/configs/example/read_config.py index b8f1d0d401..27e23b69ee 100644 --- a/configs/example/read_config.py +++ b/configs/example/read_config.py @@ -140,7 +140,7 @@ for name, parser in list(param_parsers.items()): setattr(m5.params.__dict__[name], "parse_ini", classmethod(parser)) -class PortConnection(object): +class PortConnection: """This class is similar to m5.params.PortRef but with just enough information for ConfigManager""" @@ -151,7 +151,7 @@ class PortConnection(object): @classmethod def from_string(cls, str): - m = re.match("(.*)\.([^.\[]+)(\[(\d+)\])?", str) + m = re.match(r"(.*)\.([^.\[]+)(\[(\d+)\])?", str) object_name, port_name, whole_index, index = m.groups() if index is not None: index = int(index) @@ -178,7 +178,7 @@ def to_list(v): return [v] -class ConfigManager(object): +class ConfigManager: """Manager for parsing a Root configuration from a config file""" def __init__(self, config): @@ -296,7 +296,7 @@ class ConfigManager(object): def parse_port_name(self, port): """Parse the name of a port""" - m = re.match("(.*)\.([^.\[]+)(\[(\d+)\])?", port) + m = re.match(r"(.*)\.([^.\[]+)(\[(\d+)\])?", port) peer, peer_port, whole_index, index = m.groups() if index is not None: index = int(index) @@ -415,7 +415,7 @@ class ConfigManager(object): self.bind_ports(connections) -class ConfigFile(object): +class ConfigFile: def get_flags(self): return set() @@ -444,7 +444,7 @@ class ConfigFile(object): pass def get_port_peers(self, object_name, port_name): - """Get the list of connected port names (in the string form + r"""Get the list of connected port names (in the string form object.port(\[index\])?) of the port object_name.port_name""" pass @@ -507,7 +507,7 @@ class ConfigJsonFile(ConfigFile): self.find_all_objects(elem) def load(self, config_file): - root = json.load(open(config_file, "r")) + root = json.load(open(config_file)) self.object_dicts = {} self.find_all_objects(root) diff --git a/configs/example/sst/arm_fs.py b/configs/example/sst/arm_fs.py index bee4be1118..14dd7c4743 100644 --- a/configs/example/sst/arm_fs.py +++ b/configs/example/sst/arm_fs.py @@ -48,7 +48,7 @@ from common import SysPaths class ArmSstSystem(ArmSystem): def __init__(self, cpu_clock_rate, **kwargs): - super(ArmSstSystem, self).__init__(**kwargs) + super().__init__(**kwargs) self.voltage_domain = VoltageDomain(voltage="1.0V") self.clk_domain = SrcClockDomain( diff --git a/configs/learning_gem5/part1/caches.py b/configs/learning_gem5/part1/caches.py index 3f7d26ed21..04c7d6797c 100644 --- a/configs/learning_gem5/part1/caches.py +++ b/configs/learning_gem5/part1/caches.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015 Jason Power # All rights reserved. # @@ -55,7 +54,7 @@ class L1Cache(Cache): tgts_per_mshr = 20 def __init__(self, options=None): - super(L1Cache, self).__init__() + super().__init__() pass def connectBus(self, bus): @@ -79,7 +78,7 @@ class L1ICache(L1Cache): ) def __init__(self, opts=None): - super(L1ICache, self).__init__(opts) + super().__init__(opts) if not opts or not opts.l1i_size: return self.size = opts.l1i_size @@ -100,7 +99,7 @@ class L1DCache(L1Cache): ) def __init__(self, opts=None): - super(L1DCache, self).__init__(opts) + super().__init__(opts) if not opts or not opts.l1d_size: return self.size = opts.l1d_size @@ -125,7 +124,7 @@ class L2Cache(Cache): SimpleOpts.add_option("--l2_size", help=f"L2 cache size. Default: {size}") def __init__(self, opts=None): - super(L2Cache, self).__init__() + super().__init__() if not opts or not opts.l2_size: return self.size = opts.l2_size diff --git a/configs/learning_gem5/part1/two_level.py b/configs/learning_gem5/part1/two_level.py index 1daf36a4f0..c6f4f4872f 100644 --- a/configs/learning_gem5/part1/two_level.py +++ b/configs/learning_gem5/part1/two_level.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015 Jason Power # All rights reserved. # diff --git a/configs/learning_gem5/part2/hello_goodbye.py b/configs/learning_gem5/part2/hello_goodbye.py index eeb76f708f..4a4171c990 100644 --- a/configs/learning_gem5/part2/hello_goodbye.py +++ b/configs/learning_gem5/part2/hello_goodbye.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017 Jason Lowe-Power # All rights reserved. # diff --git a/configs/learning_gem5/part2/run_simple.py b/configs/learning_gem5/part2/run_simple.py index ba91e5c36c..ce7ea277e8 100644 --- a/configs/learning_gem5/part2/run_simple.py +++ b/configs/learning_gem5/part2/run_simple.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017 Jason Lowe-Power # All rights reserved. # diff --git a/configs/learning_gem5/part2/simple_cache.py b/configs/learning_gem5/part2/simple_cache.py index 2cdebc218a..2ba138c879 100644 --- a/configs/learning_gem5/part2/simple_cache.py +++ b/configs/learning_gem5/part2/simple_cache.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017 Jason Lowe-Power # All rights reserved. # diff --git a/configs/learning_gem5/part2/simple_memobj.py b/configs/learning_gem5/part2/simple_memobj.py index aef3a700e5..c845241ced 100644 --- a/configs/learning_gem5/part2/simple_memobj.py +++ b/configs/learning_gem5/part2/simple_memobj.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017 Jason Lowe-Power # All rights reserved. # diff --git a/configs/learning_gem5/part3/msi_caches.py b/configs/learning_gem5/part3/msi_caches.py index de1d8c185f..f628cca96d 100644 --- a/configs/learning_gem5/part3/msi_caches.py +++ b/configs/learning_gem5/part3/msi_caches.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017 Jason Power # All rights reserved. # @@ -48,7 +47,7 @@ class MyCacheSystem(RubySystem): if buildEnv["PROTOCOL"] != "MSI": fatal("This system assumes MSI from learning gem5!") - super(MyCacheSystem, self).__init__() + super().__init__() def setup(self, system, cpus, mem_ctrls): """Set up the Ruby cache subsystem. Note: This can't be done in the @@ -121,7 +120,7 @@ class L1Cache(L1Cache_Controller): """CPUs are needed to grab the clock domain and system is needed for the cache block size. """ - super(L1Cache, self).__init__() + super().__init__() self.version = self.versionCount() # This is the cache memory object that stores the cache data and tags @@ -184,7 +183,7 @@ class DirController(Directory_Controller): """ranges are the memory ranges assigned to this controller.""" if len(mem_ctrls) > 1: panic("This cache system can only be connected to one mem ctrl") - super(DirController, self).__init__() + super().__init__() self.version = self.versionCount() self.addr_ranges = ranges self.ruby_system = ruby_system @@ -216,7 +215,7 @@ class MyNetwork(SimpleNetwork): """A simple point-to-point network. This doesn't not use garnet.""" def __init__(self, ruby_system): - super(MyNetwork, self).__init__() + super().__init__() self.netifs = [] self.ruby_system = ruby_system diff --git a/configs/learning_gem5/part3/ruby_caches_MI_example.py b/configs/learning_gem5/part3/ruby_caches_MI_example.py index f929cb224d..aec54b1068 100644 --- a/configs/learning_gem5/part3/ruby_caches_MI_example.py +++ b/configs/learning_gem5/part3/ruby_caches_MI_example.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015 Jason Power # All rights reserved. # @@ -50,7 +49,7 @@ class MyCacheSystem(RubySystem): if buildEnv["PROTOCOL"] != "MI_example": fatal("This system assumes MI_example!") - super(MyCacheSystem, self).__init__() + super().__init__() def setup(self, system, cpus, mem_ctrls): """Set up the Ruby cache subsystem. Note: This can't be done in the @@ -119,7 +118,7 @@ class L1Cache(L1Cache_Controller): """CPUs are needed to grab the clock domain and system is needed for the cache block size. """ - super(L1Cache, self).__init__() + super().__init__() self.version = self.versionCount() # This is the cache memory object that stores the cache data and tags @@ -173,7 +172,7 @@ class DirController(Directory_Controller): """ranges are the memory ranges assigned to this controller.""" if len(mem_ctrls) > 1: panic("This cache system can only be connected to one mem ctrl") - super(DirController, self).__init__() + super().__init__() self.version = self.versionCount() self.addr_ranges = ranges self.ruby_system = ruby_system @@ -202,7 +201,7 @@ class MyNetwork(SimpleNetwork): """A simple point-to-point network. This doesn't not use garnet.""" def __init__(self, ruby_system): - super(MyNetwork, self).__init__() + super().__init__() self.netifs = [] self.ruby_system = ruby_system diff --git a/configs/learning_gem5/part3/ruby_test.py b/configs/learning_gem5/part3/ruby_test.py index e46f07bb0a..5b00e1169e 100644 --- a/configs/learning_gem5/part3/ruby_test.py +++ b/configs/learning_gem5/part3/ruby_test.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015 Jason Power # All rights reserved. # diff --git a/configs/learning_gem5/part3/simple_ruby.py b/configs/learning_gem5/part3/simple_ruby.py index f3f84353e8..6e22beb4dd 100644 --- a/configs/learning_gem5/part3/simple_ruby.py +++ b/configs/learning_gem5/part3/simple_ruby.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015 Jason Power # All rights reserved. # diff --git a/configs/learning_gem5/part3/test_caches.py b/configs/learning_gem5/part3/test_caches.py index 7b0ce52dad..ebd646ffab 100644 --- a/configs/learning_gem5/part3/test_caches.py +++ b/configs/learning_gem5/part3/test_caches.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017 Jason Power # All rights reserved. # @@ -48,7 +47,7 @@ class TestCacheSystem(RubySystem): if buildEnv["PROTOCOL"] != "MSI": fatal("This system assumes MSI from learning gem5!") - super(TestCacheSystem, self).__init__() + super().__init__() def setup(self, system, tester, mem_ctrls): """Set up the Ruby cache subsystem. Note: This can't be done in the diff --git a/configs/ruby/CHI_config.py b/configs/ruby/CHI_config.py index 1288cf95d6..3cccfd0676 100644 --- a/configs/ruby/CHI_config.py +++ b/configs/ruby/CHI_config.py @@ -116,7 +116,7 @@ class CHI_Node(SubSystem): router_list = None def __init__(self, ruby_system): - super(CHI_Node, self).__init__() + super().__init__() self._ruby_system = ruby_system self._network = ruby_system.network @@ -201,7 +201,7 @@ class CHI_Cache_Controller(Cache_Controller): """ def __init__(self, ruby_system): - super(CHI_Cache_Controller, self).__init__( + super().__init__( version=Versions.getVersion(Cache_Controller), ruby_system=ruby_system, mandatoryQueue=MessageBuffer(), @@ -228,7 +228,7 @@ class CHI_L1Controller(CHI_Cache_Controller): """ def __init__(self, ruby_system, sequencer, cache, prefetcher): - super(CHI_L1Controller, self).__init__(ruby_system) + super().__init__(ruby_system) self.sequencer = sequencer self.cache = cache self.use_prefetcher = False @@ -265,7 +265,7 @@ class CHI_L2Controller(CHI_Cache_Controller): """ def __init__(self, ruby_system, cache, prefetcher): - super(CHI_L2Controller, self).__init__(ruby_system) + super().__init__(ruby_system) self.sequencer = NULL self.cache = cache self.use_prefetcher = False @@ -301,7 +301,7 @@ class CHI_HNFController(CHI_Cache_Controller): """ def __init__(self, ruby_system, cache, prefetcher, addr_ranges): - super(CHI_HNFController, self).__init__(ruby_system) + super().__init__(ruby_system) self.sequencer = NULL self.cache = cache self.use_prefetcher = False @@ -340,7 +340,7 @@ class CHI_MNController(MiscNode_Controller): def __init__( self, ruby_system, addr_range, l1d_caches, early_nonsync_comp ): - super(CHI_MNController, self).__init__( + super().__init__( version=Versions.getVersion(MiscNode_Controller), ruby_system=ruby_system, mandatoryQueue=MessageBuffer(), @@ -371,7 +371,7 @@ class CHI_DMAController(CHI_Cache_Controller): """ def __init__(self, ruby_system, sequencer): - super(CHI_DMAController, self).__init__(ruby_system) + super().__init__(ruby_system) self.sequencer = sequencer class DummyCache(RubyCache): @@ -463,7 +463,7 @@ class CHI_RNF(CHI_Node): l1Iprefetcher_type=None, l1Dprefetcher_type=None, ): - super(CHI_RNF, self).__init__(ruby_system) + super().__init__(ruby_system) self._block_size_bits = int(math.log(cache_line_size, 2)) @@ -606,7 +606,7 @@ class CHI_HNF(CHI_Node): # The CHI controller can be a child of this object or another if # 'parent' if specified def __init__(self, hnf_idx, ruby_system, llcache_type, parent): - super(CHI_HNF, self).__init__(ruby_system) + super().__init__(ruby_system) addr_ranges, intlvHighBit = self.getAddrRanges(hnf_idx) # All ranges should have the same interleaving @@ -644,7 +644,7 @@ class CHI_MN(CHI_Node): # The CHI controller can be a child of this object or another if # 'parent' if specified def __init__(self, ruby_system, l1d_caches, early_nonsync_comp=False): - super(CHI_MN, self).__init__(ruby_system) + super().__init__(ruby_system) # MiscNode has internal address range starting at 0 addr_range = AddrRange(0, size="1kB") @@ -675,7 +675,7 @@ class CHI_SNF_Base(CHI_Node): # The CHI controller can be a child of this object or another if # 'parent' if specified def __init__(self, ruby_system, parent): - super(CHI_SNF_Base, self).__init__(ruby_system) + super().__init__(ruby_system) self._cntrl = Memory_Controller( version=Versions.getVersion(Memory_Controller), @@ -722,7 +722,7 @@ class CHI_SNF_BootMem(CHI_SNF_Base): """ def __init__(self, ruby_system, parent, bootmem): - super(CHI_SNF_BootMem, self).__init__(ruby_system, parent) + super().__init__(ruby_system, parent) self._cntrl.memory_out_port = bootmem.port self._cntrl.addr_ranges = self.getMemRange(bootmem) @@ -733,7 +733,7 @@ class CHI_SNF_MainMem(CHI_SNF_Base): """ def __init__(self, ruby_system, parent, mem_ctrl=None): - super(CHI_SNF_MainMem, self).__init__(ruby_system, parent) + super().__init__(ruby_system, parent) if mem_ctrl: self._cntrl.memory_out_port = mem_ctrl.port self._cntrl.addr_ranges = self.getMemRange(mem_ctrl) @@ -748,7 +748,7 @@ class CHI_RNI_Base(CHI_Node): # The CHI controller can be a child of this object or another if # 'parent' if specified def __init__(self, ruby_system, parent): - super(CHI_RNI_Base, self).__init__(ruby_system) + super().__init__(ruby_system) self._sequencer = RubySequencer( version=Versions.getSeqId(), @@ -777,7 +777,7 @@ class CHI_RNI_DMA(CHI_RNI_Base): """ def __init__(self, ruby_system, dma_port, parent): - super(CHI_RNI_DMA, self).__init__(ruby_system, parent) + super().__init__(ruby_system, parent) assert dma_port != None self._sequencer.in_ports = dma_port @@ -788,5 +788,5 @@ class CHI_RNI_IO(CHI_RNI_Base): """ def __init__(self, ruby_system, parent): - super(CHI_RNI_IO, self).__init__(ruby_system, parent) + super().__init__(ruby_system, parent) ruby_system._io_port = self._sequencer diff --git a/configs/topologies/BaseTopology.py b/configs/topologies/BaseTopology.py index cdcca3f7eb..2e5132927c 100644 --- a/configs/topologies/BaseTopology.py +++ b/configs/topologies/BaseTopology.py @@ -27,7 +27,7 @@ import m5 -class BaseTopology(object): +class BaseTopology: description = "BaseTopology" def __init__(self): diff --git a/ext/testlib/configuration.py b/ext/testlib/configuration.py index 244fde8f93..a635b6d3a9 100644 --- a/ext/testlib/configuration.py +++ b/ext/testlib/configuration.py @@ -105,7 +105,7 @@ class UninitializedConfigException(Exception): pass -class TagRegex(object): +class TagRegex: def __init__(self, include, regex): self.include = include self.regex = re.compile(regex) @@ -115,7 +115,7 @@ class TagRegex(object): return "%10s: %s" % (type_, self.regex.pattern) -class _Config(object): +class _Config: _initialized = False __shared_dict = {} @@ -185,8 +185,8 @@ class _Config(object): return (getattr(self._defaults, attr),) def __getattr__(self, attr): - if attr in dir(super(_Config, self)): - return getattr(super(_Config, self), attr) + if attr in dir(super()): + return getattr(super(), attr) elif not self._initialized: raise UninitializedConfigException( "Cannot directly access elements from the config before it is" @@ -434,7 +434,7 @@ def define_post_processors(config): ) -class Argument(object): +class Argument: """ Class represents a cli argument/flag for a argparse parser. @@ -651,7 +651,7 @@ def define_common_args(config): common_args = AttrDict({arg.name: arg for arg in common_args}) -class ArgParser(object, metaclass=abc.ABCMeta): +class ArgParser(metaclass=abc.ABCMeta): class ExtendAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): items = getattr(namespace, self.dest, []) @@ -679,7 +679,7 @@ class CommandParser(ArgParser): def __init__(self): parser = argparse.ArgumentParser() - super(CommandParser, self).__init__(parser) + super().__init__(parser) self.subparser = self.add_subparsers(dest="command") @@ -691,7 +691,7 @@ class RunParser(ArgParser): def __init__(self, subparser): parser = subparser.add_parser("run", help="""Run Tests.""") - super(RunParser, self).__init__(parser) + super().__init__(parser) common_args.uid.add_to(parser) common_args.skip_build.add_to(parser) @@ -718,7 +718,7 @@ class ListParser(ArgParser): parser = subparser.add_parser( "list", help="""List and query test metadata.""" ) - super(ListParser, self).__init__(parser) + super().__init__(parser) Argument( "--suites", @@ -777,7 +777,7 @@ class ListParser(ArgParser): class RerunParser(ArgParser): def __init__(self, subparser): parser = subparser.add_parser("rerun", help="""Rerun failed tests.""") - super(RerunParser, self).__init__(parser) + super().__init__(parser) common_args.skip_build.add_to(parser) common_args.directories.add_to(parser) diff --git a/ext/testlib/fixture.py b/ext/testlib/fixture.py index aa735cc1c5..16fc39c29f 100644 --- a/ext/testlib/fixture.py +++ b/ext/testlib/fixture.py @@ -34,14 +34,14 @@ from typing import Optional class SkipException(Exception): def __init__(self, fixture, testitem): - self.msg = 'Fixture "%s" raised SkipException for "%s".' % ( + self.msg = 'Fixture "{}" raised SkipException for "{}".'.format( fixture.name, testitem.name, ) - super(SkipException, self).__init__(self.msg) + super().__init__(self.msg) -class Fixture(object): +class Fixture: """ Base Class for a test Fixture. @@ -60,7 +60,7 @@ class Fixture(object): collector = helper.InstanceCollector() def __new__(klass, *args, **kwargs): - obj = super(Fixture, klass).__new__(klass) + obj = super().__new__(klass) Fixture.collector.collect(obj) return obj diff --git a/ext/testlib/handlers.py b/ext/testlib/handlers.py index 029ac8baa4..6a6f654355 100644 --- a/ext/testlib/handlers.py +++ b/ext/testlib/handlers.py @@ -48,7 +48,7 @@ from queue import Queue, Empty from testlib.configuration import constants -class _TestStreamManager(object): +class _TestStreamManager: def __init__(self): self._writers = {} @@ -75,7 +75,7 @@ class _TestStreamManager(object): self._writers.clear() -class _TestStreams(object): +class _TestStreams: def __init__(self, stdout, stderr): helper.mkdir_p(os.path.dirname(stdout)) helper.mkdir_p(os.path.dirname(stderr)) @@ -87,7 +87,7 @@ class _TestStreams(object): self.stderr.close() -class ResultHandler(object): +class ResultHandler: """ Log handler which listens for test results and output saving data as it is reported. @@ -184,7 +184,7 @@ class ResultHandler(object): # TODO Change from a handler to an internal post processor so it can be used # to reprint results -class SummaryHandler(object): +class SummaryHandler: """ A log handler which listens to the log for test results and reports the aggregate results when closed. @@ -255,7 +255,7 @@ class SummaryHandler(object): string = ( " Results:" + string - + " in {:.2} seconds ".format(self._timer.active_time()) + + f" in {self._timer.active_time():.2} seconds " ) string += " " return terminal.insert_separator( @@ -263,7 +263,7 @@ class SummaryHandler(object): ) -class TerminalHandler(object): +class TerminalHandler: color = terminal.get_termcap() verbosity_mapping = { log.LogLevel.Warn: color.Yellow, @@ -339,7 +339,7 @@ class TerminalHandler(object): ) def _colorize(self, message, level, bold=False): - return "%s%s%s%s" % ( + return "{}{}{}{}".format( self.color.Bold if bold else "", self.verbosity_mapping.get(level, ""), message, @@ -355,7 +355,7 @@ class TerminalHandler(object): pass -class MultiprocessingHandlerWrapper(object): +class MultiprocessingHandlerWrapper: """ A handler class which forwards log records to subhandlers, enabling logging across multiprocessing python processes. diff --git a/ext/testlib/helper.py b/ext/testlib/helper.py index c8680e6948..0fd0cf539e 100644 --- a/ext/testlib/helper.py +++ b/ext/testlib/helper.py @@ -56,7 +56,7 @@ import threading import time -class TimedWaitPID(object): +class TimedWaitPID: """Utility to monkey-patch os.waitpid() with os.wait4(). This allows process usage time to be obtained directly from the OS @@ -73,7 +73,7 @@ class TimedWaitPID(object): TimeRecord = namedtuple("_TimeRecord", "user_time system_time") - class Wrapper(object): + class Wrapper: def __init__(self): self._time_for_pid = {} self._access_lock = threading.Lock() @@ -93,7 +93,7 @@ class TimedWaitPID(object): def get_time_for_pid(self, pid): with self._access_lock: if pid not in self._time_for_pid: - raise Exception("No resource usage for pid {}".format(pid)) + raise Exception(f"No resource usage for pid {pid}") time_for_pid = self._time_for_pid[pid] del self._time_for_pid[pid] return time_for_pid @@ -346,8 +346,8 @@ class OrderedSet(MutableSet): def __repr__(self): if not self: - return "%s()" % (self.__class__.__name__,) - return "%s(%r)" % (self.__class__.__name__, list(self)) + return f"{self.__class__.__name__}()" + return f"{self.__class__.__name__}({list(self)!r})" def __eq__(self, other): if isinstance(other, OrderedSet): @@ -386,7 +386,7 @@ class FrozenSetException(Exception): pass -class AttrDict(object): +class AttrDict: """Object which exposes its own internal dictionary through attributes.""" def __init__(self, dict_={}): @@ -417,7 +417,7 @@ class FrozenAttrDict(AttrDict): __initialized = False def __init__(self, dict_={}): - super(FrozenAttrDict, self).__init__(dict_) + super().__init__(dict_) self.__initialized = True def __setattr__(self, attr, val): @@ -426,7 +426,7 @@ class FrozenAttrDict(AttrDict): "Cannot modify an attribute in a FozenAttrDict" ) else: - super(FrozenAttrDict, self).__setattr__(attr, val) + super().__setattr__(attr, val) def update(self, items): if self.__initialized: @@ -434,10 +434,10 @@ class FrozenAttrDict(AttrDict): "Cannot modify an attribute in a FozenAttrDict" ) else: - super(FrozenAttrDict, self).update(items) + super().update(items) -class InstanceCollector(object): +class InstanceCollector: """ A class used to simplify collecting of Classes. @@ -475,7 +475,7 @@ def append_dictlist(dict_, key, value): def _filter_file(fname, filters): - with open(fname, "r") as file_: + with open(fname) as file_: for line in file_: for regex in filters: if re.match(regex, line): @@ -529,7 +529,7 @@ def diff_out_file(ref_file, out_file, logger, ignore_regexes=tuple()): except OSError: # Likely signals that diff does not exist on this system. fallback # to difflib - with open(out_file, "r") as outf, open(ref_file, "r") as reff: + with open(out_file) as outf, open(ref_file) as reff: diff = difflib.unified_diff( iter(reff.readline, ""), iter(outf.readline, ""), diff --git a/ext/testlib/loader.py b/ext/testlib/loader.py index f5eacfc2ce..192632adab 100644 --- a/ext/testlib/loader.py +++ b/ext/testlib/loader.py @@ -110,7 +110,7 @@ def path_as_modulename(filepath): def path_as_suitename(filepath): - return os.path.split(os.path.dirname(os.path.abspath((filepath))))[-1] + return os.path.split(os.path.dirname(os.path.abspath(filepath)))[-1] def _assert_files_in_same_dir(files): @@ -121,7 +121,7 @@ def _assert_files_in_same_dir(files): assert os.path.dirname(f) == directory -class Loader(object): +class Loader: """ Class for discovering tests. diff --git a/ext/testlib/log.py b/ext/testlib/log.py index 346fea747d..e66d1bbc02 100644 --- a/ext/testlib/log.py +++ b/ext/testlib/log.py @@ -57,7 +57,7 @@ class RecordTypeCounterMetaclass(type): RecordTypeCounterMetaclass.counter += 1 -class Record(object, metaclass=RecordTypeCounterMetaclass): +class Record(metaclass=RecordTypeCounterMetaclass): """ A generic object that is passed to the :class:`Log` and its handlers. @@ -70,9 +70,7 @@ class Record(object, metaclass=RecordTypeCounterMetaclass): def __getitem__(self, item): if item not in self.data: - raise KeyError( - "%s not in record %s" % (item, self.__class__.__name__) - ) + raise KeyError(f"{item} not in record {self.__class__.__name__}") return self.data[item] def __str__(self): @@ -132,7 +130,7 @@ class LibraryMessage(Record): pass -class Log(object): +class Log: _result_typemap = { wrappers.LoadedLibrary.__name__: LibraryResult, wrappers.LoadedSuite.__name__: SuiteResult, diff --git a/ext/testlib/main.py b/ext/testlib/main.py index f8d04cec56..fdd4c17b2f 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -141,7 +141,7 @@ def filter_with_config_tags(loaded_library): filters = list(itertools.chain(final_tags, tags)) string = "Filtering suites with tags as follows:\n" - filter_string = "\t\n".join((str(f) for f in filters)) + filter_string = "\t\n".join(str(f) for f in filters) log.test_log.trace(string + filter_string) return filter_with_tags(loaded_library, filters) @@ -307,11 +307,11 @@ def run_schedule(test_schedule, log_handler): log.test_log.message(terminal.separator()) log.test_log.message( - "Running Tests from {} suites".format(len(test_schedule.suites)), + f"Running Tests from {len(test_schedule.suites)} suites", bold=True, ) log.test_log.message( - "Results will be stored in {}".format(configuration.config.result_path) + f"Results will be stored in {configuration.config.result_path}" ) log.test_log.message(terminal.separator()) diff --git a/ext/testlib/query.py b/ext/testlib/query.py index 6b49bc2b00..ead567a360 100644 --- a/ext/testlib/query.py +++ b/ext/testlib/query.py @@ -32,7 +32,7 @@ import testlib.log as log # TODO Refactor print logic out of this so the objects # created are separate from print logic. -class QueryRunner(object): +class QueryRunner: def __init__(self, test_schedule): self.schedule = test_schedule diff --git a/ext/testlib/result.py b/ext/testlib/result.py index 38295f3a04..b6977d3542 100644 --- a/ext/testlib/result.py +++ b/ext/testlib/result.py @@ -189,7 +189,7 @@ class InternalSavedResults: return pickle.load(f) -class XMLElement(object): +class XMLElement: def write(self, file_): self.begin(file_) self.end(file_) @@ -219,15 +219,13 @@ class XMLElement(object): file_.write("" % self.name) -class XMLAttribute(object): +class XMLAttribute: def __init__(self, name, value): self.name = name self.value = value def write(self, file_): - file_.write( - "%s=%s" % (self.name, xml.sax.saxutils.quoteattr(self.value)) - ) + file_.write(f"{self.name}={xml.sax.saxutils.quoteattr(self.value)}") class JUnitTestSuites(XMLElement): @@ -328,10 +326,10 @@ class LargeFileElement(XMLElement): def body(self, file_): try: - with open(self.filename, "r") as f: + with open(self.filename) as f: for line in f: file_.write(xml.sax.saxutils.escape(line)) - except IOError: + except OSError: # TODO Better error logic, this is sometimes O.K. # if there was no stdout/stderr captured for the test # diff --git a/ext/testlib/runner.py b/ext/testlib/runner.py index bfae7ce308..1e3512af2b 100644 --- a/ext/testlib/runner.py +++ b/ext/testlib/runner.py @@ -75,7 +75,7 @@ def compute_aggregate_result(iterable): return Result(Result.Passed) -class TestParameters(object): +class TestParameters: def __init__(self, test, suite): self.test = test self.suite = suite @@ -188,10 +188,10 @@ class BrokenFixtureException(Exception): 'Exception raised building "%s" raised SkipException' ' for "%s".' % (trace, fixture.name, testitem.name) ) - super(BrokenFixtureException, self).__init__(self.msg) + super().__init__(self.msg) -class FixtureBuilder(object): +class FixtureBuilder: def __init__(self, fixtures): self.fixtures = fixtures self.built_fixtures = [] @@ -211,7 +211,7 @@ class FixtureBuilder(object): "Exception raised while setting up fixture for %s" % testitem.uid ) - log.test_log.warn("%s\n%s" % (exc, msg)) + log.test_log.warn(f"{exc}\n{msg}") raise BrokenFixtureException( fixture, testitem, traceback.format_exc() @@ -232,4 +232,4 @@ class FixtureBuilder(object): "Exception raised while tearing down fixture for %s" % testitem.uid ) - log.test_log.warn("%s\n%s" % (exc, msg)) + log.test_log.warn(f"{exc}\n{msg}") diff --git a/ext/testlib/suite.py b/ext/testlib/suite.py index cf9f0e646a..4a24c9c481 100644 --- a/ext/testlib/suite.py +++ b/ext/testlib/suite.py @@ -31,7 +31,7 @@ import testlib.helper as helper import testlib.runner as runner_mod -class TestSuite(object): +class TestSuite: """ An object grouping a collection of tests. It provides tags which enable filtering during list and run selection. All tests held in the suite must @@ -54,7 +54,7 @@ class TestSuite(object): tags = set() def __new__(klass, *args, **kwargs): - obj = super(TestSuite, klass).__new__(klass) + obj = super().__new__(klass) TestSuite.collector.collect(obj) return obj diff --git a/ext/testlib/terminal.py b/ext/testlib/terminal.py index ef4f780ff3..f295aa2dc4 100644 --- a/ext/testlib/terminal.py +++ b/ext/testlib/terminal.py @@ -86,7 +86,7 @@ except: cap_string = null_cap_string -class ColorStrings(object): +class ColorStrings: def __init__(self, cap_string): for i, c in enumerate(color_names): setattr(self, c, cap_string("setaf", i)) @@ -123,7 +123,7 @@ def terminal_size(): ), ) return w, h - except IOError: + except OSError: # It's possible that in sandboxed environments the above ioctl is not # allowed (e.g., some jenkins setups) return 80, 24 diff --git a/ext/testlib/test_util.py b/ext/testlib/test_util.py index 5a995c7810..3ef26191c3 100644 --- a/ext/testlib/test_util.py +++ b/ext/testlib/test_util.py @@ -30,7 +30,7 @@ import testlib.helper as helper import testlib.runner as runner_mod -class TestCase(object): +class TestCase: """ Base class for all tests. @@ -47,7 +47,7 @@ class TestCase(object): collector = helper.InstanceCollector() def __new__(cls, *args, **kwargs): - obj = super(TestCase, cls).__new__(cls) + obj = super().__new__(cls) TestCase.collector.collect(obj) return obj diff --git a/ext/testlib/uid.py b/ext/testlib/uid.py index 62f477134a..84403f80fe 100644 --- a/ext/testlib/uid.py +++ b/ext/testlib/uid.py @@ -32,7 +32,7 @@ import itertools import testlib.configuration as configuration -class UID(object): +class UID: sep = ":" type_idx, path_idx = range(2) diff --git a/ext/testlib/wrappers.py b/ext/testlib/wrappers.py index 930713e36f..936d9b604d 100644 --- a/ext/testlib/wrappers.py +++ b/ext/testlib/wrappers.py @@ -75,7 +75,7 @@ class LibraryMetadata: self.status = status -class LoadedTestable(object): +class LoadedTestable: """ Base class for loaded test items. diff --git a/site_scons/gem5_scons/__init__.py b/site_scons/gem5_scons/__init__.py index 6d6226cdc6..c93a5e29e0 100644 --- a/site_scons/gem5_scons/__init__.py +++ b/site_scons/gem5_scons/__init__.py @@ -88,7 +88,7 @@ def TempFileSpawn(scons_env): # Generate a string of the form: # common/path/prefix/src1, src2 -> tgt1, tgt2 # to print while building. -class Transform(object): +class Transform: # all specific color settings should be here and nowhere else tool_color = termcap.Normal pfx_color = termcap.Yellow diff --git a/site_scons/gem5_scons/builders/config_file.py b/site_scons/gem5_scons/builders/config_file.py index 2ab7bf87b4..7ee5e4d658 100755 --- a/site_scons/gem5_scons/builders/config_file.py +++ b/site_scons/gem5_scons/builders/config_file.py @@ -53,7 +53,7 @@ def ConfigFile(env): # operands are the name of the variable and a Value node containing the # value of the variable. def build_config_file(target, source, env): - (variable, value) = [s.get_contents().decode("utf-8") for s in source] + (variable, value) = (s.get_contents().decode("utf-8") for s in source) with open(str(target[0].abspath), "w") as f: print("#define", variable, value, file=f) return None diff --git a/site_scons/gem5_scons/configure.py b/site_scons/gem5_scons/configure.py index d04cdd49cb..c1b9fb56cc 100644 --- a/site_scons/gem5_scons/configure.py +++ b/site_scons/gem5_scons/configure.py @@ -80,17 +80,17 @@ def CheckLinkFlag(context, flag, autoadd=True, set_for_shared=True): def CheckMember(context, include, decl, member, include_quotes="<>"): context.Message(f"Checking for member {member} in {decl}...") text = """ -#include %(header)s -int main(){ - %(decl)s test; - (void)test.%(member)s; +#include {header} +int main(){{ + {decl} test; + (void)test.{member}; return 0; -}; -""" % { - "header": include_quotes[0] + include + include_quotes[1], - "decl": decl, - "member": member, - } +}}; +""".format( + header=include_quotes[0] + include + include_quotes[1], + decl=decl, + member=member, + ) ret = context.TryCompile(text, extension=".cc") context.Result(ret) diff --git a/site_scons/gem5_scons/defaults.py b/site_scons/gem5_scons/defaults.py index aeca94fe59..4de9a93339 100644 --- a/site_scons/gem5_scons/defaults.py +++ b/site_scons/gem5_scons/defaults.py @@ -45,32 +45,30 @@ from gem5_python_paths import extra_python_paths def EnvDefaults(env): # initialize the toolchain related env with host environment - use_vars = set( - [ - "AS", - "AR", - "CC", - "CXX", - "HOME", - "CPATH", - "LD_LIBRARY_PATH", - "LIBRARY_PATH", - "PATH", - "PKG_CONFIG_PATH", - "PROTOC", - "PYTHONPATH", - "RANLIB", - "TERM", # for clang reports errors in color - "PYTHON_CONFIG", # gem5 specific build env - "CCFLAGS_EXTRA", # gem5 specific build env - "GEM5PY_CCFLAGS_EXTRA", # gem5 specific build env - "GEM5PY_LINKFLAGS_EXTRA", # gem5 specific build env - "LINKFLAGS_EXTRA", # gem5 specific build env - "LANG", # for work with non-ascii directory path - "LC_CTYPE", # for work with non-ascii directory path - "DISPLAY", # for gui program, ex kconfig guiconfig - ] - ) + use_vars = { + "AS", + "AR", + "CC", + "CXX", + "HOME", + "CPATH", + "LD_LIBRARY_PATH", + "LIBRARY_PATH", + "PATH", + "PKG_CONFIG_PATH", + "PROTOC", + "PYTHONPATH", + "RANLIB", + "TERM", # for clang reports errors in color + "PYTHON_CONFIG", # gem5 specific build env + "CCFLAGS_EXTRA", # gem5 specific build env + "GEM5PY_CCFLAGS_EXTRA", # gem5 specific build env + "GEM5PY_LINKFLAGS_EXTRA", # gem5 specific build env + "LINKFLAGS_EXTRA", # gem5 specific build env + "LANG", # for work with non-ascii directory path + "LC_CTYPE", # for work with non-ascii directory path + "DISPLAY", # for gui program, ex kconfig guiconfig + } use_prefixes = [ "ASAN_", # address sanitizer symbolizer path and settings diff --git a/site_scons/gem5_scons/sources.py b/site_scons/gem5_scons/sources.py index 54aeb24de1..46392a1ac0 100644 --- a/site_scons/gem5_scons/sources.py +++ b/site_scons/gem5_scons/sources.py @@ -126,7 +126,7 @@ def resolve_tags(env, tags): return tags -class SourceFilter(object): +class SourceFilter: factories = {} def __init__(self, predicate): @@ -209,11 +209,11 @@ class SourceMeta(type): particular type.""" def __init__(cls, name, bases, dict): - super(SourceMeta, cls).__init__(name, bases, dict) + super().__init__(name, bases, dict) cls.all = SourceList() -class SourceItem(object, metaclass=SourceMeta): +class SourceItem(metaclass=SourceMeta): """Base object that encapsulates the notion of a source component for gem5. This specifies a set of tags which help group components into groups based on arbitrary properties.""" diff --git a/site_scons/gem5_scons/util.py b/site_scons/gem5_scons/util.py index 045fd4ef32..ee8efdc49a 100644 --- a/site_scons/gem5_scons/util.py +++ b/site_scons/gem5_scons/util.py @@ -100,7 +100,7 @@ def compareVersions(v1, v2): return v elif isinstance(v, str): return list( - map(lambda x: int(re.match("\d+", x).group()), v.split(".")) + map(lambda x: int(re.match(r"\d+", x).group()), v.split(".")) ) else: raise TypeError() diff --git a/site_scons/site_init.py b/site_scons/site_init.py index 480dfa74da..39c893ea38 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -38,7 +38,6 @@ # (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 __future__ import print_function # Check for recent-enough Python and SCons versions. try: diff --git a/src/arch/arm/ArmPMU.py b/src/arch/arm/ArmPMU.py index a4a2ebe843..3fd619b55d 100644 --- a/src/arch/arm/ArmPMU.py +++ b/src/arch/arm/ArmPMU.py @@ -43,7 +43,7 @@ from m5.objects.Gic import ArmInterruptPin, ArmPPI from m5.util.fdthelper import * -class ProbeEvent(object): +class ProbeEvent: def __init__(self, pmu, _eventId, obj, *listOfNames): self.obj = obj self.names = listOfNames @@ -58,7 +58,7 @@ class ProbeEvent(object): ) -class SoftwareIncrement(object): +class SoftwareIncrement: def __init__(self, pmu, _eventId): self.eventId = _eventId self.pmu = pmu diff --git a/src/arch/isa_parser/isa_parser.py b/src/arch/isa_parser/isa_parser.py index 9199c7ca73..b0b2485cac 100755 --- a/src/arch/isa_parser/isa_parser.py +++ b/src/arch/isa_parser/isa_parser.py @@ -61,7 +61,7 @@ debug = False labelRE = re.compile(r"(? decoder-g.cc.inc for 'global' outputs def suffixize(self, s, sec): - extn = re.compile("(\.[^\.]+)$") # isolate extension + extn = re.compile(r"(\.[^\.]+)$") # isolate extension if self.namespace: return extn.sub(r"-ns\1.inc", s) # insert some text on either side else: @@ -686,7 +684,7 @@ class ISAParser(Grammar): # is guaranteed to have been written for parse to complete f.write(f'#include "{fn}"\n') - extn = re.compile("(\.[^\.]+)$") + extn = re.compile(r"(\.[^\.]+)$") # instruction constructors splits = self.splits[self.get_file("decoder")] @@ -1564,9 +1562,9 @@ StaticInstPtr operandsREString = r""" (? %r, %r]" % ( + return "[Transition: ({!r}, {!r}) -> {!r}, {!r}]".format( self.state, self.event, self.nextState, diff --git a/src/mem/slicc/util.py b/src/mem/slicc/util.py index 3bb4131a01..bcbf057170 100644 --- a/src/mem/slicc/util.py +++ b/src/mem/slicc/util.py @@ -28,7 +28,7 @@ import os import sys -class PairContainer(object): +class PairContainer: def __init__(self, pairs=None): self.pairs = {} if pairs: @@ -47,7 +47,7 @@ class PairContainer(object): return self.pairs.get(item, failobj) -class Location(object): +class Location: def __init__(self, filename, lineno, no_warning=False): if not isinstance(filename, str): raise AttributeError( diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index 4ba81c258b..a0ec89eafb 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -91,7 +91,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): cache_hierarchy: AbstractCacheHierarchy, ) -> None: if cache_hierarchy.is_ruby(): - raise EnvironmentError("RiscvBoard is not compatible with Ruby") + raise OSError("RiscvBoard is not compatible with Ruby") if processor.get_isa() != ISA.RISCV: raise Exception( diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py index 9853174464..746c66eb01 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py @@ -66,7 +66,7 @@ class AbstractNode(Cache_Controller): # 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__() + super().__init__() # Note: Need to call versionCount method on *this* class, not the # potentially derived class diff --git a/src/python/gem5/components/processors/abstract_processor.py b/src/python/gem5/components/processors/abstract_processor.py index a0f8b5cf44..8978513562 100644 --- a/src/python/gem5/components/processors/abstract_processor.py +++ b/src/python/gem5/components/processors/abstract_processor.py @@ -54,7 +54,7 @@ class AbstractProcessor(SubSystem): if cores: # In the stdlib we assume the system processor conforms to a single # ISA target. - assert len(set(core.get_isa() for core in cores)) == 1 + assert len({core.get_isa() for core in cores}) == 1 self.cores = cores self._isa = cores[0].get_isa() else: diff --git a/src/python/gem5/components/processors/cpu_types.py b/src/python/gem5/components/processors/cpu_types.py index e12eb99816..d2bf6548ed 100644 --- a/src/python/gem5/components/processors/cpu_types.py +++ b/src/python/gem5/components/processors/cpu_types.py @@ -62,7 +62,7 @@ def get_cpu_type_from_str(input: str) -> CPUTypes: if input.lower() == cpu_type.value: return cpu_type - valid_cpu_types_list_str = str() + valid_cpu_types_list_str = "" for cpu_type_str in get_cpu_types_str_set(): valid_cpu_types_list_str += f"{os.linesep}{cpu_type_str}" diff --git a/src/python/gem5/components/processors/switchable_processor.py b/src/python/gem5/components/processors/switchable_processor.py index 1160c2749a..88e5f4cc47 100644 --- a/src/python/gem5/components/processors/switchable_processor.py +++ b/src/python/gem5/components/processors/switchable_processor.py @@ -63,7 +63,7 @@ class SwitchableProcessor(AbstractProcessor): # In the stdlib we assume the system processor conforms to a single # ISA target. - assert len(set(core.get_isa() for core in self._current_cores)) == 1 + assert len({core.get_isa() for core in self._current_cores}) == 1 super().__init__(isa=self._current_cores[0].get_isa()) for name, core_list in self._switchable_cores.items(): @@ -113,8 +113,7 @@ class SwitchableProcessor(AbstractProcessor): def _all_cores(self): for core_list in self._switchable_cores.values(): - for core in core_list: - yield core + yield from core_list def switch_to_processor(self, switchable_core_key: str): # Run various checks. diff --git a/src/python/gem5/isas.py b/src/python/gem5/isas.py index 84f02b87e7..ad156d6f2e 100644 --- a/src/python/gem5/isas.py +++ b/src/python/gem5/isas.py @@ -80,7 +80,7 @@ def get_isa_from_str(input: str) -> ISA: if input.lower() == isa.value: return isa - valid_isas_str_list = str() + valid_isas_str_list = "" for isa_str in get_isas_str_set(): valid_isas_str_list += f"{os.linesep}{isa_str}" diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py index 571a8254e0..74475caec2 100644 --- a/src/python/gem5/resources/client.py +++ b/src/python/gem5/resources/client.py @@ -41,7 +41,7 @@ def getFileContent(file_path: Path) -> Dict: :return: The content of the file """ if file_path.exists(): - with open(file_path, "r") as file: + with open(file_path) as file: return json.load(file) else: raise Exception(f"File not found at {file_path}") diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 695ea79986..96cb5cf19d 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -686,8 +686,7 @@ class SuiteResource(AbstractResource): :yields: A generator that iterates over the workloads in the suite. """ - for workload in self._workloads.keys(): - yield workload + yield from self._workloads.keys() def __len__(self): """ diff --git a/src/python/gem5/simulate/exit_event_generators.py b/src/python/gem5/simulate/exit_event_generators.py index 37998d3a9b..6f0e0a1eac 100644 --- a/src/python/gem5/simulate/exit_event_generators.py +++ b/src/python/gem5/simulate/exit_event_generators.py @@ -48,8 +48,7 @@ def warn_default_decorator(gen: Generator, type: str, effect: str): f"No behavior was set by the user for {type}." f" Default behavior is {effect}." ) - for value in gen(*args, **kw_args): - yield value + yield from gen(*args, **kw_args) return wrapped_generator diff --git a/src/python/gem5/utils/filelock.py b/src/python/gem5/utils/filelock.py index 6fb4e3e1d1..309a9f868b 100644 --- a/src/python/gem5/utils/filelock.py +++ b/src/python/gem5/utils/filelock.py @@ -32,7 +32,7 @@ class FileLockException(Exception): pass -class FileLock(object): +class FileLock: """A file locking mechanism that has context-manager support so you can use it in a with statement. This should be relatively cross compatible as it doesn't rely on msvcrt or fcntl for the locking. diff --git a/src/python/importer.py b/src/python/importer.py index d3bdd593ef..73510f664c 100644 --- a/src/python/importer.py +++ b/src/python/importer.py @@ -42,7 +42,7 @@ class ByteCodeLoader(importlib.abc.Loader): # Simple importer that allows python to import data from a dict of # code objects. The keys are the module path, and the items are the # filename and bytecode of the file. -class CodeImporter(object): +class CodeImporter: def __init__(self): self.modules = {} override_var = os.environ.get("M5_OVERRIDE_PY_SOURCE", "false") @@ -61,7 +61,7 @@ class CodeImporter(object): abspath, code = self.modules[fullname] if self.override and os.path.exists(abspath): - src = open(abspath, "r").read() + src = open(abspath).read() code = compile(src, abspath, "exec") is_package = os.path.basename(abspath) == "__init__.py" diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index e601544b68..8d9e0a4cb3 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -521,7 +521,7 @@ def cxxMethod(*args, **kwargs): # This class holds information about each simobject parameter # that should be displayed on the command line for use in the # configuration system. -class ParamInfo(object): +class ParamInfo: def __init__(self, type, desc, type_str, example, default_val, access_str): self.type = type self.desc = desc @@ -546,7 +546,7 @@ class SimObjectCliWrapperException(Exception): super().__init__(message) -class SimObjectCliWrapper(object): +class SimObjectCliWrapper: """ Wrapper class to restrict operations that may be done from the command line on SimObjects. @@ -609,7 +609,7 @@ class SimObjectCliWrapper(object): # The SimObject class is the root of the special hierarchy. Most of # the code in this class deals with the configuration hierarchy itself # (parent/child node relationships). -class SimObject(object, metaclass=MetaSimObject): +class SimObject(metaclass=MetaSimObject): # Specify metaclass. Any class inheriting from SimObject will # get this metaclass. type = "SimObject" @@ -874,7 +874,7 @@ class SimObject(object, metaclass=MetaSimObject): hr_value = value value = param.convert(value) except Exception as e: - msg = "%s\nError setting param %s.%s to %s\n" % ( + msg = "{}\nError setting param {}.{} to {}\n".format( e, self.__class__.__name__, attr, @@ -1253,8 +1253,7 @@ class SimObject(object, metaclass=MetaSimObject): # it based on the key (name) to ensure the order is the same # on all hosts for name, child in sorted(self._children.items()): - for obj in child.descendants(): - yield obj + yield from child.descendants() # Call C++ to create C++ object corresponding to this object def createCCObject(self): @@ -1287,8 +1286,7 @@ class SimObject(object, metaclass=MetaSimObject): def recurseDeviceTree(self, state): for child in self._children.values(): for item in child: # For looping over SimObjectVectors - for dt in item.generateDeviceTree(state): - yield dt + yield from item.generateDeviceTree(state) # On a separate method otherwise certain buggy Python versions # would fail with: SyntaxError: unqualified exec is not allowed diff --git a/src/python/m5/citations.py b/src/python/m5/citations.py index 1ac8e08145..3df9de22a1 100644 --- a/src/python/m5/citations.py +++ b/src/python/m5/citations.py @@ -113,7 +113,7 @@ gem5_citations = """@article{Binkert:2011:gem5, Mohammad Alian and Rico Amslinger and Matteo Andreozzi and - Adri{\`{a}} Armejach and + Adri{\\`{a}} Armejach and Nils Asmussen and Srikant Bharadwaj and Gabe Black and diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 331c4193cb..9252a14c5a 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -513,7 +513,7 @@ def main(): if os.name == "nt" and os.sep == "\\": # If a Windows machine, we manually quote the string. arg = arg.replace('"', '\\"') - if re.search("\s", args): + if re.search(r"\s", args): # We quote args which have whitespace. arg = '"' + arg + '"' return arg @@ -615,7 +615,7 @@ def main(): if not options.P: sys.path = [os.path.dirname(sys.argv[0])] + sys.path filename = sys.argv[0] - filedata = open(filename, "r").read() + filedata = open(filename).read() filecode = compile(filedata, filename, "exec") scope = {"__file__": filename, "__name__": "__m5_main__"} diff --git a/src/python/m5/options.py b/src/python/m5/options.py index ed0dcddc97..aac7d1ac74 100644 --- a/src/python/m5/options.py +++ b/src/python/m5/options.py @@ -30,11 +30,11 @@ import sys from optparse import * -class nodefault(object): +class nodefault: pass -class splitter(object): +class splitter: def __init__(self, split): self.split = split diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 37af0b6c5c..86a33c739d 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -101,7 +101,7 @@ class MetaParamValue(type): # Dummy base class to identify types that are legitimate for SimObject # parameters. -class ParamValue(object, metaclass=MetaParamValue): +class ParamValue(metaclass=MetaParamValue): cmd_line_settable = False # Generate the code needed as a prerequisite for declaring a C++ @@ -149,7 +149,7 @@ class ParamValue(object, metaclass=MetaParamValue): # Regular parameter description. -class ParamDesc(object): +class ParamDesc: def __init__(self, ptype_str, ptype, *args, **kwargs): self.ptype_str = ptype_str # remember ptype only if it is provided @@ -298,8 +298,7 @@ class SimObjectVector(VectorParamValue): # SimObjectVector directly. def descendants(self): for v in self: - for obj in v.descendants(): - yield obj + yield from v.descendants() def get_config_as_dict(self): a = [] @@ -415,7 +414,7 @@ class VectorParamDesc(ParamDesc): code("std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};") -class ParamFactory(object): +class ParamFactory: def __init__(self, param_desc_class, ptype_str=None): self.param_desc_class = param_desc_class self.ptype_str = ptype_str @@ -966,7 +965,7 @@ class AddrRange(ParamValue): if len(self.masks) == 0: return f"{self.start}:{self.end}" else: - return "%s:%s:%s:%s" % ( + return "{}:{}:{}:{}".format( self.start, self.end, self.intlvMatch, @@ -1602,7 +1601,7 @@ class Enum(ParamValue, metaclass=MetaEnum): def cxx_ini_parse(cls, code, src, dest, ret): code("if (false) {") for elem_name in cls.map.keys(): - code('} else if (%s == "%s") {' % (src, elem_name)) + code(f'}} else if ({src} == "{elem_name}") {{') code.indent() name = cls.__name__ if cls.enum_name is None else cls.enum_name code(f"{dest} = {name if cls.is_class else 'enums'}::{elem_name};") @@ -1970,7 +1969,7 @@ class MemoryBandwidth(float, ParamValue): # make_param_value() above that lets these be assigned where a # SimObject is required. # only one copy of a particular node -class NullSimObject(object, metaclass=Singleton): +class NullSimObject(metaclass=Singleton): _name = "Null" def __call__(cls): @@ -2036,7 +2035,7 @@ AllMemory = AddrRange(0, MaxAddr) # Port reference: encapsulates a reference to a particular port on a # particular SimObject. -class PortRef(object): +class PortRef: def __init__(self, simobj, name, role, is_source): assert isSimObject(simobj) or isSimObjectClass(simobj) self.simobj = simobj @@ -2206,7 +2205,7 @@ class VectorPortElementRef(PortRef): # A reference to a complete vector-valued port (not just a single element). # Can be indexed to retrieve individual VectorPortElementRef instances. -class VectorPortRef(object): +class VectorPortRef: def __init__(self, simobj, name, role, is_source): assert isSimObject(simobj) or isSimObjectClass(simobj) self.simobj = simobj @@ -2288,7 +2287,7 @@ class VectorPortRef(object): # Port description object. Like a ParamDesc object, this represents a # logical port in the SimObject class, not a particular port on a # SimObject instance. The latter are represented by PortRef objects. -class Port(object): +class Port: # Port("role", "description") _compat_dict = {} @@ -2379,12 +2378,12 @@ VectorSlavePort = VectorResponsePort # 'Fake' ParamDesc for Port references to assign to the _pdesc slot of # proxy objects (via set_param_desc()) so that proxy error messages # make sense. -class PortParamDesc(object, metaclass=Singleton): +class PortParamDesc(metaclass=Singleton): ptype_str = "Port" ptype = Port -class DeprecatedParam(object): +class DeprecatedParam: """A special type for deprecated parameter variable names. There are times when we need to change the name of parameter, but this diff --git a/src/python/m5/proxy.py b/src/python/m5/proxy.py index 78862346b4..1ae579190e 100644 --- a/src/python/m5/proxy.py +++ b/src/python/m5/proxy.py @@ -45,7 +45,7 @@ import copy -class BaseProxy(object): +class BaseProxy: def __init__(self, search_self, search_up): self._search_self = search_self self._search_up = search_up @@ -272,7 +272,7 @@ def isproxy(obj): return False -class ProxyFactory(object): +class ProxyFactory: def __init__(self, search_self, search_up): self.search_self = search_self self.search_up = search_up diff --git a/src/python/m5/util/dot_writer.py b/src/python/m5/util/dot_writer.py index b491a98448..59886480a5 100644 --- a/src/python/m5/util/dot_writer.py +++ b/src/python/m5/util/dot_writer.py @@ -82,7 +82,7 @@ def dot_create_nodes(simNode, callgraph): label = "root" else: label = simNode._name - full_path = re.sub("\.", "_", simNode.path()) + full_path = re.sub(r"\.", "_", simNode.path()) # add class name under the label label = '"' + label + " \\n: " + simNode.__class__.__name__ + '"' @@ -109,7 +109,7 @@ def dot_create_edges(simNode, callgraph): for port_name in simNode._ports.keys(): port = simNode._port_refs.get(port_name, None) if port != None: - full_path = re.sub("\.", "_", simNode.path()) + full_path = re.sub(r"\.", "_", simNode.path()) full_port_name = full_path + "_" + port_name port_node = dot_create_node(simNode, full_port_name, port_name) # create edges @@ -128,7 +128,7 @@ def dot_create_edges(simNode, callgraph): def dot_add_edge(simNode, callgraph, full_port_name, port): peer = port.peer - full_peer_path = re.sub("\.", "_", peer.simobj.path()) + full_peer_path = re.sub(r"\.", "_", peer.simobj.path()) full_peer_port_name = full_peer_path + "_" + peer.name # Each edge is encountered twice, once for each peer. We only want one @@ -290,9 +290,9 @@ def dot_rgb_to_html(r, g, b): # We need to create all of the clock domains. We abuse the alpha channel to get # the correct domain colouring. def dot_add_clk_domain(c_dom, v_dom): - label = '"' + str(c_dom) + "\ :\ " + str(v_dom) + '"' - label = re.sub("\.", "_", str(label)) - full_path = re.sub("\.", "_", str(c_dom)) + label = '"' + str(c_dom) + r"\ :\ " + str(v_dom) + '"' + label = re.sub(r"\.", "_", str(label)) + full_path = re.sub(r"\.", "_", str(c_dom)) return pydot.Cluster( full_path, shape="box", @@ -311,7 +311,7 @@ def dot_create_dvfs_nodes(simNode, callgraph, domain=None): label = "root" else: label = simNode._name - full_path = re.sub("\.", "_", simNode.path()) + full_path = re.sub(r"\.", "_", simNode.path()) # add class name under the label label = '"' + label + " \\n: " + simNode.__class__.__name__ + '"' diff --git a/src/python/m5/util/fdthelper.py b/src/python/m5/util/fdthelper.py index 136936c512..1f565df270 100644 --- a/src/python/m5/util/fdthelper.py +++ b/src/python/m5/util/fdthelper.py @@ -86,7 +86,7 @@ class FdtPropertyBytes(pyfdt.FdtPropertyBytes): super().__init__(name, values) -class FdtState(object): +class FdtState: """Class for maintaining state while recursively generating a flattened device tree. The state tracks address, size and CPU address cell sizes, and maintains a dictionary of allocated phandles.""" @@ -270,7 +270,7 @@ class Fdt(pyfdt.Fdt): with open(filename, "wb") as f: f.write(self.to_dtb()) return filename - except IOError: + except OSError: raise RuntimeError("Failed to open DTB output file") def writeDtsFile(self, filename): @@ -280,5 +280,5 @@ class Fdt(pyfdt.Fdt): with open(filename, "w") as f: f.write(self.to_dts()) return filename - except IOError: + except OSError: raise RuntimeError("Failed to open DTS output file") diff --git a/src/python/m5/util/multidict.py b/src/python/m5/util/multidict.py index f6ca6ba90a..cff47aeda1 100644 --- a/src/python/m5/util/multidict.py +++ b/src/python/m5/util/multidict.py @@ -27,7 +27,7 @@ __all__ = ["multidict"] -class multidict(object): +class multidict: def __init__(self, parent={}, **kwargs): self.local = dict(**kwargs) self.parent = parent @@ -80,8 +80,7 @@ class multidict(object): return key in self def items(self): - for item in self.next(): - yield item + yield from self.next() def keys(self): for key, value in self.next(): diff --git a/src/python/m5/util/pybind.py b/src/python/m5/util/pybind.py index 54fd111f38..1be9bb604b 100644 --- a/src/python/m5/util/pybind.py +++ b/src/python/m5/util/pybind.py @@ -36,7 +36,7 @@ from abc import * -class PyBindExport(object, metaclass=ABCMeta): +class PyBindExport(metaclass=ABCMeta): @abstractmethod def export(self, code, cname): pass diff --git a/src/python/m5/util/terminal.py b/src/python/m5/util/terminal.py index f3d53ac460..0486b14378 100644 --- a/src/python/m5/util/terminal.py +++ b/src/python/m5/util/terminal.py @@ -84,7 +84,7 @@ except: cap_string = null_cap_string -class ColorStrings(object): +class ColorStrings: def __init__(self, cap_string): for i, c in enumerate(color_names): setattr(self, c, cap_string("setaf", i)) diff --git a/src/sim/power/ThermalModel.py b/src/sim/power/ThermalModel.py index a3d4a804cc..0d45a384c6 100644 --- a/src/sim/power/ThermalModel.py +++ b/src/sim/power/ThermalModel.py @@ -74,7 +74,7 @@ class ThermalCapacitor(SimObject): # Represents a fixed temperature node (ie. air) -class ThermalReference(SimObject, object): +class ThermalReference(SimObject): type = "ThermalReference" cxx_header = "sim/power/thermal_model.hh" cxx_class = "gem5::ThermalReference" diff --git a/src/systemc/python/systemc.py b/src/systemc/python/systemc.py index da189ffb29..f5a364a006 100644 --- a/src/systemc/python/systemc.py +++ b/src/systemc/python/systemc.py @@ -30,7 +30,7 @@ from _m5.systemc import sc_time from _m5.systemc import sc_main_result_code, sc_main_result_str -class ScMainResult(object): +class ScMainResult: def __init__(self, code, message): self.code = code self.message = message diff --git a/tests/gem5/cpu_tests/run.py b/tests/gem5/cpu_tests/run.py index fb528e5e8c..06790c7ea1 100644 --- a/tests/gem5/cpu_tests/run.py +++ b/tests/gem5/cpu_tests/run.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018 The Regents of the University of California # All Rights Reserved. # diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index 48e2a2540b..da2cf11be2 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -58,16 +58,14 @@ from typing import Optional, List class VariableFixture(Fixture): def __init__(self, value=None, name=None): - super(VariableFixture, self).__init__(name=name) + super().__init__(name=name) self.value = value class TempdirFixture(Fixture): def __init__(self): self.path = None - super(TempdirFixture, self).__init__( - name=constants.tempdir_fixture_name - ) + super().__init__(name=constants.tempdir_fixture_name) def setup(self, testitem): self.path = tempfile.mkdtemp(prefix="gem5out") @@ -113,7 +111,7 @@ class UniqueFixture(Fixture): if target in cls.fixtures: obj = cls.fixtures[target] else: - obj = super(UniqueFixture, cls).__new__(cls) + obj = super().__new__(cls) obj.lock = threading.Lock() obj.target = target cls.fixtures[target] = obj @@ -123,7 +121,7 @@ class UniqueFixture(Fixture): with self.lock: if hasattr(self, "_init_done"): return - super(UniqueFixture, self).__init__(self, **kwargs) + super().__init__(self, **kwargs) self._init(*args, **kwargs) self._init_done = True @@ -146,7 +144,7 @@ class SConsFixture(UniqueFixture): """ def __new__(cls, target): - obj = super(SConsFixture, cls).__new__(cls, target) + obj = super().__new__(cls, target) return obj def _setup(self, testitem): @@ -195,7 +193,7 @@ class Gem5Fixture(SConsFixture): if protocol: target_dir += "_" + protocol target = joinpath(target_dir, f"gem5.{variant}") - obj = super(Gem5Fixture, cls).__new__(cls, target) + obj = super().__new__(cls, target) return obj def _init(self, isa, variant, protocol=None): @@ -220,14 +218,14 @@ class Gem5Fixture(SConsFixture): class MakeFixture(Fixture): def __init__(self, directory, *args, **kwargs): name = f"make -C {directory}" - super(MakeFixture, self).__init__( + super().__init__( build_once=True, lazy_init=False, name=name, *args, **kwargs ) self.targets = [] self.directory = directory def setup(self): - super(MakeFixture, self).setup() + super().setup() targets = set(self.required_by) command = ["make", "-C", self.directory] command.extend([target.target for target in targets]) @@ -242,7 +240,7 @@ class MakeTarget(Fixture): scons we need to know what invocation to attach to. If none given, creates its own. """ - super(MakeTarget, self).__init__(name=target, *args, **kwargs) + super().__init__(name=target, *args, **kwargs) self.target = self.name if make_fixture is None: @@ -256,7 +254,7 @@ class MakeTarget(Fixture): self.require(self.make_fixture) def setup(self, testitem): - super(MakeTarget, self).setup() + super().setup() self.make_fixture.setup() return self @@ -266,7 +264,7 @@ class TestProgram(MakeTarget): make_dir = joinpath(config.bin_dir, program) make_fixture = MakeFixture(make_dir) target = joinpath("bin", isa, os, program) - super(TestProgram, self).__init__(target, make_fixture) + super().__init__(target, make_fixture) self.path = joinpath(make_dir, target) self.recompile = recompile @@ -286,7 +284,7 @@ class DownloadedProgram(UniqueFixture): def __new__(cls, url, path, filename, gzip_decompress=False): target = joinpath(path, filename) - return super(DownloadedProgram, cls).__new__(cls, target) + return super().__new__(cls, target) def _init(self, url, path, filename, gzip_decompress=False, **kwargs): """ diff --git a/tests/gem5/fs/linux/arm/configs/arm_generic.py b/tests/gem5/fs/linux/arm/configs/arm_generic.py index df118c7583..ad2ea58597 100644 --- a/tests/gem5/fs/linux/arm/configs/arm_generic.py +++ b/tests/gem5/fs/linux/arm/configs/arm_generic.py @@ -56,7 +56,7 @@ class ArmSESystemUniprocessor(BaseSESystemUniprocessor): """ def __init__(self, **kwargs): - super(ArmSESystemUniprocessor, self).__init__(**kwargs) + super().__init__(**kwargs) def create_caches_private(self, cpu): # The atomic SE configurations do not use caches @@ -67,7 +67,7 @@ class ArmSESystemUniprocessor(BaseSESystemUniprocessor): ) -class LinuxArmSystemBuilder(object): +class LinuxArmSystemBuilder: """Mix-in that implements create_system. This mix-in is intended as a convenient way of adding an diff --git a/tests/gem5/fs/linux/arm/configs/base_config.py b/tests/gem5/fs/linux/arm/configs/base_config.py index 22987d5eff..4bf374b01c 100644 --- a/tests/gem5/fs/linux/arm/configs/base_config.py +++ b/tests/gem5/fs/linux/arm/configs/base_config.py @@ -46,7 +46,7 @@ from ruby import Ruby _have_kvm_support = "BaseKvmCPU" in globals() -class BaseSystem(object, metaclass=ABCMeta): +class BaseSystem(metaclass=ABCMeta): """Base system builder. This class provides some basic functionality for creating an ARM @@ -254,10 +254,10 @@ class BaseSESystem(BaseSystem): """Basic syscall-emulation builder.""" def __init__(self, **kwargs): - super(BaseSESystem, self).__init__(**kwargs) + super().__init__(**kwargs) def init_system(self, system): - super(BaseSESystem, self).init_system(system) + super().init_system(system) def create_system(self): if issubclass(self.mem_class, m5.objects.DRAMInterface): @@ -291,7 +291,7 @@ class BaseSESystemUniprocessor(BaseSESystem): """ def __init__(self, **kwargs): - super(BaseSESystemUniprocessor, self).__init__(**kwargs) + super().__init__(**kwargs) def create_caches_private(self, cpu): # The atomic SE configurations do not use caches @@ -311,10 +311,10 @@ class BaseFSSystem(BaseSystem): """Basic full system builder.""" def __init__(self, **kwargs): - super(BaseFSSystem, self).__init__(**kwargs) + super().__init__(**kwargs) def init_system(self, system): - super(BaseFSSystem, self).init_system(system) + super().init_system(system) if self.use_ruby: # Connect the ruby io port to the PIO bus, @@ -356,7 +356,7 @@ class BaseFSSystemUniprocessor(BaseFSSystem): """ def __init__(self, **kwargs): - super(BaseFSSystemUniprocessor, self).__init__(**kwargs) + super().__init__(**kwargs) def create_caches_private(self, cpu): cpu.addTwoLevelCacheHierarchy( @@ -373,7 +373,7 @@ class BaseFSSwitcheroo(BaseFSSystem): """Uniprocessor system prepared for CPU switching""" def __init__(self, cpu_classes, **kwargs): - super(BaseFSSwitcheroo, self).__init__(**kwargs) + super().__init__(**kwargs) self.cpu_classes = tuple(cpu_classes) def create_cpus(self, cpu_clk_domain): diff --git a/tests/gem5/gem5_resources/configs/download_check.py b/tests/gem5/gem5_resources/configs/download_check.py index 7dc71908b1..4d5f9ac69c 100644 --- a/tests/gem5/gem5_resources/configs/download_check.py +++ b/tests/gem5/gem5_resources/configs/download_check.py @@ -91,7 +91,7 @@ if len(ids) == 0: # We log all the errors as they occur then dump them at the end. This means we # can be aware of all download errors in a single failure. -errors = str() +errors = "" for id in ids: if args.skip and id in args.skip: diff --git a/tests/gem5/m5threads_test_atomic/caches.py b/tests/gem5/m5threads_test_atomic/caches.py index fd87d0484d..29de48b065 100755 --- a/tests/gem5/m5threads_test_atomic/caches.py +++ b/tests/gem5/m5threads_test_atomic/caches.py @@ -51,7 +51,7 @@ class L1Cache(PrefetchCache): writeback_clean = True def __init__(self, options=None): - super(L1Cache, self).__init__(options) + super().__init__(options) pass def connectBus(self, bus): @@ -71,7 +71,7 @@ class L1ICache(L1Cache): size = "32kB" def __init__(self, opts=None): - super(L1ICache, self).__init__(opts) + super().__init__(opts) def connectCPU(self, cpu): """Connect this cache's port to a CPU icache port""" @@ -85,7 +85,7 @@ class L1DCache(L1Cache): size = "32kB" def __init__(self, opts=None): - super(L1DCache, self).__init__(opts) + super().__init__(opts) def connectCPU(self, cpu): """Connect this cache's port to a CPU dcache port""" @@ -106,7 +106,7 @@ class L2Cache(PrefetchCache): writeback_clean = True def __init__(self, opts=None): - super(L2Cache, self).__init__(opts) + super().__init__(opts) def connectCPUSideBus(self, bus): self.cpu_side = bus.mem_side_ports diff --git a/tests/gem5/verifier.py b/tests/gem5/verifier.py index 2cebf24d5f..eed9499848 100644 --- a/tests/gem5/verifier.py +++ b/tests/gem5/verifier.py @@ -49,7 +49,7 @@ from testlib.configuration import constants from testlib.helper import joinpath, diff_out_file -class Verifier(object): +class Verifier: def __init__(self, fixtures=tuple()): self.fixtures = fixtures @@ -67,7 +67,7 @@ class Verifier(object): class CheckH5StatsExist(Verifier): def __init__(self, stats_file="stats.h5"): - super(CheckH5StatsExist, self).__init__() + super().__init__() self.stats_file = stats_file def test(self, params): @@ -94,7 +94,7 @@ class MatchGoldStandard(Verifier): either which will be ignored in 'standard' and test output files when diffing. """ - super(MatchGoldStandard, self).__init__() + super().__init__() self.standard_filename = standard_filename self.test_filename = test_filename @@ -144,7 +144,7 @@ class DerivedGoldStandard(MatchGoldStandard): self._generic_instance_warning(kwargs) - super(DerivedGoldStandard, self).__init__( + super().__init__( standard_filename, test_filename=self._file, ignore_regex=ignore_regex, @@ -155,7 +155,7 @@ class DerivedGoldStandard(MatchGoldStandard): class MatchStdout(DerivedGoldStandard): _file = constants.gem5_simulation_stdout _default_ignore_regex = [ - re.compile("^\s+$"), # Remove blank lines. + re.compile(r"^\s+$"), # Remove blank lines. re.compile("^gem5 Simulator System"), re.compile("^gem5 is copyrighted software"), re.compile("^Redirecting (stdout|stderr) to"), @@ -168,8 +168,8 @@ class MatchStdout(DerivedGoldStandard): re.compile("^info: kernel located at:"), re.compile("^info: Standard input is not a terminal"), re.compile("^Couldn't unlink "), - re.compile("^Using GPU kernel code file\(s\) "), - re.compile("^.* not found locally\. Downloading"), + re.compile(r"^Using GPU kernel code file\(s\) "), + re.compile(r"^.* not found locally\. Downloading"), re.compile("^Finished downloading"), re.compile("^info: Using default config"), ] @@ -218,12 +218,12 @@ class MatchFileRegex(Verifier): """ def __init__(self, regex, filenames): - super(MatchFileRegex, self).__init__() + super().__init__() self.regex = _iterable_regex(regex) self.filenames = filenames def parse_file(self, fname): - with open(fname, "r") as file_: + with open(fname) as file_: for line in file_: for regex in self.regex: if re.match(regex, line): @@ -252,7 +252,7 @@ class MatchRegex(MatchFileRegex): filenames.append(constants.gem5_simulation_stdout) if match_stderr: filenames.append(constants.gem5_simulation_stderr) - super(MatchRegex, self).__init__(regex, filenames) + super().__init__(regex, filenames) class NoMatchRegex(MatchRegex): @@ -261,7 +261,7 @@ class NoMatchRegex(MatchRegex): """ def __init__(self, regex, match_stderr=True, match_stdout=True): - super(NoMatchRegex, self).__init__(regex, match_stderr, match_stdout) + super().__init__(regex, match_stderr, match_stdout) def test(self, params): fixtures = params.fixtures @@ -290,7 +290,7 @@ class MatchJSONStats(Verifier): :param test_name_in_m5out: True if the 'test_name' dir is to found in the `m5.options.outdir`. """ - super(MatchJSONStats, self).__init__() + super().__init__() self.truth_name = truth_name self.test_name = test_name self.test_name_in_outdir = test_name_in_outdir @@ -318,13 +318,13 @@ class MatchJSONStats(Verifier): test_util.fail(err) def test(self, params): - trusted_file = open(self.truth_name, "r") + trusted_file = open(self.truth_name) if self.test_name_in_outdir: fixtures = params.fixtures tempdir = fixtures[constants.tempdir_fixture_name].path - test_file = open(joinpath(tempdir, self.test_name), "r") + test_file = open(joinpath(tempdir, self.test_name)) else: - test_file = open(self.test_name, "r") + test_file = open(self.test_name) return self._compare_stats(trusted_file, test_file) diff --git a/tests/pyunit/pyunit_jsonserializable_check.py b/tests/pyunit/pyunit_jsonserializable_check.py index 8d5d2fa857..9979d3f9d6 100644 --- a/tests/pyunit/pyunit_jsonserializable_check.py +++ b/tests/pyunit/pyunit_jsonserializable_check.py @@ -54,18 +54,18 @@ class JsonSerializableTestSuite(unittest.TestCase): obj_json = obj.to_json() self.assertTrue("child_1" in obj_json) self.assertTrue("stat1" in obj_json["child_1"]) - self.assertEquals(2, obj_json["child_1"]["stat1"]) + self.assertEqual(2, obj_json["child_1"]["stat1"]) self.assertTrue("stat2" in obj_json["child_1"]) - self.assertEquals("3", obj_json["child_1"]["stat2"]) + self.assertEqual("3", obj_json["child_1"]["stat2"]) self.assertTrue("child_list" in obj_json) - self.assertEquals(2, len(obj_json["child_list"])) + self.assertEqual(2, len(obj_json["child_list"])) self.assertTrue("stat1" in obj_json["child_list"][0]) self.assertEqual("hello", obj_json["child_list"][0]["stat1"]) self.assertTrue("list_stat2" in obj_json["child_list"][1]) - self.assertEquals(6, len(obj_json["child_list"][1]["list_stat2"])) - self.assertEquals("1", obj_json["child_list"][1]["list_stat2"][0]) - self.assertEquals(2, obj_json["child_list"][1]["list_stat2"][1]) - self.assertEquals("3", obj_json["child_list"][1]["list_stat2"][2]) - self.assertEquals(4, obj_json["child_list"][1]["list_stat2"][3]) - self.assertEquals(5.2, obj_json["child_list"][1]["list_stat2"][4]) - self.assertEquals(None, obj_json["child_list"][1]["list_stat2"][5]) + self.assertEqual(6, len(obj_json["child_list"][1]["list_stat2"])) + self.assertEqual("1", obj_json["child_list"][1]["list_stat2"][0]) + self.assertEqual(2, obj_json["child_list"][1]["list_stat2"][1]) + self.assertEqual("3", obj_json["child_list"][1]["list_stat2"][2]) + self.assertEqual(4, obj_json["child_list"][1]["list_stat2"][3]) + self.assertEqual(5.2, obj_json["child_list"][1]["list_stat2"][4]) + self.assertEqual(None, obj_json["child_list"][1]["list_stat2"][5]) diff --git a/tests/pyunit/stdlib/pyunit_looppoint.py b/tests/pyunit/stdlib/pyunit_looppoint.py index 0b7acbd3f8..f838aa9ff5 100644 --- a/tests/pyunit/stdlib/pyunit_looppoint.py +++ b/tests/pyunit/stdlib/pyunit_looppoint.py @@ -47,21 +47,21 @@ class LooppointRegionPCTestSuite(unittest.TestCase): def test_construction_with_relative(self) -> None: region_pc = LooppointRegionPC(pc=444, globl=65, relative=454) - self.assertEquals(444, region_pc.get_pc()) - self.assertEquals(65, region_pc.get_global()) - self.assertEquals(454, region_pc.get_relative()) + self.assertEqual(444, region_pc.get_pc()) + self.assertEqual(65, region_pc.get_global()) + self.assertEqual(454, region_pc.get_relative()) def test_construction_without_relative(self) -> None: region_pc = LooppointRegionPC(pc=43454, globl=653434) - self.assertEquals(43454, region_pc.get_pc()) - self.assertEquals(653434, region_pc.get_global()) + self.assertEqual(43454, region_pc.get_pc()) + self.assertEqual(653434, region_pc.get_global()) self.assertIsNone(region_pc.get_relative()) def test_get_pc_count_pair(self) -> None: region_pc = LooppointRegionPC(pc=1, globl=2) expected = PcCountPair(1, 2) - self.assertEquals(expected, region_pc.get_pc_count_pair()) + self.assertEqual(expected, region_pc.get_pc_count_pair()) def update_relative_count(self) -> None: pass # Not really sure what to do here... @@ -70,23 +70,23 @@ class LooppointRegionPCTestSuite(unittest.TestCase): region_pc = LooppointRegionPC(pc=100, globl=200, relative=300) json_contents = region_pc.to_json() - self.assertEquals(3, len(json_contents)) + self.assertEqual(3, len(json_contents)) self.assertTrue("pc" in json_contents) - self.assertEquals(100, json_contents["pc"]) + self.assertEqual(100, json_contents["pc"]) self.assertTrue("global" in json_contents) - self.assertEquals(200, json_contents["global"]) + self.assertEqual(200, json_contents["global"]) self.assertTrue("relative" in json_contents) - self.assertEquals(300, json_contents["relative"]) + self.assertEqual(300, json_contents["relative"]) def test_to_json_without_relative(self) -> None: region_pc = LooppointRegionPC(pc=1111, globl=2222) json_contents = region_pc.to_json() - self.assertEquals(2, len(json_contents)) + self.assertEqual(2, len(json_contents)) self.assertTrue("pc" in json_contents) - self.assertEquals(1111, json_contents["pc"]) + self.assertEqual(1111, json_contents["pc"]) self.assertTrue("global" in json_contents) - self.assertEquals(2222, json_contents["global"]) + self.assertEqual(2222, json_contents["global"]) self.assertFalse("relative" in json_contents) @@ -98,8 +98,8 @@ class LooppointRegionWarmupTestSuite(unittest.TestCase): start=PcCountPair(123, 456), end=PcCountPair(789, 1011) ) - self.assertEquals(PcCountPair(123, 456), region_warmup.get_start()) - self.assertEquals(PcCountPair(789, 1011), region_warmup.get_end()) + self.assertEqual(PcCountPair(123, 456), region_warmup.get_start()) + self.assertEqual(PcCountPair(789, 1011), region_warmup.get_end()) def test_get_pc_count_pairs(self) -> None: region_warmup = LooppointRegionWarmup( @@ -107,9 +107,9 @@ class LooppointRegionWarmupTestSuite(unittest.TestCase): ) output = region_warmup.get_pc_count_pairs() - self.assertEquals(2, len(output)) - self.assertEquals(PcCountPair(1, 1), output[0]) - self.assertEquals(PcCountPair(2, 2), output[1]) + self.assertEqual(2, len(output)) + self.assertEqual(PcCountPair(1, 1), output[0]) + self.assertEqual(PcCountPair(2, 2), output[1]) def test_to_json(self) -> None: region_warmup = LooppointRegionWarmup( @@ -135,14 +135,14 @@ class LooppointSimulationTestSuite(unittest.TestCase): sim_start = sim.get_start() - self.assertEquals(444, sim_start.get_pc()) - self.assertEquals(65, sim_start.get_global()) - self.assertEquals(454, sim_start.get_relative()) + self.assertEqual(444, sim_start.get_pc()) + self.assertEqual(65, sim_start.get_global()) + self.assertEqual(454, sim_start.get_relative()) sim_end = sim.get_end() - self.assertEquals(555, sim_end.get_pc()) - self.assertEquals(699, sim_end.get_global()) + self.assertEqual(555, sim_end.get_pc()) + self.assertEqual(699, sim_end.get_global()) self.assertIsNone(sim_end.get_relative()) def test_get_pc_count_pairs(self) -> None: @@ -152,9 +152,9 @@ class LooppointSimulationTestSuite(unittest.TestCase): ) sim_pc_count_pairs = sim.get_pc_count_pairs() - self.assertEquals(2, len(sim_pc_count_pairs)) - self.assertEquals(PcCountPair(56, 45), sim_pc_count_pairs[0]) - self.assertEquals(PcCountPair(23, 12), sim_pc_count_pairs[1]) + self.assertEqual(2, len(sim_pc_count_pairs)) + self.assertEqual(PcCountPair(56, 45), sim_pc_count_pairs[0]) + self.assertEqual(PcCountPair(23, 12), sim_pc_count_pairs[1]) def test_get_json(self) -> None: sim = LooppointSimulation( @@ -193,7 +193,7 @@ class LooppointRegionTestSuite(unittest.TestCase): self.assertTrue( isinstance(region.get_simulation(), LooppointSimulation) ) - self.assertEquals(5.6, region.get_multiplier()) + self.assertEqual(5.6, region.get_multiplier()) self.assertIsNotNone(region.get_warmup()) self.assertTrue(isinstance(region.get_warmup(), LooppointRegionWarmup)) @@ -209,7 +209,7 @@ class LooppointRegionTestSuite(unittest.TestCase): self.assertTrue( isinstance(region.get_simulation(), LooppointSimulation) ) - self.assertEquals(5444.4, region.get_multiplier()) + self.assertEqual(5444.4, region.get_multiplier()) self.assertIsNone(region.get_warmup()) def test_get_pc_count_pairs_with_warmup(self): @@ -225,11 +225,11 @@ class LooppointRegionTestSuite(unittest.TestCase): ) pc_count_pairs = region.get_pc_count_pairs() - self.assertEquals(4, len(pc_count_pairs)) - self.assertEquals(PcCountPair(1, 2), pc_count_pairs[0]) - self.assertEquals(PcCountPair(6, 7), pc_count_pairs[1]) - self.assertEquals(PcCountPair(100, 200), pc_count_pairs[2]) - self.assertEquals(PcCountPair(101, 202), pc_count_pairs[3]) + self.assertEqual(4, len(pc_count_pairs)) + self.assertEqual(PcCountPair(1, 2), pc_count_pairs[0]) + self.assertEqual(PcCountPair(6, 7), pc_count_pairs[1]) + self.assertEqual(PcCountPair(100, 200), pc_count_pairs[2]) + self.assertEqual(PcCountPair(101, 202), pc_count_pairs[3]) def test_get_pc_count_pairs_without_warmup(self): region = LooppointRegion( @@ -242,9 +242,9 @@ class LooppointRegionTestSuite(unittest.TestCase): pc_count_pairs = region.get_pc_count_pairs() - self.assertEquals(2, len(pc_count_pairs)) - self.assertEquals(PcCountPair(56, 2345), pc_count_pairs[0]) - self.assertEquals(PcCountPair(645, 457), pc_count_pairs[1]) + self.assertEqual(2, len(pc_count_pairs)) + self.assertEqual(PcCountPair(56, 2345), pc_count_pairs[0]) + self.assertEqual(PcCountPair(645, 457), pc_count_pairs[1]) class LooppointTestSuite(unittest.TestCase): @@ -276,11 +276,11 @@ class LooppointTestSuite(unittest.TestCase): } ) - self.assertEquals(2, len(looppoint.get_regions())) + self.assertEqual(2, len(looppoint.get_regions())) self.assertTrue(1 in looppoint.get_regions()) - self.assertEquals(region1, looppoint.get_regions()[1]) + self.assertEqual(region1, looppoint.get_regions()[1]) self.assertTrue(3 in looppoint.get_regions()) - self.assertEquals(region2, looppoint.get_regions()[3]) + self.assertEqual(region2, looppoint.get_regions()[3]) def test_get_targets(self): region1 = LooppointRegion( @@ -309,13 +309,13 @@ class LooppointTestSuite(unittest.TestCase): ) targets = looppoint.get_targets() - self.assertEquals(6, len(targets)) - self.assertEquals(PcCountPair(56, 2345), targets[0]) - self.assertEquals(PcCountPair(645, 457), targets[1]) - self.assertEquals(PcCountPair(67, 254), targets[2]) - self.assertEquals(PcCountPair(64554, 7454), targets[3]) - self.assertEquals(PcCountPair(100, 200), targets[4]) - self.assertEquals(PcCountPair(101, 202), targets[5]) + self.assertEqual(6, len(targets)) + self.assertEqual(PcCountPair(56, 2345), targets[0]) + self.assertEqual(PcCountPair(645, 457), targets[1]) + self.assertEqual(PcCountPair(67, 254), targets[2]) + self.assertEqual(PcCountPair(64554, 7454), targets[3]) + self.assertEqual(PcCountPair(100, 200), targets[4]) + self.assertEqual(PcCountPair(101, 202), targets[5]) def test_get_region_start_id_map(self): region1 = LooppointRegion( @@ -345,15 +345,15 @@ class LooppointTestSuite(unittest.TestCase): region_start_id_map = looppoint.get_region_start_id_map() - self.assertEquals(2, len(region_start_id_map)) + self.assertEqual(2, len(region_start_id_map)) # The start of region1. self.assertTrue(PcCountPair(56, 2345) in region_start_id_map) - self.assertEquals(1, region_start_id_map[PcCountPair(56, 2345)]) + self.assertEqual(1, region_start_id_map[PcCountPair(56, 2345)]) # The start of region2. Since this has a warmup, it's the warmup. self.assertTrue(PcCountPair(100, 200) in region_start_id_map) - self.assertEquals(3, region_start_id_map[PcCountPair(100, 200)]) + self.assertEqual(3, region_start_id_map[PcCountPair(100, 200)]) def test_to_json(self) -> None: region1 = LooppointRegion( @@ -440,60 +440,60 @@ class LooppointCSVLoaderTestSuite(unittest.TestCase): ) regions = looppoint.get_regions() - self.assertEquals(3, len(regions)) + self.assertEqual(3, len(regions)) region1 = regions[1] - self.assertEquals(4.0, region1.get_multiplier()) + self.assertEqual(4.0, region1.get_multiplier()) region1start = region1.get_simulation().get_start() - self.assertEquals(0x4069D0, region1start.get_pc()) - self.assertEquals(211076617, region1start.get_global()) + self.assertEqual(0x4069D0, region1start.get_pc()) + self.assertEqual(211076617, region1start.get_global()) self.assertIsNone(region1start.get_relative()) region1end = region1.get_simulation().get_end() - self.assertEquals(0x4069D0, region1end.get_pc()) - self.assertEquals(219060252, region1end.get_global()) + self.assertEqual(0x4069D0, region1end.get_pc()) + self.assertEqual(219060252, region1end.get_global()) self.assertIsNotNone(region1end.get_relative()) - self.assertEquals(1060676, region1end.get_relative()) + self.assertEqual(1060676, region1end.get_relative()) self.assertIsNone(region1.get_warmup()) region2 = regions[2] - self.assertEquals(5.001, region2.get_multiplier()) + self.assertEqual(5.001, region2.get_multiplier()) region2start = region2.get_simulation().get_start() - self.assertEquals(0x4069D0, region2start.get_pc()) - self.assertEquals(407294228, region2start.get_global()) + self.assertEqual(0x4069D0, region2start.get_pc()) + self.assertEqual(407294228, region2start.get_global()) self.assertIsNone(region2start.get_relative()) region2end = region2.get_simulation().get_end() - self.assertEquals(0x4069D0, region2end.get_pc()) - self.assertEquals(415282447, region2end.get_global()) + self.assertEqual(0x4069D0, region2end.get_pc()) + self.assertEqual(415282447, region2end.get_global()) self.assertIsNotNone(region2end.get_relative()) - self.assertEquals(1035231, region2end.get_relative()) + self.assertEqual(1035231, region2end.get_relative()) region2warmup = region2.get_warmup() self.assertIsNotNone(region2warmup) - self.assertEquals( + self.assertEqual( PcCountPair(0x406880, 48111518), region2warmup.get_start() ) - self.assertEquals( + self.assertEqual( PcCountPair(0x4069D0, 407294228), region2warmup.get_end() ) region3 = regions[3] - self.assertEquals(4.0, region3.get_multiplier()) + self.assertEqual(4.0, region3.get_multiplier()) region3start = region3.get_simulation().get_start() - self.assertEquals(0x4069D0, region3start.get_pc()) - self.assertEquals(187978221, region3start.get_global()) + self.assertEqual(0x4069D0, region3start.get_pc()) + self.assertEqual(187978221, region3start.get_global()) self.assertIsNone(region3start.get_relative()) region3end = region3.get_simulation().get_end() - self.assertEquals(0x406880, region3end.get_pc()) - self.assertEquals(23520614, region3end.get_global()) + self.assertEqual(0x406880, region3end.get_pc()) + self.assertEqual(23520614, region3end.get_global()) self.assertIsNotNone(region3end.get_relative()) - self.assertEquals(144352, region3end.get_relative()) + self.assertEqual(144352, region3end.get_relative()) self.assertIsNone(region3.get_warmup()) @@ -508,22 +508,22 @@ class LooppointCSVLoaderTestSuite(unittest.TestCase): ) regions = looppoint.get_regions() - self.assertEquals(1, len(regions)) + self.assertEqual(1, len(regions)) self.assertTrue(1 in regions) region1 = regions[1] - self.assertEquals(4.0, region1.get_multiplier()) + self.assertEqual(4.0, region1.get_multiplier()) region1start = region1.get_simulation().get_start() - self.assertEquals(0x4069D0, region1start.get_pc()) - self.assertEquals(211076617, region1start.get_global()) + self.assertEqual(0x4069D0, region1start.get_pc()) + self.assertEqual(211076617, region1start.get_global()) self.assertIsNone(region1start.get_relative()) region1end = region1.get_simulation().get_end() - self.assertEquals(0x4069D0, region1end.get_pc()) - self.assertEquals(219060252, region1end.get_global()) + self.assertEqual(0x4069D0, region1end.get_pc()) + self.assertEqual(219060252, region1end.get_global()) self.assertIsNotNone(region1end.get_relative()) - self.assertEquals(1060676, region1end.get_relative()) + self.assertEqual(1060676, region1end.get_relative()) self.assertIsNone(region1.get_warmup()) @@ -541,31 +541,31 @@ class LooppointJsonLoaderTestSuite(unittest.TestCase): region_id="1", ) - self.assertEquals(1, len(looppoint.get_regions())) + self.assertEqual(1, len(looppoint.get_regions())) self.assertTrue("1" in looppoint.get_regions()) region = looppoint.get_regions()["1"] - self.assertEquals(4.0, region.get_multiplier()) + self.assertEqual(4.0, region.get_multiplier()) region_start = region.get_simulation().get_start() - self.assertEquals(4221392, region_start.get_pc()) - self.assertEquals(211076617, region_start.get_global()) + self.assertEqual(4221392, region_start.get_pc()) + self.assertEqual(211076617, region_start.get_global()) self.assertIsNotNone(region_start.get_relative()) - self.assertEquals(15326617, region_start.get_relative()) + self.assertEqual(15326617, region_start.get_relative()) region_end = region.get_simulation().get_end() - self.assertEquals(4221392, region_end.get_pc()) - self.assertEquals(219060252, region_end.get_global()) + self.assertEqual(4221392, region_end.get_pc()) + self.assertEqual(219060252, region_end.get_global()) self.assertIsNotNone(region_end.get_relative()) - self.assertEquals(23310252, region_end.get_relative()) + self.assertEqual(23310252, region_end.get_relative()) region_warmup = region.get_warmup() self.assertIsNotNone(region_warmup) - self.assertEquals( + self.assertEqual( PcCountPair(4221056, 23520614), region_warmup.get_start() ) - self.assertEquals( + self.assertEqual( PcCountPair(4221392, 211076617), region_warmup.get_end() ) @@ -579,20 +579,20 @@ class LooppointJsonLoaderTestSuite(unittest.TestCase): region_id="2", ) - self.assertEquals(1, len(looppoint.get_regions())) + self.assertEqual(1, len(looppoint.get_regions())) self.assertTrue("2" in looppoint.get_regions()) region = looppoint.get_regions()["2"] - self.assertEquals(5.001, region.get_multiplier()) + self.assertEqual(5.001, region.get_multiplier()) region_start = region.get_simulation().get_start() - self.assertEquals(4221392, region_start.get_pc()) - self.assertEquals(407294228, region_start.get_global()) + self.assertEqual(4221392, region_start.get_pc()) + self.assertEqual(407294228, region_start.get_global()) self.assertIsNone(region_start.get_relative()) region_end = region.get_simulation().get_end() - self.assertEquals(4221392, region_end.get_pc()) - self.assertEquals(415282447, region_end.get_global()) + self.assertEqual(4221392, region_end.get_pc()) + self.assertEqual(415282447, region_end.get_global()) self.assertIsNone(region_end.get_relative()) region_warmup = region.get_warmup() diff --git a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py index 66b934a16f..bc0d00c0f4 100644 --- a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py @@ -67,12 +67,12 @@ mock_config_combined["sources"]["baba"] = mock_config_json["sources"]["baba"] mock_json = {} -with open(Path(__file__).parent / "refs/mongo-mock.json", "r") as f: +with open(Path(__file__).parent / "refs/mongo-mock.json") as f: mock_json = json.load(f) duplicate_mock_json = {} -with open(Path(__file__).parent / "refs/mongo-dup-mock.json", "r") as f: +with open(Path(__file__).parent / "refs/mongo-dup-mock.json") as f: duplicate_mock_json = json.load(f) diff --git a/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py b/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py index 88db3d4967..82fc775975 100644 --- a/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py @@ -148,16 +148,16 @@ class JSONClientTestSuite(unittest.TestCase): "create_temp_resources_json" has been loaded correctly into a Python dictionary. """ - self.assertEquals(4, len(json)) + self.assertEqual(4, len(json)) self.assertTrue("id" in json[0]) - self.assertEquals("this-is-a-test-resource", json[0]["id"]) - self.assertEquals("binary", json[0]["category"]) + self.assertEqual("this-is-a-test-resource", json[0]["id"]) + self.assertEqual("binary", json[0]["category"]) self.assertTrue("id" in json[1]) - self.assertEquals("this-is-a-test-resource", json[1]["id"]) + self.assertEqual("this-is-a-test-resource", json[1]["id"]) self.assertTrue("id" in json[2]) - self.assertEquals("test-version", json[2]["id"]) + self.assertEqual("test-version", json[2]["id"]) self.assertTrue("id" in json[3]) - self.assertEquals("test-version", json[3]["id"]) + self.assertEqual("test-version", json[3]["id"]) def test_get_resources_json_at_path(self) -> None: # Tests JSONClient.get_resources_json() diff --git a/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py b/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py index 826d2ae2fa..7d6e1f42de 100644 --- a/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py @@ -46,7 +46,7 @@ class MD5FileTestSuite(unittest.TestCase): md5 = md5_file(Path(file.name)) os.remove(file.name) - self.assertEquals("b113b29fce251f2023066c3fda2ec9dd", md5) + self.assertEqual("b113b29fce251f2023066c3fda2ec9dd", md5) def test_identicalFilesIdenticalMd5(self) -> None: # This test ensures that two files with exactly the same contents have @@ -68,7 +68,7 @@ class MD5FileTestSuite(unittest.TestCase): os.remove(file.name) - self.assertEquals(first_file_md5, second_file_md5) + self.assertEqual(first_file_md5, second_file_md5) class MD5DirTestSuite(unittest.TestCase): @@ -98,7 +98,7 @@ class MD5DirTestSuite(unittest.TestCase): md5 = md5_dir(dir) shutil.rmtree(dir) - self.assertEquals("ad5ac785de44c9fc2fe2798cab2d7b1a", md5) + self.assertEqual("ad5ac785de44c9fc2fe2798cab2d7b1a", md5) def test_identicalDirsIdenticalMd5(self) -> None: # This test ensures that two directories with exactly the same contents @@ -112,4 +112,4 @@ class MD5DirTestSuite(unittest.TestCase): second_md5 = md5_dir(dir2) shutil.rmtree(dir2) - self.assertEquals(first_md5, second_md5) + self.assertEqual(first_md5, second_md5) diff --git a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py index 8c08cd88d5..bab91f2fb7 100644 --- a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py @@ -78,13 +78,11 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_directory=self.get_resource_dir(), gem5_version="develop", ) - self.assertEquals("1.7.0", resource.get_resource_version()) + self.assertEqual("1.7.0", resource.get_resource_version()) self.assertIsInstance(resource, BinaryResource) - self.assertEquals( - "test description v1.7.0", resource.get_description() - ) - self.assertEquals("src/test-source", resource.get_source()) - self.assertEquals(ISA.ARM, resource.get_architecture()) + self.assertEqual("test description v1.7.0", resource.get_description()) + self.assertEqual("src/test-source", resource.get_source()) + self.assertEqual(ISA.ARM, resource.get_architecture()) def test_obtain_resources_with_version_compatible(self): resource = obtain_resource( @@ -93,13 +91,13 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_version="1.5.0", gem5_version="develop", ) - self.assertEquals("1.5.0", resource.get_resource_version()) + self.assertEqual("1.5.0", resource.get_resource_version()) self.assertIsInstance(resource, BinaryResource) - self.assertEquals( + self.assertEqual( "test description for 1.5.0", resource.get_description() ) - self.assertEquals("src/test-source", resource.get_source()) - self.assertEquals(ISA.ARM, resource.get_architecture()) + self.assertEqual("src/test-source", resource.get_source()) + self.assertEqual(ISA.ARM, resource.get_architecture()) def test_obtain_resources_with_version_incompatible(self): resource = None @@ -117,13 +115,13 @@ class TestObtainResourcesCheck(unittest.TestCase): resource_version="1.5.0", gem5_version="develop", ) - self.assertEquals("1.5.0", resource.get_resource_version()) + self.assertEqual("1.5.0", resource.get_resource_version()) self.assertIsInstance(resource, BinaryResource) - self.assertEquals( + self.assertEqual( "test description for 1.5.0", resource.get_description() ) - self.assertEquals("src/test-source", resource.get_source()) - self.assertEquals(ISA.ARM, resource.get_architecture()) + self.assertEqual("src/test-source", resource.get_source()) + self.assertEqual(ISA.ARM, resource.get_architecture()) def test_obtain_resources_no_version_invalid_id(self): with self.assertRaises(Exception) as context: diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py index 93b83019b9..1bf02fd691 100644 --- a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py +++ b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py @@ -86,11 +86,11 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, BinaryResource) - self.assertEquals( + self.assertEqual( "binary-example documentation.", resource.get_description() ) - self.assertEquals("src/simple", resource.get_source()) - self.assertEquals(ISA.ARM, resource.get_architecture()) + self.assertEqual("src/simple", resource.get_source()) + self.assertEqual(ISA.ARM, resource.get_architecture()) def test_kernel_resource(self) -> None: """Tests the loading of a KernelResource.""" @@ -102,11 +102,11 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, KernelResource) - self.assertEquals( + self.assertEqual( "kernel-example documentation.", resource.get_description() ) - self.assertEquals("src/linux-kernel", resource.get_source()) - self.assertEquals(ISA.RISCV, resource.get_architecture()) + self.assertEqual("src/linux-kernel", resource.get_source()) + self.assertEqual(ISA.RISCV, resource.get_architecture()) def test_bootloader_resource(self) -> None: """Tests the loading of a BootloaderResource.""" @@ -118,7 +118,7 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, BootloaderResource) - self.assertEquals( + self.assertEqual( "bootloader documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -134,11 +134,11 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, DiskImageResource) - self.assertEquals( + self.assertEqual( "disk-image documentation.", resource.get_description() ) - self.assertEquals("src/x86-ubuntu", resource.get_source()) - self.assertEquals("1", resource.get_root_partition()) + self.assertEqual("src/x86-ubuntu", resource.get_source()) + self.assertEqual("1", resource.get_root_partition()) def test_checkpoint_resource(self) -> None: """Tests the loading of a CheckpointResource.""" @@ -150,7 +150,7 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, CheckpointResource) - self.assertEquals( + self.assertEqual( "checkpoint-example documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -178,14 +178,14 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, SimpointDirectoryResource) - self.assertEquals( + self.assertEqual( "simpoint directory documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) - self.assertEquals(1000000, resource.get_simpoint_interval()) - self.assertEquals(1000000, resource.get_warmup_interval()) - self.assertEquals( + self.assertEqual(1000000, resource.get_simpoint_interval()) + self.assertEqual(1000000, resource.get_warmup_interval()) + self.assertEqual( Path( Path(self.get_resource_dir()) / "simpoint-directory-example" @@ -193,7 +193,7 @@ class ResourceSpecializationSuite(unittest.TestCase): ), resource.get_simpoint_file(), ) - self.assertEquals( + self.assertEqual( Path( Path(self.get_resource_dir()) / "simpoint-directory-example" @@ -201,7 +201,7 @@ class ResourceSpecializationSuite(unittest.TestCase): ), resource.get_weight_file(), ) - self.assertEquals("Example Workload", resource.get_workload_name()) + self.assertEqual("Example Workload", resource.get_workload_name()) def test_simpoint_resource(self) -> None: """Tests the loading of a Simpoint resource.""" @@ -213,16 +213,14 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, SimpointResource) - self.assertEquals( - "simpoint documentation.", resource.get_description() - ) + self.assertEqual("simpoint documentation.", resource.get_description()) self.assertIsNone(resource.get_source()) self.assertIsNone(resource.get_local_path()) - self.assertEquals(1000000, resource.get_simpoint_interval()) - self.assertEquals(23445, resource.get_warmup_interval()) - self.assertEquals([2, 3, 4, 15], resource.get_simpoint_list()) - self.assertEquals([0.1, 0.2, 0.4, 0.3], resource.get_weight_list()) + self.assertEqual(1000000, resource.get_simpoint_interval()) + self.assertEqual(23445, resource.get_warmup_interval()) + self.assertEqual([2, 3, 4, 15], resource.get_simpoint_list()) + self.assertEqual([0.1, 0.2, 0.4, 0.3], resource.get_weight_list()) def test_file_resource(self) -> None: """Tests the loading of a FileResource.""" @@ -247,7 +245,7 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, DirectoryResource) - self.assertEquals( + self.assertEqual( "directory-example documentation.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -268,7 +266,7 @@ class ResourceSpecializationSuite(unittest.TestCase): # LooppointCsvLoader. self.assertIsInstance(resource, LooppointCsvLoader) - self.assertEquals( + self.assertEqual( "A looppoint pinpoints csv file.", resource.get_description() ) self.assertIsNone(resource.get_source()) @@ -287,10 +285,10 @@ class ResourceSpecializationSuite(unittest.TestCase): self.assertIsInstance(resource, LooppointJsonResource) self.assertIsInstance(resource, LooppointJsonLoader) - self.assertEquals(1, len(resource.get_regions())) + self.assertEqual(1, len(resource.get_regions())) self.assertTrue("1" in resource.get_regions()) - self.assertEquals( + self.assertEqual( "A looppoint json file resource.", resource.get_description() ) self.assertIsNone(resource.get_source()) diff --git a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py index 480ba9f024..419dbaed9f 100644 --- a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py @@ -150,7 +150,7 @@ class SuiteResourceTestSuite(unittest.TestCase): """ Tests the `list_input_groups` function. """ - expected_input_groups = set(["testtag1", "testtag2", "testtag3"]) + expected_input_groups = {"testtag1", "testtag2", "testtag3"} self.assertEqual(self.suite.get_input_groups(), expected_input_groups) @patch( diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index a9fa5e28e2..c38fc8e3b8 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -84,16 +84,16 @@ class CustomWorkloadTestSuite(unittest.TestCase): parameters = self.custom_workload.get_parameters() self.assertTrue(isinstance(parameters, Dict)) - self.assertEquals(2, len(parameters)) + self.assertEqual(2, len(parameters)) self.assertTrue("binary" in parameters) self.assertTrue(isinstance(parameters["binary"], BinaryResource)) self.assertTrue("arguments" in parameters) self.assertTrue(isinstance(parameters["arguments"], list)) - self.assertEquals(2, len(parameters["arguments"])) - self.assertEquals("hello", parameters["arguments"][0]) - self.assertEquals(6, parameters["arguments"][1]) + self.assertEqual(2, len(parameters["arguments"])) + self.assertEqual("hello", parameters["arguments"][0]) + self.assertEqual(6, parameters["arguments"][1]) def test_add_parameters(self) -> None: # Tests `CustomWorkload.set_parameter` for the case where we add a new @@ -102,7 +102,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): self.custom_workload.set_parameter("test_param", 10) self.assertTrue("test_param" in self.custom_workload.get_parameters()) - self.assertEquals( + self.assertEqual( 10, self.custom_workload.get_parameters()["test_param"] ) @@ -117,7 +117,7 @@ class CustomWorkloadTestSuite(unittest.TestCase): self.custom_workload.set_parameter("binary", "test") self.assertTrue("binary" in self.custom_workload.get_parameters()) - self.assertEquals( + self.assertEqual( "test", self.custom_workload.get_parameters()["binary"] ) @@ -141,7 +141,7 @@ class WorkloadTestSuite(unittest.TestCase): def test_get_function_str(self) -> None: # Tests `Resource.get_function_str` - self.assertEquals( + self.assertEqual( "set_kernel_disk_workload", self.workload.get_function_str() ) @@ -173,7 +173,7 @@ class WorkloadTestSuite(unittest.TestCase): self.workload.set_parameter("test_param", 10) self.assertTrue("test_param" in self.workload.get_parameters()) - self.assertEquals(10, self.workload.get_parameters()["test_param"]) + self.assertEqual(10, self.workload.get_parameters()["test_param"]) # Cleanup del self.workload.get_parameters()["test_param"] @@ -186,7 +186,7 @@ class WorkloadTestSuite(unittest.TestCase): self.workload.set_parameter("readfile_contents", "test") self.assertTrue("readfile_contents" in self.workload.get_parameters()) - self.assertEquals( + self.assertEqual( "test", self.workload.get_parameters()["readfile_contents"] ) diff --git a/tests/run.py b/tests/run.py index d72a6ceba4..f95418523e 100644 --- a/tests/run.py +++ b/tests/run.py @@ -189,7 +189,7 @@ def run_config(config, argv=None): src_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../")) abs_path = joinpath(src_root, config) - code = compile(open(abs_path, "r").read(), abs_path, "exec") + code = compile(open(abs_path).read(), abs_path, "exec") scope = {"__file__": config, "__name__": "__m5_main__"} # Set the working directory in case we are executing from diff --git a/util/checkpoint-tester.py b/util/checkpoint-tester.py index 1e4024b858..9c638dd736 100755 --- a/util/checkpoint-tester.py +++ b/util/checkpoint-tester.py @@ -102,7 +102,7 @@ print("===> Running initial simulation.") subprocess.call([m5_binary] + ["-red", cptdir] + args + checkpoint_args) dirs = os.listdir(cptdir) -expr = re.compile("cpt\.([0-9]*)") +expr = re.compile(r"cpt\.([0-9]*)") cpts = [] for dir in dirs: match = expr.match(dir) diff --git a/util/cpt_upgrader.py b/util/cpt_upgrader.py index a852294fbc..44928bcd2d 100755 --- a/util/cpt_upgrader.py +++ b/util/cpt_upgrader.py @@ -193,7 +193,7 @@ def process_file(path, **kwargs): if not osp.isfile(path): import errno - raise IOError(errno.ENOENT, "No such file", path) + raise OSError(errno.ENOENT, "No such file", path) verboseprint(f"Processing file {path}....") @@ -208,7 +208,7 @@ def process_file(path, **kwargs): cpt.optionxform = str # Read the current data - cpt_file = open(path, "r") + cpt_file = open(path) cpt.read_file(cpt_file) cpt_file.close() @@ -220,7 +220,7 @@ def process_file(path, **kwargs): # Legacy linear checkpoint version # convert to list of tags before proceeding - tags = set([]) + tags = set() for i in range(2, cpt_ver + 1): tags.add(Upgrader.legacy[i].tag) verboseprint("performed legacy version -> tags conversion") @@ -253,7 +253,7 @@ def process_file(path, **kwargs): # downgraders are present, respecting dependences to_apply = (Upgrader.tag_set - tags) | (Upgrader.untag_set & tags) while to_apply: - ready = set([t for t in to_apply if Upgrader.get(t).ready(tags)]) + ready = {t for t in to_apply if Upgrader.get(t).ready(tags)} if not ready: print("could not apply these upgrades:", " ".join(to_apply)) print("update dependences impossible to resolve; aborting") diff --git a/util/cpt_upgraders/arm-ccregs.py b/util/cpt_upgraders/arm-ccregs.py index fb17fd5886..abfbe2d5b3 100644 --- a/util/cpt_upgraders/arm-ccregs.py +++ b/util/cpt_upgraders/arm-ccregs.py @@ -5,7 +5,7 @@ def upgrader(cpt): for sec in cpt.sections(): import re - re_cpu_match = re.match("^(.*sys.*\.cpu[^.]*)\.xc\.(.+)$", sec) + re_cpu_match = re.match(r"^(.*sys.*\.cpu[^.]*)\.xc\.(.+)$", sec) # Search for all the execution contexts if not re_cpu_match: continue diff --git a/util/cpt_upgraders/arm-contextidr-el2.py b/util/cpt_upgraders/arm-contextidr-el2.py index 891fec5e0d..d016c1a224 100644 --- a/util/cpt_upgraders/arm-contextidr-el2.py +++ b/util/cpt_upgraders/arm-contextidr-el2.py @@ -5,7 +5,7 @@ def upgrader(cpt): import re # Search for all ISA sections - if re.search(".*sys.*\.cpu.*\.isa$", sec): + if re.search(r".*sys.*\.cpu.*\.isa$", sec): miscRegs = cpt.get(sec, "miscRegs").split() # CONTEXTIDR_EL2 defaults to 0b11111100000000000001 miscRegs[599:599] = [0xFC001] diff --git a/util/cpt_upgraders/arm-gem5-gic-ext.py b/util/cpt_upgraders/arm-gem5-gic-ext.py index fea852ff13..4e543a24e0 100644 --- a/util/cpt_upgraders/arm-gem5-gic-ext.py +++ b/util/cpt_upgraders/arm-gem5-gic-ext.py @@ -61,7 +61,7 @@ def upgrader(cpt): new_per_cpu_regs = (("cpuSgiPendingExt", "0"), ("cpuSgiActiveExt", "0")) for sec in cpt.sections(): - if re.search(".*\.gic$", sec): + if re.search(r".*\.gic$", sec): for reg, default in per_cpu_regs: value = cpt.get(sec, reg).split(" ") assert ( diff --git a/util/cpt_upgraders/arm-gicv2-banked-regs.py b/util/cpt_upgraders/arm-gicv2-banked-regs.py index 3e8fa3c60c..6438a178d4 100644 --- a/util/cpt_upgraders/arm-gicv2-banked-regs.py +++ b/util/cpt_upgraders/arm-gicv2-banked-regs.py @@ -40,7 +40,7 @@ def upgrader(cpt): for sec in cpt.sections(): import re - if not re.search("\.gic$", sec): + if not re.search(r"\.gic$", sec): continue cpuEnabled = cpt.get(sec, "cpuEnabled").split() diff --git a/util/cpt_upgraders/arm-hdlcd-upgrade.py b/util/cpt_upgraders/arm-hdlcd-upgrade.py index 96d6368718..87431e8b9f 100644 --- a/util/cpt_upgraders/arm-hdlcd-upgrade.py +++ b/util/cpt_upgraders/arm-hdlcd-upgrade.py @@ -69,7 +69,7 @@ def upgrader(cpt): } for sec in cpt.sections(): - if re.search(".*\.hdlcd$", sec): + if re.search(r".*\.hdlcd$", sec): options = {} for new, old in list(option_names.items()): options[new] = cpt.get(sec, old) diff --git a/util/cpt_upgraders/arm-miscreg-teehbr.py b/util/cpt_upgraders/arm-miscreg-teehbr.py index d6e81e0da1..656757d036 100644 --- a/util/cpt_upgraders/arm-miscreg-teehbr.py +++ b/util/cpt_upgraders/arm-miscreg-teehbr.py @@ -5,7 +5,7 @@ def upgrader(cpt): import re # Search for all ISA sections - if re.search(".*sys.*\.cpu.*\.isa$", sec): + if re.search(r".*sys.*\.cpu.*\.isa$", sec): mr = cpt.get(sec, "miscRegs").split() if len(mr) == 161: print("MISCREG_TEEHBR already seems to be inserted.") diff --git a/util/cpt_upgraders/arm-sve.py b/util/cpt_upgraders/arm-sve.py index ac93b9f24a..c484bae057 100644 --- a/util/cpt_upgraders/arm-sve.py +++ b/util/cpt_upgraders/arm-sve.py @@ -12,7 +12,7 @@ def upgrader(cpt): import re # Search for all ISA sections - if re.search(".*sys.*\.cpu.*\.isa$", sec): + if re.search(r".*sys.*\.cpu.*\.isa$", sec): # haveSVE = false cpt.set(sec, "haveSVE", "false") diff --git a/util/cpt_upgraders/arm-sysreg-mapping-ns.py b/util/cpt_upgraders/arm-sysreg-mapping-ns.py index 5551b301da..c0a76549a0 100644 --- a/util/cpt_upgraders/arm-sysreg-mapping-ns.py +++ b/util/cpt_upgraders/arm-sysreg-mapping-ns.py @@ -41,7 +41,7 @@ def upgrader(cpt): import re # Search for all ISA sections - if re.search(".*sys.*\.cpu.*\.isa\d*$", sec): + if re.search(r".*sys.*\.cpu.*\.isa\d*$", sec): mr = cpt.get(sec, "miscRegs").split() if int(mr[0]) & 16 == 0: # CPSR reg width; 0 for AArch64 mr[112] = mr[111] # ACTLR_NS = ACTLR diff --git a/util/cpt_upgraders/armv8.py b/util/cpt_upgraders/armv8.py index 6679beb88a..e5453770fa 100644 --- a/util/cpt_upgraders/armv8.py +++ b/util/cpt_upgraders/armv8.py @@ -12,7 +12,7 @@ def upgrader(cpt): ) # Find the CPU context's and upgrade their registers for sec in cpt.sections(): - re_xc_match = re.match("^.*?sys.*?\.cpu(\d+)*\.xc\.*", sec) + re_xc_match = re.match(r"^.*?sys.*?\.cpu(\d+)*\.xc\.*", sec) if not re_xc_match: continue @@ -38,7 +38,7 @@ def upgrader(cpt): # Update the cpu interrupt field for sec in cpt.sections(): - re_int_match = re.match("^.*?sys.*?\.cpu(\d+)*$", sec) + re_int_match = re.match(r"^.*?sys.*?\.cpu(\d+)*$", sec) if not re_int_match: continue @@ -49,7 +49,7 @@ def upgrader(cpt): # Update the per cpu interrupt structure for sec in cpt.sections(): - re_int_match = re.match("^.*?sys.*?\.cpu(\d+)*\.interrupts$", sec) + re_int_match = re.match(r"^.*?sys.*?\.cpu(\d+)*\.interrupts$", sec) if not re_int_match: continue @@ -60,7 +60,7 @@ def upgrader(cpt): # Update the misc regs and add in new isa specific fields for sec in cpt.sections(): - re_isa_match = re.match("^.*?sys.*?\.cpu(\d+)*\.isa$", sec) + re_isa_match = re.match(r"^.*?sys.*?\.cpu(\d+)*\.isa$", sec) if not re_isa_match: continue @@ -254,7 +254,7 @@ def upgrader(cpt): cpu_prefix = {} # Add in state for ITB/DTB for sec in cpt.sections(): - re_tlb_match = re.match("(^.*?sys.*?\.cpu(\d+)*)\.(dtb|itb)$", sec) + re_tlb_match = re.match(r"(^.*?sys.*?\.cpu(\d+)*)\.(dtb|itb)$", sec) if not re_tlb_match: continue @@ -271,7 +271,7 @@ def upgrader(cpt): # Add in extra state for the new TLB Entries for sec in cpt.sections(): re_tlbentry_match = re.match( - "(^.*?sys.*?\.cpu(\d+)*)\.(dtb|itb).TlbEntry\d+$", sec + r"(^.*?sys.*?\.cpu(\d+)*)\.(dtb|itb).TlbEntry\d+$", sec ) if not re_tlbentry_match: continue diff --git a/util/cpt_upgraders/isa-is-simobject.py b/util/cpt_upgraders/isa-is-simobject.py index 6305eeba5c..fa6734cbfa 100644 --- a/util/cpt_upgraders/isa-is-simobject.py +++ b/util/cpt_upgraders/isa-is-simobject.py @@ -60,7 +60,7 @@ def upgrader(cpt): for sec in cpt.sections(): import re - re_cpu_match = re.match("^(.*sys.*\.cpu[^.]*)\.xc\.(.+)$", sec) + re_cpu_match = re.match(r"^(.*sys.*\.cpu[^.]*)\.xc\.(.+)$", sec) # Search for all the execution contexts if not re_cpu_match: continue diff --git a/util/cpt_upgraders/memory-per-range.py b/util/cpt_upgraders/memory-per-range.py index d75a4acf8c..24fa0b592e 100644 --- a/util/cpt_upgraders/memory-per-range.py +++ b/util/cpt_upgraders/memory-per-range.py @@ -6,7 +6,7 @@ def upgrader(cpt): import re # Search for a physical memory - if re.search(".*sys.*\.physmem$", sec): + if re.search(r".*sys.*\.physmem$", sec): # Add the number of stores attribute to the global physmem cpt.set(sec, "nbr_of_stores", "1") @@ -24,7 +24,7 @@ def upgrader(cpt): cpt.set(section_name, "store_id", "0") cpt.set(section_name, "range_size", mem_size) cpt.set(section_name, "filename", mem_filename) - elif re.search(".*sys.*\.\w*mem$", sec): + elif re.search(r".*sys.*\.\w*mem$", sec): # Due to the lack of information about a start address, # this migration only works if there is a single memory in # the system, thus starting at 0 diff --git a/util/cpt_upgraders/remove-arm-cpsr-mode-miscreg.py b/util/cpt_upgraders/remove-arm-cpsr-mode-miscreg.py index 8eba866f1a..66b6cd8bd7 100644 --- a/util/cpt_upgraders/remove-arm-cpsr-mode-miscreg.py +++ b/util/cpt_upgraders/remove-arm-cpsr-mode-miscreg.py @@ -5,7 +5,7 @@ def upgrader(cpt): import re # Search for all ISA sections - if re.search(".*sys.*\.cpu.*\.isa$", sec): + if re.search(r".*sys.*\.cpu.*\.isa$", sec): mr = cpt.get(sec, "miscRegs").split() # Remove MISCREG_CPSR_MODE del mr[137] diff --git a/util/cpt_upgraders/riscv-pcstate.py b/util/cpt_upgraders/riscv-pcstate.py index c8220ddbb8..4182355419 100644 --- a/util/cpt_upgraders/riscv-pcstate.py +++ b/util/cpt_upgraders/riscv-pcstate.py @@ -32,7 +32,7 @@ def upgrader(cpt): for sec in cpt.sections(): import re - if re.search(".*processor.*\.core.*\.xc.*", sec): + if re.search(r".*processor.*\.core.*\.xc.*", sec): if cpt.get(sec, "_rvType", fallback="") == "": cpt.set(sec, "_rvType", "1") diff --git a/util/cpt_upgraders/riscv-vext.py b/util/cpt_upgraders/riscv-vext.py index 8b340ac3d7..d335f74b83 100644 --- a/util/cpt_upgraders/riscv-vext.py +++ b/util/cpt_upgraders/riscv-vext.py @@ -39,7 +39,7 @@ def upgrader(cpt): import re # Search for all XC sections - if re.search(".*processor.*\.core.*\.xc.*", sec): + if re.search(r".*processor.*\.core.*\.xc.*", sec): # Updating RVV vector registers (dummy values) # Assuming VLEN = 256 bits (32 bytes) mr = cpt.get(sec, "regs.vector").split() @@ -56,7 +56,7 @@ def upgrader(cpt): cpt.set(sec, "regs.matrix", "") # Search for all ISA sections - if re.search(".*processor.*\.core.*\.isa$", sec): + if re.search(r".*processor.*\.core.*\.isa$", sec): # Updating RVV misc registers (dummy values) mr = cpt.get(sec, "miscRegFile").split() if len(mr) == 164: diff --git a/util/cpt_upgraders/smt-interrupts.py b/util/cpt_upgraders/smt-interrupts.py index d8366c2aa4..0e0e0e963a 100644 --- a/util/cpt_upgraders/smt-interrupts.py +++ b/util/cpt_upgraders/smt-interrupts.py @@ -5,7 +5,7 @@ def upgrader(cpt): for sec in cpt.sections(): import re - re_cpu_match = re.match("^(.*sys.*\.cpu[^._]*)$", sec) + re_cpu_match = re.match(r"^(.*sys.*\.cpu[^._]*)$", sec) if re_cpu_match != None: interrupts = cpt.get(sec, "interrupts") intStatus = cpt.get(sec, "intStatus") diff --git a/util/cpt_upgraders/x86-add-tlb.py b/util/cpt_upgraders/x86-add-tlb.py index 5b6778bcbf..4903704731 100644 --- a/util/cpt_upgraders/x86-add-tlb.py +++ b/util/cpt_upgraders/x86-add-tlb.py @@ -5,11 +5,11 @@ def upgrader(cpt): import re # Search for all ISA sections - if re.search(".*sys.*\.cpu.*\.dtb$", sec): + if re.search(r".*sys.*\.cpu.*\.dtb$", sec): cpt.set(sec, "_size", "0") cpt.set(sec, "lruSeq", "0") - if re.search(".*sys.*\.cpu.*\.itb$", sec): + if re.search(r".*sys.*\.cpu.*\.itb$", sec): cpt.set(sec, "_size", "0") cpt.set(sec, "lruSeq", "0") else: diff --git a/util/decode_inst_dep_trace.py b/util/decode_inst_dep_trace.py index ded0051ae1..dcb5a7077b 100755 --- a/util/decode_inst_dep_trace.py +++ b/util/decode_inst_dep_trace.py @@ -125,7 +125,7 @@ def main(): try: ascii_out = open(sys.argv[2], "w") - except IOError: + except OSError: print("Failed to open ", sys.argv[2], " for writing") exit(-1) diff --git a/util/decode_inst_trace.py b/util/decode_inst_trace.py index 8e59f6955d..5e77138689 100755 --- a/util/decode_inst_trace.py +++ b/util/decode_inst_trace.py @@ -85,7 +85,7 @@ def main(): try: ascii_out = open(sys.argv[2], "w") - except IOError: + except OSError: print("Failed to open ", sys.argv[2], " for writing") exit(-1) @@ -153,7 +153,9 @@ def main(): for mem_acc in inst.mem_access: ascii_out.write( - " %#x-%#x;" % (mem_acc.addr, mem_acc.addr + mem_acc.size) + " {:#x}-{:#x};".format( + mem_acc.addr, mem_acc.addr + mem_acc.size + ) ) ascii_out.write("\n") diff --git a/util/decode_packet_trace.py b/util/decode_packet_trace.py index 66a74c6f01..5111ea4618 100755 --- a/util/decode_packet_trace.py +++ b/util/decode_packet_trace.py @@ -59,7 +59,7 @@ def main(): try: ascii_out = open(sys.argv[2], "w") - except IOError: + except OSError: print("Failed to open ", sys.argv[2], " for writing") exit(-1) diff --git a/util/encode_inst_dep_trace.py b/util/encode_inst_dep_trace.py index 9ab95bd7ed..5ca3cda79b 100755 --- a/util/encode_inst_dep_trace.py +++ b/util/encode_inst_dep_trace.py @@ -127,8 +127,8 @@ def main(): # Open the file in read mode try: - ascii_in = open(sys.argv[1], "r") - except IOError: + ascii_in = open(sys.argv[1]) + except OSError: print("Failed to open ", sys.argv[1], " for reading") exit(-1) diff --git a/util/encode_packet_trace.py b/util/encode_packet_trace.py index bdf1c3db06..5df3b21c7c 100755 --- a/util/encode_packet_trace.py +++ b/util/encode_packet_trace.py @@ -92,14 +92,14 @@ def main(): exit(-1) try: - ascii_in = open(sys.argv[1], "r") - except IOError: + ascii_in = open(sys.argv[1]) + except OSError: print("Failed to open ", sys.argv[1], " for reading") exit(-1) try: proto_out = open(sys.argv[2], "wb") - except IOError: + except OSError: print("Failed to open ", sys.argv[2], " for writing") exit(-1) diff --git a/util/find_copyrights.py b/util/find_copyrights.py index 0bd0ef3a51..28e3b4c66b 100644 --- a/util/find_copyrights.py +++ b/util/find_copyrights.py @@ -6,7 +6,7 @@ import sys from file_types import lang_type, find_files -mode_line = re.compile("(-\*- *mode:.* *-\*-)") +mode_line = re.compile(r"(-\*- *mode:.* *-\*-)") shell_comment = re.compile(r"^\s*#") lisp_comment = re.compile(r";") cpp_comment = re.compile(r"//") @@ -116,7 +116,7 @@ def process_dates(dates): for date in dates: match = date_range_re.match(date) if match: - f, l = [int(d) for d in match.groups()] + f, l = (int(d) for d in match.groups()) for i in range(f, l + 1): output.add(i) else: diff --git a/util/gem5-resources-manager/api/create_resources_json.py b/util/gem5-resources-manager/api/create_resources_json.py index 8d406a9ad5..3179142939 100644 --- a/util/gem5-resources-manager/api/create_resources_json.py +++ b/util/gem5-resources-manager/api/create_resources_json.py @@ -63,7 +63,7 @@ class ResourceJsonCreator: def __init__(self): self.schema = {} - with open("schema/schema.json", "r") as f: + with open("schema/schema.json") as f: self.schema = json.load(f) def _get_file_data(self, url): @@ -104,9 +104,7 @@ class ResourceJsonCreator: for filename in os.listdir(folder_path): file_path = os.path.join(folder_path, filename) if os.path.isfile(file_path): - with open( - file_path, "r", encoding="utf-8", errors="ignore" - ) as f: + with open(file_path, encoding="utf-8", errors="ignore") as f: contents = f.read() if id in contents: file_path = file_path.replace("\\", "/") diff --git a/util/gem5-resources-manager/test/json_client_test.py b/util/gem5-resources-manager/test/json_client_test.py index e08eb18452..0168d475ac 100644 --- a/util/gem5-resources-manager/test/json_client_test.py +++ b/util/gem5-resources-manager/test/json_client_test.py @@ -35,14 +35,14 @@ from api.json_client import JSONClient def get_json(): - with open("test/refs/test_json.json", "r") as f: + with open("test/refs/test_json.json") as f: jsonFile = f.read() return json.loads(jsonFile) def mockinit(self, file_path): self.file_path = Path("test/refs/") / file_path - with open(self.file_path, "r") as f: + with open(self.file_path) as f: self.resources = json.load(f) diff --git a/util/gem5art/artifact/gem5art/artifact/_artifactdb.py b/util/gem5art/artifact/gem5art/artifact/_artifactdb.py index 16d35e86e8..a18f47d7d0 100644 --- a/util/gem5art/artifact/gem5art/artifact/_artifactdb.py +++ b/util/gem5art/artifact/gem5art/artifact/_artifactdb.py @@ -185,22 +185,21 @@ class ArtifactMongoDB(ArtifactDB): def searchByName(self, name: str, limit: int) -> Iterable[Dict[str, Any]]: """Returns an iterable of all artifacts in the database that match some name.""" - for d in self.artifacts.find({"name": name}, limit=limit): - yield d + yield from self.artifacts.find({"name": name}, limit=limit) def searchByType(self, typ: str, limit: int) -> Iterable[Dict[str, Any]]: """Returns an iterable of all artifacts in the database that match some type.""" - for d in self.artifacts.find({"type": typ}, limit=limit): - yield d + yield from self.artifacts.find({"type": typ}, limit=limit) def searchByNameType( self, name: str, typ: str, limit: int ) -> Iterable[Dict[str, Any]]: """Returns an iterable of all artifacts in the database that match some name and type.""" - for d in self.artifacts.find({"type": typ, "name": name}, limit=limit): - yield d + yield from self.artifacts.find( + {"type": typ, "name": name}, limit=limit + ) def searchByLikeNameType( self, name: str, typ: str, limit: int @@ -211,8 +210,7 @@ class ArtifactMongoDB(ArtifactDB): data = self.artifacts.find( {"type": typ, "name": {"$regex": f"{name}"}}, limit=limit ) - for d in data: - yield d + yield from data class ArtifactFileDB(ArtifactDB): @@ -318,7 +316,7 @@ class ArtifactFileDB(ArtifactDB): uuid_mapping: Dict[str, Dict[str, str]] = {} hash_mapping: Dict[str, List[str]] = {} if json_file.exists(): - with open(json_file, "r") as f: + with open(json_file) as f: j = json.load(f) for an_artifact in j: the_uuid = an_artifact["_id"] diff --git a/util/gem5art/artifact/tests/test_artifact.py b/util/gem5art/artifact/tests/test_artifact.py index 548409c8c9..a12cc8f028 100644 --- a/util/gem5art/artifact/tests/test_artifact.py +++ b/util/gem5art/artifact/tests/test_artifact.py @@ -85,7 +85,7 @@ class TestGit(unittest.TestCase): def test_keys(self): git = artifact.artifact.getGit(Path(".")) self.assertSetEqual( - set(git.keys()), set(["origin", "hash", "name"]), "git keys wrong" + set(git.keys()), {"origin", "hash", "name"}, "git keys wrong" ) def test_origin(self): diff --git a/util/gem5art/artifact/tests/test_filedb.py b/util/gem5art/artifact/tests/test_filedb.py index 9b5cd02d52..b7144ffcf3 100644 --- a/util/gem5art/artifact/tests/test_filedb.py +++ b/util/gem5art/artifact/tests/test_filedb.py @@ -62,7 +62,7 @@ class TestArtifactFileDB(unittest.TestCase): self.assertTrue(Path("test.json").exists()) def test_json_content(self): - with open("test.json", "r") as f: + with open("test.json") as f: artifacts = json.load(f) self.assertTrue(len(artifacts) == 1) artifact = artifacts[0] diff --git a/util/gem5img.py b/util/gem5img.py index 298c43c1c3..dcb66e0bc9 100755 --- a/util/gem5img.py +++ b/util/gem5img.py @@ -140,7 +140,7 @@ def findProg(program, cleanupDev=None): return out.strip() -class LoopbackDevice(object): +class LoopbackDevice: def __init__(self, devFile=None): self.devFile = devFile @@ -228,7 +228,7 @@ commands = {} commandOrder = [] -class Command(object): +class Command: def addArgument(self, *args, **kargs): self.parser.add_argument(*args, **kargs) diff --git a/util/gerrit-bot/bot.py b/util/gerrit-bot/bot.py index f6b9469d9b..5ef4151a48 100755 --- a/util/gerrit-bot/bot.py +++ b/util/gerrit-bot/bot.py @@ -97,7 +97,7 @@ class GerritBot: def __read_auth_file(self, auth_file_path): username = "" password = "" - with open(auth_file_path, "r") as f: + with open(auth_file_path) as f: lines = f.readlines() username = lines[0].strip() password = lines[1].strip() @@ -107,7 +107,7 @@ class GerritBot: prev_query_time = 0 try: - with open(file_path, "r") as f: + with open(file_path) as f: lines = f.readlines() prev_query_time = int(float(lines[0].strip())) except FileNotFoundError: @@ -134,7 +134,7 @@ class GerritBot: def __read_maintainer_account_id_file(self, maintainers, file_path): account_ids = {} try: - with open(file_path, "r") as f: + with open(file_path) as f: account_ids = json.load(f) except (FileNotFoundError, json.decoder.JSONDecodeError): # create a placeholder file @@ -147,7 +147,7 @@ class GerritBot: def __update_maintainer_account_id_file(self, file_path, maintainers): # get the current map - with open(file_path, "r") as f: + with open(file_path) as f: account_ids = json.load(f) # get maintainer email addresses email_addresses = set() diff --git a/util/gerrit-bot/extract_gitcookies.py b/util/gerrit-bot/extract_gitcookies.py index ef17be10de..4487513dee 100755 --- a/util/gerrit-bot/extract_gitcookies.py +++ b/util/gerrit-bot/extract_gitcookies.py @@ -44,7 +44,7 @@ def parse_gitcookies_line(raw): def parse_gitcookies(input_path): username_password_dict = {} - with open(input_path, "r") as input_stream: + with open(input_path) as input_stream: for line in input_stream: username, password = parse_gitcookies_line(line) if not username: diff --git a/util/gerrit-bot/util.py b/util/gerrit-bot/util.py index b410858e14..16a3b49216 100644 --- a/util/gerrit-bot/util.py +++ b/util/gerrit-bot/util.py @@ -78,10 +78,8 @@ def add_maintainers_to_change( maintainer_emails.add(email) except KeyError: print( - ( - f"warning: `change-{change_id}` has an unknown tag: " - f"`{tag}`" - ) + f"warning: `change-{change_id}` has an unknown tag: " + f"`{tag}`" ) for email in maintainer_emails: if email in avoid_emails: diff --git a/util/git-commit-msg.py b/util/git-commit-msg.py index c12b0cd215..f0a60110c7 100755 --- a/util/git-commit-msg.py +++ b/util/git-commit-msg.py @@ -57,7 +57,7 @@ def _printErrorQuit(error_message): -------------------------------------------------------------------------- """ ) - print(open(sys.argv[1], "r").read()) + print(open(sys.argv[1]).read()) print( """ -------------------------------------------------------------------------- @@ -105,7 +105,7 @@ def _validateTags(commit_header): tags = "".join(commit_header.split(":")[0].split()).split(",") if any(tag not in valid_tags for tag in tags): - invalid_tag = next((tag for tag in tags if tag not in valid_tags)) + invalid_tag = next(tag for tag in tags if tag not in valid_tags) _printErrorQuit("Invalid Gem5 tag: " + invalid_tag) @@ -120,7 +120,7 @@ commit_message = open(sys.argv[1]).read() commit_message_lines = commit_message.splitlines() commit_header = commit_message_lines[0] commit_header_match = re.search( - "^(fixup! )?(\S[\w\-][,\s*[\w\-]+]*:.+\S$)", commit_header + r"^(fixup! )?(\S[\w\-][,\s*[\w\-]+]*:.+\S$)", commit_header ) if commit_header_match is None: _printErrorQuit("Invalid commit header") diff --git a/util/logroll.py b/util/logroll.py index e3dfb7d78c..04f7d5c69d 100755 --- a/util/logroll.py +++ b/util/logroll.py @@ -105,7 +105,7 @@ class CopyingMock(unittest.mock.MagicMock): def __call__(self, *args, **kwargs): args = copy.deepcopy(args) kwargs = copy.deepcopy(kwargs) - return super(CopyingMock, self).__call__(*args, **kwargs) + return super().__call__(*args, **kwargs) class TestLogroll(unittest.TestCase): @@ -125,14 +125,12 @@ class TestLogroll(unittest.TestCase): # Generator which returns lines like a file object would. def line_gen(self, lines): - for line in lines: - yield line + yield from lines # Generator like above, but which simulates a signal midway through. def signal_line_gen(self, lines, pos, sig_dict, signal): # Return the first few lines. - for line in lines[:pos]: - yield line + yield from lines[:pos] # Simulate receiving the signal. self.assertIn(signal, sig_dict) @@ -141,8 +139,7 @@ class TestLogroll(unittest.TestCase): sig_dict[signal](None, None) # Return the remaining lines. - for line in lines[pos:]: - yield line + yield from lines[pos:] # Set up a mock of signal.signal to record handlers in a dict. def mock_signal_dict(self, mock): diff --git a/util/maint/lib/maintainers.py b/util/maint/lib/maintainers.py index 947e268112..4cc713aada 100644 --- a/util/maint/lib/maintainers.py +++ b/util/maint/lib/maintainers.py @@ -83,7 +83,7 @@ class Status(enum.Enum): ] -class Subsystem(object): +class Subsystem: tag: str status: Status maintainers: List[Tuple[str, str]] # Name, email @@ -102,7 +102,7 @@ class Subsystem(object): self.description = description if description is not None else "" -class Maintainers(object): +class Maintainers: DEFAULT_MAINTAINERS = os.path.join( os.path.dirname(__file__), "../../../MAINTAINERS.yaml" ) @@ -132,7 +132,7 @@ class Maintainers(object): path_or_file = cls.DEFAULT_MAINTAINERS if isinstance(path_or_file, str): - with open(path_or_file, "r") as fin: + with open(path_or_file) as fin: return yaml.load(fin, Loader=yaml.SafeLoader) else: return yaml.load(path_or_file, Loader=yaml.SafeLoader) diff --git a/util/maint/list_changes.py b/util/maint/list_changes.py index 0d61e39fde..1dcb70def2 100755 --- a/util/maint/list_changes.py +++ b/util/maint/list_changes.py @@ -41,7 +41,7 @@ import re from functools import wraps -class Commit(object): +class Commit: _re_tag = re.compile(r"^((?:\w|-)+): (.*)$") def __init__(self, rev): @@ -137,12 +137,12 @@ def list_changes(upstream, feature, paths=[]): feature_revs = tuple(list_revs(upstream, feature, paths=paths)) upstream_revs = tuple(list_revs(feature, upstream, paths=paths)) - feature_cids = dict( - [(c.change_id, c) for c in feature_revs if c.change_id is not None] - ) - upstream_cids = dict( - [(c.change_id, c) for c in upstream_revs if c.change_id is not None] - ) + feature_cids = { + c.change_id: c for c in feature_revs if c.change_id is not None + } + upstream_cids = { + c.change_id: c for c in upstream_revs if c.change_id is not None + } incoming = [ r @@ -251,13 +251,11 @@ def _main(): if args.deep_search: print("Incorrectly rebased changes:") all_upstream_revs = list_revs(args.upstream, paths=args.paths) - all_upstream_cids = dict( - [ - (c.change_id, c) - for c in all_upstream_revs - if c.change_id is not None - ] - ) + all_upstream_cids = { + c.change_id: c + for c in all_upstream_revs + if c.change_id is not None + } incorrect_outgoing = [ r for r in outgoing if r.change_id in all_upstream_cids ] diff --git a/util/maint/show_changes_by_file.py b/util/maint/show_changes_by_file.py index 75b7e7edd9..8da3ee64bd 100755 --- a/util/maint/show_changes_by_file.py +++ b/util/maint/show_changes_by_file.py @@ -38,7 +38,7 @@ from collections import OrderedDict, defaultdict class OrderedDefaultDict(OrderedDict, defaultdict): def __init__(self, default_factory=None, *args, **kwargs): - super(OrderedDefaultDict, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.default_factory = default_factory diff --git a/util/minorview/blobs.py b/util/minorview/blobs.py index 51b28d0d1e..8d379f0cb8 100644 --- a/util/minorview/blobs.py +++ b/util/minorview/blobs.py @@ -181,7 +181,7 @@ def cross(cr, centre, size): cr.line_to(x, bottom) -class Blob(object): +class Blob: """Blob super class""" def __init__(self, picChar, unit, topLeft, colour, size=Point(1, 1)): @@ -217,7 +217,7 @@ class Block(Blob): colour=colours.black, size=Point(1, 1), ): - super(Block, self).__init__(picChar, unit, topLeft, colour, size=size) + super().__init__(picChar, unit, topLeft, colour, size=size) # {horiz, vert} self.stripDir = "horiz" # {LR, RL}: LR means the first strip will be on the left/top, @@ -388,7 +388,7 @@ class Key(Blob): def __init__( self, picChar, unit, topLeft, colour=colours.black, size=Point(1, 1) ): - super(Key, self).__init__(picChar, unit, topLeft, colour, size=size) + super().__init__(picChar, unit, topLeft, colour, size=size) self.colours = "BBBB" self.displayName = unit @@ -464,7 +464,7 @@ class Arrow(Blob): size=Point(1.0, 1.0), direc="right", ): - super(Arrow, self).__init__(unit, unit, topLeft, colour, size=size) + super().__init__(unit, unit, topLeft, colour, size=size) self.direc = direc def render(self, cr, view, event, select, time): diff --git a/util/minorview/model.py b/util/minorview/model.py index 126b730bea..cf8c04bc04 100644 --- a/util/minorview/model.py +++ b/util/minorview/model.py @@ -45,10 +45,10 @@ import os id_parts = "TSPLFE" all_ids = set(id_parts) -no_ids = set([]) +no_ids = set() -class BlobDataSelect(object): +class BlobDataSelect: """Represents which data is displayed for Ided object""" def __init__(self): @@ -62,7 +62,7 @@ class BlobDataSelect(object): return ret -class BlobVisualData(object): +class BlobVisualData: """Super class for block data colouring""" def to_striped_block(self, select): @@ -113,7 +113,7 @@ class Id(BlobVisualData): def from_string(self, string): m = re.match( - "^(F;)?(\d+)/(\d+)\.(\d+)/(\d+)(/(\d+)(\.(\d+))?)?", string + r"^(F;)?(\d+)/(\d+)\.(\d+)/(\d+)(/(\d+)(\.(\d+))?)?", string ) def seqnum_from_string(string): @@ -205,7 +205,7 @@ class Branch(BlobVisualData): self.id = Id() def from_string(self, string): - m = re.match("^(\w+);(\d+)\.(\d+);([0-9a-fA-Fx]+);(.*)$", string) + m = re.match(r"^(\w+);(\d+)\.(\d+);([0-9a-fA-Fx]+);(.*)$", string) if m is not None: ( @@ -283,7 +283,7 @@ class DcacheAccess(BlobVisualData): return [direc_colour] + self.id.to_striped_block(select) -class ColourPattern(object): +class ColourPattern: """Super class for decoders that make 2D grids rather than just single striped blocks""" @@ -493,7 +493,7 @@ def find_colour_decoder(stripSpace, decoderName, dataName, picPairs): return None -class IdedObj(object): +class IdedObj: """An object identified by an Id carrying paired data. The super class for Inst and Line""" @@ -518,7 +518,7 @@ class Inst(IdedObj): """A non-fault instruction""" def __init__(self, id, disassembly, addr, pairs={}): - super(Inst, self).__init__(id, pairs) + super().__init__(id, pairs) if "nextAddr" in pairs: self.nextAddr = int(pairs["nextAddr"], 0) del pairs["nextAddr"] @@ -542,7 +542,7 @@ class InstFault(IdedObj): """A fault instruction""" def __init__(self, id, fault, addr, pairs={}): - super(InstFault, self).__init__(id, pairs) + super().__init__(id, pairs) self.fault = fault self.addr = addr @@ -557,7 +557,7 @@ class Line(IdedObj): """A fetched line""" def __init__(self, id, vaddr, paddr, size, pairs={}): - super(Line, self).__init__(id, pairs) + super().__init__(id, pairs) self.vaddr = vaddr self.paddr = paddr self.size = size @@ -573,7 +573,7 @@ class LineFault(IdedObj): """A faulting line""" def __init__(self, id, fault, vaddr, pairs={}): - super(LineFault, self).__init__(id, pairs) + super().__init__(id, pairs) self.vaddr = vaddr self.fault = fault @@ -584,7 +584,7 @@ class LineFault(IdedObj): return ret -class BlobEvent(object): +class BlobEvent: """Time event for a single blob""" def __init__(self, unit, time, pairs={}): @@ -624,7 +624,7 @@ class BlobEvent(object): return sorted(ret) -class BlobModel(object): +class BlobModel: """Model bringing together blob definitions and parsed events""" def __init__(self, unitNamePrefix=""): @@ -856,7 +856,7 @@ class BlobModel(object): still_skipping = True l = f.readline() while l and still_skipping: - match = re.match("^\s*(\d+):", l) + match = re.match(r"^\s*(\d+):", l) if match is not None: event_time = match.groups() if int(event_time[0]) >= startTime: @@ -867,7 +867,7 @@ class BlobModel(object): l = f.readline() match_line_re = re.compile( - "^\s*(\d+):\s*([\w\.]+):\s*(Minor\w+:)?\s*(.*)$" + r"^\s*(\d+):\s*([\w\.]+):\s*(Minor\w+:)?\s*(.*)$" ) # Parse each line of the events file, accumulating comments to be @@ -880,13 +880,13 @@ class BlobModel(object): event_time = int(event_time) unit = re.sub( - "^" + self.unitNamePrefix + "\.?(.*)$", "\\1", unit + "^" + self.unitNamePrefix + r"\.?(.*)$", "\\1", unit ) # When the time changes, resolve comments if event_time != time: if self.numEvents > next_progress_print_event_count: - print(("Parsed to time: %d" % event_time)) + print("Parsed to time: %d" % event_time) next_progress_print_event_count = self.numEvents + 1000 update_comments(comments, time) comments = [] @@ -1137,7 +1137,7 @@ class BlobModel(object): def line_is_comment(line): """Returns true if a line starts with #, returns False for lines which are None""" - return line is not None and re.match("^\s*#", line) is not None + return line is not None and re.match(r"^\s*#", line) is not None def get_line(f): """Get a line from file f extending that line if it ends in @@ -1186,19 +1186,19 @@ class BlobModel(object): l = parse.remove_trailing_ws(l) l = re.sub("#.*", "", l) - if re.match("^\s*$", l) is not None: + if re.match(r"^\s*$", l) is not None: pass elif l == "<<<": in_picture = True elif l == ">>>": in_picture = False elif in_picture: - picture.append(re.sub("\s*$", "", l)) + picture.append(re.sub(r"\s*$", "", l)) else: line_match = re.match( - "^([a-zA-Z0-9][a-zA-Z0-9]):\s+([\w.]+)\s*(.*)", l + r"^([a-zA-Z0-9][a-zA-Z0-9]):\s+([\w.]+)\s*(.*)", l ) - macro_match = re.match("macro\s+(\w+):(.*)", l) + macro_match = re.match(r"macro\s+(\w+):(.*)", l) if macro_match is not None: name, defn = macro_match.groups() diff --git a/util/minorview/parse.py b/util/minorview/parse.py index 5b6bea0c79..bc12536980 100644 --- a/util/minorview/parse.py +++ b/util/minorview/parse.py @@ -44,14 +44,14 @@ def list_parser(names): ret = [] accum = [] for elem in elems: - if re.search("^\((.*)\)$", elem): - accum.append(re.sub("^\((.*)\)", "\\1", elem)) + if re.search(r"^\((.*)\)$", elem): + accum.append(re.sub(r"^\((.*)\)", "\\1", elem)) ret.append(accum) accum = [] - elif re.search("^\(", elem): - accum.append(re.sub("^\(", "", elem)) - elif re.search("\)$", elem): - accum.append(re.sub("\)$", "", elem)) + elif re.search(r"^\(", elem): + accum.append(re.sub(r"^\(", "", elem)) + elif re.search(r"\)$", elem): + accum.append(re.sub(r"\)$", "", elem)) ret.append(accum) accum = [] elif len(accum) != 0: @@ -72,18 +72,18 @@ def map2(f, ls): def remove_trailing_ws(line): - return re.sub("\s*$", "", line) + return re.sub(r"\s*$", "", line) def remove_leading_and_trailing_ws(line): - return re.sub("\s*$", "", re.sub("^\s*", "", line)) + return re.sub(r"\s*$", "", re.sub(r"^\s*", "", line)) def parse_pairs_list(pairString): """parse a string like 'name=value name2=value2' into a list of pairs of ('name', 'value') ...""" ret = [] - pairs = re.finditer('(\w+)(=("[^"]*"|[^\s]*))?', pairString) + pairs = re.finditer(r'(\w+)(=("[^"]*"|[^\s]*))?', pairString) for pair in pairs: name, rest, value = pair.groups() if value is not None: diff --git a/util/minorview/point.py b/util/minorview/point.py index 17190e1ca7..636704002d 100644 --- a/util/minorview/point.py +++ b/util/minorview/point.py @@ -34,7 +34,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -class Point(object): +class Point: """2D point coordinates/size type""" def __init__(self, x, y): diff --git a/util/minorview/view.py b/util/minorview/view.py index 7c1aef873f..37564996eb 100644 --- a/util/minorview/view.py +++ b/util/minorview/view.py @@ -49,7 +49,7 @@ from .model import Id, BlobModel, BlobDataSelect, special_state_chars from . import blobs -class BlobView(object): +class BlobView: """The canvas view of the pipeline""" def __init__(self, model): @@ -189,7 +189,7 @@ class BlobView(object): self.da.set_size_request(10, int(self.initialHeight)) -class BlobController(object): +class BlobController: """The controller bar for the viewer""" def __init__( @@ -361,7 +361,7 @@ class BlobController(object): self.view.redraw() -class Overlay(object): +class Overlay: """An Overlay is a speech bubble explaining the data in a blob""" def __init__(self, model, view, point, blob): @@ -456,7 +456,7 @@ class Overlay(object): text_point += text_step -class BlobWindow(object): +class BlobWindow: """The top-level window and its mouse control""" def __init__(self, model, view, controller): diff --git a/util/o3-pipeview.py b/util/o3-pipeview.py index fe49706dad..3228832446 100755 --- a/util/o3-pipeview.py +++ b/util/o3-pipeview.py @@ -511,7 +511,7 @@ def main(): sys.exit(1) # Process trace print("Processing trace... ", end=" ") - with open(args.tracefile, "r") as trace: + with open(args.tracefile) as trace: with open(args.outfile, "w") as out: process_trace( trace, diff --git a/util/on-chip-network-power-area.py b/util/on-chip-network-power-area.py index 1dfc434be8..563bf6334d 100644 --- a/util/on-chip-network-power-area.py +++ b/util/on-chip-network-power-area.py @@ -186,9 +186,9 @@ def parseStats( # Open the stats.txt file and parse it to for the required numbers # and the number of routers. try: - stats_handle = open(stats_file, "r") + stats_handle = open(stats_file) stats_handle.close() - except IOError: + except OSError: print("Failed to open ", stats_file, " for reading") exit(-1) diff --git a/util/oprofile-top.py b/util/oprofile-top.py index 4d5a693451..2808ea10fe 100755 --- a/util/oprofile-top.py +++ b/util/oprofile-top.py @@ -66,7 +66,7 @@ total = 0 prof = {} linenum = 0 for line in f.readlines(): - line = re.sub("\(no symbols\)", "nosym", line) + line = re.sub(r"\(no symbols\)", "nosym", line) line = re.sub("anonymous.*", "nosym", line) linenum += 1 if linenum < 4: diff --git a/util/plot_dram/PlotPowerStates.py b/util/plot_dram/PlotPowerStates.py index 395c48184f..31e831f8b0 100755 --- a/util/plot_dram/PlotPowerStates.py +++ b/util/plot_dram/PlotPowerStates.py @@ -127,7 +127,7 @@ def plotLowPStates( @param delay_list: list of itt max multipliers (e.g. [1, 20, 200]) """ - stats_file = open(stats_fname, "r") + stats_file = open(stats_fname) global bankUtilValues bankUtilValues = bank_util_list diff --git a/util/plot_dram/dram_lat_mem_rd_plot.py b/util/plot_dram/dram_lat_mem_rd_plot.py index d8f2e90470..798148f714 100755 --- a/util/plot_dram/dram_lat_mem_rd_plot.py +++ b/util/plot_dram/dram_lat_mem_rd_plot.py @@ -56,14 +56,14 @@ def main(): exit(-1) try: - stats = open(sys.argv[1] + "/stats.txt", "r") - except IOError: + stats = open(sys.argv[1] + "/stats.txt") + except OSError: print("Failed to open ", sys.argv[1] + "/stats.txt", " for reading") exit(-1) try: - simout = open(sys.argv[1] + "/simout.txt", "r") - except IOError: + simout = open(sys.argv[1] + "/simout.txt") + except OSError: print("Failed to open ", sys.argv[1] + "/simout.txt", " for reading") exit(-1) @@ -77,7 +77,7 @@ def main(): if got_ranges: ranges.append(int(line) / 1024) - match = re.match("lat_mem_rd with (\d+) iterations, ranges:.*", line) + match = re.match(r"lat_mem_rd with (\d+) iterations, ranges:.*", line) if match: got_ranges = True iterations = int(match.groups(0)[0]) @@ -92,7 +92,7 @@ def main(): raw_rd_lat = [] for line in stats: - match = re.match(".*readLatencyHist::mean\s+(.+)\s+#.*", line) + match = re.match(r".*readLatencyHist::mean\s+(.+)\s+#.*", line) if match: raw_rd_lat.append(float(match.groups(0)[0]) / 1000) stats.close() diff --git a/util/plot_dram/dram_sweep_plot.py b/util/plot_dram/dram_sweep_plot.py index 50efc424f1..8fbeaf511c 100755 --- a/util/plot_dram/dram_sweep_plot.py +++ b/util/plot_dram/dram_sweep_plot.py @@ -73,14 +73,14 @@ def main(): mode = sys.argv[1][1] try: - stats = open(sys.argv[2] + "/stats.txt", "r") - except IOError: + stats = open(sys.argv[2] + "/stats.txt") + except OSError: print("Failed to open ", sys.argv[2] + "/stats.txt", " for reading") exit(-1) try: - simout = open(sys.argv[2] + "/simout.txt", "r") - except IOError: + simout = open(sys.argv[2] + "/simout.txt") + except OSError: print("Failed to open ", sys.argv[2] + "/simout.txt", " for reading") exit(-1) @@ -90,7 +90,7 @@ def main(): for line in simout: match = re.match( - "DRAM sweep with burst: (\d+), banks: (\d+), max stride: (\d+)", + r"DRAM sweep with burst: (\d+), banks: (\d+), max stride: (\d+)", line, ) if match: @@ -113,15 +113,15 @@ def main(): avg_pwr = [] for line in stats: - match = re.match(".*busUtil\s+(\d+\.\d+)\s+#.*", line) + match = re.match(r".*busUtil\s+(\d+\.\d+)\s+#.*", line) if match: bus_util.append(float(match.groups(0)[0])) - match = re.match(".*peakBW\s+(\d+\.\d+)\s+#.*", line) + match = re.match(r".*peakBW\s+(\d+\.\d+)\s+#.*", line) if match: peak_bw.append(float(match.groups(0)[0])) - match = re.match(".*averagePower\s+(\d+\.?\d*)\s+#.*", line) + match = re.match(r".*averagePower\s+(\d+\.?\d*)\s+#.*", line) if match: avg_pwr.append(float(match.groups(0)[0])) stats.close() diff --git a/util/plot_dram/lowp_dram_sweep_plot.py b/util/plot_dram/lowp_dram_sweep_plot.py index 053d7d0bc6..0f53a3319b 100755 --- a/util/plot_dram/lowp_dram_sweep_plot.py +++ b/util/plot_dram/lowp_dram_sweep_plot.py @@ -106,7 +106,7 @@ def main(): filename = plotter.stateTimePlotName(str(delay) + "-") outfile.write(wrapForGraphic(filename, textwidth)) outfile.write(getCaption(delay)) - outfile.write("\end{figure}\n") + outfile.write("\\end{figure}\n") # Energy plots for all delay values outfile.write("\\begin{figure} \n\\centering\n") diff --git a/util/protolib.py b/util/protolib.py index dcfb7aabb5..e795625c39 100644 --- a/util/protolib.py +++ b/util/protolib.py @@ -89,9 +89,9 @@ def openFileRd(in_file): # reading the first message. proto_in.seek(1) proto_in.seek(0) - except IOError: + except OSError: proto_in = open(in_file, "rb") - except IOError: + except OSError: print("Failed to open ", in_file, " for reading") exit(-1) return proto_in @@ -125,7 +125,7 @@ def _DecodeVarint32(in_file): return (result, pos) shift += 7 if shift >= 64: - raise IOError("Too many bytes when decoding varint.") + raise OSError("Too many bytes when decoding varint.") def decodeMessage(in_file, message): @@ -140,7 +140,7 @@ def decodeMessage(in_file, message): buf = in_file.read(size) message.ParseFromString(buf) return True - except IOError: + except OSError: return False diff --git a/util/streamline/m5stats2streamline.py b/util/streamline/m5stats2streamline.py index 5b91cb648d..e350806e87 100755 --- a/util/streamline/m5stats2streamline.py +++ b/util/streamline/m5stats2streamline.py @@ -126,7 +126,7 @@ parser.add_argument( args = parser.parse_args() -if not re.match("(.*)\.apc", args.output_path): +if not re.match(r"(.*)\.apc", args.output_path): print("ERROR: should end with '.apc'!") sys.exit(1) @@ -188,7 +188,7 @@ idle_uid = -1 kernel_uid = -1 -class Task(object): +class Task: def __init__(self, uid, pid, tgid, task_name, is_process, tick): if pid == 0: # Idle self.uid = 0 @@ -204,7 +204,7 @@ class Task(object): self.tick = tick # time this task first appeared -class Event(object): +class Event: def __init__(self, tick, task): self.tick = tick self.task = task @@ -662,8 +662,8 @@ def parseProcessInfo(task_file): sys.exit(1) process_re = re.compile( - "tick=(\d+)\s+(\d+)\s+cpu_id=(\d+)\s+" - + "next_pid=([-\d]+)\s+next_tgid=([-\d]+)\s+next_task=(.*)" + r"tick=(\d+)\s+(\d+)\s+cpu_id=(\d+)\s+" + + r"next_pid=([-\d]+)\s+next_tgid=([-\d]+)\s+next_task=(.*)" ) task_name_failure_warned = False @@ -813,7 +813,7 @@ def writeXmlFile(xml, filename): # StatsEntry that contains individual statistics -class StatsEntry(object): +class StatsEntry: def __init__(self, name, group, group_index, per_cpu, key): # Full name of statistics self.name = name @@ -826,12 +826,14 @@ class StatsEntry(object): # Shorter name with "system" stripped off # and symbols converted to alphanumerics - self.short_name = re.sub("system\.", "", name) + self.short_name = re.sub(r"system\.", "", name) self.short_name = re.sub(":", "_", name) # Regex for this stat (string version used to construct union regex) - self.regex_string = "^" + name + "\s+([\d\.]+)" - self.regex = re.compile("^" + name + "\s+([\d\.e\-]+)\s+# (.*)$", re.M) + self.regex_string = "^" + name + r"\s+([\d\.]+)" + self.regex = re.compile( + "^" + name + r"\s+([\d\.e\-]+)\s+# (.*)$", re.M + ) self.description = "" # Whether this stat is use per CPU or not @@ -869,11 +871,11 @@ class StatsEntry(object): print("\t", per_cpu_name) self.per_cpu_regex_string.append( - "^" + per_cpu_name + "\s+[\d\.]+" + "^" + per_cpu_name + r"\s+[\d\.]+" ) self.per_cpu_regex.append( re.compile( - "^" + per_cpu_name + "\s+([\d\.e\-]+)\s+# (.*)$", re.M + "^" + per_cpu_name + r"\s+([\d\.e\-]+)\s+# (.*)$", re.M ) ) self.values.append([]) @@ -888,7 +890,7 @@ class StatsEntry(object): # Global stats object that contains the list of stats entries # and other utility functions -class Stats(object): +class Stats: def __init__(self): self.stats_list = [] self.tick_list = [] @@ -982,17 +984,17 @@ def readGem5Stats(stats, gem5_stats_file): window_end_regex = re.compile( "^---------- End Simulation Statistics ----------" ) - final_tick_regex = re.compile("^final_tick\s+(\d+)") + final_tick_regex = re.compile(r"^final_tick\s+(\d+)") global ticks_in_ns - sim_freq_regex = re.compile("^sim_freq\s+(\d+)") + sim_freq_regex = re.compile(r"^sim_freq\s+(\d+)") sim_freq = -1 try: if ext == ".gz": f = gzip.open(gem5_stats_file, "r") else: - f = open(gem5_stats_file, "r") + f = open(gem5_stats_file) except: print("ERROR opening stats file", gem5_stats_file, "!") sys.exit(1) @@ -1004,7 +1006,7 @@ def readGem5Stats(stats, gem5_stats_file): error = False try: line = f.readline() - except IOError: + except OSError: print("") print("WARNING: IO error in stats file") print("(gzip stream not closed properly?)...continuing for now") @@ -1146,7 +1148,7 @@ def doCapturedXML(output_path, stats): counters = ET.SubElement(xml, "counters") for stat in stats.stats_list: s = ET.SubElement(counters, "counter") - stat_name = re.sub("\.", "_", stat.short_name) + stat_name = re.sub(r"\.", "_", stat.short_name) stat_name = re.sub("#", "", stat_name) s.set("title", stat.group) s.set("name", stat_name) @@ -1273,7 +1275,7 @@ def writeVisualAnnotations(blob, input_path, output_path): frame_count = 0 file_list = os.listdir(frame_path) file_list.sort() - re_fb = re.compile("fb\.(\d+)\.(\d+)\.bmp.gz") + re_fb = re.compile(r"fb\.(\d+)\.(\d+)\.bmp.gz") # Use first non-negative pid to tag visual annotations annotate_pid = -1 diff --git a/util/style.py b/util/style.py index 27d6568ec3..1b3ebe1602 100755 --- a/util/style.py +++ b/util/style.py @@ -45,7 +45,7 @@ from style.region import all_regions from style.style import StdioUI from style import repo -verifier_names = dict([(c.__name__, c) for c in style.verifiers.all_verifiers]) +verifier_names = {c.__name__: c for c in style.verifiers.all_verifiers} def verify( diff --git a/util/style/file_types.py b/util/style/file_types.py index 3a6b93098b..1ce8363a1e 100644 --- a/util/style/file_types.py +++ b/util/style/file_types.py @@ -101,7 +101,7 @@ def lang_type(filename, firstline=None, openok=True): # if a first line was not provided but the file is ok to open, # grab the first line of the file. if firstline is None and openok: - handle = open(filename, "r") + handle = open(filename) firstline = handle.readline() handle.close() diff --git a/util/style/region.py b/util/style/region.py index bd2fc89251..05b0073e50 100644 --- a/util/style/region.py +++ b/util/style/region.py @@ -25,7 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -class _neg_inf(object): +class _neg_inf: """This object always compares less than any other object""" def __repr__(self): @@ -53,7 +53,7 @@ class _neg_inf(object): neg_inf = _neg_inf() -class _pos_inf(object): +class _pos_inf: """This object always compares greater than any other object""" def __repr__(self): @@ -176,7 +176,7 @@ class Region(tuple): return self[1] > other -class Regions(object): +class Regions: """A set of regions (ranges). Basically a region with holes. Includes utility functions to merge regions and figure out if something is in one of the regions.""" diff --git a/util/style/repo.py b/util/style/repo.py index 18079cea6a..04db36d15d 100644 --- a/util/style/repo.py +++ b/util/style/repo.py @@ -43,7 +43,7 @@ from .region import * from .style import modified_regions -class AbstractRepo(object, metaclass=ABCMeta): +class AbstractRepo(metaclass=ABCMeta): def file_path(self, fname): """Get the absolute path to a file relative within the repository. The input file name must be a valid path within the repository. @@ -76,7 +76,7 @@ class AbstractRepo(object, metaclass=ABCMeta): to the repository root. """ - with open(self.file_path(name), "r") as f: + with open(self.file_path(name)) as f: return f.read() @abstractmethod diff --git a/util/style/sort_includes.py b/util/style/sort_includes.py index 9c532b5669..86d886f213 100644 --- a/util/style/sort_includes.py +++ b/util/style/sort_includes.py @@ -94,7 +94,7 @@ def _include_matcher(keyword="#include", delim="<>"): """Match an include statement and return a (keyword, file, extra) duple, or a touple of None values if there isn't a match.""" - rex = re.compile(r"^(%s)\s*%s(.*)%s(.*)$" % (keyword, delim[0], delim[1])) + rex = re.compile(rf"^({keyword})\s*{delim[0]}(.*){delim[1]}(.*)$") def matcher(context, line): m = rex.match(line) @@ -146,7 +146,7 @@ def _include_matcher_main(): return matcher -class SortIncludes(object): +class SortIncludes: # different types of includes for different sorting of headers # - Python header needs to be first if it exists # <*.h> - system headers (directories before files) @@ -155,17 +155,21 @@ class SortIncludes(object): # "*" - M5 headers (directories before files) includes_re = ( ("main", '""', _include_matcher_main()), - ("python", "<>", _include_matcher_fname("^Python\.h$")), + ("python", "<>", _include_matcher_fname(r"^Python\.h$")), ( "pybind", '""', - _include_matcher_fname("^pybind11/.*\.h$", delim='""'), + _include_matcher_fname(r"^pybind11/.*\.h$", delim='""'), ), ("m5shared", "<>", _include_matcher_fname("^gem5/")), - ("c", "<>", _include_matcher_fname("^.*\.h$")), - ("stl", "<>", _include_matcher_fname("^\w+$")), - ("cc", "<>", _include_matcher_fname("^.*\.(hh|hxx|hpp|H)$")), - ("m5header", '""', _include_matcher_fname("^.*\.h{1,2}$", delim='""')), + ("c", "<>", _include_matcher_fname(r"^.*\.h$")), + ("stl", "<>", _include_matcher_fname(r"^\w+$")), + ("cc", "<>", _include_matcher_fname(r"^.*\.(hh|hxx|hpp|H)$")), + ( + "m5header", + '""', + _include_matcher_fname(r"^.*\.h{1,2}$", delim='""'), + ), ("swig0", "<>", _include_matcher(keyword="%import")), ("swig1", "<>", _include_matcher(keyword="%include")), ("swig2", '""', _include_matcher(keyword="%import", delim='""')), @@ -266,8 +270,7 @@ class SortIncludes(object): # Output pending includes, a new line between, and the # current l. - for include in self.dump_includes(): - yield include + yield from self.dump_includes() yield "" yield line else: @@ -276,8 +279,7 @@ class SortIncludes(object): # We've reached EOF, so dump any pending includes if processing_includes: - for include in self.dump_includes(): - yield include + yield from self.dump_includes() # default language types to try to apply our sorting rules to diff --git a/util/style/style.py b/util/style/style.py index 1c6ed1cf96..a40671fb47 100644 --- a/util/style/style.py +++ b/util/style/style.py @@ -52,7 +52,7 @@ trail = re.compile(r"([ \t]+)$") any_control = re.compile(r"\b(if|while|for)([ \t]*)\(") -class UserInterface(object, metaclass=ABCMeta): +class UserInterface(metaclass=ABCMeta): def __init__(self, verbose=False): self.verbose = verbose @@ -118,8 +118,8 @@ style_ignores = [ # Only include Scons files and those with extensions that suggest source # code _re_only( - "^((.*\/)?(SConscript|SConstruct)|" - ".*\.(c|h|cc|hh|cpp|hpp|isa|proto))$" + r"^((.*\/)?(SConscript|SConstruct)|" + r".*\.(c|h|cc|hh|cpp|hpp|isa|proto))$" ), ] diff --git a/util/style/verifiers.py b/util/style/verifiers.py index 7a88e59789..4860cc461e 100644 --- a/util/style/verifiers.py +++ b/util/style/verifiers.py @@ -103,7 +103,7 @@ def _modified_regions(old, new): return regions -class Verifier(object, metaclass=ABCMeta): +class Verifier(metaclass=ABCMeta): """Base class for style verifiers Verifiers check for style violations and optionally fix such @@ -292,10 +292,18 @@ class Whitespace(LineVerifier): - No trailing whitespace """ - languages = set( - ("C", "C++", "swig", "python", "asm", "isa", "scons", "make", "dts") - ) - trail_only = set(("make", "dts")) + languages = { + "C", + "C++", + "swig", + "python", + "asm", + "isa", + "scons", + "make", + "dts", + } + trail_only = {"make", "dts"} test_name = "whitespace" opt_name = "white" @@ -345,7 +353,7 @@ class SortedIncludes(Verifier): opt_name = "include" def __init__(self, *args, **kwargs): - super(SortedIncludes, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.sort_includes = sort_includes.SortIncludes() def check(self, filename, regions=all_regions, fobj=None, silent=False): @@ -404,7 +412,7 @@ class SortedIncludes(Verifier): class ControlSpace(LineVerifier): """Check for exactly one space after if/while/for""" - languages = set(("C", "C++")) + languages = {"C", "C++"} test_name = "spacing after if/while/for" opt_name = "control" @@ -420,7 +428,7 @@ class ControlSpace(LineVerifier): class LineLength(LineVerifier): - languages = set(("C", "C++", "swig", "python", "asm", "isa", "scons")) + languages = {"C", "C++", "swig", "python", "asm", "isa", "scons"} test_name = "line length" opt_name = "length" @@ -439,7 +447,7 @@ class LineLength(LineVerifier): class ControlCharacters(LineVerifier): - languages = set(("C", "C++", "swig", "python", "asm", "isa", "scons")) + languages = {"C", "C++", "swig", "python", "asm", "isa", "scons"} test_name = "control character" opt_name = "ascii" @@ -455,7 +463,7 @@ class ControlCharacters(LineVerifier): class BoolCompare(LineVerifier): - languages = set(("C", "C++", "python")) + languages = {"C", "C++", "python"} test_name = "boolean comparison" opt_name = "boolcomp" @@ -503,22 +511,22 @@ class StructureBraces(LineVerifier): : public BaseClass { """ - languages = set(("C", "C++")) + languages = {"C", "C++"} test_name = "structure opening brace position" opt_name = "structurebrace" # Matches the indentation of the line - regex_indentation = "(?P\s*)" + regex_indentation = r"(?P\s*)" # Matches an optional "typedef" before the keyword - regex_typedef = "(?P(typedef\s+)?)" + regex_typedef = r"(?P(typedef\s+)?)" # Matches the structure's keyword regex_keyword = "(?Pclass|struct|enum|union)" # A negative lookahead to avoid incorrect matches with variable's names # e.g., "classifications = {" should not be fixed here. - regex_avoid = "(?![^\{\s])" + regex_avoid = r"(?![^\{\s])" # Matches anything after the keyword and before the opening brace. # e.g., structure name, base type, type of inheritance, etc - regex_name = "(?P[^\{]*)" + regex_name = r"(?P[^\{]*)" # Matches anything after the opening brace, which should be # parsed recursively regex_extra = "(?P.*)$" @@ -529,7 +537,7 @@ class StructureBraces(LineVerifier): + regex_keyword + regex_avoid + regex_name - + "\{" + + r"\{" + regex_extra ) diff --git a/util/update_copyright/__init__.py b/util/update_copyright/__init__.py index 3b5a534696..a8bf92494b 100644 --- a/util/update_copyright/__init__.py +++ b/util/update_copyright/__init__.py @@ -79,7 +79,7 @@ def _update_copyright_years(m, cur_year, org_bytes): def update_copyright(data, cur_year, org_bytes): update_copyright_regexp = re.compile( - b" Copyright \\(c\\) ([0-9,\- ]+) " + org_bytes + b"\n", re.IGNORECASE + b" Copyright \\(c\\) ([0-9,\\- ]+) " + org_bytes + b"\n", re.IGNORECASE ) return update_copyright_regexp.sub( lambda m: _update_copyright_years(m, cur_year, org_bytes), From c4156b06fb6e393ce9d253eb2af6e042267e84f0 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 10 Oct 2023 11:46:56 -0700 Subject: [PATCH 437/693] python: Fix `base` logic in `MetaSimObject` This ensures `class Foo` is considered equivalent to `class Foo(object)`. Change-Id: I65a8aec27280a0806308bbc9d32281dfa6a8f84e --- src/python/m5/SimObject.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 8d9e0a4cb3..31b0f5d180 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -231,7 +231,10 @@ class MetaSimObject(type): "SimObjects do not support multiple inheritance" ) - base = bases[0] + # If the base class is not set, we assume type `object`. This ensures + # `class Foo(object): pass` is considered equivalent to + # `class Foo: pass`. + base = bases[0] if len(bases) > 0 else object # Set up general inheritance via multidicts. A subclass will # inherit all its settings from the base class. The only time From f65df9b959d8e2fc3b57d8204f481c2fca912b28 Mon Sep 17 00:00:00 2001 From: David Schall Date: Sun, 8 Oct 2023 17:30:54 +0000 Subject: [PATCH 438/693] cpu: Refactor indirect predictor Simplify indirect predictor interface. Several of the existing functions where merged together into four clear once. Those four are similar to the main direction predictor interface. 'lookup', 'update', 'squash' and 'commit'. This makes the interface much more clear, allows better functionality isolation and makes it simpler to develop new predictor models. A new parameter is added to allow additional buffer space for speculative path history. Change-Id: I6d6b43965b2986ef959953a64c428e50bc68d38e Signed-off-by: David Schall --- src/cpu/pred/BranchPredictor.py | 10 +- src/cpu/pred/bpred_unit.cc | 54 +++-- src/cpu/pred/indirect.hh | 83 ++++++-- src/cpu/pred/simple_indirect.cc | 351 +++++++++++++++++++++++--------- src/cpu/pred/simple_indirect.hh | 109 ++++++++-- 5 files changed, 446 insertions(+), 161 deletions(-) diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index 3bf5e52ae0..ed356b166d 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -100,6 +100,13 @@ class SimpleIndirectPredictor(IndirectPredictor): indirectPathLength = Param.Unsigned( 3, "Previous indirect targets to use for path history" ) + speculativePathLength = Param.Unsigned( + 256, + "Additional buffer space to store speculative path history. " + "If there are more speculative branches in flight the history cannot " + "be recovered. Set this to an appropriate value respective the CPU" + "pipeline depth or a high value e.g. 256 to make it 'unlimited'.", + ) indirectGHRBits = Param.Unsigned(13, "Indirect GHR number of bits") instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") @@ -119,7 +126,8 @@ class BranchPredictor(SimObject): indirectBranchPred = Param.IndirectPredictor( SimpleIndirectPredictor(), - "Indirect branch predictor, set to NULL to disable indirect predictions", + "Indirect branch predictor, set to NULL to disable " + "indirect predictions", ) diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index 85cb7c9e2f..813ac86f24 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -158,10 +158,6 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, tid, seqNum, pred_taken, pc); } - const bool orig_pred_taken = pred_taken; - if (iPred) { - iPred->genIndirectInfo(tid, indirect_history); - } DPRINTF(Branch, "[tid:%i] [sn:%llu] Creating prediction history for PC %s\n", @@ -250,11 +246,16 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, predict_record.wasIndirect = true; ++stats.indirectLookups; //Consult indirect predictor on indirect control - if (iPred->lookup(pc.instAddr(), *target, tid)) { + const PCStateBase *itarget = iPred->lookup(tid, + seqNum, pc.instAddr(), + predict_record.indirectHistory); + if (itarget) { // Indirect predictor hit ++stats.indirectHits; + set(target, *itarget); + DPRINTF(Branch, - "[tid:%i] [sn:%llu] Instruction %s predicted " + "[tid:%i, sn:%llu] Instruction %s predicted " "indirect target is %s\n", tid, seqNum, pc, *target); } else { @@ -262,9 +263,9 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, pred_taken = false; predict_record.predTaken = pred_taken; DPRINTF(Branch, - "[tid:%i] [sn:%llu] Instruction %s no indirect " - "target\n", - tid, seqNum, pc); + "[tid:%i, sn:%llu] PC:%#x no indirect target\n", + tid, seqNum, pc.instAddr()); + if (!inst->isCall() && !inst->isReturn()) { } else if (inst->isCall() && !inst->isUncondCtrl()) { @@ -273,8 +274,6 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, } inst->advancePC(*target); } - iPred->recordIndirect(pc.instAddr(), target->instAddr(), - seqNum, tid); } } } else { @@ -289,11 +288,10 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, if (iPred) { // Update the indirect predictor with the direction prediction - // Note that this happens after indirect lookup, so it does not use - // the new information - // Note also that we use orig_pred_taken instead of pred_taken in - // as this is the actual outcome of the direction prediction - iPred->updateDirectionInfo(tid, orig_pred_taken); + iPred->update(tid, seqNum, predict_record.pc, false, + predict_record.predTaken, *target, + getBranchType(inst), + predict_record.indirectHistory); } predHist[tid].push_front(predict_record); @@ -321,8 +319,10 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) predHist[tid].back().inst, predHist[tid].back().target); + // Commite also Indirect predictor and RAS if (iPred) { - iPred->commit(done_sn, tid, predHist[tid].back().indirectHistory); + iPred->commit(tid, predHist[tid].back().seqNum, + predHist[tid].back().indirectHistory); } predHist[tid].pop_back(); @@ -334,10 +334,6 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) { History &pred_hist = predHist[tid]; - if (iPred) { - iPred->squash(squashed_sn, tid); - } - while (!pred_hist.empty() && pred_hist.front().seqNum > squashed_sn) { if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) { @@ -369,7 +365,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) // This call should delete the bpHistory. squash(tid, pred_hist.front().bpHistory); if (iPred) { - iPred->deleteIndirectInfo(tid, pred_hist.front().indirectHistory); + iPred->squash(tid, pred_hist.front().seqNum, + pred_hist.front().indirectHistory); } DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " @@ -453,9 +450,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, pred_hist.front().bpHistory, true, pred_hist.front().inst, corr_target.instAddr()); + // Correct Indirect predictor ------------------- if (iPred) { - iPred->changeDirectionPrediction(tid, - pred_hist.front().indirectHistory, actually_taken); + iPred->update(tid, squashed_sn, (*hist_it).pc, + true, actually_taken, corr_target, + getBranchType(pred_hist.front().inst), + (*hist_it).indirectHistory); + } if (actually_taken) { @@ -470,11 +471,6 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, } if (hist_it->wasIndirect) { ++stats.indirectMispredicted; - if (iPred) { - iPred->recordTarget( - hist_it->seqNum, pred_hist.front().indirectHistory, - corr_target, tid); - } } else { DPRINTF(Branch,"[tid:%i] [squash sn:%llu] " "BTB Update called for [sn:%llu] " diff --git a/src/cpu/pred/indirect.hh b/src/cpu/pred/indirect.hh index 5f855b14fd..54c55d0dcb 100644 --- a/src/cpu/pred/indirect.hh +++ b/src/cpu/pred/indirect.hh @@ -1,6 +1,16 @@ /* * Copyright (c) 2014 ARM Limited - * All rights reserved. + * Copyright (c) 2023 The University of Edinburgh + * 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -26,11 +36,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* @file + * Indirect target predictor interface + */ + #ifndef __CPU_PRED_INDIRECT_BASE_HH__ #define __CPU_PRED_INDIRECT_BASE_HH__ #include "arch/generic/pcstate.hh" #include "cpu/inst_seq.hh" +#include "cpu/pred/branch_type.hh" #include "params/IndirectPredictor.hh" #include "sim/sim_object.hh" @@ -51,21 +66,57 @@ class IndirectPredictor : public SimObject { } - virtual bool lookup(Addr br_addr, PCStateBase& br_target, - ThreadID tid) = 0; - virtual void recordIndirect(Addr br_addr, Addr tgt_addr, - InstSeqNum seq_num, ThreadID tid) = 0; - virtual void commit(InstSeqNum seq_num, ThreadID tid, - void * indirect_history) = 0; - virtual void squash(InstSeqNum seq_num, ThreadID tid) = 0; - virtual void recordTarget(InstSeqNum seq_num, void * indirect_history, - const PCStateBase& target, ThreadID tid) = 0; - virtual void genIndirectInfo(ThreadID tid, void* & indirect_history) = 0; - virtual void updateDirectionInfo(ThreadID tid, bool actually_taken) = 0; - virtual void deleteIndirectInfo(ThreadID tid, void * indirect_history) = 0; - virtual void changeDirectionPrediction(ThreadID tid, - void * indirect_history, - bool actually_taken) = 0; + virtual void reset() {}; + + /** + * Predicts the indirect target of an indirect branch. + * @param tid Thread ID of the branch. + * @param sn The sequence number of the branch. + * @param pc The branch PC address. + * @param i_history The pointer to the history object. + * @return For a hit the predictor returns a pointer to the target PCState + * otherwise a nullptr is returned. + */ + virtual const PCStateBase* lookup(ThreadID tid, InstSeqNum sn, + Addr pc, void * &i_history) = 0; + + /** + * Updates the indirect predictor with history information of a branch. + * Is called right after the prediction which updates the state + * speculatively. In case the branch was mispredicted the function + * is called again with the corrected information. + * The function is called for ALL branches as some predictors incooperate + * all branches in their history. + * @param tid Thread ID + * @param sn The sequence number of the branch. + * @param pc The branch PC address. + * @param squash Whether the update is called at a misprediction + * @param taken Whether a conditional branch was taken + * @param target The target address if this branch. + * @param br_type The branch instruction type. + * @param i_history The pointer to the history object. + */ + virtual void update(ThreadID tid, InstSeqNum sn, Addr pc, bool squash, + bool taken, const PCStateBase& target, + BranchType br_type, void * &i_history) = 0; + + /** + * Squashes a branch. If the branch modified the history + * reverts the modification. + * @param tid Thread ID + * @param sn The sequence number of the branch. + * @param i_history The pointer to the history object. + */ + virtual void squash(ThreadID tid, InstSeqNum sn, void * &i_history) = 0; + + /** + * A branch gets finally commited. Updates the internal state of + * the indirect predictor (counter and target information). + * @param tid Thread ID + * @param sn The sequence number of the branch. + * @param i_history The pointer to the history object. + */ + virtual void commit(ThreadID tid, InstSeqNum sn, void * &i_history) = 0; }; } // namespace branch_prediction diff --git a/src/cpu/pred/simple_indirect.cc b/src/cpu/pred/simple_indirect.cc index f09cdeef55..815e8bf31b 100644 --- a/src/cpu/pred/simple_indirect.cc +++ b/src/cpu/pred/simple_indirect.cc @@ -1,6 +1,16 @@ /* * Copyright (c) 2014 ARM Limited - * All rights reserved. + * Copyright (c) 2022-2023 The University of Edinburgh + * 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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -46,9 +56,11 @@ SimpleIndirectPredictor::SimpleIndirectPredictor( numWays(params.indirectWays), tagBits(params.indirectTagSize), pathLength(params.indirectPathLength), + speculativePathLength(params.speculativePathLength), instShift(params.instShiftAmt), ghrNumBits(params.indirectGHRBits), - ghrMask((1 << params.indirectGHRBits)-1) + ghrMask((1 << params.indirectGHRBits)-1), + stats(this) { if (!isPowerOf2(numSets)) { panic("Indirect predictor requires power of 2 number of sets"); @@ -64,172 +76,292 @@ SimpleIndirectPredictor::SimpleIndirectPredictor( fatal_if(ghrNumBits > (sizeof(ThreadInfo::ghr)*8), "ghr_size is too big"); } + void -SimpleIndirectPredictor::genIndirectInfo(ThreadID tid, - void* & indirect_history) +SimpleIndirectPredictor::reset() { - // record the GHR as it was before this prediction + DPRINTF(Indirect, "Reset Indirect predictor\n"); + + for (auto& ti : threadInfo) { + ti.ghr = 0; + ti.pathHist.clear(); + } + + for (unsigned i = 0; i < numSets; i++) { + for (unsigned j = 0; j < numWays; j++) { + targetCache[i][j].tag = 0; + } + } +} + + +void +SimpleIndirectPredictor::genIndirectInfo(ThreadID tid, void* &i_history) +{ + // Record the GHR as it was before this prediction // It will be used to recover the history in case this prediction is // wrong or belongs to bad path - indirect_history = new unsigned(threadInfo[tid].ghr); + IndirectHistory* history = new IndirectHistory; + history->ghr = threadInfo[tid].ghr; + i_history = static_cast(history); } void -SimpleIndirectPredictor::updateDirectionInfo( - ThreadID tid, bool actually_taken) +SimpleIndirectPredictor::updateDirectionInfo(ThreadID tid, bool taken, + Addr pc, Addr target) { + // Direction history threadInfo[tid].ghr <<= 1; - threadInfo[tid].ghr |= actually_taken; + threadInfo[tid].ghr |= taken; threadInfo[tid].ghr &= ghrMask; } -void -SimpleIndirectPredictor::changeDirectionPrediction(ThreadID tid, - void * indirect_history, bool actually_taken) + + +// Interface methods ------------------------------ +const PCStateBase * +SimpleIndirectPredictor::lookup(ThreadID tid, InstSeqNum sn, + Addr pc, void * &i_history) { - unsigned * previousGhr = static_cast(indirect_history); - threadInfo[tid].ghr = ((*previousGhr) << 1) + actually_taken; - threadInfo[tid].ghr &= ghrMask; + assert(i_history==nullptr); + + genIndirectInfo(tid, i_history); + IndirectHistory *history = static_cast(i_history); + + history->pcAddr = pc; + history->was_indirect = true; + + /** Do the prediction for indirect branches (no returns) */ + PCStateBase* target = nullptr; + history->hit = lookup(tid, pc, target, history); + return target; } bool -SimpleIndirectPredictor::lookup(Addr br_addr, PCStateBase& target, - ThreadID tid) +SimpleIndirectPredictor::lookup(ThreadID tid, Addr br_addr, + PCStateBase * &target, + IndirectHistory * &history) { - Addr set_index = getSetIndex(br_addr, threadInfo[tid].ghr, tid); - Addr tag = getTag(br_addr); - assert(set_index < numSets); + history->set_index = getSetIndex(br_addr, tid); + history->tag = getTag(br_addr); + assert(history->set_index < numSets); + stats.lookups++; - DPRINTF(Indirect, "Looking up %x (set:%d)\n", br_addr, set_index); - const auto &iset = targetCache[set_index]; + DPRINTF(Indirect, "Looking up PC:%#x, (set:%d, tag:%d), " + "ghr:%#x, pathHist sz:%#x\n", + history->pcAddr, history->set_index, history->tag, + history->ghr, threadInfo[tid].pathHist.size()); + + const auto &iset = targetCache[history->set_index]; for (auto way = iset.begin(); way != iset.end(); ++way) { // tag may be 0 and match the default in way->tag, so we also have to // check that way->target has been initialized. - if (way->tag == tag && way->target) { + if (way->tag == history->tag && way->target) { DPRINTF(Indirect, "Hit %x (target:%s)\n", br_addr, *way->target); set(target, *way->target); - return true; + history->hit = true; + stats.hits++; + return history->hit; } } DPRINTF(Indirect, "Miss %x\n", br_addr); - return false; + history->hit = false; + stats.misses++; + return history->hit; +} + + +void +SimpleIndirectPredictor::commit(ThreadID tid, InstSeqNum sn, void * &i_history) +{ + if (i_history == nullptr) return; + // we do not need to recover the GHR, so delete the information + IndirectHistory *history = static_cast(i_history); + + DPRINTF(Indirect, "Committing seq:%d, PC:%#x, ghr:%#x, pathHist sz:%lu\n", + sn, history->pcAddr, history->ghr, + threadInfo[tid].pathHist.size()); + + delete history; + i_history = nullptr; + + /** Delete histories if the history grows to much */ + while (threadInfo[tid].pathHist.size() + >= (pathLength + speculativePathLength)) { + + threadInfo[tid].pathHist.pop_front(); + } } void -SimpleIndirectPredictor::recordIndirect(Addr br_addr, Addr tgt_addr, - InstSeqNum seq_num, ThreadID tid) +SimpleIndirectPredictor::update(ThreadID tid, InstSeqNum sn, Addr pc, + bool squash, bool taken, const PCStateBase& target, + BranchType br_type, void * &i_history) { - DPRINTF(Indirect, "Recording %x seq:%d\n", br_addr, seq_num); - HistoryEntry entry(br_addr, tgt_addr, seq_num); - threadInfo[tid].pathHist.push_back(entry); + // If there is no history we did not use the indirect predictor yet. + // Create one + if (i_history==nullptr) { + genIndirectInfo(tid, i_history); + } + IndirectHistory *history = static_cast(i_history); + assert(history!=nullptr); + + DPRINTF(Indirect, "Update sn:%i PC:%#x, squash:%i, ghr:%#x,path sz:%i\n", + sn, pc, squash, history->ghr, threadInfo[tid].pathHist.size()); + + /** If update was called during squash we need to fix the indirect + * path history and the global path history. + * We restore the state before this branch incorrectly updated it + * and perform the update afterwards again. + */ + history->was_indirect = isIndirectNoReturn(br_type); + if (squash) { + + /** restore global history */ + threadInfo[tid].ghr = history->ghr; + + /** For indirect branches recalculate index and tag */ + if (history->was_indirect) { + if (!threadInfo[tid].pathHist.empty()) { + threadInfo[tid].pathHist.pop_back(); + } + + history->set_index = getSetIndex(history->pcAddr, tid); + history->tag = getTag(history->pcAddr); + + DPRINTF(Indirect, "Record Target seq:%d, PC:%#x, TGT:%#x, " + "ghr:%#x, (set:%x, tag:%x)\n", + sn, history->pcAddr, target, history->ghr, + history->set_index, history->tag); + } + } + + // Only indirect branches are recorded in the path history + if (history->was_indirect) { + + DPRINTF(Indirect, "Recording %x seq:%d\n", history->pcAddr, sn); + threadInfo[tid].pathHist.emplace_back( + history->pcAddr, target.instAddr(), sn); + + stats.indirectRecords++; + } + + // All branches update the global history + updateDirectionInfo(tid,taken, history->pcAddr, target.instAddr()); + + // Finally if update is called during at squash we know the target + // we predicted was wrong therefore we update the target. + // We only record the target if the branch was indirect and taken + if (squash && history->was_indirect && taken) + recordTarget(tid, sn, target, history); } + + void -SimpleIndirectPredictor::commit(InstSeqNum seq_num, ThreadID tid, - void * indirect_history) +SimpleIndirectPredictor::squash(ThreadID tid, InstSeqNum sn, void * &i_history) { - DPRINTF(Indirect, "Committing seq:%d\n", seq_num); - ThreadInfo &t_info = threadInfo[tid]; + if (i_history == nullptr) return; // we do not need to recover the GHR, so delete the information - unsigned * previousGhr = static_cast(indirect_history); - delete previousGhr; + IndirectHistory *history = static_cast(i_history); - if (t_info.pathHist.empty()) return; + DPRINTF(Indirect, "Squashing seq:%d, PC:%#x, indirect:%i, " + "ghr:%#x, pathHist sz:%#x\n", + sn, history->pcAddr, history->was_indirect, + history->ghr, + threadInfo[tid].pathHist.size()); - if (t_info.headHistEntry < t_info.pathHist.size() && - t_info.pathHist[t_info.headHistEntry].seqNum <= seq_num) { - if (t_info.headHistEntry >= pathLength) { - t_info.pathHist.pop_front(); - } else { - ++t_info.headHistEntry; + + // Revert the global history register. + threadInfo[tid].ghr = history->ghr; + + // If we record this branch as indirect branch + // remove it from the history. + // Restore the old head in the history. + if (history->was_indirect) { + + // Should not be empty + if (threadInfo[tid].pathHist.size() < pathLength) { + stats.speculativeOverflows++; + } + + if (!threadInfo[tid].pathHist.empty()) { + threadInfo[tid].pathHist.pop_back(); } } + + delete history; + i_history = nullptr; } -void -SimpleIndirectPredictor::squash(InstSeqNum seq_num, ThreadID tid) -{ - DPRINTF(Indirect, "Squashing seq:%d\n", seq_num); - ThreadInfo &t_info = threadInfo[tid]; - auto squash_itr = t_info.pathHist.begin(); - while (squash_itr != t_info.pathHist.end()) { - if (squash_itr->seqNum > seq_num) { - break; - } - ++squash_itr; - } - if (squash_itr != t_info.pathHist.end()) { - DPRINTF(Indirect, "Squashing series starting with sn:%d\n", - squash_itr->seqNum); - } - t_info.pathHist.erase(squash_itr, t_info.pathHist.end()); -} + + + +// Internal functions ------------------------------ + + void -SimpleIndirectPredictor::deleteIndirectInfo(ThreadID tid, - void * indirect_history) +SimpleIndirectPredictor::recordTarget(ThreadID tid, InstSeqNum sn, + const PCStateBase& target, IndirectHistory * &history) { - unsigned * previousGhr = static_cast(indirect_history); - threadInfo[tid].ghr = *previousGhr; - - delete previousGhr; -} - -void -SimpleIndirectPredictor::recordTarget( - InstSeqNum seq_num, void * indirect_history, const PCStateBase& target, - ThreadID tid) -{ - ThreadInfo &t_info = threadInfo[tid]; - - unsigned * ghr = static_cast(indirect_history); - // Should have just squashed so this branch should be the oldest - auto hist_entry = *(t_info.pathHist.rbegin()); - // Temporarily pop it off the history so we can calculate the set - t_info.pathHist.pop_back(); - Addr set_index = getSetIndex(hist_entry.pcAddr, *ghr, tid); - Addr tag = getTag(hist_entry.pcAddr); - hist_entry.targetAddr = target.instAddr(); - t_info.pathHist.push_back(hist_entry); + // and it should be predicted as indirect. + assert(!threadInfo[tid].pathHist.empty()); + assert(history->was_indirect); - assert(set_index < numSets); + if (threadInfo[tid].pathHist.rbegin()->pcAddr != history->pcAddr) { + DPRINTF(Indirect, "History seems to be corrupted. %#x != %#x\n", + history->pcAddr, + threadInfo[tid].pathHist.rbegin()->pcAddr); + } - auto &iset = targetCache[set_index]; + DPRINTF(Indirect, "Record Target seq:%d, PC:%#x, TGT:%#x, " + "ghr:%#x, (set:%x, tag:%x)\n", + sn, history->pcAddr, target.instAddr(), history->ghr, + history->set_index, history->tag); + + assert(history->set_index < numSets); + stats.targetRecords++; + + // Update the target cache + auto &iset = targetCache[history->set_index]; for (auto way = iset.begin(); way != iset.end(); ++way) { - if (way->tag == tag) { - DPRINTF(Indirect, "Updating Target (seq: %d br:%x set:%d target:" - "%s)\n", seq_num, hist_entry.pcAddr, set_index, target); + if (way->tag == history->tag) { + DPRINTF(Indirect, + "Updating Target (seq: %d br:%x set:%d target:%s)\n", + sn, history->pcAddr, history->set_index, target); set(way->target, target); return; } } DPRINTF(Indirect, "Allocating Target (seq: %d br:%x set:%d target:%s)\n", - seq_num, hist_entry.pcAddr, set_index, target); + sn, history->pcAddr, history->set_index, target); + // Did not find entry, random replacement auto &way = iset[rand() % numWays]; - way.tag = tag; + way.tag = history->tag; set(way.target, target); } -inline Addr -SimpleIndirectPredictor::getSetIndex(Addr br_addr, unsigned ghr, ThreadID tid) -{ - ThreadInfo &t_info = threadInfo[tid]; + +inline Addr +SimpleIndirectPredictor::getSetIndex(Addr br_addr, ThreadID tid) +{ Addr hash = br_addr >> instShift; if (hashGHR) { - hash ^= ghr; + hash ^= threadInfo[tid].ghr; } if (hashTargets) { unsigned hash_shift = floorLog2(numSets) / pathLength; - for (int i = t_info.pathHist.size()-1, p = 0; + for (int i = threadInfo[tid].pathHist.size()-1, p = 0; i >= 0 && p < pathLength; i--, p++) { - hash ^= (t_info.pathHist[i].targetAddr >> + hash ^= (threadInfo[tid].pathHist[i].targetAddr >> (instShift + p*hash_shift)); } } @@ -242,5 +374,26 @@ SimpleIndirectPredictor::getTag(Addr br_addr) return (br_addr >> instShift) & ((0x1< +#include "base/statistics.hh" #include "cpu/inst_seq.hh" #include "cpu/pred/indirect.hh" #include "params/SimpleIndirectPredictor.hh" @@ -46,19 +57,23 @@ class SimpleIndirectPredictor : public IndirectPredictor public: SimpleIndirectPredictor(const SimpleIndirectPredictorParams ¶ms); - bool lookup(Addr br_addr, PCStateBase& br_target, ThreadID tid); - void recordIndirect(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num, - ThreadID tid); - void commit(InstSeqNum seq_num, ThreadID tid, void * indirect_history); - void squash(InstSeqNum seq_num, ThreadID tid); - void recordTarget(InstSeqNum seq_num, void * indirect_history, - const PCStateBase& target, ThreadID tid); - void genIndirectInfo(ThreadID tid, void* & indirect_history); - void updateDirectionInfo(ThreadID tid, bool actually_taken); - void deleteIndirectInfo(ThreadID tid, void * indirect_history); - void changeDirectionPrediction(ThreadID tid, void * indirect_history, - bool actually_taken); + /** Indirect predictor interface */ + void reset() override; + const PCStateBase * lookup(ThreadID tid, InstSeqNum sn, + Addr pc, void * &iHistory) override; + void update(ThreadID tid, InstSeqNum sn, Addr pc, bool squash, + bool taken, const PCStateBase& target, + BranchType br_type, void * &iHistory) override; + void squash(ThreadID tid, InstSeqNum sn, void * &iHistory) override; + void commit(ThreadID tid, InstSeqNum sn, void * &iHistory) override; + + + + /** ------------------ + * The actual predictor + * ------------------- + * */ private: const bool hashGHR; const bool hashTargets; @@ -66,6 +81,7 @@ class SimpleIndirectPredictor : public IndirectPredictor const unsigned numWays; const unsigned tagBits; const unsigned pathLength; + const unsigned speculativePathLength; const unsigned instShift; const unsigned ghrNumBits; const unsigned ghrMask; @@ -78,27 +94,88 @@ class SimpleIndirectPredictor : public IndirectPredictor std::vector > targetCache; - Addr getSetIndex(Addr br_addr, unsigned ghr, ThreadID tid); - Addr getTag(Addr br_addr); + struct HistoryEntry { HistoryEntry(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num) : pcAddr(br_addr), targetAddr(tgt_addr), seqNum(seq_num) { } + HistoryEntry() : pcAddr(0), targetAddr(0), seqNum(0) { } Addr pcAddr; Addr targetAddr; InstSeqNum seqNum; }; + /** Indirect branch history information + * Used for prediction, update and recovery + */ + struct IndirectHistory + { + /* data */ + Addr pcAddr; + Addr targetAddr; + InstSeqNum seqNum; + Addr set_index; + Addr tag; + bool hit; + unsigned ghr; + uint64_t pathHist; + + bool was_indirect; + + IndirectHistory() + : pcAddr(MaxAddr), + targetAddr(MaxAddr), + was_indirect(false) + {} + }; + + /** Per thread path and global history registers*/ struct ThreadInfo { + // Path history register std::deque pathHist; - unsigned headHistEntry = 0; + // Global direction history register unsigned ghr = 0; }; std::vector threadInfo; + + + // ---- Internal functions ----- // + bool lookup(ThreadID tid, Addr br_addr, + PCStateBase * &target, IndirectHistory * &history); + void recordTarget(ThreadID tid, InstSeqNum sn, + const PCStateBase& target, IndirectHistory * &history); + + // Helper functions to generate and modify the + // direction info + void genIndirectInfo(ThreadID tid, void* &iHistory); + void updateDirectionInfo(ThreadID tid, bool taken, Addr pc, Addr target); + + // Helper to compute set and tag + inline Addr getSetIndex(Addr br_addr, ThreadID tid); + inline Addr getTag(Addr br_addr); + + inline bool isIndirectNoReturn(BranchType type) { + return (type == BranchType::CallIndirect) || + (type == BranchType::IndirectUncond); + } + + protected: + struct IndirectStats : public statistics::Group + { + IndirectStats(statistics::Group *parent); + // STATS + statistics::Scalar lookups; + statistics::Scalar hits; + statistics::Scalar misses; + statistics::Scalar targetRecords; + statistics::Scalar indirectRecords; + statistics::Scalar speculativeOverflows; + + } stats; }; } // namespace branch_prediction From 4b85a1710e0b33424de7315a08a9fbd08abd0ae2 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 6 Oct 2023 11:22:46 -0500 Subject: [PATCH 439/693] arch-vega: Implement buffer_atomic_cmpswap This is a standard compare and swap but implemented on vector memory buffer instructions (i.e., it is the same as FLAT_ATOMIC_CMPSWAP with MUBUF's special address calculation). This was tested using a Tensile kernel, a backend for rocBLAS, which is used by PyTorch and Tensorflow. Prior to this patch both ML frameworks crashed. With this patch they both make forward progress. Change-Id: Ie76447a72d210f81624e01e1fa374e41c2c21e06 --- src/arch/amdgpu/vega/insts/instructions.cc | 81 +++++++++++++++++++++- src/arch/amdgpu/vega/insts/instructions.hh | 2 + src/arch/amdgpu/vega/insts/op_encodings.hh | 13 ++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index bb6a2233cd..287c9a9541 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -40581,8 +40581,87 @@ namespace VegaISA void Inst_MUBUF__BUFFER_ATOMIC_CMPSWAP::execute(GPUDynInstPtr gpuDynInst) { - panicUnimplemented(); + Wavefront *wf = gpuDynInst->wavefront(); + + if (gpuDynInst->exec_mask.none()) { + wf->decVMemInstsIssued(); + return; + } + + gpuDynInst->execUnitId = wf->execUnitId; + gpuDynInst->latency.init(gpuDynInst->computeUnit()); + gpuDynInst->latency.set(gpuDynInst->computeUnit()->clockPeriod()); + + ConstVecOperandU32 addr0(gpuDynInst, extData.VADDR); + ConstVecOperandU32 addr1(gpuDynInst, extData.VADDR + 1); + ConstScalarOperandU128 rsrcDesc(gpuDynInst, extData.SRSRC * 4); + ConstScalarOperandU32 offset(gpuDynInst, extData.SOFFSET); + ConstVecOperandU32 src(gpuDynInst, extData.VDATA); + ConstVecOperandU32 cmp(gpuDynInst, extData.VDATA + 1); + + rsrcDesc.read(); + offset.read(); + src.read(); + cmp.read(); + + int inst_offset = instData.OFFSET; + + if (!instData.IDXEN && !instData.OFFEN) { + calcAddr(gpuDynInst, + addr0, addr1, rsrcDesc, offset, inst_offset); + } else if (!instData.IDXEN && instData.OFFEN) { + addr0.read(); + calcAddr(gpuDynInst, + addr0, addr1, rsrcDesc, offset, inst_offset); + } else if (instData.IDXEN && !instData.OFFEN) { + addr0.read(); + calcAddr(gpuDynInst, + addr1, addr0, rsrcDesc, offset, inst_offset); + } else { + addr0.read(); + addr1.read(); + calcAddr(gpuDynInst, + addr1, addr0, rsrcDesc, offset, inst_offset); + } + + for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) { + if (gpuDynInst->exec_mask[lane]) { + (reinterpret_cast(gpuDynInst->x_data))[lane] + = src[lane]; + (reinterpret_cast(gpuDynInst->a_data))[lane] + = cmp[lane]; + } + } + + gpuDynInst->computeUnit()->globalMemoryPipe.issueRequest(gpuDynInst); } // execute + + void + Inst_MUBUF__BUFFER_ATOMIC_CMPSWAP::initiateAcc(GPUDynInstPtr gpuDynInst) + { + initAtomicAccess(gpuDynInst); + } // initiateAcc + + void + Inst_MUBUF__BUFFER_ATOMIC_CMPSWAP::completeAcc(GPUDynInstPtr gpuDynInst) + { + if (isAtomicRet()) { + VecOperandU32 vdst(gpuDynInst, extData.VDATA); + + for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) { + if (gpuDynInst->exec_mask[lane]) { + vdst[lane] = (reinterpret_cast( + gpuDynInst->d_data))[lane]; + } + } + + vdst.write(); + } + } // completeAcc // --- Inst_MUBUF__BUFFER_ATOMIC_ADD class methods --- Inst_MUBUF__BUFFER_ATOMIC_ADD diff --git a/src/arch/amdgpu/vega/insts/instructions.hh b/src/arch/amdgpu/vega/insts/instructions.hh index 0e4ec04764..ca349c365f 100644 --- a/src/arch/amdgpu/vega/insts/instructions.hh +++ b/src/arch/amdgpu/vega/insts/instructions.hh @@ -37220,6 +37220,8 @@ namespace VegaISA } // getOperandSize void execute(GPUDynInstPtr) override; + void initiateAcc(GPUDynInstPtr) override; + void completeAcc(GPUDynInstPtr) override; }; // Inst_MUBUF__BUFFER_ATOMIC_CMPSWAP class Inst_MUBUF__BUFFER_ATOMIC_ADD : public Inst_MUBUF diff --git a/src/arch/amdgpu/vega/insts/op_encodings.hh b/src/arch/amdgpu/vega/insts/op_encodings.hh index 613d78b25e..a1c5e99c91 100644 --- a/src/arch/amdgpu/vega/insts/op_encodings.hh +++ b/src/arch/amdgpu/vega/insts/op_encodings.hh @@ -713,6 +713,19 @@ namespace VegaISA gpuDynInst->exec_mask = old_exec_mask; } + template + void + initAtomicAccess(GPUDynInstPtr gpuDynInst) + { + // temporarily modify exec_mask to supress memory accesses to oob + // regions. Only issue memory requests for lanes that have their + // exec_mask set and are not out of bounds. + VectorMask old_exec_mask = gpuDynInst->exec_mask; + gpuDynInst->exec_mask &= ~oobMask; + initMemReqHelper(gpuDynInst, MemCmd::SwapReq, true); + gpuDynInst->exec_mask = old_exec_mask; + } + void injectGlobalMemFence(GPUDynInstPtr gpuDynInst) { From 4b7f25fcb6b4e72c92c8105e4e6745d8a1144983 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 11 Oct 2023 15:51:00 -0500 Subject: [PATCH 440/693] arch-vega: Ignore s_setprio instruction instead of panic This instruction is used by ML frameworks to prioritize certain wavefronts. Since gem5 does not have any support for wavefront scheduling based on priority (besides wavefront age), we ignore this instruction and warn_once rather than calling panic. Since hardware can override this priority anyways, we can be sure that ignoring the value will not inhibit forward progress resulting in application hangs. Change-Id: Ic5eef14f9685dd2b316c5cf76078bb78d5bfe3cc --- src/arch/amdgpu/vega/insts/instructions.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index bb6a2233cd..510d6d924b 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -4728,6 +4728,7 @@ namespace VegaISA Inst_SOPP__S_SETPRIO::Inst_SOPP__S_SETPRIO(InFmt_SOPP *iFmt) : Inst_SOPP(iFmt, "s_setprio") { + setFlag(ALU); } // Inst_SOPP__S_SETPRIO Inst_SOPP__S_SETPRIO::~Inst_SOPP__S_SETPRIO() @@ -4742,7 +4743,10 @@ namespace VegaISA void Inst_SOPP__S_SETPRIO::execute(GPUDynInstPtr gpuDynInst) { - panicUnimplemented(); + ScalarRegU16 simm16 = instData.SIMM16; + ScalarRegU32 userPrio = simm16 & 0x3; + + warn_once("S_SETPRIO ignored -- Requested priority %d\n", userPrio); } // execute // --- Inst_SOPP__S_SENDMSG class methods --- From f7ad8fe4350be7d4299b22d9030385e3f261c7d8 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 11 Oct 2023 14:20:27 -0700 Subject: [PATCH 441/693] configs: GPUFS option to disable KVM perf counters (#433) Add a --no-kvm-perf option to disable KVM perf counters for GPUFS scripts. This is useful for users who have KVM enabled but configured with more restrictive settings, which seems to be the default in newer Linux distros. Change-Id: I7508113d0f7c74deb21ea7b2770522885a0ec822 --- configs/example/gpufs/runfs.py | 7 +++++++ configs/example/gpufs/system/system.py | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index 5d29959eff..8192503373 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -168,6 +168,13 @@ def addRunFSOptions(parser): "be disabled for correct functionality ", ) + parser.add_argument( + "--no-kvm-perf", + default=False, + action="store_true", + help="Disable KVM perf counters (use this with LSF / ETX)", + ) + def runGpuFSSystem(args): """ diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index 241b68c2b9..ee0e0c0fbf 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -296,6 +296,12 @@ def makeGpuFSSystem(args): obj.eventq_index = 0 cpu.eventq_index = i + 1 + # Disable KVM Perf counters if specified. This is useful for machines + # with more restrictive KVM paranoid levels. + if args.no_kvm_perf and ObjectList.is_kvm_cpu(TestCPUClass): + for i, cpu in enumerate(system.cpu[:-1]): + cpu.usePerf = False + gpu_port_idx = ( len(system.ruby._cpu_ports) - args.num_compute_units From 3816ea563352d94d7b5de48010fccc9fc60d4c27 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 12 Oct 2023 07:00:19 -0700 Subject: [PATCH 442/693] misc,tests: Add dummy jobs to workflows for status checks Change-Id: I52e42b6f93cfbb1a8e4800a3f6e264d49bebb06c --- .github/workflows/compiler-tests.yaml | 13 +++++++++++++ .github/workflows/daily-tests.yaml | 16 ++++++++++++++++ .github/workflows/weekly-tests.yaml | 12 ++++++++++++ 3 files changed, 41 insertions(+) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 6e25720f2e..1a340e0bf5 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -55,3 +55,16 @@ jobs: - name: Compile build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} with ${{ matrix.image }} run: /usr/bin/env python3 /usr/bin/scons --ignore-style build/${{ matrix.gem5-compilation }}/gem5${{ matrix.opts }} -j$(nproc) timeout-minutes: 600 # 10 hours + + compiler-tests: + # The dummy job is used to indicate whether the compiler tests have + # passed or not. This can be used as status check for pull requests. + # I.e., if we want to stop pull requests from being merged if the + # compiler tests are failing, we can add this job as a required status + # check. + runs-on: ubuntu-22.04 + needs: + - latest-compilers-all-gem5-builds + - all-compilers + steps: + - run: echo "This compiler tests have passed." diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 351c0301be..06423d95e4 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -284,3 +284,19 @@ jobs: - name: Run allSyncPrims-1kernel lfTreeBarrUsing test with GCN3_X86/gem5.opt (SE mode) run: ./build/GCN3_X86/gem5.opt configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c allSyncPrims-1kernel --options="lfTreeBarrUniq 10 16 4" + daily-tests: + # The dummy job is used to indicate whether the daily tests have + # passed or not. This can be used as status check for pull requests. + # I.e., if we want to stop pull requests from being merged if the + # daily tests are failing we can add this job as a required status + # check. + runs-on: ubuntu-22.04 + needs: + - unittests-fast-debug + - testlib-long-tests + - testlib-long-gem5_library_example_tests + - sst-test + - systemc-test + - gpu-tests + steps: + - run: echo "This daily tests have passed." diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index d322833153..b21613f7a1 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -106,3 +106,15 @@ jobs: ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/arm-hello-dramsys.py ./build/ALL/gem5.opt configs/example/gem5_library/dramsys/dramsys-traffic.py ./build/ALL/gem5.opt configs/example/dramsys.py + weekly-tests: + # The dummy job is used to indicate whether the weekly tests have + # passed or not. This can be used as status check for pull requests. + # I.e., if we want to stop pull requests from being merged if the + # weekly tests are failing we can add this job as a required status + # check. + runs-on: ubuntu-22.04 + needs: + - testlib-very-long-tests + - dramsys-tests + steps: + - run: echo "This weekly tests have passed." From bf1c10d4b2df4bbe56c6a834e138c7f400ef8940 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 12 Oct 2023 07:37:11 -0700 Subject: [PATCH 443/693] tests,misc: Update CI Tests 'testlib-quick' runs-on Here it's more sensible to use a GitHub hosted runner. This job is miniscule and is used to check the other tests have completed successfully. It makes sense for this not to be on our own self-hosted runner. Change-Id: I5377e025334d43eaedd0fc61e5c708ba61255d28 --- .github/workflows/ci-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index b1905c30ec..08ec318660 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -173,7 +173,7 @@ jobs: # merged. The 'testlib-quick-execution' is a matrix job which runs all the # the testlib quick tests. This job is therefore a stub which will pass if # all the testlib-quick-execution jobs pass. - runs-on: [self-hosted, linux, x64] + runs-on: ubuntu-22.04 needs: testlib-quick-execution steps: - run: echo "This job's status is ${{ job.status }}." From 08c1af1b16150e68c17acf877249b5017a08f975 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Thu, 12 Oct 2023 14:49:06 -0500 Subject: [PATCH 444/693] mem-ruby: Use RubyPort vector to access Ruby in cache recorder Previously, the cache recorder used a vector of sequencer pointers to access Ruby objects. A recent commit updated the cache recorder to also maintain a vector of GPUCoalescer pointers in order for GPUs to support flushin. This added redundant code to the cache recorder. This commit replaces the sequencer and GPUCoalescer vectors with a vector of RubyPort pointers so that the code does not contain redundant lines Change-Id: Id5da33fb870f17bb9daef816cc43c0bcd70a8706 --- src/mem/ruby/system/CacheRecorder.cc | 65 ++++++---------------------- src/mem/ruby/system/CacheRecorder.hh | 21 ++------- src/mem/ruby/system/RubySystem.cc | 50 +++++++-------------- 3 files changed, 33 insertions(+), 103 deletions(-) diff --git a/src/mem/ruby/system/CacheRecorder.cc b/src/mem/ruby/system/CacheRecorder.cc index 057b6aa041..3326856849 100644 --- a/src/mem/ruby/system/CacheRecorder.cc +++ b/src/mem/ruby/system/CacheRecorder.cc @@ -31,7 +31,6 @@ #include "debug/RubyCacheTrace.hh" #include "mem/packet.hh" -#include "mem/ruby/system/GPUCoalescer.hh" #include "mem/ruby/system/RubySystem.hh" #include "mem/ruby/system/Sequencer.hh" #include "sim/sim_exit.hh" @@ -57,29 +56,16 @@ CacheRecorder::CacheRecorder() { } -#if BUILD_GPU CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, uint64_t uncompressed_trace_size, - std::vector& seq_map, - std::vector& coal_map, + std::vector& ruby_port_map, uint64_t block_size_bytes) : m_uncompressed_trace(uncompressed_trace), m_uncompressed_trace_size(uncompressed_trace_size), - m_seq_map(seq_map), m_coalescer_map(coal_map), m_bytes_read(0), - m_records_read(0), m_records_flushed(0), - m_block_size_bytes(block_size_bytes) -#else -CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, - uint64_t uncompressed_trace_size, - std::vector& seq_map, - uint64_t block_size_bytes) - : m_uncompressed_trace(uncompressed_trace), - m_uncompressed_trace_size(uncompressed_trace_size), - m_seq_map(seq_map), m_bytes_read(0), + m_ruby_port_map(ruby_port_map), m_bytes_read(0), m_records_read(0), m_records_flushed(0), m_block_size_bytes(block_size_bytes) -#endif { if (m_uncompressed_trace != NULL) { if (m_block_size_bytes < RubySystem::getBlockSizeBytes()) { @@ -98,10 +84,7 @@ CacheRecorder::~CacheRecorder() delete [] m_uncompressed_trace; m_uncompressed_trace = NULL; } - m_seq_map.clear(); -#if BUILD_GPU - m_coalescer_map.clear(); -#endif + m_ruby_port_map.clear(); } void @@ -115,22 +98,12 @@ CacheRecorder::enqueueNextFlushRequest() Request::funcRequestorId); MemCmd::Command requestType = MemCmd::FlushReq; Packet *pkt = new Packet(req, requestType); + pkt->req->setReqInstSeqNum(m_records_flushed); - Sequencer* m_sequencer_ptr = m_seq_map[rec->m_cntrl_id]; -#if BUILD_GPU - GPUCoalescer* m_coal_ptr = m_coalescer_map[rec->m_cntrl_id]; -#endif - assert(m_sequencer_ptr != NULL); -#if BUILD_GPU - if (m_coal_ptr == NULL) - m_sequencer_ptr->makeRequest(pkt); - else { - pkt->req->setReqInstSeqNum(m_records_flushed - 1); - m_coal_ptr->makeRequest(pkt); - } -#else - m_sequencer_ptr->makeRequest(pkt); -#endif + + RubyPort* m_ruby_port_ptr = m_ruby_port_map[rec->m_cntrl_id]; + assert(m_ruby_port_ptr != NULL); + m_ruby_port_ptr->makeRequest(pkt); DPRINTF(RubyCacheTrace, "Flushing %s\n", *rec); @@ -178,23 +151,13 @@ CacheRecorder::enqueueNextFetchRequest() Packet *pkt = new Packet(req, requestType); pkt->dataStatic(traceRecord->m_data + rec_bytes_read); + pkt->req->setReqInstSeqNum(m_records_read); - Sequencer* m_sequencer_ptr = m_seq_map[traceRecord->m_cntrl_id]; -#if BUILD_GPU - GPUCoalescer* m_coal_ptr; - m_coal_ptr = m_coalescer_map[traceRecord->m_cntrl_id]; -#endif - assert(m_sequencer_ptr != NULL); -#if BUILD_GPU - if (m_coal_ptr == NULL) - m_sequencer_ptr->makeRequest(pkt); - else { - pkt->req->setReqInstSeqNum(m_records_read); - m_coal_ptr->makeRequest(pkt); - } -#else - m_sequencer_ptr->makeRequest(pkt); -#endif + + RubyPort* m_ruby_port_ptr = + m_ruby_port_map[traceRecord->m_cntrl_id]; + assert(m_ruby_port_ptr != NULL); + m_ruby_port_ptr->makeRequest(pkt); } m_bytes_read += (sizeof(TraceRecord) + m_block_size_bytes); diff --git a/src/mem/ruby/system/CacheRecorder.hh b/src/mem/ruby/system/CacheRecorder.hh index e94dfad97a..021da6a4da 100644 --- a/src/mem/ruby/system/CacheRecorder.hh +++ b/src/mem/ruby/system/CacheRecorder.hh @@ -38,7 +38,6 @@ #include #include "base/types.hh" -#include "config/build_gpu.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/common/TypeDefines.hh" @@ -51,10 +50,7 @@ namespace ruby { class Sequencer; -#if BUILD_GPU -class GPUCoalescer; -#endif - +class RubyPort; /*! * Class for recording cache contents. Note that the last element of the * class is an array of length zero. It is used for creating variable @@ -80,18 +76,10 @@ class CacheRecorder CacheRecorder(); ~CacheRecorder(); -#if BUILD_GPU CacheRecorder(uint8_t* uncompressed_trace, uint64_t uncompressed_trace_size, - std::vector& SequencerMap, - std::vector& CoalescerMap, + std::vector& ruby_port_map, uint64_t block_size_bytes); -#else - CacheRecorder(uint8_t* uncompressed_trace, - uint64_t uncompressed_trace_size, - std::vector& SequencerMap, - uint64_t block_size_bytes); -#endif void addRecord(int cntrl, Addr data_addr, Addr pc_addr, RubyRequestType type, Tick time, DataBlock& data); @@ -126,10 +114,7 @@ class CacheRecorder std::vector m_records; uint8_t* m_uncompressed_trace; uint64_t m_uncompressed_trace_size; - std::vector m_seq_map; -#if BUILD_GPU - std::vector m_coalescer_map; -#endif + std::vector m_ruby_port_map; uint64_t m_bytes_read; uint64_t m_records_read; uint64_t m_records_flushed; diff --git a/src/mem/ruby/system/RubySystem.cc b/src/mem/ruby/system/RubySystem.cc index 32dec7b9e0..109fd43051 100644 --- a/src/mem/ruby/system/RubySystem.cc +++ b/src/mem/ruby/system/RubySystem.cc @@ -177,44 +177,32 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, uint64_t cache_trace_size, uint64_t block_size_bytes) { - std::vector sequencer_map; -#if BUILD_GPU - std::vector coalescer_map; - GPUCoalescer* coalescer_ptr = NULL; -#endif - Sequencer* sequencer_ptr = NULL; + std::vector ruby_port_map; + RubyPort* ruby_port_ptr = NULL; for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { - sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getCPUSequencer()); -#if BUILD_GPU - coalescer_map.push_back(m_abs_cntrl_vec[cntrl]->getGPUCoalescer()); -#endif - - if (sequencer_ptr == NULL) { - sequencer_ptr = sequencer_map[cntrl]; + if (m_abs_cntrl_vec[cntrl]->getGPUCoalescer() != NULL) { + ruby_port_map.push_back( + (RubyPort*)m_abs_cntrl_vec[cntrl]->getGPUCoalescer()); + } else { + ruby_port_map.push_back( + (RubyPort*)m_abs_cntrl_vec[cntrl]->getCPUSequencer()); } -#if BUILD_GPU - if (coalescer_ptr == NULL) { - coalescer_ptr = coalescer_map[cntrl]; + if (ruby_port_ptr == NULL) { + ruby_port_ptr = ruby_port_map[cntrl]; } -#endif - } - assert(sequencer_ptr != NULL); + assert(ruby_port_ptr != NULL); for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { - if (sequencer_map[cntrl] == NULL) { - sequencer_map[cntrl] = sequencer_ptr; + if (ruby_port_map[cntrl] == NULL) { + ruby_port_map[cntrl] = ruby_port_ptr; + } else { + ruby_port_ptr = ruby_port_map[cntrl]; } -#if BUILD_GPU - if (coalescer_map[cntrl] == NULL) { - coalescer_map[cntrl] = coalescer_ptr; - } -#endif - } // Remove the old CacheRecorder if it's still hanging about. @@ -223,15 +211,9 @@ RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, } // Create the CacheRecorder and record the cache trace -#if BUILD_GPU m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size, - sequencer_map, coalescer_map, + ruby_port_map, block_size_bytes); -#else - m_cache_recorder = new CacheRecorder(uncompressed_trace, cache_trace_size, - sequencer_map, - block_size_bytes); -#endif } void From 8d54a5cbaba50739889056293905930fea4ee1f4 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Thu, 12 Oct 2023 14:53:29 -0500 Subject: [PATCH 445/693] mem-ruby: Remove BUILD_GPU guards from ruby coalescer models A previous commit added BUILD_GPU guards to gpu coalescer models since a related cache recorder commit added GPU support. This is no longer needed since the cache recorder moved to using a vector of RubyPorts instead of Sequencer/GPUCoalescer pointers. This commit removes BUILD_GPU guards from the Ruby coalescer models Change-Id: I23a7957d82524d6cd3483d22edfb35ac51796eca --- src/mem/ruby/slicc_interface/AbstractController.hh | 2 -- src/mem/ruby/system/GPUCoalescer.hh | 5 ----- src/mem/ruby/system/VIPERCoalescer.hh | 5 ----- 3 files changed, 12 deletions(-) diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 7d93644bd8..72b679d6cf 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -70,9 +70,7 @@ namespace ruby { class Network; -#ifdef BUILD_GPU class GPUCoalescer; -#endif class DMASequencer; // used to communicate that an in_port peeked the wrong message type diff --git a/src/mem/ruby/system/GPUCoalescer.hh b/src/mem/ruby/system/GPUCoalescer.hh index 3f936b4b41..d6db5c00ba 100644 --- a/src/mem/ruby/system/GPUCoalescer.hh +++ b/src/mem/ruby/system/GPUCoalescer.hh @@ -32,10 +32,6 @@ #ifndef __MEM_RUBY_SYSTEM_GPU_COALESCER_HH__ #define __MEM_RUBY_SYSTEM_GPU_COALESCER_HH__ -#include "config/build_gpu.hh" - -#if BUILD_GPU - #include #include @@ -550,5 +546,4 @@ operator<<(std::ostream& out, const GPUCoalescer& obj) } // namespace ruby } // namespace gem5 -#endif // BUILD_GPU #endif // __MEM_RUBY_SYSTEM_GPU_COALESCER_HH__ diff --git a/src/mem/ruby/system/VIPERCoalescer.hh b/src/mem/ruby/system/VIPERCoalescer.hh index d185620244..c7e21e946b 100644 --- a/src/mem/ruby/system/VIPERCoalescer.hh +++ b/src/mem/ruby/system/VIPERCoalescer.hh @@ -32,10 +32,6 @@ #ifndef __MEM_RUBY_SYSTEM_VIPERCOALESCER_HH__ #define __MEM_RUBY_SYSTEM_VIPERCOALESCER_HH__ -#include "config/build_gpu.hh" - -#if BUILD_GPU - #include #include "mem/ruby/common/Address.hh" @@ -96,5 +92,4 @@ class VIPERCoalescer : public GPUCoalescer } // namespace ruby } // namespace gem5 -#endif // BUILD_GPU #endif //__MEM_RUBY_SYSTEM_VIPERCOALESCER_HH__ From a33f3d3967ef4f215986792986d6dd8c09392c9a Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 5 Jun 2023 09:44:22 +0100 Subject: [PATCH 446/693] arch-arm: Remove Jazelle state support Jazelle state has been officially removed in Armv8. Every AArch32 implementation must still support the "Trivial Jazelle implementation", which means that while the instruction set has been removed, it is still possible for privileged software to access some Jazelle registers like JIDR,JMCR, and JOSCR which are just treated as RAZ Change-Id: Ie403c4f004968eb4cb45fa51067178a550726c87 Signed-off-by: Giacomo Travaglini --- .../arm/fastmodel/CortexA76/thread_context.cc | 2 +- .../arm/fastmodel/CortexR52/thread_context.cc | 2 +- src/arch/arm/fastmodel/iris/thread_context.cc | 2 - src/arch/arm/faults.cc | 4 -- src/arch/arm/isa.cc | 2 - src/arch/arm/isa/formats/branch.isa | 4 -- src/arch/arm/isa/insts/data.isa | 1 - src/arch/arm/isa/insts/macromem.isa | 1 - src/arch/arm/isa/insts/misc.isa | 27 +------- src/arch/arm/isa/operands.isa | 1 - src/arch/arm/pcstate.hh | 64 ++++--------------- src/arch/arm/regs/misc.hh | 2 +- src/arch/arm/regs/misc_types.hh | 2 +- src/arch/arm/tracers/tarmac_base.cc | 6 +- 14 files changed, 20 insertions(+), 100 deletions(-) diff --git a/src/arch/arm/fastmodel/CortexA76/thread_context.cc b/src/arch/arm/fastmodel/CortexA76/thread_context.cc index c6704852fc..26e7193803 100644 --- a/src/arch/arm/fastmodel/CortexA76/thread_context.cc +++ b/src/arch/arm/fastmodel/CortexA76/thread_context.cc @@ -228,7 +228,7 @@ Iris::ThreadContext::IdxNameMap CortexA76TC::miscRegIdxNameMap({ // ArmISA::MISCREG_SCTLR_RST? { ArmISA::MISCREG_SEV_MAILBOX, "SEV_STATE" }, - // AArch32 CP14 registers (debug/trace/ThumbEE/Jazelle control) + // AArch32 CP14 registers (debug/trace/ThumbEE control) // ArmISA::MISCREG_DBGDIDR? // ArmISA::MISCREG_DBGDSCRint? // ArmISA::MISCREG_DBGDCCINT? diff --git a/src/arch/arm/fastmodel/CortexR52/thread_context.cc b/src/arch/arm/fastmodel/CortexR52/thread_context.cc index a20f8e0a89..45fa6e924f 100644 --- a/src/arch/arm/fastmodel/CortexR52/thread_context.cc +++ b/src/arch/arm/fastmodel/CortexR52/thread_context.cc @@ -188,7 +188,7 @@ Iris::ThreadContext::IdxNameMap CortexR52TC::miscRegIdxNameMap({ // ArmISA::MISCREG_SCTLR_RST? // ArmISA::MISCREG_SEV_MAILBOX? - // AArch32 CP14 registers (debug/trace/ThumbEE/Jazelle control) + // AArch32 CP14 registers (debug/trace/ThumbEE control) // ArmISA::MISCREG_DBGDIDR? // ArmISA::MISCREG_DBGDSCRint? // ArmISA::MISCREG_DBGDCCINT? diff --git a/src/arch/arm/fastmodel/iris/thread_context.cc b/src/arch/arm/fastmodel/iris/thread_context.cc index 462995a19a..0919251a9b 100644 --- a/src/arch/arm/fastmodel/iris/thread_context.cc +++ b/src/arch/arm/fastmodel/iris/thread_context.cc @@ -581,8 +581,6 @@ ThreadContext::pcState() const pc.thumb(cpsr.t); pc.nextThumb(pc.thumb()); - pc.jazelle(cpsr.j); - pc.nextJazelle(cpsr.j); pc.aarch64(!cpsr.width); pc.nextAArch64(!cpsr.width); pc.illegalExec(false); diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 379e761f98..4b906f226f 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -565,7 +565,6 @@ ArmFault::invoke32(ThreadContext *tc, const StaticInstPtr &inst) cpsr.i = 1; } cpsr.it1 = cpsr.it2 = 0; - cpsr.j = 0; cpsr.pan = span ? 1 : saved_cpsr.pan; tc->setMiscReg(MISCREG_CPSR, cpsr); @@ -622,8 +621,6 @@ ArmFault::invoke32(ThreadContext *tc, const StaticInstPtr &inst) PCState pc(new_pc); pc.thumb(cpsr.t); pc.nextThumb(pc.thumb()); - pc.jazelle(cpsr.j); - pc.nextJazelle(pc.jazelle()); pc.aarch64(!cpsr.width); pc.nextAArch64(!cpsr.width); pc.illegalExec(false); @@ -666,7 +663,6 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) // Force some bitfields to 0 spsr.q = 0; spsr.it1 = 0; - spsr.j = 0; spsr.ge = 0; spsr.it2 = 0; spsr.t = 0; diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index a395d1a35f..f961a2d2c4 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -407,7 +407,6 @@ ISA::readMiscReg(RegIndex idx) if (idx == MISCREG_CPSR) { cpsr = miscRegs[idx]; auto pc = tc->pcState().as(); - cpsr.j = pc.jazelle() ? 1 : 0; cpsr.t = pc.thumb() ? 1 : 0; return cpsr; } @@ -678,7 +677,6 @@ ISA::setMiscReg(RegIndex idx, RegVal val) miscRegs[idx], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode); PCState pc = tc->pcState().as(); pc.nextThumb(cpsr.t); - pc.nextJazelle(cpsr.j); pc.illegalExec(cpsr.il == 1); selfDebug->setDebugMask(cpsr.d == 1); diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa index ff6bfda54e..8213ab9ff8 100644 --- a/src/arch/arm/isa/formats/branch.isa +++ b/src/arch/arm/isa/formats/branch.isa @@ -212,10 +212,6 @@ def format Thumb32BranchesAndMiscCtrl() {{ { const uint32_t op = bits(machInst, 7, 4); switch (op) { - case 0x0: - return new Leavex(machInst); - case 0x1: - return new Enterx(machInst); case 0x2: return new Clrex(machInst); case 0x4: diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa index 31fc172883..cec761905e 100644 --- a/src/arch/arm/isa/insts/data.isa +++ b/src/arch/arm/isa/insts/data.isa @@ -268,7 +268,6 @@ let {{ CondCodesGE = new_cpsr.ge; NextThumb = (new_cpsr).t; - NextJazelle = (new_cpsr).j; NextItState = (((new_cpsr).it2 << 2) & 0xFC) | ((new_cpsr).it1 & 0x3); SevMailbox = 1; diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa index edd7228cf8..5e11c3ba95 100644 --- a/src/arch/arm/isa/insts/macromem.isa +++ b/src/arch/arm/isa/insts/macromem.isa @@ -668,7 +668,6 @@ let {{ 0xF, true, sctlr.nmfi, xc->tcBase()); Cpsr = ~CondCodesMask & new_cpsr; NextThumb = new_cpsr.t; - NextJazelle = new_cpsr.j; NextItState = ((((CPSR)URb).it2 << 2) & 0xFC) | (((CPSR)URb).it1 & 0x3); CondCodesNZ = new_cpsr.nz; diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 86e9e8943c..9ee753e385 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -173,9 +173,8 @@ let {{ CondCodesGE = new_cpsr.ge; NextThumb = (new_cpsr).t; - NextJazelle = (new_cpsr).j; - NextItState = (((new_cpsr).it2 << 2) & 0xFC) - | ((new_cpsr).it1 & 0x3); + NextItState = (((new_cpsr).it2 << 2) & 0xFC) + | ((new_cpsr).it1 & 0x3); NPC = (old_cpsr.mode == MODE_HYP) ? ElrHyp : LR; ''' @@ -1083,28 +1082,6 @@ let {{ exec_output += PredOpExecute.subst(mcrr15Iop) - enterxCode = ''' - NextThumb = true; - NextJazelle = true; - ''' - enterxIop = ArmInstObjParams("enterx", "Enterx", "PredOp", - { "code": enterxCode, - "predicate_test": predicateTest }, []) - header_output += BasicDeclare.subst(enterxIop) - decoder_output += BasicConstructor.subst(enterxIop) - exec_output += PredOpExecute.subst(enterxIop) - - leavexCode = ''' - NextThumb = true; - NextJazelle = false; - ''' - leavexIop = ArmInstObjParams("leavex", "Leavex", "PredOp", - { "code": leavexCode, - "predicate_test": predicateTest }, []) - header_output += BasicDeclare.subst(leavexIop) - decoder_output += BasicConstructor.subst(leavexIop) - exec_output += PredOpExecute.subst(leavexIop) - setendCode = ''' CPSR cpsr = Cpsr; cpsr.e = imm; diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index 5bba00f138..5e6506d0e8 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa @@ -526,7 +526,6 @@ def operands {{ 'IWNPC': PCStateReg('instIWNPC', srtPC), 'Thumb': PCStateReg('thumb', srtPC), 'NextThumb': PCStateReg('nextThumb', srtMode), - 'NextJazelle': PCStateReg('nextJazelle', srtMode), 'NextItState': PCStateReg('nextItstate', srtMode), 'Itstate': PCStateReg('itstate', srtMode), 'NextAArch64': PCStateReg('nextAArch64', srtMode), diff --git a/src/arch/arm/pcstate.hh b/src/arch/arm/pcstate.hh index a2f0463fab..98e3202eb3 100644 --- a/src/arch/arm/pcstate.hh +++ b/src/arch/arm/pcstate.hh @@ -75,7 +75,6 @@ class PCState : public GenericISA::UPCState<4> enum FlagBits { ThumbBit = (1 << 0), - JazelleBit = (1 << 1), AArch64Bit = (1 << 2) }; @@ -202,36 +201,6 @@ class PCState : public GenericISA::UPCState<4> } - bool - jazelle() const - { - return flags & JazelleBit; - } - - void - jazelle(bool val) - { - if (val) - flags |= JazelleBit; - else - flags &= ~JazelleBit; - } - - bool - nextJazelle() const - { - return nextFlags & JazelleBit; - } - - void - nextJazelle(bool val) - { - if (val) - nextFlags |= JazelleBit; - else - nextFlags &= ~JazelleBit; - } - bool aarch64() const { @@ -354,29 +323,18 @@ class PCState : public GenericISA::UPCState<4> void instIWNPC(Addr val) { - bool thumbEE = (thumb() && jazelle()); - - Addr newPC = val; - if (thumbEE) { - if (bits(newPC, 0)) { - newPC = newPC & ~mask(1); - } // else we have a bad interworking address; do not call - // panic() since the instruction could be executed - // speculatively + if (bits(val, 0)) { + nextThumb(true); + val = val & ~mask(1); + } else if (!bits(val, 1)) { + nextThumb(false); } else { - if (bits(newPC, 0)) { - nextThumb(true); - newPC = newPC & ~mask(1); - } else if (!bits(newPC, 1)) { - nextThumb(false); - } else { - // This state is UNPREDICTABLE in the ARM architecture - // The easy thing to do is just mask off the bit and - // stay in the current mode, so we'll do that. - newPC &= ~mask(2); - } + // This state is UNPREDICTABLE in the ARM architecture + // The easy thing to do is just mask off the bit and + // stay in the current mode, so we'll do that. + val &= ~mask(2); } - npc(newPC); + npc(val); } // Perform an interworking branch in ARM mode, a regular branch @@ -384,7 +342,7 @@ class PCState : public GenericISA::UPCState<4> void instAIWNPC(Addr val) { - if (!thumb() && !jazelle()) + if (!thumb()) instIWNPC(val); else instNPC(val); diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index 6a4933c5d6..6f5e9ead6c 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -96,7 +96,7 @@ namespace ArmISA MISCREG_SEV_MAILBOX, MISCREG_TLBINEEDSYNC, - // AArch32 CP14 registers (debug/trace/ThumbEE/Jazelle control) + // AArch32 CP14 registers (debug/trace/ThumbEE control) MISCREG_DBGDIDR, MISCREG_DBGDSCRint, MISCREG_DBGDCCINT, diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index abbe2afa98..00d0cc49fa 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -54,7 +54,7 @@ namespace ArmISA Bitfield<28> v; Bitfield<27> q; Bitfield<26, 25> it1; - Bitfield<24> j; + Bitfield<24> dit; // AArch64 Bitfield<23> uao; // AArch64 Bitfield<22> pan; Bitfield<21> ss; // AArch64 diff --git a/src/arch/arm/tracers/tarmac_base.cc b/src/arch/arm/tracers/tarmac_base.cc index 99ed3bb0f1..25524d24b6 100644 --- a/src/arch/arm/tracers/tarmac_base.cc +++ b/src/arch/arm/tracers/tarmac_base.cc @@ -107,12 +107,12 @@ TarmacBaseRecord::pcToISetState(const PCStateBase &pc) if (apc.aarch64()) isetstate = TarmacBaseRecord::ISET_A64; - else if (!apc.thumb() && !apc.jazelle()) + else if (!apc.thumb()) isetstate = TarmacBaseRecord::ISET_ARM; - else if (apc.thumb() && !apc.jazelle()) + else if (apc.thumb()) isetstate = TarmacBaseRecord::ISET_THUMB; else - // No Jazelle state in TARMAC + // Unsupported state in TARMAC isetstate = TarmacBaseRecord::ISET_UNSUPPORTED; return isetstate; From 1c45cdcc416bc0d2b0621da28c096748bdb4254d Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 27 Sep 2023 09:34:19 +0100 Subject: [PATCH 447/693] arch-arm: Remove legacy ThumbEE references ThumbEE had already been removed but there were still some references to it dangling around. We were also signaling ThumbEE as being available through HWCAPS in SE which was not correct. This patch is fixing it Change-Id: I8b196f5bd27822cd4dd8b3ab3ad9f12a6f54b047 Signed-off-by: Giacomo Travaglini --- src/arch/arm/fastmodel/CortexA76/thread_context.cc | 2 +- src/arch/arm/fastmodel/CortexR52/thread_context.cc | 2 +- src/arch/arm/process.cc | 2 +- src/arch/arm/regs/misc.hh | 2 +- src/arch/arm/regs/misc_types.hh | 2 -- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/arch/arm/fastmodel/CortexA76/thread_context.cc b/src/arch/arm/fastmodel/CortexA76/thread_context.cc index 26e7193803..eb936b8ea4 100644 --- a/src/arch/arm/fastmodel/CortexA76/thread_context.cc +++ b/src/arch/arm/fastmodel/CortexA76/thread_context.cc @@ -228,7 +228,7 @@ Iris::ThreadContext::IdxNameMap CortexA76TC::miscRegIdxNameMap({ // ArmISA::MISCREG_SCTLR_RST? { ArmISA::MISCREG_SEV_MAILBOX, "SEV_STATE" }, - // AArch32 CP14 registers (debug/trace/ThumbEE control) + // AArch32 CP14 registers (debug/trace control) // ArmISA::MISCREG_DBGDIDR? // ArmISA::MISCREG_DBGDSCRint? // ArmISA::MISCREG_DBGDCCINT? diff --git a/src/arch/arm/fastmodel/CortexR52/thread_context.cc b/src/arch/arm/fastmodel/CortexR52/thread_context.cc index 45fa6e924f..b88bd7d99b 100644 --- a/src/arch/arm/fastmodel/CortexR52/thread_context.cc +++ b/src/arch/arm/fastmodel/CortexR52/thread_context.cc @@ -188,7 +188,7 @@ Iris::ThreadContext::IdxNameMap CortexR52TC::miscRegIdxNameMap({ // ArmISA::MISCREG_SCTLR_RST? // ArmISA::MISCREG_SEV_MAILBOX? - // AArch32 CP14 registers (debug/trace/ThumbEE control) + // AArch32 CP14 registers (debug/trace control) // ArmISA::MISCREG_DBGDIDR? // ArmISA::MISCREG_DBGDSCRint? // ArmISA::MISCREG_DBGDCCINT? diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index 9aa519fe36..b169f849d1 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -169,7 +169,7 @@ ArmProcess32::armHwcapImpl() const }; return Arm_Swp | Arm_Half | Arm_Thumb | Arm_FastMult | - Arm_Vfp | Arm_Edsp | Arm_ThumbEE | Arm_Neon | + Arm_Vfp | Arm_Edsp | Arm_Neon | Arm_Vfpv3 | Arm_Vfpv3d16; } diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index 6f5e9ead6c..065e5439c2 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -96,7 +96,7 @@ namespace ArmISA MISCREG_SEV_MAILBOX, MISCREG_TLBINEEDSYNC, - // AArch32 CP14 registers (debug/trace/ThumbEE control) + // AArch32 CP14 registers (debug/trace control) MISCREG_DBGDIDR, MISCREG_DBGDSCRint, MISCREG_DBGDCCINT, diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index 00d0cc49fa..0e6bdc8fe3 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -457,8 +457,6 @@ namespace ArmISA Bitfield<7> itd; // IT disable // (ARMv8 AArch32 and AArch64 SCTLR_EL1 only) Bitfield<6, 3> rao4; // Read as one - Bitfield<6> thee; // ThumbEE enable - // (ARMv8 AArch32 and AArch64 SCTLR_EL1 only) Bitfield<5> cp15ben; // CP15 barrier enable // (AArch32 and AArch64 SCTLR_EL1 only) Bitfield<4> sa0; // Stack Alignment Check Enable for EL0 From 68af3f45c94546ca9e2886633bd10c1ae7b64d03 Mon Sep 17 00:00:00 2001 From: Kaustav Goswami <39310478+kaustav-goswami@users.noreply.github.com> Date: Fri, 13 Oct 2023 14:31:35 -0700 Subject: [PATCH 448/693] tests: updated the nightly tests to use SST 13.0.0 (#441) PR https://github.com/gem5/gem5/pull/396 updates the gem5 SST bridge to use StandardMem in SST. This change updates the nightly tests to use SST 13.0.0 instead of SST 11.1.0. It also updates the dockerfile. Change-Id: I5c109c40379d2f09601a1c9f19c51dd716c6582e --------- Signed-off-by: Kaustav Goswami Co-authored-by: Bobby R. Bruce --- .github/workflows/daily-tests.yaml | 3 +++ tests/deprecated/nightly.sh | 3 ++- util/dockerfiles/docker-compose.yaml | 2 +- util/dockerfiles/{sst-11.1.0 => sst}/Dockerfile | 14 +++++++------- 4 files changed, 13 insertions(+), 9 deletions(-) rename util/dockerfiles/{sst-11.1.0 => sst}/Dockerfile (89%) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 06423d95e4..36006d03e4 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -220,6 +220,9 @@ jobs: ref: develop - name: Build RISCV/libgem5_opt.so with SST run: scons build/RISCV/libgem5_opt.so --without-tcmalloc --duplicate-sources --ignore-style -j $(nproc) + - name: Makefile ext/sst + working-directory: ${{ github.workspace }}/ext/sst + run: mv Makefile.linux Makefile - name: Compile ext/sst working-directory: ${{ github.workspace }}/ext/sst run: make -j $(nproc) diff --git a/tests/deprecated/nightly.sh b/tests/deprecated/nightly.sh index cea1ad0be9..9503cd1f61 100755 --- a/tests/deprecated/nightly.sh +++ b/tests/deprecated/nightly.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2021-2023 The Regents of the University of California # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -161,6 +161,7 @@ build_and_run_SST () { scons build/${isa}/libgem5_${variant}.so -j${compile_threads} \ --without-tcmalloc --duplicate-sources --ignore-style && \ cd ext/sst && \ +mv Makefile.linux Makefile && \ make clean; make -j ${compile_threads} && \ sst --add-lib-path=./ sst/example.py && \ cd -; diff --git a/util/dockerfiles/docker-compose.yaml b/util/dockerfiles/docker-compose.yaml index a4f585f6d7..005e415484 100644 --- a/util/dockerfiles/docker-compose.yaml +++ b/util/dockerfiles/docker-compose.yaml @@ -14,7 +14,7 @@ services: image: gcr.io/gem5-test/gpu-fs:latest sst: build: - context: sst-11.1.0 + context: sst dockerfile: Dockerfile image: gcr.io/gem5-test/sst-env:latest systemc: diff --git a/util/dockerfiles/sst-11.1.0/Dockerfile b/util/dockerfiles/sst/Dockerfile similarity index 89% rename from util/dockerfiles/sst-11.1.0/Dockerfile rename to util/dockerfiles/sst/Dockerfile index 970e6979b4..b392c241fc 100644 --- a/util/dockerfiles/sst-11.1.0/Dockerfile +++ b/util/dockerfiles/sst/Dockerfile @@ -1,4 +1,4 @@ -# Copyright (c) 2021 The Regents of the University of California +# Copyright (c) 2021-2023 The Regents of the University of California # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -41,9 +41,9 @@ RUN mkdir /sst # Download and build SST-Core without MPI support WORKDIR /sst/ -RUN wget https://github.com/sstsimulator/sst-core/releases/download/v11.1.0_Final/sstcore-11.1.0.tar.gz; \ - tar xf sstcore-11.1.0.tar.gz; -WORKDIR /sst/sstcore-11.1.0/ +RUN wget https://github.com/sstsimulator/sst-core/releases/download/v13.0.0_Final/sstcore-13.0.0.tar.gz; \ + tar xf sstcore-13.0.0.tar.gz; +WORKDIR /sst/sstcore-13.0.0/ RUN ./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ --disable-mpi; \ make all -j $(nproc); \ @@ -51,9 +51,9 @@ RUN ./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ # Download and build SST-Elements WORKDIR /sst -RUN wget https://github.com/sstsimulator/sst-elements/releases/download/v11.1.0_Final/sstelements-11.1.0.tar.gz; \ - tar xf sstelements-11.1.0.tar.gz; -WORKDIR /sst/sst-elements-library-11.1.0/ +RUN wget https://github.com/sstsimulator/sst-elements/releases/download/v13.0.0_Final/sstelements-13.0.0.tar.gz; \ + tar xf sstelements-13.0.0.tar.gz; +WORKDIR /sst/sst-elements-library-13.0.0/ RUN ./configure --prefix=$SST_CORE_HOME --with-python=/usr/bin/python3-config \ --with-sst-core=$SST_CORE_HOME; \ make all -j $(nproc); \ From a3c51ca38cdccfde04d6a8771da3b267c7a2f113 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Sat, 14 Oct 2023 06:20:42 +0800 Subject: [PATCH 449/693] arch-riscv: Fix write back register issue of vmask_mv_micro (#443) After removing the setRegOperand in VecRegOperand https://github.com/gem5/gem5/pull/341. The vmask_vm_micro will not write back to register because tmp_d0 is not the reference type. The PR will make tmp_d0 as reference of regFile. Change-Id: I2a934ad28045ac63950d4e2ed3eecc4a7d137919 --- src/arch/riscv/insts/vector.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index fb6c7821b5..822ee7616e 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -555,7 +555,7 @@ class VMaskMergeMicroInst : public VectorArithMicroInst Fault execute(ExecContext* xc, trace::InstRecord* traceData) const override { - vreg_t tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); + vreg_t& tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); auto Vd = tmp_d0.as(); constexpr uint8_t elems_per_vreg = VLENB / sizeof(ElemType); size_t bit_cnt = elems_per_vreg; From 4931fb0010825ca5fe979226e2fcd293423e143a Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Sat, 14 Oct 2023 08:39:50 -0500 Subject: [PATCH 450/693] mem-ruby: Always pass on GPU atomics to dir in write-through TCC (#367) Added checks to ensure that atomics are not performed in the TCC when it is configured as a write-through cache. Also added SLC bit overwrite to ensure directory preforms atomics when there is a write-through TCC. Change-Id: I4514e6c8022aeb7785f2c59871cd9acec8161ed8 --- configs/ruby/GPU_VIPER.py | 1 + src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 32 ++++++++++++--------- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 9 +++--- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index b8757c273d..fae9f1ba9c 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -555,6 +555,7 @@ def construct_dirs(options, system, ruby_system, network): dir_cntrl.create(options, dir_ranges, ruby_system, system) dir_cntrl.number_of_TBEs = options.num_tbes dir_cntrl.useL3OnWT = options.use_L3_on_WT + dir_cntrl.L2isWB = options.WB_L2 # the number_of_TBEs is inclusive of TBEs below # Connect the Directory controller to the ruby network diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index be1243aaa5..d1905c3b96 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -300,16 +300,22 @@ machine(MachineType:TCC, "TCC Cache") // checked when the read response is received. if (in_msg.Type == CoherenceResponseType:NBSysWBAck) { trigger(Event:WBAck, in_msg.addr, cache_entry, tbe); - } else if (is_slc_set) { - // If the SLC bit is set, the response needs to bypass the cache - // and should not be allocated an entry. + } else if(in_msg.Type == CoherenceResponseType:NBSysResp) { + // If the SLC bit is set or the cache is write-through and + // we're receiving modified data (such as from an atomic), + // the response needs to bypass the cache and should not be + // allocated an entry. + if(is_slc_set || (!WB && in_msg.State == CoherenceState:Modified)) { trigger(Event:Bypass, in_msg.addr, cache_entry, tbe); - } else if (in_msg.Type == CoherenceResponseType:NBSysResp) { - if(presentOrAvail(in_msg.addr)) { - trigger(Event:Data, in_msg.addr, cache_entry, tbe); } else { - Addr victim := L2cache.cacheProbe(in_msg.addr); - trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); + if(presentOrAvail(in_msg.addr)) { + // Responses with atomic data will only reach here if the + // SLC bit isn't set and the cache is WB + trigger(Event:Data, in_msg.addr, cache_entry, tbe); + } else { + Addr victim := L2cache.cacheProbe(in_msg.addr); + trigger(Event:L2_Repl, victim, getCacheEntry(victim), TBEs.lookup(victim)); + } } } else { error("Unexpected Response Message to Core"); @@ -358,13 +364,13 @@ machine(MachineType:TCC, "TCC Cache") trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe); } } else if (in_msg.Type == CoherenceRequestType:Atomic) { - // If the request is system-level, or if the address isn't in the cache, - // then send the request to the directory. Since non-SLC atomics won't be - // performed by the directory, TCC will perform the atomic on the return path - // on Event:Data. + // If the request is system-level, if the address isn't in the cache, + // or if this cache is write-through, then send the request to the + // directory. Since non-SLC atomics won't be performed by the directory, + // TCC will perform the atomic on the return path on Event:Data. // The action will invalidate the cache line if SLC is set and the address is // in the cache. - if(in_msg.isSLCSet || !presentOrAvail(in_msg.addr)) { + if(in_msg.isSLCSet || !WB || !presentOrAvail(in_msg.addr)) { trigger(Event:AtomicPassOn, in_msg.addr, cache_entry, tbe); } else { trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index eed750832f..c3bbfa1950 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -39,6 +39,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") bool GPUonly := "False"; int TCC_select_num_bits; bool useL3OnWT := "False"; + bool L2isWB; Cycles to_memory_controller_latency := 1; // DMA @@ -1039,11 +1040,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") action(wd_writeBackData, "wd", desc="Write back data if needed") { if (tbe.wtData || tbe.atomicData || tbe.Dirty == false) { - // If SLC is not set, the atomic is handled in the L2 - // Atomic needs to be done at the L3 only if this is - // not the case - - if (tbe.atomicData && tbe.isSLCSet) { + // Only perform atomics in the directory if the SLC bit is set, or + // if the L2 is WT + if (tbe.atomicData && (tbe.isSLCSet || !L2isWB)) { tbe.DataBlk.atomicPartial(tbe.DataBlk, tbe.writeMask); } enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) { From ca2592d3ba6b5344de0502865cf20ad233cd0056 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sat, 14 Oct 2023 20:07:39 -0700 Subject: [PATCH 451/693] configs: Fix missing param exchange for GPUFS (#457) PR #367 adds an option to configs/ruby/GPU_VIPER.py that was not added to the corresponding dGPU equal for GPUFS and thus all GPUFS runs are failing. Fixed in this patch. --- configs/ruby/GPU_VIPER.py | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index fae9f1ba9c..b034cf76fd 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -619,6 +619,7 @@ def construct_gpudirs(options, system, ruby_system, network): dir_cntrl.create(options, [addr_range], ruby_system, system) dir_cntrl.number_of_TBEs = options.num_tbes dir_cntrl.useL3OnWT = False + dir_cntrl.L2isWB = options.WB_L2 # Connect the Directory controller to the ruby network dir_cntrl.requestFromCores = MessageBuffer(ordered=True) From 20f5555f30e13ae0931464f36f32c65336711569 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Sat, 14 Oct 2023 20:08:06 -0700 Subject: [PATCH 452/693] python: Enable -m switch on gem5 binary (#453) With -m, you can now run a module from the command line that is embedded in the gem5 binary. This will allow us to put some common "scripts" in the stdlib instead of in the "configs" directory. --- src/python/importer.py | 3 ++ src/python/m5/main.py | 89 +++++++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/python/importer.py b/src/python/importer.py index 73510f664c..6b64f1cb5c 100644 --- a/src/python/importer.py +++ b/src/python/importer.py @@ -38,6 +38,9 @@ class ByteCodeLoader(importlib.abc.Loader): def exec_module(self, module): exec(self.code, module.__dict__) + def get_code(self, _): + return self.code + # Simple importer that allows python to import data from a dict of # code objects. The keys are the module path, and the items are the diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 9252a14c5a..fa73fc3e33 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -39,6 +39,7 @@ import code import datetime import os +import runpy import socket import sys @@ -183,6 +184,16 @@ def parse_options(): del parser.rargs[:] setattr(parser.values, option.dest, (value, extra_args)) + option( + "-m", + type=str, + help="run library module as a script (terminates option list)", + default="", + metavar="mod", + action="callback", + callback=collect_args, + ) + option( "-c", type=str, @@ -525,7 +536,9 @@ def main(): print() # check to make sure we can find the listed script - if not options.c and (not arguments or not os.path.isfile(arguments[0])): + if not (options.c or options.m) and ( + not arguments or not os.path.isfile(arguments[0]) + ): if arguments and not os.path.isfile(arguments[0]): print(f"Script {arguments[0]} not found") @@ -603,43 +616,49 @@ def main(): sys.argv = arguments - if options.c: - filedata = options.c[0] - filecode = compile(filedata, "", "exec") - sys.argv = ["-c"] + options.c[1] - scope = {"__name__": "__m5_main__"} + if options.m: + sys.argv = [options.m[0]] + options.m[1] + runpy.run_module(options.m[0], run_name="__m5_main__") else: - # If `-P` was used (`options.P == true`), don't prepend the script - # directory to the `sys.path`. This mimics Python 3's `-P` option - # (https://docs.python.org/3/using/cmdline.html#cmdoption-P). - if not options.P: - sys.path = [os.path.dirname(sys.argv[0])] + sys.path - filename = sys.argv[0] - filedata = open(filename).read() - filecode = compile(filedata, filename, "exec") - scope = {"__file__": filename, "__name__": "__m5_main__"} + if options.c: + filedata = options.c[0] + filecode = compile(filedata, "", "exec") + sys.argv = ["-c"] + options.c[1] + scope = {"__name__": "__m5_main__"} + else: + # If `-P` was used (`options.P == true`), don't prepend the script + # directory to the `sys.path`. This mimics Python 3's `-P` option + # (https://docs.python.org/3/using/cmdline.html#cmdoption-P). + if not options.P: + sys.path = [os.path.dirname(sys.argv[0])] + sys.path + filename = sys.argv[0] + filedata = open(filename).read() + filecode = compile(filedata, filename, "exec") + scope = {"__file__": filename, "__name__": "__m5_main__"} - # if pdb was requested, execfile the thing under pdb, otherwise, - # just do the execfile normally - if options.pdb: - import pdb - import traceback + # if pdb was requested, execfile the thing under pdb, otherwise, + # just do the execfile normally + if options.pdb: + import pdb + import traceback - pdb = pdb.Pdb() - try: - pdb.run(filecode, scope) - except SystemExit: - print("The program exited via sys.exit(). Exit status: ", end=" ") - print(sys.exc_info()[1]) - except: - traceback.print_exc() - print("Uncaught exception. Entering post mortem debugging") - t = sys.exc_info()[2] - while t.tb_next is not None: - t = t.tb_next - pdb.interaction(t.tb_frame, t) - else: - exec(filecode, scope) + pdb = pdb.Pdb() + try: + pdb.run(filecode, scope) + except SystemExit: + print( + "The program exited via sys.exit(). Exit status: ", end=" " + ) + print(sys.exc_info()[1]) + except: + traceback.print_exc() + print("Uncaught exception. Entering post mortem debugging") + t = sys.exc_info()[2] + while t.tb_next is not None: + t = t.tb_next + pdb.interaction(t.tb_frame, t) + else: + exec(filecode, scope) # once the script is done if options.interactive: From a3b1bfdbf0edc969ec0371efc8fc290a9f2b9a7b Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 15:38:26 +0100 Subject: [PATCH 453/693] cpu: Add a IsPseudo StaticInstFlag for gem5 pseudo-ops Being able to recognise pseudo ops from the static instruction pointer is actually quite useful in several circumstances Change-Id: Ib39badf9aabba15ab3ebe7a8e9717583412731e4 Signed-off-by: Giacomo Travaglini --- src/cpu/StaticInstFlags.py | 13 ++++++++++++- src/cpu/static_inst.hh | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/cpu/StaticInstFlags.py b/src/cpu/StaticInstFlags.py index d562dd5645..4ab6cc499c 100644 --- a/src/cpu/StaticInstFlags.py +++ b/src/cpu/StaticInstFlags.py @@ -1,4 +1,14 @@ -# Copyright (c) 2020 ARM Limited +# Copyright (c) 2020, 2023 Arm Limited +# +# 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) 2003-2005 The Regents of The University of Michigan # Copyright (c) 2013 Advanced Micro Devices, Inc. # All rights reserved. @@ -75,6 +85,7 @@ class StaticInstFlags(Enum): "IsNonSpeculative", # Should not be executed speculatively "IsQuiesce", # Is a quiesce instruction "IsUnverifiable", # Can't be verified by a checker + "IsPseudo", # Is a gem5 pseudo-op "IsSyscall", # Causes a system call to be emulated in syscall # emulation mode. # Flags for microcode diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index b98c01f872..12b05f9b0e 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020 ARM Limited + * Copyright (c) 2017, 2020, 2023 Arm Limited * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * @@ -182,6 +182,7 @@ class StaticInst : public RefCounted, public StaticInstFlags bool isNonSpeculative() const { return flags[IsNonSpeculative]; } bool isQuiesce() const { return flags[IsQuiesce]; } bool isUnverifiable() const { return flags[IsUnverifiable]; } + bool isPseudo() const { return flags[IsPseudo]; } bool isSyscall() const { return flags[IsSyscall]; } bool isMacroop() const { return flags[IsMacroop]; } bool isMicroop() const { return flags[IsMicroop]; } From 3f925c4084790b4876207657158b2e83d9760b9b Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 16:00:04 +0100 Subject: [PATCH 454/693] arch-arm: Mark gem5 pseudo-ops with IsPseudo flag Change-Id: I9c8a146d73596597f28cdeca22ad7b7b01b381a7 Signed-off-by: Giacomo Travaglini --- src/arch/arm/isa/insts/m5ops.isa | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/arch/arm/isa/insts/m5ops.isa b/src/arch/arm/isa/insts/m5ops.isa index 4e508f0186..f912204fe7 100644 --- a/src/arch/arm/isa/insts/m5ops.isa +++ b/src/arch/arm/isa/insts/m5ops.isa @@ -1,5 +1,5 @@ // -// Copyright (c) 2010, 2012-2013 ARM Limited +// Copyright (c) 2010, 2012-2013, 2023 Arm Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -47,7 +47,8 @@ let {{ { "code": gem5OpCode % "RegABI64" + 'X0 = ret;', "predicate_test": predicateTest }, - [ "IsNonSpeculative", "IsUnverifiable" ]); + [ "IsNonSpeculative", "IsUnverifiable", + "IsPseudo" ]); header_output += BasicDeclare.subst(gem5OpIop) decoder_output += BasicConstructor.subst(gem5OpIop) exec_output += PredOpExecute.subst(gem5OpIop) @@ -57,7 +58,8 @@ let {{ 'R0 = bits(ret, 31, 0);\n' + \ 'R1 = bits(ret, 63, 32);', "predicate_test": predicateTest }, - [ "IsNonSpeculative", "IsUnverifiable" ]); + [ "IsNonSpeculative", "IsUnverifiable", + "IsPseudo" ]); header_output += BasicDeclare.subst(gem5OpIop) decoder_output += BasicConstructor.subst(gem5OpIop) exec_output += PredOpExecute.subst(gem5OpIop) From d702d3b90abf6a7fb521d87028970ae25b0a05d7 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Mon, 16 Oct 2023 07:23:08 -0700 Subject: [PATCH 455/693] misc: fix clang13 overloaded-virtual warning (#454) Like #363 clang is also unhappy about the overloaded virtual. However, clang needs to have the diagnostic in a different place Fixes #437 --- src/systemc/ext/core/sc_port.hh | 5 ----- src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/systemc/ext/core/sc_port.hh b/src/systemc/ext/core/sc_port.hh index bd57553559..796950e29b 100644 --- a/src/systemc/ext/core/sc_port.hh +++ b/src/systemc/ext/core/sc_port.hh @@ -114,10 +114,6 @@ class sc_port_base : public sc_object virtual sc_port_policy _portPolicy() const = 0; }; -// The overloaded virtual is intended in SystemC, so we'll disable the warning. -// Please check section 9.3 of SystemC 2.3.1 release note for more details. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverloaded-virtual" template class sc_port_b : public sc_port_base { @@ -248,7 +244,6 @@ class sc_port_b : public sc_port_base sc_port_b(const sc_port_b &) {} sc_port_b &operator = (const sc_port_b &) { return *this; } }; -#pragma GCC diagnostic pop template class sc_port : public sc_port_b diff --git a/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh b/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh index 71fbf1b900..4f67b59237 100644 --- a/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh +++ b/src/systemc/ext/tlm_core/2/sockets/initiator_socket.hh @@ -51,6 +51,10 @@ template class tlm_base_target_socket; +// The overloaded virtual is intended in SystemC, so we'll disable the warning. +// Please check section 9.3 of SystemC 2.3.1 release note for more details. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" template , typename BW_IF=tlm_bw_transport_if<>, int N=1, sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND> @@ -170,6 +174,7 @@ class tlm_base_initiator_socket : protected: export_type m_export; }; +#pragma GCC diagnostic pop // // Convenience socket classes From 97f4b44dd394674d2221c1979a0dc8db335362ba Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 08:35:54 -0700 Subject: [PATCH 456/693] arch-arm: Fix line-length error in misc.cc (#459) --- src/arch/arm/regs/misc.cc | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 039717a8b7..10dfa5cb74 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -1928,8 +1928,15 @@ faultSctlr2EL1(const MiscRegLUTEntry &entry, if (HaveExt(tc, ArmExtension::FEAT_SCTLR2)) { const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); const HCRX hcrx = tc->readMiscReg(MISCREG_HCRX_EL2); - if (auto fault = faultHcrFgtEL1(entry, tc, inst); - fault != NoFault) { + if ( + auto fault = faultHcrFgtEL1 + ( + entry, + tc, + inst + ); + fault != NoFault + ) { return fault; } else if (EL2Enabled(tc) && (!isHcrxEL2Enabled(tc) || !hcrx.sctlr2En)) { return inst.generateTrap(EL2); @@ -1988,8 +1995,15 @@ faultTcr2EL1(const MiscRegLUTEntry &entry, if (HaveExt(tc, ArmExtension::FEAT_TCR2)) { const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); const HCRX hcrx = tc->readMiscReg(MISCREG_HCRX_EL2); - if (auto fault = faultHcrFgtEL1(entry, tc, inst); - fault != NoFault) { + if ( + auto fault = faultHcrFgtEL1 + ( + entry, + tc, + inst + ); + fault != NoFault + ) { return fault; } else if (EL2Enabled(tc) && (!isHcrxEL2Enabled(tc) || !hcrx.tcr2En)) { return inst.generateTrap(EL2); @@ -4488,7 +4502,8 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_ID_AA64MMFR1_EL1) .reset([p,release=release](){ AA64MMFR1 mmfr1_el1 = p.id_aa64mmfr1_el1; - mmfr1_el1.vmidbits = release->has(ArmExtension::FEAT_VMID16) ? 0x2 : 0x0; + mmfr1_el1.vmidbits = + release->has(ArmExtension::FEAT_VMID16) ? 0x2 : 0x0; mmfr1_el1.vh = release->has(ArmExtension::FEAT_VHE) ? 0x1 : 0x0; mmfr1_el1.hpds = release->has(ArmExtension::FEAT_HPDS) ? 0x1 : 0x0; mmfr1_el1.pan = release->has(ArmExtension::FEAT_PAN) ? 0x1 : 0x0; @@ -4513,7 +4528,8 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_ID_AA64MMFR3_EL1) .reset([p,release=release](){ AA64MMFR3 mmfr3_el1 = 0; - mmfr3_el1.sctlrx = release->has(ArmExtension::FEAT_SCTLR2) ? 0x1 : 0x0; + mmfr3_el1.sctlrx = + release->has(ArmExtension::FEAT_SCTLR2) ? 0x1 : 0x0; mmfr3_el1.tcrx = release->has(ArmExtension::FEAT_TCR2) ? 0x1 : 0x0; return mmfr3_el1; }()) From 5240c07d3c8302714e70299cd4878a2139082aa4 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 09:20:13 -0700 Subject: [PATCH 457/693] util: Fix runners to extent to max disk size (#460) THe `lvextend` command extends the logical volume. However, the `resize2fs` command is needed to extend the filesystem to fill the logical volume. Prior to this patch the filesystem ran out of space despite there being enough room in the volume. This was just wasted free space. --- util/github-runners-vagrant/provision_root.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/util/github-runners-vagrant/provision_root.sh b/util/github-runners-vagrant/provision_root.sh index f18a170c95..34c2d811de 100644 --- a/util/github-runners-vagrant/provision_root.sh +++ b/util/github-runners-vagrant/provision_root.sh @@ -75,3 +75,4 @@ apt-get autoremove -y # Resize the root partition to fill up all the free size on the disk lvextend -l +100%FREE $(df / --output=source | sed 1d) +resize2fs $(df / --output=source | sed 1d) From 322b105b9d7c812144c23f6252848faf6f0145f7 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 09:37:51 -0700 Subject: [PATCH 458/693] arch-arm: Fix (another) line-length error in misc.cc https://github.com/gem5/gem5/pull/459 missed one. This commit should complete the task. Change-Id: I0aeba79d6f13ddc45effe141945f5636b75daecc --- src/arch/arm/regs/misc.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index 10dfa5cb74..f00fc09f2d 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -1938,7 +1938,9 @@ faultSctlr2EL1(const MiscRegLUTEntry &entry, fault != NoFault ) { return fault; - } else if (EL2Enabled(tc) && (!isHcrxEL2Enabled(tc) || !hcrx.sctlr2En)) { + } else if ( + EL2Enabled(tc) && (!isHcrxEL2Enabled(tc) || !hcrx.sctlr2En) + ) { return inst.generateTrap(EL2); } else if (ArmSystem::haveEL(tc, EL3) && !scr.sctlr2En) { return inst.generateTrap(EL3); From a9464a41f571b9d54872fa1da4487dc0ee6b9536 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 09:39:44 -0700 Subject: [PATCH 459/693] stdlib,resources: Generalize exception for request retry (#466) In commit bbc301f2f027f10976c23ae4f64b81f48aade826 the generalized `Exception` was changed back to the more specific `HTTPError`. In this case we do not desire specific error handling. If the connection to the database fails I want the exception handled in the way outlined: i.e., i want the connection to be retried 4 times before giving up. With `HTTPError`, only `HTTPError`s warrent a retry. Changing this to `HTTPError` cause tests to fail due to a failure to retry downloading of a resource. Here is an example: https://github.com/gem5/gem5/actions/runs/6521543885/job/17710779784 In this case `request.urlopen` raised a `URLError`. I suspect this was some issued to do with reaching the DNS servers. It likely would've succeeded if it had just tried again. --- src/python/gem5/resources/client_api/atlasclient.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py index 511ef71fed..7b1d263936 100644 --- a/src/python/gem5/resources/client_api/atlasclient.py +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -30,7 +30,6 @@ import json import time import itertools from .abstract_client import AbstractClient -from urllib.error import HTTPError from m5.util import warn @@ -122,7 +121,7 @@ class AtlasClient(AbstractClient): try: response = request.urlopen(req) break - except HTTPError as e: + except Exception as e: if attempt >= max_failed_attempts: raise AtlasClientHttpJsonRequestError( client=self, From 9b2b6cd8d25b055c4b64f044e7d0c7dab76e2595 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 16 Oct 2023 09:40:09 -0700 Subject: [PATCH 460/693] arch-riscv: Mark vector configuration insts as vector insts (#463) --- src/arch/riscv/insts/vector.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index 822ee7616e..b25a6e3a09 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -74,7 +74,9 @@ class VConfOp : public RiscvStaticInst zimm10(_extMachInst.zimm_vsetivli), zimm11(_extMachInst.zimm_vsetvli), uimm(_extMachInst.uimm_vsetivli) - {} + { + this->flags[IsVector] = true; + } std::string generateDisassembly( Addr pc, const loader::SymbolTable *symtab) const override; From 2825bc1d552e71b4f9816ad186be394b21991f06 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Tue, 17 Oct 2023 00:45:28 +0800 Subject: [PATCH 461/693] misc: Add missing RISCV valid ISA option to README.md (#462) The list of valid ISA options should be same as the website: https://www.gem5.org/documentation/general_docs/building Change-Id: Id5ace5b0356ec35634caec5b11159551801c0615 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c7c0d14463..6ca80bd0ef 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ Once you have all dependencies resolved, execute `scons build/ALL/gem5.opt` to build an optimized version of the gem5 binary (`gem5.opt`) containing all gem5 ISAs. If you only wish to compile gem5 to include a single ISA, you can replace `ALL` with the name of the ISA. Valid -options include `ARM`, `NULL`, `MIPS`, `POWER`, `SPARC`, and `X86` The complete -list of options can be found in the build_opts directory. +options include `ARM`, `NULL`, `MIPS`, `POWER`, `RISCV`, `SPARC`, and `X86` +The complete list of options can be found in the build_opts directory. See https://www.gem5.org/documentation/general_docs/building for more information on building gem5. From d048ad34d6d316c065f2d7f072fa0457de4da309 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 16 Oct 2023 10:07:40 -0700 Subject: [PATCH 462/693] arch-riscv: Change to VS bits to DIRTY for rvv insts changing vregs (#376) This is similar to [1] and [2]. Essentially, the VS bits of STATUS CSR keep track of the state of the vector registers. (VS bits == DIRTY) means the content of vector registers have been updated since the last time the VS bits were updated. This chain of changes is supposed to change the VS bits to DIRTY for if any vector register is potentially updated. [1] https://gem5-review.googlesource.com/c/public/gem5/+/65272 [2] https://github.com/gem5/gem5/pull/370 Change-Id: I0427890dadc63b74a470d7405807dcfcad18005b --- src/arch/riscv/isa/templates/vector_arith.isa | 93 +++++++++++++++++++ src/arch/riscv/isa/templates/vector_mem.isa | 35 +++++++ 2 files changed, 128 insertions(+) diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa index 1bc7b110f8..9b5ee0e7fa 100644 --- a/src/arch/riscv/isa/templates/vector_arith.isa +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -168,6 +168,9 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -247,6 +250,9 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + auto SEW = vtype_SEW(vtype); auto offset = (VLEN / SEW) * (microIdx % %(ext_div)d); switch (SEW / %(ext_div)d) { @@ -412,6 +418,10 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + const int64_t vlmul = vtype_vlmul(machInst.vtype8); const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; @@ -451,6 +461,10 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + const int64_t vlmul = vtype_vlmul(machInst.vtype8); const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; @@ -577,6 +591,9 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + VRM_REQUIRED; %(op_decl)s; @@ -671,6 +688,9 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + VRM_REQUIRED; const int64_t vlmul = vtype_vlmul(machInst.vtype8); @@ -712,6 +732,9 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + VRM_REQUIRED; const int64_t vlmul = vtype_vlmul(machInst.vtype8); @@ -842,6 +865,10 @@ Fault } if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -883,8 +910,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -941,8 +973,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_rd)s; uint64_t Rd = 0; %(vm_decl_rd)s; @@ -1053,9 +1090,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1170,9 +1211,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1265,11 +1310,15 @@ Fault // TODO: If vd is equal to vs2 the instruction is an architectural NOP. MISA misa = xc->readMiscReg(MISCREG_ISA); STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { return std::make_shared( "RVV is disabled or VPU is off", machInst); } + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; for (size_t i = 0; i < (VLEN / 64); i++) { @@ -1327,6 +1376,9 @@ Fault if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; // TODO: remove it @@ -1388,8 +1440,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1415,8 +1472,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1521,9 +1583,14 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1562,9 +1629,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1605,9 +1676,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1755,9 +1830,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -1919,9 +1998,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(vm_decl_rd)s; @@ -2084,8 +2167,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); %(op_decl)s; @@ -2115,8 +2203,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); %(op_decl)s; diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index 1fe989ffce..2b3b9187bf 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -137,8 +137,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + if(!machInst.vm) { xc->getRegOperand(this, _numSrcRegs - 1, &tmp_v0); v0 = tmp_v0.as(); @@ -204,6 +209,10 @@ Fault %(op_decl)s; %(op_rd)s; + STATUS status = xc->readMiscReg(MISCREG_STATUS); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + RiscvISA::vreg_t tmp_v0; uint8_t *v0; if(!machInst.vm) { @@ -642,6 +651,10 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -694,6 +707,10 @@ Fault %(op_decl)s; %(op_rd)s; + STATUS status = xc->readMiscReg(MISCREG_STATUS); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); size_t elem_per_reg = VLEN / width_EEW(machInst.width); @@ -794,8 +811,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; constexpr uint8_t elem_size = sizeof(Vd[0]); @@ -873,6 +895,10 @@ Fault %(op_decl)s; %(op_rd)s; + STATUS status = xc->readMiscReg(MISCREG_STATUS); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + constexpr uint8_t elem_size = sizeof(Vd[0]); RiscvISA::vreg_t old_vd; @@ -1177,8 +1203,13 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + if (machInst.vill) return std::make_shared("VILL is set", machInst); + + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + %(op_decl)s; %(op_rd)s; %(ea_code)s; @@ -1255,6 +1286,10 @@ Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, trace::InstRecord *traceData) const { + STATUS status = xc->readMiscReg(MISCREG_STATUS); + status.vs = VPUStatus::DIRTY; + xc->setMiscReg(MISCREG_STATUS, status); + using vu = std::make_unsigned_t; %(op_decl)s; %(op_rd)s; From aaefda3b081ac6a19a88fbb5d4da25ea7460e96b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 10:57:03 -0700 Subject: [PATCH 463/693] arch-arm: Fix line-length error in branch64.is Change-Id: I62c5d5fd47927a838e6731a464fc7e6d8afab768 --- src/arch/arm/isa/insts/branch64.isa | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arch/arm/isa/insts/branch64.isa b/src/arch/arm/isa/insts/branch64.isa index 73ab70b5f1..5910a434f0 100644 --- a/src/arch/arm/isa/insts/branch64.isa +++ b/src/arch/arm/isa/insts/branch64.isa @@ -208,7 +208,9 @@ let {{ ExceptionLevel curr_el = currEL(cpsr); if (fgtEnabled(xc->tcBase()) && curr_el == EL1 && - static_cast(xc->tcBase()->readMiscReg(MISCREG_HFGITR_EL2)).eret) { + static_cast( + xc->tcBase()->readMiscReg(MISCREG_HFGITR_EL2)).eret) + { return std::make_shared( machInst, %(trap_iss)d, ExceptionClass::TRAPPED_ERET); } From df471092d94cec540525a4d9c529eaed046b2718 Mon Sep 17 00:00:00 2001 From: Ivana Mitrovic Date: Thu, 5 Oct 2023 10:53:07 -0700 Subject: [PATCH 464/693] dockerfiles: multi-platform setup (#336) Updated Dockerfiles to work with multi-platform setups --- util/dockerfiles/gcn-gpu/Dockerfile | 2 +- util/dockerfiles/gem5-all-min-dependencies/Dockerfile | 4 ++-- util/dockerfiles/gpu-fs/Dockerfile | 2 +- util/dockerfiles/llvm-gnu-cross-compiler-riscv64/Dockerfile | 2 +- util/dockerfiles/sst/Dockerfile | 2 +- util/dockerfiles/systemc-2.3.3/Dockerfile | 2 +- util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile | 2 +- util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile | 2 +- util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile | 2 +- util/dockerfiles/ubuntu-22.04_gcc-version/Dockerfile | 2 +- util/dockerfiles/ubuntu-22.04_min-dependencies/Dockerfile | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/util/dockerfiles/gcn-gpu/Dockerfile b/util/dockerfiles/gcn-gpu/Dockerfile index 85ec6d7c0d..9aead08c43 100644 --- a/util/dockerfiles/gcn-gpu/Dockerfile +++ b/util/dockerfiles/gcn-gpu/Dockerfile @@ -23,7 +23,7 @@ # 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 ubuntu:20.04 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ diff --git a/util/dockerfiles/gem5-all-min-dependencies/Dockerfile b/util/dockerfiles/gem5-all-min-dependencies/Dockerfile index b28b674fa7..cb73ab0bce 100644 --- a/util/dockerfiles/gem5-all-min-dependencies/Dockerfile +++ b/util/dockerfiles/gem5-all-min-dependencies/Dockerfile @@ -24,13 +24,13 @@ # (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 gcr.io/gem5-test/ubuntu-22.04_min-dependencies:latest as source +FROM --platform=${BUILDPLATFORM} ghcr.io/gem5/ubuntu-22.04_min-dependencies:latest as source RUN apt -y update && apt -y install git RUN git clone -b develop https://github.com/gem5/gem5/ /gem5 WORKDIR /gem5 RUN scons -j`nproc` build/ALL/gem5.fast -FROM gcr.io/gem5-test/ubuntu-22.04_min-dependencies:latest +FROM ghcr.io/gem5/ubuntu-22.04_min-dependencies:latest COPY --from=source /gem5/build/ALL/gem5.fast /usr/local/bin/gem5 ENTRYPOINT [ "/usr/local/bin/gem5" ] diff --git a/util/dockerfiles/gpu-fs/Dockerfile b/util/dockerfiles/gpu-fs/Dockerfile index 63ae6b0783..fb2465e50c 100644 --- a/util/dockerfiles/gpu-fs/Dockerfile +++ b/util/dockerfiles/gpu-fs/Dockerfile @@ -27,7 +27,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -FROM ubuntu:20.04 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ diff --git a/util/dockerfiles/llvm-gnu-cross-compiler-riscv64/Dockerfile b/util/dockerfiles/llvm-gnu-cross-compiler-riscv64/Dockerfile index 0f01e7931d..cc84f3d45a 100644 --- a/util/dockerfiles/llvm-gnu-cross-compiler-riscv64/Dockerfile +++ b/util/dockerfiles/llvm-gnu-cross-compiler-riscv64/Dockerfile @@ -26,7 +26,7 @@ # stage 1: download the dependencies -FROM ubuntu:20.04 AS stage1 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 AS stage1 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && apt -y install \ diff --git a/util/dockerfiles/sst/Dockerfile b/util/dockerfiles/sst/Dockerfile index b392c241fc..50027fe5b2 100644 --- a/util/dockerfiles/sst/Dockerfile +++ b/util/dockerfiles/sst/Dockerfile @@ -24,7 +24,7 @@ # (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 ubuntu:20.04 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ diff --git a/util/dockerfiles/systemc-2.3.3/Dockerfile b/util/dockerfiles/systemc-2.3.3/Dockerfile index ac94666d6d..41d4fafb93 100644 --- a/util/dockerfiles/systemc-2.3.3/Dockerfile +++ b/util/dockerfiles/systemc-2.3.3/Dockerfile @@ -24,7 +24,7 @@ # (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 ubuntu:22.04 +FROM --platform=${BUILDPLATFORM} ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ diff --git a/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile b/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile index 0ec8083c53..f79bcef2d9 100644 --- a/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile @@ -23,7 +23,7 @@ # 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 ubuntu:20.04 +FROM --platform=${BUILDPLATFORM} ubuntu:20.04 # Valid version values: # 7 diff --git a/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile b/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile index efefcc063f..045efbd13a 100644 --- a/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_clang-16/Dockerfile @@ -23,7 +23,7 @@ # 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 ubuntu:22.04 +FROM --platform=${BUILDPLATFORM} ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive diff --git a/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile b/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile index 2c8d7c7b21..7ddf7fe825 100644 --- a/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_clang-version/Dockerfile @@ -23,7 +23,7 @@ # 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 ubuntu:22.04 +FROM --platform=${BUILDPLATFORM} ubuntu:22.04 # Valid version values: # 13 diff --git a/util/dockerfiles/ubuntu-22.04_gcc-version/Dockerfile b/util/dockerfiles/ubuntu-22.04_gcc-version/Dockerfile index fcf909cec2..feac348780 100644 --- a/util/dockerfiles/ubuntu-22.04_gcc-version/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_gcc-version/Dockerfile @@ -23,7 +23,7 @@ # 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 ubuntu:22.04 +FROM --platform=${BUILDPLATFORM} ubuntu:22.04 # Valid version values: # 11 diff --git a/util/dockerfiles/ubuntu-22.04_min-dependencies/Dockerfile b/util/dockerfiles/ubuntu-22.04_min-dependencies/Dockerfile index 978e2c6af5..690959da91 100644 --- a/util/dockerfiles/ubuntu-22.04_min-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_min-dependencies/Dockerfile @@ -24,7 +24,7 @@ # (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 ubuntu:22.04 +FROM --platform=${BUILDPLATFORM} ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt -y update && apt -y upgrade && \ From 5b721b033f841cbd5d342160ee5312899a9c5074 Mon Sep 17 00:00:00 2001 From: Ivana Mitrovic Date: Thu, 5 Oct 2023 11:23:38 -0700 Subject: [PATCH 465/693] docker-bake: modified .hcl file Migrated all the image build definitions from docker-compose.yaml to the bake file. --- util/dockerfiles/docker-bake.hcl | 135 +++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 14 deletions(-) diff --git a/util/dockerfiles/docker-bake.hcl b/util/dockerfiles/docker-bake.hcl index d508ecd45e..29df790a95 100644 --- a/util/dockerfiles/docker-bake.hcl +++ b/util/dockerfiles/docker-bake.hcl @@ -40,11 +40,19 @@ variable "TAG" { # `docker buildx bake --push ubuntu-20-04_all-dependencies` or # `docker buildx bake --push ubuntu-releases`. group "default" { - targets=["clang-compilers", "ubuntu-releases"] + targets=["clang-compilers", "ubuntu-releases", "gcc-compilers", "gcn-gpu", "gpu-fs", "sst", "systemc", "llvm-gnu-cross-compiler-riscv64", "gem5-all-min-dependencies"] } group "ubuntu-releases" { - targets=["ubuntu-22-04_all-dependencies", "ubuntu-20-04_all-dependencies"] + targets=["ubuntu-22-04_all-dependencies", "ubuntu-20-04_all-dependencies", "ubuntu-22-04_min-dependencies"] +} + +group "clang-compilers" { + targets = ["clang-compilers-a", "clang-compilers-b", "clang-compilers-16"] +} + +group "gcc-compilers" { + targets = ["gcc-compilers-a", "gcc-compilers-b"] } # Common attributes across all targets. Note: these can be overwritten. @@ -54,18 +62,32 @@ target "common" { platforms = ["linux/amd64", "linux/arm64"] } -target "clang-compilers" { - name="clang-compilers-${replace(ver, ".", "-")}" - inherits = ["common"] - context = "ubuntu-20.04_clang-version" - dockerfile = "Dockerfile" - matrix = { - ver = ["6.0","7","8","9","10","11"] - } - args = { - version=ver - } - tags = ["${IMAGE_URI}/clang-version-${ver}:${TAG}"] +target "gcn-gpu" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "gcn-gpu" + tags = ["${IMAGE_URI}/gcn-gpu:${TAG}"] +} + +target "gpu-fs" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "gpu-fs" + tags = ["${IMAGE_URI}/gpu-fs:${TAG}"] +} + +target "sst" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "sst-11.1.0" + tags = ["${IMAGE_URI}/sst-env:${TAG}"] +} + +target "systemc" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "systemc-2.3.3" + tags = ["${IMAGE_URI}/systemc-env:${TAG}"] } target "ubuntu-22-04_all-dependencies" { @@ -81,3 +103,88 @@ target "ubuntu-20-04_all-dependencies" { context = "ubuntu-20.04_all-dependencies" tags = ["${IMAGE_URI}/ubuntu-20.04_all-dependencies:${TAG}"] } + +target "ubuntu-22-04_min-dependencies" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "ubuntu-22.04_min-dependencies" + tags = ["${IMAGE_URI}/ubuntu-22.04_min-dependencies:${TAG}"] +} + +target "gcc-compilers-a" { + name = "gcc-compilers-${replace(ver, ".", "-")}" + inherits = ["common"] + context = "ubuntu-20.04_gcc-version" + dockerfile = "Dockerfile" + matrix = { + ver = ["8", "9", "10"] + } + args = { + version = ver + } + tags = ["${IMAGE_URI}/gcc-version-${ver}:${TAG}"] +} + +target "gcc-compilers-b" { + name = "gcc-compilers-${replace(ver, ".", "-")}" + inherits = ["common"] + context = "ubuntu-22.04_gcc-version" + dockerfile = "Dockerfile" + matrix = { + ver = ["11", "12"] + } + args = { + version = ver + } + tags = ["${IMAGE_URI}/gcc-version-${ver}:${TAG}"] +} + +target "clang-compilers-a" { + name = "clang-compilers-${replace(ver, ".", "-")}" + inherits = ["common"] + context = "ubuntu-20.04_clang-version" + dockerfile = "Dockerfile" + matrix = { + ver = ["7", "8", "9", "10", "11", "12"] + } + args = { + version = ver + } + tags = ["${IMAGE_URI}/clang-version-${ver}:${TAG}"] +} + +target "clang-compilers-b" { + name = "clang-compilers-${replace(ver, ".", "-")}" + inherits = ["common"] + context = "ubuntu-22.04_clang-version" + dockerfile = "Dockerfile" + matrix = { + ver = ["13", "14", "15"] + } + args = { + version = ver + } + tags = ["${IMAGE_URI}/clang-version-${ver}:${TAG}"] +} + +target "clang-compilers-16" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "ubuntu-22.04_clang_16" + tags = ["${IMAGE_URI}/clang-version-16:${TAG}"] +} + +target "llvm-gnu-cross-compiler-riscv64" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "llvm-gnu-cross-compiler-riscv64" + tags = ["${IMAGE_URI}/llvm-gnu-cross-compiler-riscv64:${TAG}"] +} + +target "gem5-all-min-dependencies" { + inherits = ["common"] + dockerfile = "Dockerfile" + context = "gem5-all-min-dependencies" + tags = ["${IMAGE_URI}/gem5-all-min-dependencies:${TAG}"] +} + From 45df1dbb557204f056f201a69c252effa2e5922f Mon Sep 17 00:00:00 2001 From: Ivana Mitrovic Date: Mon, 9 Oct 2023 08:55:54 -0700 Subject: [PATCH 466/693] docker-images: Changed path from Google Registry to GitHub Replaced all instances of the Google Docker registry (gcr.io/gem5-test/) with the GitHub Docker registry (ghcr.io/gem5/). --- .github/workflows/compiler-tests.yaml | 4 ++-- .github/workflows/daily-tests.yaml | 14 +++++++------- .github/workflows/gpu-tests.yaml | 4 ++-- .github/workflows/weekly-tests.yaml | 6 +++--- tests/deprecated/compiler-tests.sh | 2 +- tests/deprecated/jenkins/presubmit.sh | 4 ++-- tests/deprecated/nightly.sh | 22 +++++++++++----------- tests/deprecated/weekly.sh | 14 +++++++------- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index 1a340e0bf5..ac092cd3d3 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -22,7 +22,7 @@ jobs: opts: [.opt, .fast] runs-on: [self-hosted, linux, x64] timeout-minutes: 2880 # 48 hours - container: gcr.io/gem5-test/${{ matrix.image }}:latest + container: ghcr.io/gem5/${{ matrix.image }}:latest steps: - uses: actions/checkout@v3 with: @@ -45,7 +45,7 @@ jobs: opts: [.opt] runs-on: [self-hosted, linux, x64] timeout-minutes: 2880 # 48 hours - container: gcr.io/gem5-test/${{ matrix.image }}:latest + container: ghcr.io/gem5/${{ matrix.image }}:latest steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 36006d03e4..89a72fd852 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -39,7 +39,7 @@ jobs: command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) runs-on: [self-hosted, linux, x64] needs: name-artifacts - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest steps: - uses: actions/checkout@v3 with: @@ -61,7 +61,7 @@ jobs: matrix: type: [fast, debug] runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest timeout-minutes: 60 steps: - uses: actions/checkout@v3 @@ -80,7 +80,7 @@ jobs: test-type: [arm_boot_tests, fs, gpu, insttest_se, learning_gem5, m5threads_test_atomic, memory, multi_isa, replacement_policies, riscv_boot_tests, stdlib, x86_boot_tests] runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours for entire matrix to run steps: @@ -169,7 +169,7 @@ jobs: matrix: test-type: [gem5-library-example-x86-ubuntu-run-ALL-x86_64-opt, gem5-library-example-riscv-ubuntu-run-ALL-x86_64-opt, lupv-example-ALL-x86_64-opt, gem5-library-example-arm-ubuntu-run-test-ALL-x86_64-opt, gem5-library-example-riscvmatched-hello-ALL-x86_64-opt] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [name-artifacts, build-gem5] timeout-minutes: 1440 # 24 hours steps: @@ -209,7 +209,7 @@ jobs: # ext/sst/sst/example.py. sst-test: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/sst-env:latest + container: ghcr.io/gem5/sst-env:latest timeout-minutes: 180 steps: @@ -234,7 +234,7 @@ jobs: # simulation with it. systemc-test: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/systemc-env:latest + container: ghcr.io/gem5/systemc-env:latest timeout-minutes: 180 steps: @@ -258,7 +258,7 @@ jobs: # Runs the gem5 Nighyly GPU tests. gpu-tests: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/gcn-gpu:latest + container: ghcr.io/gem5/gcn-gpu:latest timeout-minutes: 720 # 12 hours steps: diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index 43eff95529..fe6df5eb1e 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -13,7 +13,7 @@ on: jobs: build-gem5: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/gcn-gpu:latest + container: ghcr.io/gem5/gcn-gpu:latest steps: - uses: actions/checkout@v3 with: @@ -31,7 +31,7 @@ jobs: HACC-tests: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/gcn-gpu:latest + container: ghcr.io/gem5/gcn-gpu:latest needs: build-gem5 timeout-minutes: 120 # 2 hours steps: diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index b21613f7a1..17f111fc42 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -13,7 +13,7 @@ on: jobs: build-gem5: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest outputs: build-name: ${{ steps.artifact-name.outputs.name }} steps: @@ -41,7 +41,7 @@ jobs: matrix: test-type: [gem5_library_example_tests, gem5_resources, parsec_benchmarks, x86_boot_tests] runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest needs: [build-gem5] timeout-minutes: 4320 # 3 days steps: @@ -78,7 +78,7 @@ jobs: dramsys-tests: runs-on: [self-hosted, linux, x64] - container: gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest timeout-minutes: 4320 # 3 days steps: - uses: actions/checkout@v3 diff --git a/tests/deprecated/compiler-tests.sh b/tests/deprecated/compiler-tests.sh index a7ae397eac..e8da335de4 100755 --- a/tests/deprecated/compiler-tests.sh +++ b/tests/deprecated/compiler-tests.sh @@ -73,7 +73,7 @@ opts=(".opt" builds_per_compiler=1 # Base URL of the gem5 testing images. -base_url="gcr.io/gem5-test" +base_url="ghcr.io/gem5" # Arguments passed into scons on every build target test. if [ $# -eq 0 ];then diff --git a/tests/deprecated/jenkins/presubmit.sh b/tests/deprecated/jenkins/presubmit.sh index 91eb95f81b..becf499d28 100755 --- a/tests/deprecated/jenkins/presubmit.sh +++ b/tests/deprecated/jenkins/presubmit.sh @@ -37,8 +37,8 @@ set -e -DOCKER_IMAGE_ALL_DEP=gcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest -DOCKER_IMAGE_CLANG_COMPILE=gcr.io/gem5-test/clang-version-14:latest +DOCKER_IMAGE_ALL_DEP=ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest +DOCKER_IMAGE_CLANG_COMPILE=ghcr.io/gem5/clang-version-14:latest PRESUBMIT_STAGE2=tests/jenkins/presubmit-stage2.sh GEM5ART_TESTS=tests/jenkins/gem5art-tests.sh diff --git a/tests/deprecated/nightly.sh b/tests/deprecated/nightly.sh index 9503cd1f61..53ad374c3c 100755 --- a/tests/deprecated/nightly.sh +++ b/tests/deprecated/nightly.sh @@ -70,13 +70,13 @@ unit_test () { docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ scons build/ALL/unittests.${build} -j${compile_threads} \ --ignore-style } # Ensure we have the latest docker images. -docker pull gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} +docker pull ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} # Run the unit tests. unit_test opt @@ -85,7 +85,7 @@ unit_test debug # Run the gem5 long tests. docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}"/tests --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ ./main.py run --length long -j${compile_threads} -t${run_threads} -vv # Unfortunately, due docker being unable run KVM, we do so separately. @@ -105,10 +105,10 @@ cd "${gem5_root}/tests" cd "${gem5_root}" # For the GPU tests we compile and run the GPU ISA inside a gcn-gpu container. -docker pull gcr.io/gem5-test/gcn-gpu:${tag} +docker pull ghcr.io/gem5/gcn-gpu:${tag} docker run --rm -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" \ - gcr.io/gem5-test/gcn-gpu:${tag} bash -c \ + ghcr.io/gem5/gcn-gpu:${tag} bash -c \ "scons build/${gpu_isa}/gem5.opt -j${compile_threads} --ignore-style \ || (rm -rf build && scons build/${gpu_isa}/gem5.opt \ -j${compile_threads} --ignore-style)" @@ -123,7 +123,7 @@ mkdir -p tests/testing-results # basic GPU functionality is working. docker run --rm -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" \ - gcr.io/gem5-test/gcn-gpu:${tag} build/${gpu_isa}/gem5.opt \ + ghcr.io/gem5/gcn-gpu:${tag} build/${gpu_isa}/gem5.opt \ configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c square # get HeteroSync @@ -135,7 +135,7 @@ wget -qN http://dist.gem5.org/dist/develop/test-progs/heterosync/gcn3/allSyncPri # atomics are tested. docker run --rm -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" \ - gcr.io/gem5-test/gcn-gpu:${tag} build/${gpu_isa}/gem5.opt \ + ghcr.io/gem5/gcn-gpu:${tag} build/${gpu_isa}/gem5.opt \ configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c \ allSyncPrims-1kernel --options="sleepMutex 10 16 4" @@ -146,7 +146,7 @@ docker run --rm -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ # atomics are tested. docker run --rm -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" \ - gcr.io/gem5-test/gcn-gpu:${tag} build/${gpu_isa}/gem5.opt \ + ghcr.io/gem5/gcn-gpu:${tag} build/${gpu_isa}/gem5.opt \ configs/example/apu_se.py --reg-alloc-policy=dynamic -n3 -c \ allSyncPrims-1kernel --options="lfTreeBarrUniq 10 16 4" @@ -157,7 +157,7 @@ build_and_run_SST () { docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --rm --memory="${docker_mem_limit}" \ - gcr.io/gem5-test/sst-env:${tag} bash -c "\ + ghcr.io/gem5/sst-env:${tag} bash -c "\ scons build/${isa}/libgem5_${variant}.so -j${compile_threads} \ --without-tcmalloc --duplicate-sources --ignore-style && \ cd ext/sst && \ @@ -173,7 +173,7 @@ build_and_run_systemc () { rm -rf "${gem5_root}/build/ARM" docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_min-dependencies:${tag} bash -c "\ + ghcr.io/gem5/ubuntu-22.04_min-dependencies:${tag} bash -c "\ scons -j${compile_threads} --ignore-style --duplicate-sources \ build/ARM/gem5.opt && \ scons --with-cxx-config --without-python --without-tcmalloc \ @@ -183,7 +183,7 @@ scons --with-cxx-config --without-python --without-tcmalloc \ docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/systemc-env:${tag} bash -c "\ + ghcr.io/gem5/systemc-env:${tag} bash -c "\ cd util/systemc/gem5_within_systemc && \ make -j${compile_threads} && \ ../../../build/ARM/gem5.opt ../../../configs/deprecated/example/se.py -c \ diff --git a/tests/deprecated/weekly.sh b/tests/deprecated/weekly.sh index 809c9a1427..17d68426a6 100755 --- a/tests/deprecated/weekly.sh +++ b/tests/deprecated/weekly.sh @@ -72,7 +72,7 @@ fi # Run the gem5 very-long tests. docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}"/tests --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ ./main.py run --length very-long -j${threads} -t${run_threads} -vv mkdir -p tests/testing-results @@ -81,7 +81,7 @@ mkdir -p tests/testing-results # before pulling gem5 resources, make sure it doesn't exist already docker run -u $UID:$GID --rm --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" \ - gcr.io/gem5-test/gcn-gpu:${tag} bash -c \ + ghcr.io/gem5/gcn-gpu:${tag} bash -c \ "rm -rf ${gem5_root}/gem5-resources" # delete m5out, Pannotia datasets, and output files in case a failed regression @@ -127,7 +127,7 @@ cd "${gem5_root}" # avoid needing to set all of these, we instead build a docker for it, which # has all these variables pre-set in its Dockerfile # To avoid compiling gem5 multiple times, all GPU benchmarks will use this -docker pull gcr.io/gem5-test/gcn-gpu:${tag} +docker pull ghcr.io/gem5/gcn-gpu:${tag} docker build -t hacc-test-weekly ${gem5_root}/gem5-resources/src/gpu/halo-finder docker run --rm -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ @@ -419,23 +419,23 @@ rm -rf "${gem5_root}/build/ALL" docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ scons build/ALL/gem5.opt -j${threads} docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ ./build/ALL/gem5.opt \ configs/example/gem5_library/dramsys/arm-hello-dramsys.py docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ ./build/ALL/gem5.opt \ configs/example/gem5_library/dramsys/dramsys-traffic.py docker run -u $UID:$GID --volume "${gem5_root}":"${gem5_root}" -w \ "${gem5_root}" --memory="${docker_mem_limit}" --rm \ - gcr.io/gem5-test/ubuntu-22.04_all-dependencies:${tag} \ + ghcr.io/gem5/ubuntu-22.04_all-dependencies:${tag} \ ./build/ALL/gem5.opt \ configs/example/dramsys.py From cb078f14c6da185cac1cdde5a90c0437a44cb725 Mon Sep 17 00:00:00 2001 From: Ivana Mitrovic Date: Thu, 12 Oct 2023 10:44:43 -0700 Subject: [PATCH 467/693] docker-bake: Changed compilers names to be more descriptive --- util/dockerfiles/docker-bake.hcl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/util/dockerfiles/docker-bake.hcl b/util/dockerfiles/docker-bake.hcl index 29df790a95..8f98a07558 100644 --- a/util/dockerfiles/docker-bake.hcl +++ b/util/dockerfiles/docker-bake.hcl @@ -48,11 +48,11 @@ group "ubuntu-releases" { } group "clang-compilers" { - targets = ["clang-compilers-a", "clang-compilers-b", "clang-compilers-16"] + targets = ["clang-compilers-base-20-04", "clang-compilers-base-22-04", "clang-compilers-16"] } group "gcc-compilers" { - targets = ["gcc-compilers-a", "gcc-compilers-b"] + targets = ["gcc-compilers-base-20-04", "gcc-compilers-base-22-04"] } # Common attributes across all targets. Note: these can be overwritten. @@ -111,7 +111,7 @@ target "ubuntu-22-04_min-dependencies" { tags = ["${IMAGE_URI}/ubuntu-22.04_min-dependencies:${TAG}"] } -target "gcc-compilers-a" { +target "gcc-compilers-base-20-04" { name = "gcc-compilers-${replace(ver, ".", "-")}" inherits = ["common"] context = "ubuntu-20.04_gcc-version" @@ -125,7 +125,7 @@ target "gcc-compilers-a" { tags = ["${IMAGE_URI}/gcc-version-${ver}:${TAG}"] } -target "gcc-compilers-b" { +target "gcc-compilers-base-22-04" { name = "gcc-compilers-${replace(ver, ".", "-")}" inherits = ["common"] context = "ubuntu-22.04_gcc-version" @@ -139,7 +139,7 @@ target "gcc-compilers-b" { tags = ["${IMAGE_URI}/gcc-version-${ver}:${TAG}"] } -target "clang-compilers-a" { +target "clang-compilers-base-20-04" { name = "clang-compilers-${replace(ver, ".", "-")}" inherits = ["common"] context = "ubuntu-20.04_clang-version" @@ -153,7 +153,7 @@ target "clang-compilers-a" { tags = ["${IMAGE_URI}/clang-version-${ver}:${TAG}"] } -target "clang-compilers-b" { +target "clang-compilers-base-22-04" { name = "clang-compilers-${replace(ver, ".", "-")}" inherits = ["common"] context = "ubuntu-22.04_clang-version" From cfef2ac23be67c9d38917abef47de91736930118 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 12:06:01 -0700 Subject: [PATCH 468/693] util-docker: Fix end-of-line error in docker-bake.hcl Change-Id: I2c792f35d8c74e29cf0dc0bc1287b6b5f3e4d6c8 --- util/dockerfiles/docker-bake.hcl | 1 - 1 file changed, 1 deletion(-) diff --git a/util/dockerfiles/docker-bake.hcl b/util/dockerfiles/docker-bake.hcl index 8f98a07558..8218290bd2 100644 --- a/util/dockerfiles/docker-bake.hcl +++ b/util/dockerfiles/docker-bake.hcl @@ -187,4 +187,3 @@ target "gem5-all-min-dependencies" { context = "gem5-all-min-dependencies" tags = ["${IMAGE_URI}/gem5-all-min-dependencies:${TAG}"] } - From 4b9c4e1e17a80c9ceb4f9c7ccd1fa843bf2f8a25 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 13:33:30 -0700 Subject: [PATCH 469/693] misc: Add `--all` to Runner `docker system prune` Without `--all` `docker prune --force --volumes` will remove everything exception non-dangling images. For an image to be considered dangling it must be untagged and/or not used by a container at that time. As most of the images we download are tagged (e.g., `:latest`) then most of our images are never removed without the inclusion of `--all` which will remove any image not currently used by a container. Images were starting to accumulate on runners. This will ensure they do not and are cleaned after each job run. Change-Id: I6d8441a11d22fdcf827e9c44422dbcf02cf600e0 --- util/github-runners-vagrant/action-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/github-runners-vagrant/action-run.sh b/util/github-runners-vagrant/action-run.sh index b802a7c739..b3c343e495 100755 --- a/util/github-runners-vagrant/action-run.sh +++ b/util/github-runners-vagrant/action-run.sh @@ -77,5 +77,5 @@ while true; do # 4. Cleanup the machine rm -rf "${WORK_DIR}" - docker system prune --force --volumes + docker system prune --force --volumes --all done From d18087af969a4263db6d6fb68d95169f8c99b79c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 21:14:09 -0700 Subject: [PATCH 470/693] util: Add halt-helper.sh This script helps use safely halt vagrant VMs. Change-Id: I2f2f36b93f82e07756d069334db178604a9915b3 --- util/github-runners-vagrant/halt-helper.sh | 83 ++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 util/github-runners-vagrant/halt-helper.sh diff --git a/util/github-runners-vagrant/halt-helper.sh b/util/github-runners-vagrant/halt-helper.sh new file mode 100755 index 0000000000..9b4caf7e28 --- /dev/null +++ b/util/github-runners-vagrant/halt-helper.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This script will try to safely halt each VM specified in the Vagrantfile. +# A VM is skipped if it is currently running a job and returned to after +# attempted shutdowns on the other VMs. This cycle continues indefinitely until +# all the runners are shutdown. +# +# This script is usefull as the VMs occasionally need to be halted to apply +# patches and do maintenance. This script allows us to do this without +# interrupting any jobs that may be running. + +while true; do + # This will list all the VMs still running. If there are no VM's running, + # we infer all have been shutdown and we exit the script. Otherwise, we + # iterate over he VMs in an attempt to shut them down. + active=$(vagrant status | grep running | tr -s ' ' | cut -d ' ' -f1) + if [ "$active" == "" ]; then + echo "All VMs have been shutdown. Exiting." + exit 0 + fi + echo "The following VMs are still running:" + echo "${active}" + + for virtm in $active + do + # This script will first list the contents of the "_diag" directory. + # This directory hosts the github action runner job logs. Each job + # is logged to a seperate file in the directpry. This script then + # sort these files by name. The last file in this sorted list is the + # most recent file and therefore for the most recent job. We can sort + # them in this was because their filenames are appended with UTC + # timestamps. + # + # One one job ever runs at a time on a GitHub runner so if there is any + # job running, it be being logged in the most recent file in the + # "_diag" directory. + # + # If the job has completed the last line in the file will contain the + # string "Job completed.". This script checks for this and, if found, + # we assume there are no jobs running safely run `vagrant halt` to + # shutdown the VM. If the job is still running we print a message + # saying the job is still running and will return to it on the next + # iteration of the loop. + echo "Inspecting \"${virtm}\"..." + vagrant ssh $virtm -c 'ls _diag | sort | tail -1 | xargs -I % cat "_diag/%" | tail -1 | grep -q "Job completed"' + status=$? + if [[ ${status} == 0 ]]; then + echo "${virtm} is Idle. Attempting shutdown" + vagrant halt ${virtm} && echo "${virtm} successfully halted" || echo "${virtm} experience a failure halting" + else + echo "${virtm} is Busy. Skipping for now." + fi + done + # Sleep here for 20 seconds just to ensure all the VMs have time + # to shutdown. + sleep 20 +done From 3783afff5d5c4e2e4c7b1e3e846185900f06ab4d Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 16 Oct 2023 21:21:31 -0700 Subject: [PATCH 471/693] util: Enable KVM on VMs and ensure working in Runners This patch: 1. Adds setup scripting to "provision_root.sh" to setup and enable KVM, for the 'vagrant' user, for VMs which are capable of this. 2. Runs a check on each VM to see if KVM can be run sucessfully within a docker container. If so, the GitHub Actions runner is given a 'kvm' label. It is unknown at this time if GitHub Runners can utlized KVM but it is open to their processes. Change-Id: Idfcbb7bfa3e5b7cc47d29aea50fb1ebcafdb7acc --- util/github-runners-vagrant/Vagrantfile | 28 +++++++++++++++++-- util/github-runners-vagrant/provision_root.sh | 19 ++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/util/github-runners-vagrant/Vagrantfile b/util/github-runners-vagrant/Vagrantfile index 3446f703dd..0e505ba38b 100644 --- a/util/github-runners-vagrant/Vagrantfile +++ b/util/github-runners-vagrant/Vagrantfile @@ -58,8 +58,32 @@ Vagrant.configure("2") do |config| # Copy the "action-run.sh" script from the host to the VM. runner.vm.provision "file", source: "./action-run.sh", destination: "/tmp/action-run.sh" runner.vm.provision :shell, privileged: false, inline: "cp /tmp/action-run.sh ." - # Execute the actions-run.sh script on every boot. This configures the and starts the runner. - runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} >> action-run.log 2>&1 &" + + # The following attempts to see if KVM can be used inside the docker + # container. + # + # Almost all github action jobs run within a docker container. Therefore + # to be compatible with KVM, KVM must be enabled inside the docker. + # + # We used existence of "kvm-works" in the VM home directory is how we + # indicate that KVM is working. It is created if the 'kvm-ok' command is + # successful. This is then passed to the action-run.sh script to indicate + # that the runner can be used for KVM via the `kvm` label. + runner.vm.provision :shell, privileged: false, run: 'always', inline: <<-SHELL + rm -f kvm-works + docker run --device /dev/kvm -v$(pwd):/work -w /work --rm ubuntu:22.04 bash -c "apt update -y && apt install -y cpu-checker && kvm-ok" + status=$? + if [[ ${status} == 0 ]]; then + echo >&1 "Success. KVM enabled." + echo "success" > kvm-works + else + echo >&2 "Failure. KVM not enabled." + fi + exit 0 + SHELL + # Execute the actions-run.sh script on every boot. This configures and starts the runner. + # Note the 'kvm' label is applied to this runner if the "kvm-works" file eixsts. See above. + runner.vm.provision :shell, privileged: false, run: 'always', inline: "./action-run.sh #{PERSONAL_ACCESS_TOKEN} #{GITHUB_ORG} $(if [ -f 'kvm-works' ]; then echo 'kvm'; fi) >> action-run.log 2>&1 &" end end end diff --git a/util/github-runners-vagrant/provision_root.sh b/util/github-runners-vagrant/provision_root.sh index 34c2d811de..d3e6bb574c 100644 --- a/util/github-runners-vagrant/provision_root.sh +++ b/util/github-runners-vagrant/provision_root.sh @@ -56,7 +56,8 @@ apt-get install -y \ apt-transport-https ca-certificates \ curl \ gnupg \ - lsb-release + lsb-release \ + cpu-checker # Install docker apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release @@ -70,6 +71,22 @@ apt-get install -y docker-ce docker-ce-cli containerd.io # work. usermod -aG docker vagrant +kvm-ok +kvm_ok_status=$? + +# `kvm-ok` will return a exit zero if the machine supports KVM, and non-zero +# otherwise. If the machine support KVM, let's enable it. +if [[ ${kvm_ok_status} == 0 ]]; then + apt install -y qemu-kvm \ + virt-manager \ + libvirt-daemon-system virtinst \ + libvirt-clients bridge-utils && \ + sudo systemctl enable --now libvirtd && \ + sudo systemctl start libvirtd && \ + usermod -aG kvm vagrant && \ + usermod -aG libvirt vagrant +fi + # Cleanup apt-get autoremove -y From 5387e6711433b7b0d18b629f5b36cdb44355a84c Mon Sep 17 00:00:00 2001 From: David Schall Date: Tue, 5 Sep 2023 08:01:13 +0000 Subject: [PATCH 472/693] cpu: Restructure RAS The return address stack (RAS) is restructured to be a separate SimObject. This enables disabling the RAS and better separation of the functionality. Furthermore, easier statistics and debugging. Change-Id: I8aacf7d4c8e308165d0e7e15bc5a5d0df77f8192 Signed-off-by: David Schall --- configs/common/cores/arm/HPI.py | 2 +- configs/common/cores/arm/O3_ARM_v7a.py | 2 +- configs/common/cores/arm/ex5_big.py | 2 +- src/cpu/pred/BranchPredictor.py | 15 +- src/cpu/pred/SConscript | 2 + src/cpu/pred/bpred_unit.cc | 169 +++++------- src/cpu/pred/bpred_unit.hh | 29 +- src/cpu/pred/ras.cc | 256 +++++++++++++++++- src/cpu/pred/ras.hh | 201 +++++++++++--- .../riscvmatched/riscvmatched_core.py | 2 +- 10 files changed, 508 insertions(+), 172 deletions(-) diff --git a/configs/common/cores/arm/HPI.py b/configs/common/cores/arm/HPI.py index f7e9348622..8fe396abfa 100644 --- a/configs/common/cores/arm/HPI.py +++ b/configs/common/cores/arm/HPI.py @@ -1687,6 +1687,7 @@ class HPI_BTB(SimpleBTB): class HPI_BP(TournamentBP): btb = HPI_BTB() + ras = ReturnAddrStack(numEntries=8) localPredictorSize = 64 localCtrBits = 2 localHistoryTableSize = 64 @@ -1694,7 +1695,6 @@ class HPI_BP(TournamentBP): globalCtrBits = 2 choicePredictorSize = 1024 choiceCtrBits = 2 - RASSize = 8 instShiftAmt = 2 diff --git a/configs/common/cores/arm/O3_ARM_v7a.py b/configs/common/cores/arm/O3_ARM_v7a.py index e8a7826372..de258324be 100644 --- a/configs/common/cores/arm/O3_ARM_v7a.py +++ b/configs/common/cores/arm/O3_ARM_v7a.py @@ -116,11 +116,11 @@ class O3_ARM_v7a_BTB(SimpleBTB): # Bi-Mode Branch Predictor class O3_ARM_v7a_BP(BiModeBP): btb = O3_ARM_v7a_BTB() + ras = ReturnAddrStack(numEntries=16) globalPredictorSize = 8192 globalCtrBits = 2 choicePredictorSize = 8192 choiceCtrBits = 2 - RASSize = 16 instShiftAmt = 2 diff --git a/configs/common/cores/arm/ex5_big.py b/configs/common/cores/arm/ex5_big.py index daf5102e28..7803c1e0cc 100644 --- a/configs/common/cores/arm/ex5_big.py +++ b/configs/common/cores/arm/ex5_big.py @@ -113,11 +113,11 @@ class ex5_big_BTB(SimpleBTB): # Bi-Mode Branch Predictor class ex5_big_BP(BiModeBP): btb = ex5_big_BTB() + ras = ReturnAddrStack(numEntries=48) globalPredictorSize = 4096 globalCtrBits = 2 choicePredictorSize = 1024 choiceCtrBits = 3 - RASSize = 48 instShiftAmt = 2 diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index ed356b166d..5ae4ee8963 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -57,6 +57,15 @@ class BranchType(Enum): ] +class ReturnAddrStack(SimObject): + type = "ReturnAddrStack" + cxx_class = "gem5::branch_prediction::ReturnAddrStack" + cxx_header = "cpu/pred/ras.hh" + + numThreads = Param.Unsigned(Parent.numThreads, "Number of threads") + numEntries = Param.Unsigned(16, "Number of RAS entries") + + class BranchTargetBuffer(ClockedObject): type = "BranchTargetBuffer" cxx_class = "gem5::branch_prediction::BranchTargetBuffer" @@ -120,10 +129,10 @@ class BranchPredictor(SimObject): numThreads = Param.Unsigned(Parent.numThreads, "Number of threads") instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") - RASSize = Param.Unsigned(16, "RAS size") - btb = Param.BranchTargetBuffer(SimpleBTB(), "Branch target buffer (BTB)") - + ras = Param.ReturnAddrStack( + ReturnAddrStack(), "Return address stack, set to NULL to disable RAS." + ) indirectBranchPred = Param.IndirectPredictor( SimpleIndirectPredictor(), "Indirect branch predictor, set to NULL to disable " diff --git a/src/cpu/pred/SConscript b/src/cpu/pred/SConscript index 89054ba8e8..c6c2a94cc8 100644 --- a/src/cpu/pred/SConscript +++ b/src/cpu/pred/SConscript @@ -46,6 +46,7 @@ SimObject('BranchPredictor.py', 'BranchPredictor', 'IndirectPredictor', 'SimpleIndirectPredictor', 'BranchTargetBuffer', 'SimpleBTB', + 'ReturnAddrStack', 'LocalBP', 'TournamentBP', 'BiModeBP', 'TAGEBase', 'TAGE', 'LoopPredictor', 'TAGE_SC_L_TAGE', 'TAGE_SC_L_TAGE_64KB', 'TAGE_SC_L_TAGE_8KB', 'LTAGE', 'TAGE_SC_L_LoopPredictor', 'StatisticalCorrector', 'TAGE_SC_L', @@ -85,6 +86,7 @@ Source('btb.cc') Source('simple_btb.cc') DebugFlag('Indirect') DebugFlag('BTB') +DebugFlag('RAS') DebugFlag('FreeList') DebugFlag('Branch') DebugFlag('Tage') diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index 813ac86f24..a338cbdafd 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -60,13 +60,11 @@ BPredUnit::BPredUnit(const Params ¶ms) numThreads(params.numThreads), predHist(numThreads), btb(params.btb), - RAS(numThreads), + ras(params.ras), iPred(params.indirectBranchPred), stats(this), instShiftAmt(params.instShiftAmt) { - for (auto& r : RAS) - r.init(params.RASSize); } BPredUnit::BPredUnitStats::BPredUnitStats(statistics::Group *parent) @@ -172,19 +170,12 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, // support coroutines. if (inst->isReturn()) { ++stats.RASUsed; - predict_record.wasReturn = true; - // If it's a function return call, then look up the address - // in the RAS. - const PCStateBase *ras_top = RAS[tid].top(); - if (ras_top) - set(target, inst->buildRetPC(pc, *ras_top)); - - // Record the top entry of the RAS, and its index. - predict_record.usedRAS = true; - predict_record.RASIndex = RAS[tid].topIdx(); - set(predict_record.RASTarget, ras_top); - - RAS[tid].pop(); + // If it's a return from a function call, then look up the + // RETURN address in the RAS. + const PCStateBase *return_addr = ras->pop(tid, + predict_record.rasHistory); + if (return_addr) + set(target, return_addr); DPRINTF(Branch, "[tid:%i] [sn:%llu] Instruction %s is a return, " "RAS predicted target: %s, RAS index: %i\n", @@ -192,17 +183,17 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, } if (inst->isCall()) { - RAS[tid].push(pc); - predict_record.pushedRAS = true; + // In case of a call build the return address and + // push it to the RAS. + auto return_addr = inst->buildRetPC(pc, pc); + ras->push(tid, *return_addr, predict_record.rasHistory); // Record that it was a call so that the top RAS entry can // be popped off if the speculation is incorrect. - predict_record.wasCall = true; + DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s was " + "a call, push return address %s onto the RAS\n", + tid, seqNum, pc, *return_addr); - DPRINTF(Branch, - "[tid:%i] [sn:%llu] Instruction %s was a call, adding " - "%s to the RAS index: %i\n", - tid, seqNum, pc, pc, RAS[tid].topIdx()); } // The target address is not predicted by RAS. @@ -237,7 +228,7 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, "called for %s\n", tid, seqNum, pc); } else if (inst->isCall() && !inst->isUncondCtrl()) { - RAS[tid].pop(); + ras->squash(tid, predict_record.rasHistory); predict_record.pushedRAS = false; } inst->advancePC(*target); @@ -269,17 +260,13 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, if (!inst->isCall() && !inst->isReturn()) { } else if (inst->isCall() && !inst->isUncondCtrl()) { - RAS[tid].pop(); - predict_record.pushedRAS = false; + ras->squash(tid, predict_record.rasHistory); } inst->advancePC(*target); } } } } else { - if (inst->isReturn()) { - predict_record.wasReturn = true; - } inst->advancePC(*target); } predict_record.target = target->instAddr(); @@ -325,6 +312,12 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) predHist[tid].back().indirectHistory); } + if (ras) { + ras->commit(tid, predHist[tid].back().mispredict, + getBranchType(predHist[tid].back().inst), + predHist[tid].back().rasHistory); + } + predHist[tid].pop_back(); } } @@ -336,30 +329,15 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) while (!pred_hist.empty() && pred_hist.front().seqNum > squashed_sn) { - if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) { - // Was a call but predicated false. Pop RAS here - DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Squashing" - " Call [sn:%llu] PC: %s Popping RAS\n", tid, squashed_sn, - pred_hist.front().seqNum, pred_hist.front().pc); - RAS[tid].pop(); - } - if (pred_hist.front().usedRAS) { - if (pred_hist.front().RASTarget != nullptr) { - DPRINTF(Branch, "[tid:%i] [squash sn:%llu]" - " Restoring top of RAS to: %i," - " target: %s\n", tid, squashed_sn, - pred_hist.front().RASIndex, - *pred_hist.front().RASTarget); - } - else { - DPRINTF(Branch, "[tid:%i] [squash sn:%llu]" - " Restoring top of RAS to: %i," - " target: INVALID_TARGET\n", tid, squashed_sn, - pred_hist.front().RASIndex); - } - RAS[tid].restore(pred_hist.front().RASIndex, - pred_hist.front().RASTarget.get()); + if (pred_hist.front().rasHistory) { + assert(ras); + + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect call/return " + "PC %#x. Fix RAS.\n", tid, pred_hist.front().seqNum, + pred_hist.front().pc); + + ras->squash(tid, pred_hist.front().rasHistory); } // This call should delete the bpHistory. @@ -425,8 +403,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, assert(pred_hist.front().seqNum == squashed_sn); } - - if ((*hist_it).usedRAS) { + if ((*hist_it).rasHistory) { ++stats.RASIncorrect; DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect RAS [sn:%llu]\n", @@ -445,6 +422,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, // Remember the correct direction for the update at commit. pred_hist.front().predTaken = actually_taken; pred_hist.front().target = corr_target.instAddr(); + pred_hist.front().mispredict = true; update(tid, (*hist_it).pc, actually_taken, pred_hist.front().bpHistory, true, pred_hist.front().inst, @@ -459,16 +437,45 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, } - if (actually_taken) { - if (hist_it->wasReturn && !hist_it->usedRAS) { - DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " - "Incorrectly predicted " - "return [sn:%llu] PC: %#x\n", tid, squashed_sn, - hist_it->seqNum, - hist_it->pc); - RAS[tid].pop(); - hist_it->usedRAS = true; + // Correct RAS --------------------------------- + if (ras) { + // The branch was taken and the RAS was not updated. + // In case of call or return that needs to be fixed. + if (actually_taken && (hist_it->rasHistory == nullptr)) { + + // A return has not poped the RAS. + if (hist_it->inst->isReturn()) { + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " + "Incorrectly predicted return [sn:%llu] PC: %#x\n", + tid, squashed_sn, hist_it->seqNum, hist_it->pc); + + ras->pop(tid, hist_it->rasHistory); + } + + // A call has not pushed a return address to the RAS. + if (hist_it->inst->isCall()) { + // In case of a call build the return address and + // push it to the RAS. + auto return_addr = hist_it->inst->buildRetPC( + corr_target, corr_target); + + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " + "Incorrectly predicted call: [sn:%llu,PC:%#x] " + " Push return address %s onto RAS\n", tid, + squashed_sn, hist_it->seqNum, hist_it->pc, + *return_addr); + ras->push(tid, *return_addr, hist_it->rasHistory); + } + + // The branch was not taken but the RAS modified. + } else if (!actually_taken && (hist_it->rasHistory != nullptr)) { + // The branch was not taken but the RAS was modified. + // Needs to be fixed. + ras->squash(tid, hist_it->rasHistory); } + } + + if (actually_taken) { if (hist_it->wasIndirect) { ++stats.indirectMispredicted; } else { @@ -481,42 +488,6 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, btb->update(tid, hist_it->pc, corr_target, getBranchType(hist_it->inst)); } - } else { - //Actually not Taken - if (hist_it->wasCall && hist_it->pushedRAS) { - //Was a Call but predicated false. Pop RAS here - DPRINTF(Branch, - "[tid:%i] [squash sn:%llu] " - "Incorrectly predicted " - "Call [sn:%llu] PC: %s Popping RAS\n", - tid, squashed_sn, - hist_it->seqNum, hist_it->pc); - RAS[tid].pop(); - hist_it->pushedRAS = false; - } - if (hist_it->usedRAS) { - - std::string RASTarget; - - DPRINTF(Branch, - "[tid:%i] [squash sn:%llu] Incorrectly predicted " - "return [sn:%llu] PC: %#x Restoring RAS\n", tid, - squashed_sn, - hist_it->seqNum, hist_it->pc); - if (hist_it->RASTarget) { - std::ostringstream os; - os << *hist_it->RASTarget.get(); - RASTarget = os.str(); - } else { - RASTarget = "no RAS"; - } - DPRINTF(Branch, - "[tid:%i] [squash sn:%llu] Restoring top of RAS " - "to: %i, target: %s\n", tid, squashed_sn, - hist_it->RASIndex, RASTarget.c_str()); - RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get()); - hist_it->usedRAS = false; - } } } else { DPRINTF(Branch, "[tid:%i] [sn:%llu] pred_hist empty, can't " diff --git a/src/cpu/pred/bpred_unit.hh b/src/cpu/pred/bpred_unit.hh index 1b10d44a7c..18f3f562cb 100644 --- a/src/cpu/pred/bpred_unit.hh +++ b/src/cpu/pred/bpred_unit.hh @@ -218,17 +218,19 @@ class BPredUnit : public SimObject void *indirect_history, ThreadID _tid, const StaticInstPtr & inst) : seqNum(seq_num), pc(instPC), bpHistory(bp_history), - indirectHistory(indirect_history), tid(_tid), + indirectHistory(indirect_history), rasHistory(nullptr), + tid(_tid), predTaken(pred_taken), inst(inst) {} PredictorHistory(const PredictorHistory &other) : seqNum(other.seqNum), pc(other.pc), bpHistory(other.bpHistory), - indirectHistory(other.indirectHistory), RASIndex(other.RASIndex), + indirectHistory(other.indirectHistory), + rasHistory(other.rasHistory), RASIndex(other.RASIndex), tid(other.tid), predTaken(other.predTaken), usedRAS(other.usedRAS), - pushedRAS(other.pushedRAS), wasCall(other.wasCall), - wasReturn(other.wasReturn), wasIndirect(other.wasIndirect), - target(other.target), inst(other.inst) + pushedRAS(other.pushedRAS), wasIndirect(other.wasIndirect), + target(other.target), inst(other.inst), + mispredict(other.mispredict) { set(RASTarget, other.RASTarget); } @@ -253,6 +255,8 @@ class BPredUnit : public SimObject void *indirectHistory = nullptr; + void *rasHistory = nullptr; + /** The RAS target (only valid if a return). */ std::unique_ptr RASTarget; @@ -271,12 +275,6 @@ class BPredUnit : public SimObject /* Whether or not the RAS was pushed */ bool pushedRAS = false; - /** Whether or not the instruction was a call. */ - bool wasCall = false; - - /** Whether or not the instruction was a return. */ - bool wasReturn = false; - /** Wether this instruction was an indirect branch */ bool wasIndirect = false; @@ -287,6 +285,9 @@ class BPredUnit : public SimObject /** The branch instrction */ const StaticInstPtr inst; + + /** Whether this branch was mispredicted */ + bool mispredict = false; }; typedef std::deque History; @@ -303,10 +304,10 @@ class BPredUnit : public SimObject std::vector predHist; /** The BTB. */ - BranchTargetBuffer* btb; + BranchTargetBuffer * btb; - /** The per-thread return address stack. */ - std::vector RAS; + /** The return address stack. */ + ReturnAddrStack * ras; /** The indirect target predictor. */ IndirectPredictor * iPred; diff --git a/src/cpu/pred/ras.cc b/src/cpu/pred/ras.cc index 8d415b7fbd..f29b265657 100644 --- a/src/cpu/pred/ras.cc +++ b/src/cpu/pred/ras.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -28,30 +40,46 @@ #include "cpu/pred/ras.hh" +#include + +#include "debug/RAS.hh" + namespace gem5 { namespace branch_prediction { + void -ReturnAddrStack::init(unsigned _numEntries) +ReturnAddrStack::AddrStack::init(unsigned _numEntries) { numEntries = _numEntries; addrStack.resize(numEntries); + for (unsigned i = 0; i < numEntries; ++i) { + addrStack[i] = nullptr; + } reset(); } void -ReturnAddrStack::reset() +ReturnAddrStack::AddrStack::reset() { usedEntries = 0; tos = 0; } -void -ReturnAddrStack::push(const PCStateBase &return_addr) +const PCStateBase * +ReturnAddrStack::AddrStack::top() { + return addrStack[tos].get(); +} + + +void +ReturnAddrStack::AddrStack::push(const PCStateBase &return_addr) +{ + incrTos(); set(addrStack[tos], return_addr); @@ -62,7 +90,7 @@ ReturnAddrStack::push(const PCStateBase &return_addr) } void -ReturnAddrStack::pop() +ReturnAddrStack::AddrStack::pop() { if (usedEntries > 0) { --usedEntries; @@ -72,9 +100,10 @@ ReturnAddrStack::pop() } void -ReturnAddrStack::restore(unsigned top_entry_idx, const PCStateBase *restored) +ReturnAddrStack::AddrStack::restore(unsigned _tos, + const PCStateBase *restored) { - tos = top_entry_idx; + tos = _tos; set(addrStack[tos], restored); @@ -83,5 +112,218 @@ ReturnAddrStack::restore(unsigned top_entry_idx, const PCStateBase *restored) } } +std::string +ReturnAddrStack::AddrStack::toString(int n) +{ + std::stringstream ss; + for (int i = 0; i < n; i++) { + int idx = int(tos)-i; + if (idx < 0 || addrStack[idx] == nullptr) { + break; + } + ss << std::dec << idx << ":0x" << std::setfill('0') << std::setw(16) + << std::hex << addrStack[idx]->instAddr() << ";"; + } + return ss.str(); +} + + +// Return address stack class. +// + +ReturnAddrStack::ReturnAddrStack(const Params &p) + : SimObject(p), + numEntries(p.numEntries), + numThreads(p.numThreads), + stats(this) +{ + DPRINTF(RAS, "Create RAS stacks.\n"); + + for (unsigned i = 0; i < numThreads; ++i) { + addrStacks.emplace_back(*this); + addrStacks[i].init(numEntries); + } +} + +void +ReturnAddrStack::reset() +{ + DPRINTF(RAS, "RAS Reset.\n"); + for (auto& r : addrStacks) + r.reset(); +} + +void +ReturnAddrStack::makeRASHistory(void* &ras_history) +{ + RASHistory* history = new RASHistory; + history->pushed = false; + history->poped = false; + ras_history = static_cast(history); +} + +void +ReturnAddrStack::push(ThreadID tid, const PCStateBase &pc, + void * &ras_history) +{ + // Note: The RAS may be both popped and pushed to + // support coroutines. + if (ras_history == nullptr) { + makeRASHistory(ras_history); + } + RASHistory *history = static_cast(ras_history); + stats.pushes++; + history->pushed = true; + + addrStacks[tid].push(pc); + + DPRINTF(RAS, "%s: RAS[%i] <= %#x. Entries used: %i, tid:%i\n", __func__, + addrStacks[tid].tos, pc.instAddr(), + addrStacks[tid].usedEntries,tid); + // DPRINTF(RAS, "[%s]\n", addrStacks[tid].toString(10)); +} + + +const PCStateBase* +ReturnAddrStack::pop(ThreadID tid, void * &ras_history) +{ + // Note: The RAS may be both popped and pushed to + // support coroutines. + if (ras_history == nullptr) { + makeRASHistory(ras_history); + } + RASHistory *history = static_cast(ras_history); + stats.pops++; + + history->poped = true; + history->tos = addrStacks[tid].tos; + + + set(history->ras_entry, addrStacks[tid].top()); + // Pop the top of stack + addrStacks[tid].pop(); + + DPRINTF(RAS, "%s: RAS[%i] => %#x. Entries used: %i, tid:%i\n", __func__, + addrStacks[tid].tos, (history->ras_entry.get() != nullptr) + ? history->ras_entry->instAddr() : 0, + addrStacks[tid].usedEntries, tid); + // DPRINTF(RAS, "[%s]\n", addrStacks[tid].toString(10)); + + return history->ras_entry.get(); +} + +void +ReturnAddrStack::squash(ThreadID tid, void * &ras_history) +{ + if (ras_history == nullptr) { + // If ras_history is null no stack operation was performed for + // this branch. Nothing to be done. + return; + } + stats.squashes++; + + RASHistory *history = static_cast(ras_history); + + if (history->pushed) { + stats.pops++; + addrStacks[tid].pop(); + + DPRINTF(RAS, "RAS::%s Incorrect push. Pop RAS[%i]. " + "Entries used: %i, tid:%i\n", __func__, + addrStacks[tid].tos, addrStacks[tid].usedEntries, tid); + } + + if (history->poped) { + stats.pushes++; + addrStacks[tid].restore(history->tos, history->ras_entry.get()); + DPRINTF(RAS, "RAS::%s Incorrect pop. Restore to: RAS[%i]:%#x. " + "Entries used: %i, tid:%i\n", __func__, + history->tos, (history->ras_entry.get() != nullptr) + ? history->ras_entry->instAddr() : 0, + addrStacks[tid].usedEntries, tid); + } + // DPRINTF(RAS, "[%s]\n", addrStacks[tid].toString(10)); + delete history; + ras_history = nullptr; +} + +void +ReturnAddrStack::commit(ThreadID tid, bool misp, + const BranchType brType, void * &ras_history) +{ + // Skip branches that are not call or returns + if (!(brType == BranchType::Return || + brType == BranchType::CallDirect || + brType == BranchType::CallIndirect)) { + // If its not a call or return there should be no ras history. + assert(ras_history == nullptr); + return; + } + + DPRINTF(RAS, "RAS::%s Commit Branch inst: %s, tid:%i\n", + __func__, toString(brType),tid); + + + if (ras_history == nullptr) { + /** + * The only case where we could have no history at this point is + * for a conditional call that is not taken. + * + * Conditional calls + * + * Conditional calls have different scenarios: + * 1. the call was predicted as non taken but was actually taken + * 2. the call was predicted taken but was actually not taken. + * 3. the call was taken but the target was incorrect. + * 4. the call was correct. + * + * In case of mispredictions they will be handled during squashing + * of the BPU. It will push and pop the RAS accordingly. + **/ + return; + } + + /* Handle all other commited returns and calls */ + RASHistory *history = static_cast(ras_history); + + if (history->poped) { + stats.used++; + if (misp) { + stats.incorrect++; + } else { + stats.correct++; + } + + DPRINTF(RAS, "RAS::%s Commit Return PC %#x, correct:%i, tid:%i\n", + __func__, !misp, (history->ras_entry.get() != nullptr) + ? history->ras_entry->instAddr() : 0, tid); + } + delete history; + ras_history = nullptr; +} + + + +ReturnAddrStack::ReturnAddrStackStats::ReturnAddrStackStats( + statistics::Group *parent) + : statistics::Group(parent), + ADD_STAT(pushes, statistics::units::Count::get(), + "Number of times a PC was pushed onto the RAS"), + ADD_STAT(pops, statistics::units::Count::get(), + "Number of times a PC was poped from the RAS"), + ADD_STAT(squashes, statistics::units::Count::get(), + "Number of times the stack operation was squashed due to " + "wrong speculation."), + ADD_STAT(used, statistics::units::Count::get(), + "Number of times the RAS is the provider"), + ADD_STAT(correct, statistics::units::Count::get(), + "Number of times the RAS is the provider and the " + "prediction is correct"), + ADD_STAT(incorrect, statistics::units::Count::get(), + "Number of times the RAS is the provider and the " + "prediction is wrong") +{ +} + } // namespace branch_prediction } // namespace gem5 diff --git a/src/cpu/pred/ras.hh b/src/cpu/pred/ras.hh index 0b4b471c03..294055965e 100644 --- a/src/cpu/pred/ras.hh +++ b/src/cpu/pred/ras.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -32,7 +44,12 @@ #include #include "arch/generic/pcstate.hh" +#include "base/statistics.hh" #include "base/types.hh" +#include "cpu/pred/branch_type.hh" +#include "cpu/static_inst.hh" +#include "params/ReturnAddrStack.hh" +#include "sim/sim_object.hh" namespace gem5 { @@ -41,70 +58,164 @@ namespace branch_prediction { /** Return address stack class, implements a simple RAS. */ -class ReturnAddrStack +class ReturnAddrStack : public SimObject { public: - /** Creates a return address stack, but init() must be called prior to - * use. - */ - ReturnAddrStack() {} - /** Initializes RAS with a specified number of entries. - * @param numEntries Number of entries in the RAS. + /** Subclass that implements the actual address stack. ****** */ - void init(unsigned numEntries); + class AddrStack + { + public: + AddrStack(ReturnAddrStack &_parent) + : parent(_parent) + {} + + + /** Initializes RAS with a specified number of entries. + * @param numEntries Number of entries in the RAS. + */ + void init(unsigned numEntries); + + void reset(); + + /** Returns the top address on the RAS. */ + const PCStateBase *top(); + + /** Returns the index of the top of the RAS. */ + unsigned topIdx() { return tos; } + + /** Pushes an address onto the RAS. */ + void push(const PCStateBase &return_addr); + + /** Pops the top address from the RAS. */ + void pop(); + + /** Changes index to the top of the RAS, and replaces the top address + * with a new target. + * @param top_of_stack the index saved at the time of the prediction. + * @param restored The new target address of the new top of the RAS. + */ + void restore(unsigned top_of_stack, const PCStateBase *restored); + + bool empty() { return usedEntries == 0; } + + bool full() { return usedEntries >= numEntries; } + + /** Returns the top n entries of the stack as string. For debugging. */ + std::string toString(int n); + + /** Increments the top of stack index. */ + inline void + incrTos() + { + if (++tos == numEntries) + tos = 0; + } + + /** Decrements the top of stack index. */ + inline void + decrTos() + { + tos = (tos == 0 ? numEntries - 1 : tos - 1); + } + + /** The Stack itself. */ + std::vector> addrStack; + + /** The number of entries in the RAS. */ + unsigned numEntries; + + /** The number of used entries in the RAS. */ + unsigned usedEntries; + + /** The top of stack index. */ + unsigned tos; + + protected: + ReturnAddrStack &parent; + }; + + + + public: + // typedef RASParams Params; + typedef ReturnAddrStackParams Params; + + // ReturnAddrStack(BPredUnit &_parent, const RASParams); + ReturnAddrStack(const Params &p); void reset(); - /** Returns the top address on the RAS. */ - const PCStateBase *top() { return addrStack[tos].get(); } - - /** Returns the index of the top of the RAS. */ - unsigned topIdx() { return tos; } - - /** Pushes an address onto the RAS. */ - void push(const PCStateBase &return_addr); - - /** Pops the top address from the RAS. */ - void pop(); - - /** Changes index to the top of the RAS, and replaces the top address with - * a new target. - * @param top_entry_idx The index of the RAS that will now be the top. - * @param restored The new target address of the new top of the RAS. + /** + * Pushes an address onto the RAS. + * @param PC The current PC (should be a call). + * @param ras_history Pointer that will be set to an object that + * has the return address state associated when the address was pushed. */ - void restore(unsigned top_entry_idx, const PCStateBase *restored); + void push(ThreadID tid, const PCStateBase &pc, void * &ras_history); - bool empty() { return usedEntries == 0; } + /** + * Pops the top address from the RAS. + * @param ras_history Pointer that will be set to an object that + * has the return address state associated when an address was poped. + * @return The address that got poped from the stack. + * */ + const PCStateBase* pop(ThreadID tid, void * &ras_history); + + /** + * The branch (call/return) got squashed. + * Restores the state of the RAS and delete history + * @param res_history The pointer to the history object. + */ + void squash(ThreadID tid, void * &ras_history); + + /** + * A branch got finally got finally commited. + * @param misp Whether the branch was mispredicted. + * @param brType The type of the branch. + * @param ras_history The pointer to the history object. + */ + void commit(ThreadID tid, bool misp, + const BranchType brType, void * &ras_history); - bool full() { return usedEntries == numEntries; } private: - /** Increments the top of stack index. */ - inline void - incrTos() - { - if (++tos == numEntries) - tos = 0; - } - /** Decrements the top of stack index. */ - inline void - decrTos() + class RASHistory { - tos = (tos == 0 ? numEntries - 1 : tos - 1); - } + public: + /* Was the RAS pushed or poped for this branch. */ + bool pushed = false; + bool poped = false; + /* Was it a call */ + bool wasReturn = false; + bool wasCall = false; + /** The entry that poped from the RAS (only valid if a return). */ + std::unique_ptr ras_entry; + /** The RAS index (top of stack pointer) of the instruction */ + unsigned tos = 0; + }; + + void makeRASHistory(void* &ras_history); /** The RAS itself. */ - std::vector> addrStack; + std::vector addrStacks; /** The number of entries in the RAS. */ unsigned numEntries; + /** The number of threads */ + unsigned numThreads; - /** The number of used entries in the RAS. */ - unsigned usedEntries; - - /** The top of stack index. */ - unsigned tos; + struct ReturnAddrStackStats : public statistics::Group + { + ReturnAddrStackStats(statistics::Group *parent); + statistics::Scalar pushes; + statistics::Scalar pops; + statistics::Scalar squashes; + statistics::Scalar used; + statistics::Scalar correct; + statistics::Scalar incorrect; + } stats; }; } // namespace branch_prediction diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py index ce265449c9..22ec29e59d 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py @@ -96,7 +96,7 @@ class U74FUPool(MinorFUPool): class U74BP(TournamentBP): btb = SimpleBTB(numEntries=32) - RASSize = 12 + ras = ReturnAddrStack(numEntries=12) localHistoryTableSize = 4096 # is 3.6 KiB but gem5 requires power of 2 localPredictorSize = 16384 globalPredictorSize = 16384 From 7bd0b99635fe34fc7c9c2b67397b9978ac0eda10 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 18 Oct 2023 10:09:45 -0700 Subject: [PATCH 473/693] tests: Changed percent atomics to 0 in memtest to fix daily test (#477) --- src/cpu/testers/memtest/MemTest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/testers/memtest/MemTest.py b/src/cpu/testers/memtest/MemTest.py index 15c329ee85..2d6a0e33c5 100644 --- a/src/cpu/testers/memtest/MemTest.py +++ b/src/cpu/testers/memtest/MemTest.py @@ -63,7 +63,7 @@ class MemTest(ClockedObject): percent_reads = Param.Percent(65, "Percentage reads") percent_functional = Param.Percent(50, "Percentage functional accesses") percent_uncacheable = Param.Percent(10, "Percentage uncacheable") - percent_atomic = Param.Percent(50, "Percentage atomics") + percent_atomic = Param.Percent(0, "Percentage atomics") # Determine how often to print progress messages and what timeout # to use for checking progress of both requests and responses From c3acfdc9b89b60cfd6a426af24d25c5cf58ef2ae Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 18 Oct 2023 10:51:37 -0700 Subject: [PATCH 474/693] arch-riscv: Copy Misc Regs when swiching cpus (#479) Misc Regs might contain rather important information about the state of a core, e.g., information in CSR registers. This patch enforces copying the CSR registers when switching cpus. The bug and the proposed fix are reported here [1]. [1] https://github.com/gem5/gem5/issues/451 Change-Id: I611782e6e3bcd5530ddac346342a9e0e44b0f757 Signed-off-by: Hoa Nguyen --- src/arch/riscv/isa.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 4cb5082cad..a1f4056bf5 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -294,6 +294,10 @@ ISA::copyRegsFrom(ThreadContext *src) tc->setReg(id, &vc); } + // Copying Misc Regs + for (int i = 0; i < NUM_MISCREGS; i++) + tc->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); + // Lastly copy PC/NPC tc->pcState(src->pcState()); } From 57e0ba7765d385ba4983747f2d27e0c8379a8460 Mon Sep 17 00:00:00 2001 From: Alvaro Moreno Date: Wed, 9 Aug 2023 12:30:13 +0200 Subject: [PATCH 475/693] arch-riscv: Define VecRegContainer with maximum expected length This path redefine VecRegContainer for RISCV so it can hold every VLEN + ELEN possible configuration used at execution time Change-Id: Ie6abd01a1c4ebe9aae3d93f4e835fcfdc4a82dcd --- src/arch/riscv/regs/vector.hh | 8 +++----- src/arch/riscv/types.hh | 4 ++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/regs/vector.hh b/src/arch/riscv/regs/vector.hh index 388e1cb78d..60c840395f 100644 --- a/src/arch/riscv/regs/vector.hh +++ b/src/arch/riscv/regs/vector.hh @@ -36,6 +36,7 @@ #include "arch/generic/vec_pred_reg.hh" #include "arch/generic/vec_reg.hh" +#include "arch/riscv/types.hh" #include "base/bitunion.hh" #include "cpu/reg_class.hh" #include "debug/VecRegs.hh" @@ -46,13 +47,10 @@ namespace gem5 namespace RiscvISA { -constexpr unsigned ELEN = 64; -constexpr unsigned VLEN = 256; -constexpr unsigned VLENB = VLEN / 8; - -using VecRegContainer = gem5::VecRegContainer; +using VecRegContainer = gem5::VecRegContainer; using vreg_t = VecRegContainer; + const int NumVecStandardRegs = 32; const int NumVecInternalRegs = 8; // Used by vector uop const int NumVecRegs = NumVecStandardRegs + NumVecInternalRegs; diff --git a/src/arch/riscv/types.hh b/src/arch/riscv/types.hh index 1d501dc05f..01c600d148 100644 --- a/src/arch/riscv/types.hh +++ b/src/arch/riscv/types.hh @@ -178,6 +178,10 @@ BitUnion64(ExtMachInst) EndBitUnion(ExtMachInst) +constexpr unsigned MaxVecLenInBits = 65536; +constexpr unsigned MaxVecLenInBytes = MaxVecLenInBits >> 3; + + } // namespace RiscvISA } // namespace gem5 From 5d97cb8b0b8c1e60e3d0b09e45c92bc4c89658e0 Mon Sep 17 00:00:00 2001 From: Alvaro Moreno Date: Sat, 9 Sep 2023 12:43:28 +0200 Subject: [PATCH 476/693] arch-riscv: Define VLEN and ELEN through the ISA object This commit define VLEN and ELEN values as parameters of the RiscvISA class. Change-Id: Ic5b80397d316522d729e4db4f906aa189f27a491 --- src/arch/riscv/RiscvISA.py | 38 +++++++++++++++++++++++++++++++++++++- src/arch/riscv/isa.cc | 13 +++++++++---- src/arch/riscv/isa.hh | 17 ++++++++++++++++- src/arch/riscv/pcstate.hh | 4 ++-- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index f66171a95a..3f123405e9 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -38,11 +38,37 @@ # (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.params import Enum +from m5.params import Enum, UInt32 from m5.params import Param from m5.objects.BaseISA import BaseISA +class RiscvVectorLength(UInt32): + min = 8 + max = 65536 + + def _check(self): + super()._check() + + # VLEN needs to be a whole power of 2. We already know value is + # not zero. Hence: + if self.value & (self.value - 1) != 0: + raise TypeError("VLEN is not a power of 2: %d" % self.value) + + +class RiscvVectorElementLength(UInt32): + min = 8 + max = 64 + + def _check(self): + super()._check() + + # ELEN needs to be a whole power of 2. We already know value is + # not zero. Hence: + if self.value & (self.value - 1) != 0: + raise TypeError("ELEN is not a power of 2: %d" % self.value) + + class RiscvType(Enum): vals = ["RV32", "RV64"] @@ -58,3 +84,13 @@ class RiscvISA(BaseISA): riscv_type = Param.RiscvType("RV64", "RV32 or RV64") enable_rvv = Param.Bool(True, "Enable vector extension") + vlen = Param.RiscvVectorLength( + 256, + "Length of each vector register in bits. \ + VLEN in Ch. 2 of RISC-V vector spec", + ) + elen = Param.RiscvVectorElementLength( + 64, + "Length of each vector element in bits. \ + ELEN in Ch. 2 of RISC-V vector spec", + ) diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index a1f4056bf5..5785a14e92 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -36,6 +36,7 @@ #include #include "arch/riscv/faults.hh" +#include "arch/riscv/insts/static_inst.hh" #include "arch/riscv/interrupts.hh" #include "arch/riscv/mmu.hh" #include "arch/riscv/pagetable.hh" @@ -253,10 +254,9 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs); } // anonymous namespace -ISA::ISA(const Params &p) : - BaseISA(p), _rvType(p.riscv_type), checkAlignment(p.check_alignment), - enableRvv(p.enable_rvv) - +ISA::ISA(const Params &p) :BaseISA(p), + _rvType(p.riscv_type), checkAlignment(p.check_alignment), + enableRvv(p.enable_rvv),vlen(p.vlen),elen(p.elen) { _regClasses.push_back(&intRegClass); _regClasses.push_back(&floatRegClass); @@ -267,6 +267,11 @@ ISA::ISA(const Params &p) : _regClasses.push_back(&ccRegClass); _regClasses.push_back(&miscRegClass); + fatal_if( p.vlen < p.elen, + "VLEN should be greater or equal", + "than ELEN. Ch. 2RISC-V vector spec."); + + miscRegFile.resize(NUM_MISCREGS); clear(); } diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 13366ef4c3..5581c3b677 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -84,6 +84,16 @@ class ISA : public BaseISA const Addr INVALID_RESERVATION_ADDR = (Addr)-1; std::unordered_map load_reservation_addrs; + /** Length of each vector register in bits. + * VLEN in Ch. 2 of RISC-V vector spec + */ + unsigned vlen; + + /** Length of each vector element in bits. + * ELEN in Ch. 2 of RISC-V vector spec + */ + unsigned elen; + public: using Params = RiscvISAParams; @@ -92,7 +102,8 @@ class ISA : public BaseISA PCStateBase* newPCState(Addr new_inst_addr=0) const override { - return new PCState(new_inst_addr, _rvType, VLENB); + unsigned vlenb = vlen >> 3; + return new PCState(new_inst_addr, _rvType, vlenb); } public: @@ -147,6 +158,10 @@ class ISA : public BaseISA Addr& load_reservation_addr = load_reservation_addrs[cid]; load_reservation_addr = INVALID_RESERVATION_ADDR; } + /** Methods for getting VLEN, VLENB and ELEN values */ + unsigned getVecLenInBits() { return vlen; } + unsigned getVecLenInBytes() { return vlen >> 3; } + unsigned getVecElemLenInBits() { return elen; } }; } // namespace RiscvISA diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh index 918e85708b..03a7fc415f 100644 --- a/src/arch/riscv/pcstate.hh +++ b/src/arch/riscv/pcstate.hh @@ -62,7 +62,7 @@ class PCState : public GenericISA::UPCState<4> bool _compressed = false; RiscvType _rvType = RV64; - uint64_t _vlenb = VLENB; + uint64_t _vlenb = 256; VTYPE _vtype = (1ULL << 63); // vtype.vill = 1 at initial; uint32_t _vl = 0; @@ -74,7 +74,7 @@ class PCState : public GenericISA::UPCState<4> PCState &operator=(const PCState &other) = default; PCState() = default; explicit PCState(Addr addr) { set(addr); } - explicit PCState(Addr addr, RiscvType rvType, uint64_t vlenb = VLENB) + explicit PCState(Addr addr, RiscvType rvType, uint64_t vlenb) { set(addr); _rvType = rvType; From 8a20f20f791a316c5543af2e5c45bcca94bc3667 Mon Sep 17 00:00:00 2001 From: Alvaro Moreno Date: Thu, 14 Sep 2023 09:43:43 +0200 Subject: [PATCH 477/693] arch-riscv: Add vlen component to decoder state This patch add vlen definition to the riscv decoder so it can be used in Vector Instruction Constructors Change-Id: I52292bc261c43562b690062b16d2b323675c2fe0 --- src/arch/riscv/decoder.cc | 2 ++ src/arch/riscv/decoder.hh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index b1e2948e93..3c199b3210 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -41,6 +41,8 @@ namespace RiscvISA Decoder::Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst) { + ISA *isa = dynamic_cast(p.isa); + vlen = isa->getVecLenInBits(); reset(); } diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh index c827e85f90..b53c48445d 100644 --- a/src/arch/riscv/decoder.hh +++ b/src/arch/riscv/decoder.hh @@ -60,6 +60,8 @@ class Decoder : public InstDecoder ExtMachInst emi; uint32_t machInst; + uint32_t vlen; + virtual StaticInstPtr decodeInst(ExtMachInst mach_inst); /// Decode a machine instruction. From 2c9fca7b607dc5bfcc0dcf47141eeafa1f1aadc4 Mon Sep 17 00:00:00 2001 From: Alvaro Moreno Date: Wed, 9 Aug 2023 12:39:03 +0200 Subject: [PATCH 478/693] arch-riscv: Add vlen configuration to vector instructions In first place, vlen is added as a member of Vector Macro Instructions where it is needed to split the instruction in Micro Instructions. Then, new PCState methods are used to get dynamic vlen and vlenb values at execution. Finally, vector length data types are fixed to 32 bits so every vlen value is considered. Change-Id: I5b8ceb0d291f456a30a4b0ae2f58601231d33a7a --- src/arch/riscv/insts/vector.cc | 12 +- src/arch/riscv/insts/vector.hh | 128 ++++---- src/arch/riscv/isa.cc | 3 + src/arch/riscv/isa/decoder.isa | 39 ++- src/arch/riscv/isa/formats/vector_arith.isa | 94 +++++- src/arch/riscv/isa/formats/vector_conf.isa | 3 +- src/arch/riscv/isa/formats/vector_mem.isa | 39 ++- src/arch/riscv/isa/templates/vector_arith.isa | 301 +++++++++++------- src/arch/riscv/isa/templates/vector_mem.isa | 218 ++++++++----- src/arch/riscv/pcstate.hh | 2 +- src/arch/riscv/types.hh | 1 - src/arch/riscv/utility.hh | 5 +- 12 files changed, 567 insertions(+), 278 deletions(-) diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc index 6ecec44dc5..c99e806e9b 100644 --- a/src/arch/riscv/insts/vector.cc +++ b/src/arch/riscv/insts/vector.cc @@ -215,8 +215,9 @@ std::string VleMicroInst::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const { std::stringstream ss; + unsigned vlenb = vlen >> 3; ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " - << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')' << ", " + << vlenb * microIdx << '(' << registerName(srcRegIdx(0)) << ')' << ", " << registerName(srcRegIdx(1)); if (!machInst.vm) ss << ", v0.t"; return ss.str(); @@ -226,8 +227,9 @@ std::string VlWholeMicroInst::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const { std::stringstream ss; + unsigned vlenb = vlen >> 3; ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " - << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; + << vlenb * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; return ss.str(); } @@ -235,8 +237,9 @@ std::string VseMicroInst::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const { std::stringstream ss; + unsigned vlenb = vlen >> 3; ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " - << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; + << vlenb * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; if (!machInst.vm) ss << ", v0.t"; return ss.str(); } @@ -245,8 +248,9 @@ std::string VsWholeMicroInst::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const { std::stringstream ss; + unsigned vlenb = vlen >> 3; ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " - << VLENB * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; + << vlenb * microIdx << '(' << registerName(srcRegIdx(0)) << ')'; return ss.str(); } diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index b25a6e3a09..58a76e0ab1 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -32,6 +32,7 @@ #include #include "arch/riscv/insts/static_inst.hh" +#include "arch/riscv/isa.hh" #include "arch/riscv/regs/misc.hh" #include "arch/riscv/regs/vector.hh" #include "arch/riscv/utility.hh" @@ -116,11 +117,14 @@ class VectorMacroInst : public RiscvMacroInst protected: uint32_t vl; uint8_t vtype; + uint32_t vlen; + VectorMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) + OpClass __opClass, uint32_t _vlen = 256) : RiscvMacroInst(mnem, _machInst, __opClass), vl(_machInst.vl), - vtype(_machInst.vtype8) + vtype(_machInst.vtype8), + vlen(_vlen) { this->flags[IsVector] = true; } @@ -128,13 +132,15 @@ class VectorMacroInst : public RiscvMacroInst class VectorMicroInst : public RiscvMicroInst { - protected: - uint8_t microVl; +protected: + uint32_t vlen; + uint32_t microVl; uint8_t microIdx; uint8_t vtype; VectorMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen = 256) : RiscvMicroInst(mnem, _machInst, __opClass), + vlen(_vlen), microVl(_microVl), microIdx(_microIdx), vtype(_machInst.vtype8) @@ -169,7 +175,7 @@ class VectorArithMicroInst : public VectorMicroInst { protected: VectorArithMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, + OpClass __opClass, uint32_t _microVl, uint8_t _microIdx) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) {} @@ -182,12 +188,11 @@ class VectorArithMacroInst : public VectorMacroInst { protected: VectorArithMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen = 256) + : VectorMacroInst(mnem, _machInst, __opClass, _vlen) { this->flags[IsVector] = true; } - std::string generateDisassembly( Addr pc, const loader::SymbolTable *symtab) const override; }; @@ -196,7 +201,7 @@ class VectorVMUNARY0MicroInst : public VectorMicroInst { protected: VectorVMUNARY0MicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, + OpClass __opClass, uint32_t _microVl, uint8_t _microIdx) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) {} @@ -209,8 +214,8 @@ class VectorVMUNARY0MacroInst : public VectorMacroInst { protected: VectorVMUNARY0MacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMacroInst(mnem, _machInst, __opClass, _vlen) { this->flags[IsVector] = true; } @@ -223,8 +228,8 @@ class VectorSlideMacroInst : public VectorMacroInst { protected: VectorSlideMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen = 256) + : VectorMacroInst(mnem, _machInst, __opClass, _vlen) { this->flags[IsVector] = true; } @@ -239,7 +244,7 @@ class VectorSlideMicroInst : public VectorMicroInst uint8_t vdIdx; uint8_t vs2Idx; VectorSlideMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, + OpClass __opClass, uint32_t _microVl, uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) , vdIdx(_vdIdx), vs2Idx(_vs2Idx) @@ -256,7 +261,7 @@ class VectorMemMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VectorMemMicroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, uint8_t _microIdx, + OpClass __opClass, uint32_t _microVl, uint8_t _microIdx, uint32_t _offset) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) , offset(_offset) @@ -268,8 +273,8 @@ class VectorMemMacroInst : public VectorMacroInst { protected: VectorMemMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen = 256) + : VectorMacroInst(mnem, _machInst, __opClass, _vlen) {} }; @@ -277,8 +282,8 @@ class VleMacroInst : public VectorMemMacroInst { protected: VleMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -289,8 +294,8 @@ class VseMacroInst : public VectorMemMacroInst { protected: VseMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -302,9 +307,10 @@ class VleMicroInst : public VectorMicroInst protected: Request::Flags memAccessFlags; - VleMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, - uint8_t _microVl, uint8_t _microIdx) - : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + VleMicroInst(const char *mnem, ExtMachInst _machInst,OpClass __opClass, + uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, + _microIdx, _vlen) { this->flags[IsLoad] = true; } @@ -319,8 +325,9 @@ class VseMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VseMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, - uint8_t _microVl, uint8_t _microIdx) - : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, + _microIdx, _vlen) { this->flags[IsStore] = true; } @@ -333,8 +340,8 @@ class VlWholeMacroInst : public VectorMemMacroInst { protected: VlWholeMacroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -347,8 +354,10 @@ class VlWholeMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VlWholeMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, uint8_t _microIdx) - : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) + OpClass __opClass, uint32_t _microVl, uint8_t _microIdx, + uint32_t _vlen) + : VectorMicroInst(mnem, _machInst, __opClass, _microVl, + _microIdx, _vlen) {} std::string generateDisassembly( @@ -359,8 +368,8 @@ class VsWholeMacroInst : public VectorMemMacroInst { protected: VsWholeMacroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -373,8 +382,10 @@ class VsWholeMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VsWholeMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, uint8_t _microIdx) - : VectorMicroInst(mnem, _machInst, __opClass, _microIdx, _microIdx) + OpClass __opClass, uint32_t _microVl, + uint8_t _microIdx, uint32_t _vlen) + : VectorMicroInst(mnem, _machInst, __opClass , _microVl, + _microIdx, _vlen) {} std::string generateDisassembly( @@ -385,8 +396,8 @@ class VlStrideMacroInst : public VectorMemMacroInst { protected: VlStrideMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -399,7 +410,7 @@ class VlStrideMicroInst : public VectorMemMicroInst uint8_t regIdx; VlStrideMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint8_t _regIdx, - uint8_t _microIdx, uint8_t _microVl) + uint8_t _microIdx, uint32_t _microVl) : VectorMemMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, 0) , regIdx(_regIdx) @@ -413,8 +424,8 @@ class VsStrideMacroInst : public VectorMemMacroInst { protected: VsStrideMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -427,7 +438,7 @@ class VsStrideMicroInst : public VectorMemMicroInst uint8_t regIdx; VsStrideMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint8_t _regIdx, - uint8_t _microIdx, uint8_t _microVl) + uint8_t _microIdx, uint32_t _microVl) : VectorMemMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, 0) , regIdx(_regIdx) @@ -441,8 +452,8 @@ class VlIndexMacroInst : public VectorMemMacroInst { protected: VlIndexMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -473,8 +484,8 @@ class VsIndexMacroInst : public VectorMemMacroInst { protected: VsIndexMacroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass) - : VectorMemMacroInst(mnem, _machInst, __opClass) + OpClass __opClass, uint32_t _vlen) + : VectorMemMacroInst(mnem, _machInst, __opClass, _vlen) {} std::string generateDisassembly( @@ -516,7 +527,7 @@ class VMvWholeMicroInst : public VectorArithMicroInst { protected: VMvWholeMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _microVl, + OpClass __opClass, uint32_t _microVl, uint8_t _microIdx) : VectorArithMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) {} @@ -533,10 +544,12 @@ class VMaskMergeMicroInst : public VectorArithMicroInst RegId destRegIdxArr[1]; public: - VMaskMergeMicroInst(ExtMachInst extMachInst, uint8_t _dstReg, - uint8_t _numSrcs) + uint32_t vlen; + VMaskMergeMicroInst(ExtMachInst extMachInst, + uint8_t _dstReg, uint8_t _numSrcs, uint32_t _vlen) : VectorArithMicroInst("vmask_mv_micro", extMachInst, - VectorIntegerArithOp, 0, 0) + VectorIntegerArithOp, 0, 0), + vlen(_vlen) { setRegIdxArrays( reinterpret_cast( @@ -558,26 +571,28 @@ class VMaskMergeMicroInst : public VectorArithMicroInst execute(ExecContext* xc, trace::InstRecord* traceData) const override { vreg_t& tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); + PCStateBase *pc_ptr = xc->tcBase()->pcState().clone(); auto Vd = tmp_d0.as(); - constexpr uint8_t elems_per_vreg = VLENB / sizeof(ElemType); + uint32_t vlenb = pc_ptr->as().vlenb(); + const uint32_t elems_per_vreg = vlenb / sizeof(ElemType); size_t bit_cnt = elems_per_vreg; vreg_t tmp_s; xc->getRegOperand(this, 0, &tmp_s); auto s = tmp_s.as(); // cp the first result and tail - memcpy(Vd, s, VLENB); + memcpy(Vd, s, vlenb); for (uint8_t i = 1; i < this->_numSrcRegs; i++) { xc->getRegOperand(this, i, &tmp_s); s = tmp_s.as(); - if constexpr (elems_per_vreg < 8) { - constexpr uint8_t m = (1 << elems_per_vreg) - 1; - const uint8_t mask = m << (i * elems_per_vreg % 8); + if (elems_per_vreg < 8) { + const uint32_t m = (1 << elems_per_vreg) - 1; + const uint32_t mask = m << (i * elems_per_vreg % 8); // clr & ext bits Vd[bit_cnt/8] ^= Vd[bit_cnt/8] & mask; Vd[bit_cnt/8] |= s[bit_cnt/8] & mask; bit_cnt += elems_per_vreg; } else { - constexpr uint8_t byte_offset = elems_per_vreg / 8; + const uint32_t byte_offset = elems_per_vreg / 8; memcpy(Vd + i * byte_offset, s + i * byte_offset, byte_offset); } } @@ -595,7 +610,8 @@ class VMaskMergeMicroInst : public VectorArithMicroInst for (uint8_t i = 0; i < this->_numSrcRegs; i++) { ss << ", " << registerName(srcRegIdx(i)); } - ss << ", offset:" << VLENB / sizeof(ElemType); + unsigned vlenb = vlen >> 3; + ss << ", offset:" << vlenb / sizeof(ElemType); return ss.str(); } }; diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 5785a14e92..877b795551 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -271,6 +271,9 @@ ISA::ISA(const Params &p) :BaseISA(p), "VLEN should be greater or equal", "than ELEN. Ch. 2RISC-V vector spec."); + inform("RVV enabled, VLEN = %d bits, ELEN = %d bits", + p.vlen, p.elen); + miscRegFile.resize(NUM_MISCREGS); clear(); diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 2bd3d33a7e..3d1d396165 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -3110,21 +3110,33 @@ decode QUADRANT default Unknown::unknown() { 0x12: decode VS1 { format VectorIntExtFormat { 0x02: vzext_vf8({{ + auto offset = (vlen / SEW) * index; + Vd_vu[i] = Vs2_vextu[i + offset]; }}, OPMVV, VectorIntegerExtensionOp); 0x03: vsext_vf8({{ + auto offset = (vlen / SEW) * index; + Vd_vi[i] = Vs2_vext[i + offset]; }}, OPMVV, VectorIntegerExtensionOp); 0x04: vzext_vf4({{ + auto offset = (vlen / SEW) * index; + Vd_vu[i] = Vs2_vextu[i + offset]; }}, OPMVV, VectorIntegerExtensionOp); 0x05: vsext_vf4({{ + auto offset = (vlen / SEW) * index; + Vd_vi[i] = Vs2_vext[i + offset]; }}, OPMVV, VectorIntegerExtensionOp); 0x06: vzext_vf2({{ + auto offset = (vlen / SEW) * index; + Vd_vu[i] = Vs2_vextu[i + offset]; }}, OPMVV, VectorIntegerExtensionOp); 0x07: vsext_vf2({{ + auto offset = (vlen / SEW) * index; + Vd_vi[i] = Vs2_vext[i + offset]; }}, OPMVV, VectorIntegerExtensionOp); } @@ -3185,7 +3197,8 @@ decode QUADRANT default Unknown::unknown() { auto Vs2bit = tmp_s2.as(); for (uint32_t i = 0; i < this->microVl; i++) { uint32_t ei = i + - vtype_VLMAX(vtype, true) * this->microIdx; + vtype_VLMAX(vtype, vlen, true) * + this->microIdx; bool vs2_lsb = elem_mask(Vs2bit, ei); bool do_mask = elem_mask(v0, ei); bool has_one = false; @@ -3406,7 +3419,8 @@ decode QUADRANT default Unknown::unknown() { }}, OPIVI, VectorMiscOp); 0x0e: VectorSlideUpFormat::vslideup_vi({{ const int offset = (int)(uint64_t)(SIMM5); - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vdIdx - vs2Idx; const int offsetInVreg = offset - vregOffset * microVlmax; if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { @@ -3431,7 +3445,8 @@ decode QUADRANT default Unknown::unknown() { }}, OPIVI, VectorMiscOp); 0x0f: VectorSlideDownFormat::vslidedown_vi({{ const int offset = (int)(uint64_t)(SIMM5); - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vs2Idx - vdIdx; const int offsetInVreg = offset - vregOffset * microVlmax; const int numVs2s = vtype_regs_per_group(vtype); @@ -3662,7 +3677,8 @@ decode QUADRANT default Unknown::unknown() { } 0x0e: VectorSlideUpFormat::vslideup_vx({{ const int offset = (int)Rs1_vu; - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vdIdx - vs2Idx; const int offsetInVreg = offset - vregOffset * microVlmax; if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { @@ -3687,7 +3703,8 @@ decode QUADRANT default Unknown::unknown() { }}, OPIVX, VectorMiscOp); 0x0f: VectorSlideDownFormat::vslidedown_vx({{ const int offset = (int)Rs1_vu; - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vs2Idx - vdIdx; const int offsetInVreg = offset - vregOffset * microVlmax; const int numVs2s = vtype_regs_per_group(vtype); @@ -3964,7 +3981,8 @@ decode QUADRANT default Unknown::unknown() { } 0x0e: VectorFloatSlideUpFormat::vfslide1up_vf({{ const int offset = 1; - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vdIdx - vs2Idx; const int offsetInVreg = offset - vregOffset * microVlmax; if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { @@ -3994,7 +4012,8 @@ decode QUADRANT default Unknown::unknown() { }}, OPFVF, VectorMiscOp); 0x0f: VectorFloatSlideDownFormat::vfslide1down_vf({{ const int offset = 1; - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vs2Idx - vdIdx; const int offsetInVreg = offset - vregOffset * microVlmax; const int numVs2s = vtype_regs_per_group(vtype); @@ -4239,7 +4258,8 @@ decode QUADRANT default Unknown::unknown() { } 0x0e: VectorSlideUpFormat::vslide1up_vx({{ const int offset = 1; - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vdIdx - vs2Idx; const int offsetInVreg = offset - vregOffset * microVlmax; if (std::abs(offsetInVreg) < uint32_t(microVlmax)) { @@ -4269,7 +4289,8 @@ decode QUADRANT default Unknown::unknown() { }}, OPIVX, VectorMiscOp); 0x0f: VectorSlideDownFormat::vslide1down_vx({{ const int offset = 1; - const int microVlmax = vtype_VLMAX(machInst.vtype8, true); + const int microVlmax = vtype_VLMAX(machInst.vtype8, + vlen, true); const int vregOffset = vs2Idx - vdIdx; const int offsetInVreg = offset - vregOffset * microVlmax; const int numVs2s = vtype_regs_per_group(vtype); diff --git a/src/arch/riscv/isa/formats/vector_arith.isa b/src/arch/riscv/isa/formats/vector_arith.isa index c462e6c8d4..0d5055ea8f 100644 --- a/src/arch/riscv/isa/formats/vector_arith.isa +++ b/src/arch/riscv/isa/formats/vector_arith.isa @@ -28,6 +28,10 @@ let {{ + def setVlen(): + return "uint32_t vlen = VlenbBits * 8;\n" + def setVlenb(): + return "uint32_t vlenb = VlenbBits;\n" def setDestWrapper(destRegId): return "setDestRegIdx(_numDestRegs++, " + destRegId + ");\n" + \ "_numTypedDestRegs[VecRegClass]++;\n" @@ -67,7 +71,7 @@ let {{ ''' + code else: return ''' - uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + uint32_t ei = i + vtype_VLMAX(vtype, vlen, true) * this->microIdx; ''' + code def wideningOpRegisterConstraintChecks(code): @@ -178,12 +182,15 @@ def format VectorIntFormat(code, category, *flags) {{ if v0_required: vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + microiop = InstObjParams(name + "_micro", Name + "Micro", microop_class_name, {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb' : set_vlenb, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -225,12 +232,17 @@ def format VectorIntExtFormat(code, category, *flags) {{ code = loopWrapper(code) vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx), 'ext_div': ext_div}, @@ -293,12 +305,17 @@ def format VectorIntWideningFormat(code, category, *flags) {{ if v0_required: vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -348,12 +365,17 @@ def format VectorIntNarrowingFormat(code, category, *flags) {{ code = narrowingOpRegisterConstraintChecks(code) vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx), }, @@ -416,12 +438,15 @@ def format VectorIntMaskFormat(code, category, *flags) {{ if v0_required: vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -474,12 +499,17 @@ def format VectorGatherFormat(code, category, *flags) {{ vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx), 'idx_type': idx_type}, @@ -537,12 +567,15 @@ def format VectorFloatFormat(code, category, *flags) {{ if v0_required: vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(2)}, flags) @@ -581,12 +614,15 @@ def format VectorFloatCvtFormat(code, category, *flags) {{ vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -649,12 +685,17 @@ def format VectorFloatWideningFormat(code, category, *flags) {{ if v0_required: vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(2)}, flags) @@ -693,12 +734,17 @@ def format VectorFloatWideningCvtFormat(code, category, *flags) {{ vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -738,12 +784,17 @@ def format VectorFloatNarrowingCvtFormat(code, category, *flags) {{ vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb(); + set_vlen = setVlen(); + microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -783,6 +834,7 @@ def format VectorFloatMaskFormat(code, category, *flags) {{ set_src_reg_idx += setSrcWrapper(old_dest_reg_id) set_src_reg_idx += setSrcVm() vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() code = maskCondWrapper(code) code = eiDeclarePrefix(code) @@ -795,6 +847,7 @@ def format VectorFloatMaskFormat(code, category, *flags) {{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(2)}, flags) @@ -816,7 +869,8 @@ def format VMvWholeFormat(code, category, *flags) {{ microiop = InstObjParams(name + "_micro", Name + "Micro", 'VMvWholeMicroInst', - {'code': code}, + {'code': code, + 'set_vlen': setVlen()}, flags) header_output = \ @@ -847,6 +901,7 @@ def format ViotaFormat(code, category, *flags){{ set_dest_reg_idx = setDestWrapper(dest_reg_id) vm_decl_rd = vmDeclAndReadData() set_vm_idx = setSrcVm() + set_vlenb = setVlenb() microiop = InstObjParams(name+"_micro", Name+"Micro", @@ -854,6 +909,7 @@ def format ViotaFormat(code, category, *flags){{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'set_vm_idx': set_vm_idx, 'copy_old_vd': copyOldVd(1)}, @@ -885,12 +941,14 @@ def format Vector1Vs1VdMaskFormat(code, category, *flags){{ set_dest_reg_idx = setDestWrapper(dest_reg_id) vm_decl_rd = vmDeclAndReadData() set_vm_idx = setSrcVm() + set_vlenb = setVlenb() iop = InstObjParams(name, Name, 'VectorNonSplitInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'set_vm_idx': set_vm_idx, 'copy_old_vd': copyOldVd(1)}, @@ -946,10 +1004,10 @@ def format VectorNonSplitFormat(code, category, *flags) {{ if inst_name == "vfmv" : execute_block = VectorFloatNonSplitExecute.subst(iop) - decode_block = VectorFloatDecodeBlock.subst(iop) + decode_block = VectorFloatNonSplitDecodeBlock.subst(iop) elif inst_name == "vmv" : execute_block = VectorIntNonSplitExecute.subst(iop) - decode_block = VectorIntDecodeBlock.subst(iop) + decode_block = VectorIntNonSplitDecodeBlock.subst(iop) else : error("Unsupported inst for VectorNonSplitFormat: %s" % inst_name) @@ -984,6 +1042,8 @@ def format VectorMaskFormat(code, category, *flags) {{ set_dest_reg_idx = setDestWrapper(dest_reg_id) + set_vlenb = setVlenb() + code = loopWrapper(code, micro_inst = False) iop = InstObjParams(name, @@ -992,6 +1052,7 @@ def format VectorMaskFormat(code, category, *flags) {{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) # Because of the use of templates, we had to put all parts in header to @@ -1020,6 +1081,9 @@ def format VectorReduceIntFormat(code, category, *flags) {{ set_src_reg_idx += setSrcWrapper(old_dest_reg_id) set_src_reg_idx += setSrcVm() vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + set_vlen = setVlen() + type_def = ''' using vu [[maybe_unused]] = std::make_unsigned_t; using vi [[maybe_unused]] = std::make_signed_t; @@ -1030,6 +1094,8 @@ def format VectorReduceIntFormat(code, category, *flags) {{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb' : set_vlenb, + 'set_vlen' : set_vlen, 'vm_decl_rd': vm_decl_rd, 'type_def': type_def, 'copy_old_vd': copyOldVd(2)}, @@ -1062,6 +1128,9 @@ def format VectorReduceFloatFormat(code, category, *flags) {{ set_src_reg_idx += setSrcWrapper(old_dest_reg_id) set_src_reg_idx += setSrcVm() vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + set_vlen = setVlen() + type_def = ''' using et = ElemType; using vu = decltype(et::v); @@ -1075,6 +1144,8 @@ def format VectorReduceFloatFormat(code, category, *flags) {{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'type_def': type_def, 'copy_old_vd': copyOldVd(2)}, @@ -1107,6 +1178,8 @@ def format VectorReduceFloatWideningFormat(code, category, *flags) {{ set_src_reg_idx += setSrcWrapper(old_dest_reg_id) set_src_reg_idx += setSrcVm() vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + set_vlen = setVlen() type_def = ''' using et = ElemType; using vu [[maybe_unused]] = decltype(et::v); @@ -1119,6 +1192,8 @@ def format VectorReduceFloatWideningFormat(code, category, *flags) {{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'type_def': type_def, 'copy_old_vd': copyOldVd(2)}, @@ -1162,6 +1237,8 @@ def format VectorIntVxsatFormat(code, category, *flags) {{ set_src_reg_idx += setSrcVm() vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + code = maskCondWrapper(code) code = eiDeclarePrefix(code) code = loopWrapper(code) @@ -1172,6 +1249,7 @@ def format VectorIntVxsatFormat(code, category, *flags) {{ {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) @@ -1204,12 +1282,16 @@ def format VectorReduceIntWideningFormat(code, category, *flags) {{ set_src_reg_idx += setSrcWrapper(old_dest_reg_id) set_src_reg_idx += setSrcVm() vm_decl_rd = vmDeclAndReadData() + set_vlenb = setVlenb() + set_vlen = setVlen() microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(2)}, flags) @@ -1261,12 +1343,16 @@ def VectorSlideBase(name, Name, category, code, flags, macro_construtor, set_dest_reg_idx = setDestWrapper(dest_reg_id) vm_decl_rd = vmDeclAndReadData() set_src_reg_idx += setSrcVm() + set_vlenb = setVlenb() + set_vlen = setVlen() microiop = InstObjParams(name + "_micro", Name + "Micro", microop_class_name, {'code': code, 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, + 'set_vlenb': set_vlenb, + 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx)}, flags) diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa index 457c5ce40d..b997dbec97 100644 --- a/src/arch/riscv/isa/formats/vector_conf.isa +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -157,7 +157,8 @@ def template VConfExecute {{ tc->setMiscReg(MISCREG_VSTART, 0); - VTYPE new_vtype = getNewVtype(Vtype, requested_vtype, vlen); + VTYPE new_vtype = getNewVtype(Vtype, requested_vtype, + vlen); vlmax = new_vtype.vill ? 0 : getVlmax(new_vtype, vlen); uint32_t new_vl = getNewVL( current_vl, requested_vl, vlmax, rd_bits, rs1_bits); diff --git a/src/arch/riscv/isa/formats/vector_mem.isa b/src/arch/riscv/isa/formats/vector_mem.isa index 113250d5cf..da53d80d0a 100644 --- a/src/arch/riscv/isa/formats/vector_mem.isa +++ b/src/arch/riscv/isa/formats/vector_mem.isa @@ -29,10 +29,15 @@ let {{ +def setVlen(): + return "uint32_t vlen = VlenbBits * 8;\n" +def setVlenb(): + return "uint32_t vlenb = VlenbBits;\n" + def VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, base_class, postacc_code='', declare_template_base=VMemMacroDeclare, - decode_template=BasicDecode, exec_template_base='', + decode_template=VMemBaseDecodeBlock, exec_template_base='', # If it's a macroop, the corresponding microops will be # generated. is_macroop=True): @@ -63,7 +68,9 @@ def VMemBase(name, Name, ea_code, memacc_code, mem_flags, exec_template_base + 'MicroInst', {'ea_code': ea_code, 'memacc_code': memacc_code, - 'postacc_code': postacc_code}, + 'postacc_code': postacc_code, + 'set_vlenb': setVlenb(), + 'set_vlen': setVlen()}, inst_flags) if mem_flags: @@ -90,7 +97,9 @@ def VMemBase(name, Name, ea_code, memacc_code, mem_flags, def format VleOp( memacc_code, - ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + ea_code={{ + EA = Rs1 + vlenb * microIdx; + }}, mem_flags=[], inst_flags=[] ) {{ @@ -101,7 +110,9 @@ def format VleOp( def format VseOp( memacc_code, - ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + ea_code={{ + EA = Rs1 + vlenb * microIdx; + }}, mem_flags=[], inst_flags=[] ) {{ @@ -134,7 +145,9 @@ def format VsmOp( def format VlWholeOp( memacc_code, - ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + ea_code={{ + EA = Rs1 + vlenb * microIdx; + }}, mem_flags=[], inst_flags=[] ) {{ @@ -145,7 +158,9 @@ def format VlWholeOp( def format VsWholeOp( memacc_code, - ea_code={{ EA = Rs1 + VLENB * microIdx; }}, + ea_code={{ + EA = Rs1 + vlenb * microIdx; + }}, mem_flags=[], inst_flags=[] ) {{ @@ -156,7 +171,9 @@ def format VsWholeOp( def format VlStrideOp( memacc_code, - ea_code={{ EA = Rs1 + Rs2 * (regIdx * VLENB / elem_size + microIdx); }}, + ea_code={{ + EA = Rs1 + Rs2 * (regIdx * vlenb / elem_size + microIdx); + }}, mem_flags=[], inst_flags=[] ) {{ @@ -167,7 +184,9 @@ def format VlStrideOp( def format VsStrideOp( memacc_code, - ea_code={{ EA = Rs1 + Rs2 * (regIdx * VLENB / elem_size + microIdx); }}, + ea_code={{ + EA = Rs1 + Rs2 * (regIdx * vlenb / elem_size + microIdx); + }}, mem_flags=[], inst_flags=[] ) {{ @@ -186,7 +205,7 @@ def format VlIndexOp( VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 'VlIndexMacroInst', exec_template_base='VlIndex', declare_template_base=VMemTemplateMacroDeclare, - decode_template=VMemTemplateDecodeBlock + decode_template=VMemSplitTemplateDecodeBlock ) }}; @@ -200,6 +219,6 @@ def format VsIndexOp( VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 'VsIndexMacroInst', exec_template_base='VsIndex', declare_template_base=VMemTemplateMacroDeclare, - decode_template=VMemTemplateDecodeBlock + decode_template=VMemSplitTemplateDecodeBlock ) }}; diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa index 9b5ee0e7fa..306b1c53f1 100644 --- a/src/arch/riscv/isa/templates/vector_arith.isa +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -35,8 +35,8 @@ output header {{ [[maybe_unused]] RiscvISA::vreg_t old_vd; \ [[maybe_unused]] decltype(Vd) old_Vd = nullptr; \ xc->getRegOperand(this, (idx), &old_vd); \ - old_Vd = old_vd.as >(); \ - memcpy(Vd, old_Vd, VLENB); + old_Vd = old_vd.as >(); \ + memcpy(Vd, old_Vd, vlenb); #define VRM_REQUIRED \ uint_fast8_t frm = xc->readMiscReg(MISCREG_FRM); \ @@ -73,7 +73,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -82,14 +82,14 @@ public: def template VectorIntMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -121,7 +121,7 @@ private: RegId destRegIdxArr[1]; bool vm; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; @@ -133,7 +133,7 @@ def template VectorIntMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -173,6 +173,7 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -190,7 +191,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override { @@ -214,7 +215,7 @@ private: RegId destRegIdxArr[1]; bool vm; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; std::string generateDisassembly(Addr pc, @@ -254,13 +255,16 @@ Fault xc->setMiscReg(MISCREG_STATUS, status); auto SEW = vtype_SEW(vtype); - auto offset = (VLEN / SEW) * (microIdx % %(ext_div)d); + auto index = (microIdx % %(ext_div)d); + switch (SEW / %(ext_div)d) { case 8: { using vext [[maybe_unused]] = int8_t; using vextu [[maybe_unused]] = uint8_t; %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -272,6 +276,8 @@ Fault using vextu [[maybe_unused]] = uint16_t; %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -283,6 +289,8 @@ Fault using vextu [[maybe_unused]] = uint32_t; %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -300,10 +308,10 @@ Fault def template VectorIntDecodeBlock {{ switch(machInst.vtype8.vsew) { -case 0b000: return new %(class_name)s(machInst); -case 0b001: return new %(class_name)s(machInst); -case 0b010: return new %(class_name)s(machInst); -case 0b011: return new %(class_name)s(machInst); +case 0b000: return new %(class_name)s(machInst, vlen); +case 0b001: return new %(class_name)s(machInst, vlen); +case 0b010: return new %(class_name)s(machInst, vlen); +case 0b011: return new %(class_name)s(machInst, vlen); default: GEM5_UNREACHABLE; } @@ -316,7 +324,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -325,8 +333,8 @@ public: def template VectorIntWideningMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; @@ -337,7 +345,7 @@ template const uint32_t num_microops = 1 << std::max(0, vlmul + 1); int32_t tmp_vl = this->vl; - const int32_t t_micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t t_micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -370,7 +378,7 @@ private: RegId destRegIdxArr[1]; bool vm; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; @@ -382,7 +390,7 @@ def template VectorIntWideningMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -415,6 +423,10 @@ Fault return std::make_shared( "RVV is disabled or VPU is off", machInst); } + %(op_decl)s; + %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -423,13 +435,11 @@ Fault xc->setMiscReg(MISCREG_STATUS, status); const int64_t vlmul = vtype_vlmul(machInst.vtype8); - const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; [[maybe_unused]] const size_t offset = (this->microIdx % 2 == 0) ? 0 : micro_vlmax; - %(op_decl)s; - %(op_rd)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -459,6 +469,11 @@ Fault "RVV is disabled or VPU is off", machInst); } + %(op_decl)s; + %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; + if (machInst.vill) return std::make_shared("VILL is set", machInst); @@ -466,13 +481,11 @@ Fault xc->setMiscReg(MISCREG_STATUS, status); const int64_t vlmul = vtype_vlmul(machInst.vtype8); - const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; [[maybe_unused]] const size_t offset = (this->microIdx % 2 == 0) ? 0 : micro_vlmax; - %(op_decl)s; - %(op_rd)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -485,9 +498,9 @@ Fault def template VectorIntWideningDecodeBlock {{ switch(machInst.vtype8.vsew) { -case 0b000: return new %(class_name)s(machInst); -case 0b001: return new %(class_name)s(machInst); -case 0b010: return new %(class_name)s(machInst); +case 0b000: return new %(class_name)s(machInst, vlen); +case 0b001: return new %(class_name)s(machInst, vlen); +case 0b010: return new %(class_name)s(machInst, vlen); default: GEM5_UNREACHABLE; } @@ -500,7 +513,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -508,14 +521,14 @@ public: def template VectorFloatMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -547,7 +560,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -557,7 +570,7 @@ public: def template VectorFloatMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -598,6 +611,7 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -611,8 +625,8 @@ Fault def template VectorFloatDecodeBlock {{ switch(machInst.vtype8.vsew) { -case 0b010: return new %(class_name)s(machInst); -case 0b011: return new %(class_name)s(machInst); +case 0b010: return new %(class_name)s(machInst, vlen); +case 0b011: return new %(class_name)s(machInst, vlen); default: GEM5_UNREACHABLE; } @@ -625,7 +639,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override { @@ -650,7 +664,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override @@ -693,14 +707,17 @@ Fault VRM_REQUIRED; + %(op_decl)s; + %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; + const int64_t vlmul = vtype_vlmul(machInst.vtype8); - const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; [[maybe_unused]] const size_t offset = (this->microIdx % 2 == 0) ? 0 : micro_vlmax; - %(op_decl)s; - %(op_rd)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -737,14 +754,17 @@ Fault VRM_REQUIRED; + %(op_decl)s; + %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; + const int64_t vlmul = vtype_vlmul(machInst.vtype8); - const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const int32_t t_micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); const int32_t micro_vlmax = vlmul < 0 ? t_micro_vlmax : t_micro_vlmax / 2; [[maybe_unused]] const size_t offset = (this->microIdx % 2 == 0) ? 0 : micro_vlmax; - %(op_decl)s; - %(op_rd)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -757,7 +777,7 @@ Fault def template VectorFloatWideningDecodeBlock {{ switch(machInst.vtype8.vsew) { -case 0b010: return new %(class_name)s(machInst); +case 0b010: return new %(class_name)s(machInst, vlen); default: GEM5_UNREACHABLE; } @@ -771,7 +791,7 @@ private: int cnt = 0; %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -781,14 +801,14 @@ public: def template ViotaMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -819,7 +839,7 @@ private: bool vm; int* cnt; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx, int* cnt); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; @@ -831,7 +851,7 @@ def template ViotaMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, int* cnt) + uint32_t _microVl, uint8_t _microIdx, int* cnt) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -871,6 +891,7 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -919,6 +940,7 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -997,7 +1019,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -1006,14 +1028,14 @@ public: def template VectorIntMaskMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -1028,7 +1050,7 @@ template micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); } microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, - this->microops.size()); + this->microops.size(), _vlen); this->microops.push_back(microop); this->microops.front()->setFirstMicroop(); @@ -1050,7 +1072,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1061,7 +1083,7 @@ def template VectorIntMaskMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1099,10 +1121,11 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(vm_decl_rd)s; %(copy_old_vd)s; - constexpr uint16_t bit_offset = VLENB / sizeof(ElemType); + const uint16_t bit_offset = vlenb / sizeof(ElemType); const uint16_t offset = bit_offset * microIdx; %(code)s; @@ -1119,7 +1142,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -1128,14 +1151,14 @@ public: def template VectorFloatMaskMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -1150,7 +1173,7 @@ template micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); } microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, - this->microops.size()); + this->microops.size(), _vlen); this->microops.push_back(microop); this->microops.front()->setFirstMicroop(); @@ -1171,7 +1194,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1182,7 +1205,7 @@ def template VectorFloatMaskMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1220,10 +1243,11 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(vm_decl_rd)s; %(copy_old_vd)s; - constexpr uint16_t bit_offset = VLENB / sizeof(ElemType); + const uint16_t bit_offset = vlenb / sizeof(ElemType); const uint16_t offset = bit_offset * microIdx; %(code)s; @@ -1276,7 +1300,7 @@ private: RegId destRegIdxArr[1]; bool vm; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; @@ -1287,7 +1311,7 @@ public: def template VMvWholeMicroConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1321,7 +1345,8 @@ Fault %(op_decl)s; %(op_rd)s; - for (size_t i = 0; i < (VLEN / 64); i++) { + %(set_vlen)s; + for (size_t i = 0; i < (vlen / 64); i++) { %(code)s; } %(op_wb)s; @@ -1382,6 +1407,7 @@ Fault %(op_decl)s; %(op_rd)s; // TODO: remove it + %(set_vlenb)s; %(copy_old_vd)s; %(code)s; %(op_wb)s; @@ -1489,6 +1515,28 @@ Fault }}; +def template VectorFloatNonSplitDecodeBlock {{ + +switch(machInst.vtype8.vsew) { +case 0b010: return new %(class_name)s(machInst); +case 0b011: return new %(class_name)s(machInst); +default: GEM5_UNREACHABLE; +} + +}}; + +def template VectorIntNonSplitDecodeBlock {{ + +switch(machInst.vtype8.vsew) { +case 0b000: return new %(class_name)s(machInst); +case 0b001: return new %(class_name)s(machInst); +case 0b010: return new %(class_name)s(machInst); +case 0b011: return new %(class_name)s(machInst); +default: GEM5_UNREACHABLE; +} + +}}; + def template VectorReduceMacroDeclare {{ template @@ -1496,7 +1544,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -1505,14 +1553,14 @@ public: def template VectorReduceMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -1544,7 +1592,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1555,7 +1603,7 @@ def template VectorReduceMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1593,6 +1641,8 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; @@ -1600,7 +1650,8 @@ Fault [&, this](const auto& f, const auto* _, const auto* vs2) { ElemType microop_result = this->microIdx != 0 ? old_Vd[0] : Vs1[0]; for (uint32_t i = 0; i < this->microVl; i++) { - uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + uint32_t ei = i + vtype_VLMAX(vtype, vlen, true) * + this->microIdx; if (this->vm || elem_mask(v0, ei)) { microop_result = f(microop_result, Vs2[i]); } @@ -1625,6 +1676,7 @@ Fault %(type_def)s; MISA misa = xc->readMiscReg(MISCREG_ISA); STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { return std::make_shared( "RVV is disabled or VPU is off", machInst); @@ -1638,6 +1690,8 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; @@ -1647,7 +1701,8 @@ Fault [&, this](const auto& f, const auto* _, const auto* vs2) { vu tmp_val = Vd[0]; for (uint32_t i = 0; i < this->microVl; i++) { - uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + uint32_t ei = i + vtype_VLMAX(vtype, vlen, true) * + this->microIdx; if (this->vm || elem_mask(v0, ei)) { tmp_val = f(tmp_val, Vs2[i]).v; } @@ -1685,6 +1740,8 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; @@ -1694,7 +1751,8 @@ Fault [&, this](const auto& f, const auto* _, const auto* vs2) { vwu tmp_val = Vd[0]; for (uint32_t i = 0; i < this->microVl; i++) { - uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + uint32_t ei = i + vtype_VLMAX(vtype, vlen, true) * + this->microIdx; if (this->vm || elem_mask(v0, ei)) { tmp_val = f(tmp_val, Vs2[i]).v; } @@ -1716,7 +1774,7 @@ class %(class_name)s : public %(base_class)s{ private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -1725,8 +1783,9 @@ public: def template VectorGatherMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; @@ -1740,7 +1799,8 @@ template const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; const uint8_t vs1_vregs = vs1_emul < 0 ? 1 : 1 << vs1_emul; const uint8_t vd_vregs = vs2_vregs; - const int32_t micro_vlmax = VLENB / std::max(vd_eewb, vs1_eewb); + uint32_t vlenb = vlen >> 3; + const int32_t micro_vlmax = vlenb / std::max(vd_eewb, vs1_eewb); int32_t remaining_vl = this->vl; int32_t micro_vl = std::min(remaining_vl, micro_vlmax); StaticInstPtr microop; @@ -1778,7 +1838,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1789,7 +1849,7 @@ def template VectorGatherMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint8_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1839,17 +1899,19 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; - const uint32_t vlmax = vtype_VLMAX(vtype); + const uint32_t vlmax = vtype_VLMAX(vtype,vlen); constexpr uint8_t vd_eewb = sizeof(ElemType); constexpr uint8_t vs1_eewb = sizeof(IndexType); constexpr uint8_t vs2_eewb = sizeof(ElemType); constexpr uint8_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; constexpr uint8_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; - [[maybe_unused]] constexpr uint16_t vd_elems = VLENB / vd_eewb; - [[maybe_unused]] constexpr uint16_t vs1_elems = VLENB / vs1_eewb; - [[maybe_unused]] constexpr uint16_t vs2_elems = VLENB / vs2_eewb; + [[maybe_unused]] const uint16_t vd_elems = vlenb / vd_eewb; + [[maybe_unused]] const uint16_t vs1_elems = vlenb / vs1_eewb; + [[maybe_unused]] const uint16_t vs2_elems = vlenb / vs2_eewb; [[maybe_unused]] const int8_t lmul = vtype_vlmul(vtype); [[maybe_unused]] const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; [[maybe_unused]] const uint8_t vs2_idx = microIdx % vs2_vregs; @@ -1875,19 +1937,19 @@ def template VectorGatherDecodeBlock {{ switch(machInst.vtype8.vsew) { case 0b000: { using elem_type [[maybe_unused]] = uint8_t; - return new %(class_name)s(machInst); + return new %(class_name)s(machInst, vlen); } case 0b001: { using elem_type [[maybe_unused]] = uint16_t; - return new %(class_name)s(machInst); + return new %(class_name)s(machInst, vlen); } case 0b010: { using elem_type [[maybe_unused]] = uint32_t; - return new %(class_name)s(machInst); + return new %(class_name)s(machInst, vlen); } case 0b011: { using elem_type [[maybe_unused]] = uint64_t; - return new %(class_name)s(machInst); + return new %(class_name)s(machInst, vlen); } default: GEM5_UNREACHABLE; } @@ -1902,7 +1964,7 @@ private: %(reg_idx_arr_decl)s; bool vxsat = false; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -1911,14 +1973,14 @@ public: def template VectorIntVxsatMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -1954,7 +2016,7 @@ private: bool vm; bool* vxsatptr; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx, bool* vxsatptr); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; @@ -1966,7 +2028,7 @@ def template VectorIntVxsatMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, bool* vxsatptr) + uint32_t _microVl, uint8_t _microIdx, bool* vxsatptr) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -2007,6 +2069,8 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(vm_decl_rd)s; %(copy_old_vd)s; @@ -2016,7 +2080,8 @@ Fault [&, this](const auto& f, const auto* _, const auto* vs2) { vwu tmp_val = Vd[0]; for (uint32_t i = 0; i < this->microVl; i++) { - uint32_t ei = i + vtype_VLMAX(vtype, true) * this->microIdx; + uint32_t ei = i + vtype_VLMAX(vtype, vlen, true) * + this->microIdx; if (this->vm || elem_mask(v0, ei)) { tmp_val = f(tmp_val, Vs2[i]); } @@ -2038,7 +2103,7 @@ class %(class_name)s : public %(base_class)s { private: %(reg_idx_arr_decl)s; public: - %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -2047,14 +2112,14 @@ public: def template VectorSlideUpMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -2082,14 +2147,14 @@ template def template VectorSlideDownMacroConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; const uint32_t num_microops = vtype_regs_per_group(vtype); int32_t tmp_vl = this->vl; - const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, true); + const int32_t micro_vlmax = vtype_VLMAX(_machInst.vtype8, vlen, true); int32_t micro_vl = std::min(tmp_vl, micro_vlmax); StaticInstPtr microop; @@ -2126,7 +2191,7 @@ private: RegId destRegIdxArr[1]; bool vm; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; @@ -2138,7 +2203,7 @@ def template VectorSlideMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) + uint32_t _microVl, uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vdIdx, _vs2Idx) { @@ -2174,10 +2239,13 @@ Fault status.vs = VPUStatus::DIRTY; xc->setMiscReg(MISCREG_STATUS, status); - [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); - %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; + + [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype, vlen); + %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; @@ -2210,10 +2278,13 @@ Fault status.vs = VPUStatus::DIRTY; xc->setMiscReg(MISCREG_STATUS, status); - [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype); - %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; + + [[maybe_unused]]const uint32_t vlmax = vtype_VLMAX(vtype, vlen); + %(vm_decl_rd)s; %(copy_old_vd)s; %(code)s; diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index 2b3b9187bf..fc1b93548c 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -34,6 +34,7 @@ private: %(reg_idx_arr_decl)s; public: %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -48,6 +49,7 @@ private: %(reg_idx_arr_decl)s; public: %(class_name)s(ExtMachInst _machInst); + %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); using %(base_class)s::generateDisassembly; }; @@ -55,16 +57,17 @@ public: def template VleConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; - const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const int32_t micro_vlmax = vlen / width_EEW(_machInst.width); const uint32_t num_microops = ceil((float) this->vl / (micro_vlmax)); int32_t remaining_vl = this->vl; int32_t micro_vl = std::min(remaining_vl, micro_vlmax); + StaticInstPtr microop; if (micro_vl == 0) { @@ -72,7 +75,7 @@ def template VleConstructor {{ this->microops.push_back(microop); } for (int i = 0; i < num_microops && micro_vl > 0; ++i) { - microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop = new %(class_name)sMicro(_machInst, micro_vl, i, vlen); microop->setDelayedCommit(); microop->setFlag(IsLoad); this->microops.push_back(microop); @@ -93,9 +96,10 @@ private: RegId srcRegIdxArr[3]; RegId destRegIdxArr[1]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, - _microIdx) + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, + uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _microVl, _microIdx, _vlen) { %(set_reg_idx_arr)s; _numSrcRegs = 0; @@ -127,12 +131,15 @@ Fault Addr EA; %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(ea_code)s; RiscvISA::vreg_t tmp_v0; uint8_t *v0; MISA misa = xc->readMiscReg(MISCREG_ISA); STATUS status = xc->readMiscReg(MISCREG_STATUS); + if (!misa.rvv || status.vs == VPUStatus::OFF) { return std::make_shared( "RVV is disabled or VPU is off", machInst); @@ -150,15 +157,18 @@ Fault } uint32_t mem_size = width_EEW(machInst.width) / 8 * this->microVl; + const std::vector byte_enable(mem_size, true); Fault fault = xc->readMem(EA, Mem.as(), mem_size, memAccessFlags, byte_enable); if (fault != NoFault) return fault; - const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); - const size_t micro_elems = VLEN / width_EEW(machInst.width); + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); + const size_t micro_elems = vlen / width_EEW(machInst.width); + size_t ei; + for (size_t i = 0; i < micro_elems; i++) { ei = i + micro_vlmax * microIdx; %(memacc_code)s; @@ -176,10 +186,12 @@ Fault %(class_name)s::initiateAcc(ExecContext* xc, trace::InstRecord* traceData) const { + Addr EA; %(op_src_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; MISA misa = xc->readMiscReg(MISCREG_ISA); @@ -192,6 +204,7 @@ Fault return std::make_shared("VILL is set", machInst); uint32_t mem_size = width_EEW(this->machInst.width) / 8 * this->microVl; + const std::vector byte_enable(mem_size, true); Fault fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, byte_enable); @@ -208,6 +221,7 @@ Fault { %(op_decl)s; %(op_rd)s; + %(set_vlen)s; STATUS status = xc->readMiscReg(MISCREG_STATUS); status.vs = VPUStatus::DIRTY; @@ -222,8 +236,9 @@ Fault memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); - const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); - const size_t micro_elems = VLEN / width_EEW(machInst.width); + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); + const size_t micro_elems = vlen / width_EEW(machInst.width); + size_t ei; for (size_t i = 0; i < micro_elems; i++) { ei = i + micro_vlmax * microIdx; @@ -238,13 +253,13 @@ Fault def template VseConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; - const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const int32_t micro_vlmax = vlen / width_EEW(_machInst.width); const uint32_t num_microops = ceil((float) this->vl / (micro_vlmax)); int32_t remaining_vl = this->vl; int32_t micro_vl = std::min(remaining_vl, micro_vlmax); @@ -256,7 +271,7 @@ def template VseConstructor {{ this->microops.push_back(microop); } for (int i = 0; i < num_microops && micro_vl > 0; ++i) { - microop = new %(class_name)sMicro(_machInst, micro_vl, i); + microop = new %(class_name)sMicro(_machInst, micro_vl, i, vlen); microop->setDelayedCommit(); microop->setFlag(IsStore); this->microops.push_back(microop); @@ -277,9 +292,10 @@ private: RegId srcRegIdxArr[3]; RegId destRegIdxArr[0]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _microVl, _microIdx) + %(class_name)s(ExtMachInst _machInst, + uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _microVl, _microIdx, _vlen) { %(set_reg_idx_arr)s; _numSrcRegs = 0; @@ -326,9 +342,11 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(ea_code)s; - const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); const size_t eewb = width_EEW(machInst.width) / 8; const size_t mem_size = eewb * microVl; std::vector byte_enable(mem_size, false); @@ -375,9 +393,11 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(ea_code)s; - const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, true); + const size_t micro_vlmax = vtype_VLMAX(machInst.vtype8, vlen, true); const size_t eewb = width_EEW(machInst.width) / 8; const size_t mem_size = eewb * microVl; std::vector byte_enable(mem_size, false); @@ -412,20 +432,20 @@ Fault def template VlmConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; - const uint32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const uint32_t micro_vlmax = vlen / width_EEW(_machInst.width); int32_t micro_vl = (std::min(this->vl, micro_vlmax) + 7) / 8; StaticInstPtr microop; if (micro_vl == 0) { microop = new VectorNopMicroInst(_machInst); } else { - microop = new Vle8_vMicro(_machInst, micro_vl, 0); + microop = new Vle8_vMicro(_machInst, micro_vl, 0, vlen); microop->setDelayedCommit(); microop->setFlag(IsLoad); } @@ -439,20 +459,20 @@ def template VlmConstructor {{ def template VsmConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; - const uint32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const uint32_t micro_vlmax = vlen / width_EEW(_machInst.width); int32_t micro_vl = (std::min(this->vl, micro_vlmax) + 7) / 8; StaticInstPtr microop; if (micro_vl == 0) { microop = new VectorNopMicroInst(_machInst); } else { - microop = new Vse8_vMicro(_machInst, micro_vl, 0); + microop = new Vse8_vMicro(_machInst, micro_vl, 0, vlen); microop->setDelayedCommit(); microop->setFlag(IsStore); } @@ -466,18 +486,18 @@ def template VsmConstructor {{ def template VsWholeConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; size_t NFIELDS = machInst.nf + 1; - const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + const int32_t micro_vlmax = vlen / width_EEW(_machInst.width); StaticInstPtr microop; for (int i = 0; i < NFIELDS; ++i) { - microop = new %(class_name)sMicro(_machInst, micro_vlmax, i); + microop = new %(class_name)sMicro(_machInst, micro_vlmax, i, vlen); microop->setDelayedCommit(); microop->setFlag(IsStore); this->microops.push_back(microop); @@ -497,9 +517,10 @@ private: RegId destRegIdxArr[0]; RegId srcRegIdxArr[2]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _microVl, _microIdx) + %(class_name)s(ExtMachInst _machInst, + uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, + %(op_class)s, _microVl, _microIdx, _vlen) { %(set_reg_idx_arr)s; _numSrcRegs = 0; @@ -532,9 +553,11 @@ Fault } %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; - for (size_t i = 0; i < VLENB; i++) { + + for (size_t i = 0; i < vlenb; i++) { %(memacc_code)s; } @@ -560,9 +583,11 @@ Fault } %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; - for (size_t i = 0; i < VLENB; i++) { + + for (size_t i = 0; i < vlenb; i++) { %(memacc_code)s; } @@ -586,18 +611,19 @@ Fault def template VlWholeConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; size_t NFIELDS = machInst.nf + 1; - const int32_t micro_vlmax = VLEN / width_EEW(_machInst.width); + + const int32_t micro_vlmax = vlen / width_EEW(_machInst.width); StaticInstPtr microop; for (int i = 0; i < NFIELDS; ++i) { - microop = new %(class_name)sMicro(_machInst, micro_vlmax, i); + microop = new %(class_name)sMicro(_machInst, micro_vlmax, i, vlen); microop->setDelayedCommit(); microop->setFlag(IsLoad); this->microops.push_back(microop); @@ -617,9 +643,10 @@ private: RegId destRegIdxArr[1]; RegId srcRegIdxArr[1]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, uint8_t _microIdx) - : %(base_class)s("%(mnemonic)s_micro", _machInst, %(op_class)s, - _microVl, _microIdx) + %(class_name)s(ExtMachInst _machInst, + uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s_micro", _machInst, + %(op_class)s, _microVl, _microIdx, _vlen) { %(set_reg_idx_arr)s; _numSrcRegs = 0; @@ -657,6 +684,8 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; + %(set_vlen)s; %(ea_code)s; Fault fault = readMemAtomicLE(xc, traceData, EA, @@ -664,7 +693,7 @@ Fault if (fault != NoFault) return fault; - size_t elem_per_reg = VLEN / width_EEW(machInst.width); + size_t elem_per_reg = vlen / width_EEW(machInst.width); for (size_t i = 0; i < elem_per_reg; i++) { %(memacc_code)s; } @@ -690,6 +719,7 @@ Fault } %(op_src_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; Fault fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); @@ -706,6 +736,7 @@ Fault { %(op_decl)s; %(op_rd)s; + %(set_vlen)s; STATUS status = xc->readMiscReg(MISCREG_STATUS); status.vs = VPUStatus::DIRTY; @@ -713,7 +744,7 @@ Fault memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); - size_t elem_per_reg = VLEN / width_EEW(machInst.width); + size_t elem_per_reg = vlen / width_EEW(machInst.width); for (size_t i = 0; i < elem_per_reg; ++i) { %(memacc_code)s; } @@ -726,13 +757,13 @@ Fault def template VlStrideConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; - const int32_t num_elems_per_vreg = VLEN / width_EEW(_machInst.width); + const int32_t num_elems_per_vreg = vlen / width_EEW(_machInst.width); int32_t remaining_vl = this->vl; // Num of elems in one vreg int32_t micro_vl = std::min(remaining_vl, num_elems_per_vreg); @@ -770,7 +801,7 @@ private: RegId destRegIdxArr[1]; public: %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, - uint8_t _microVl) + uint32_t _microVl) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _regIdx, _microIdx, _microVl) { @@ -820,6 +851,7 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; constexpr uint8_t elem_size = sizeof(Vd[0]); %(ea_code)s; // ea_code depends on elem_size @@ -833,7 +865,7 @@ Fault uint32_t mem_size = elem_size; const std::vector byte_enable(mem_size, true); - size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + size_t ei = this->regIdx * vlenb / elem_size + this->microIdx; if (machInst.vm || elem_mask(v0, ei)) { fault = xc->readMem(EA, Mem.as(), mem_size, memAccessFlags, byte_enable); @@ -866,6 +898,7 @@ Fault return std::make_shared("VILL is set", machInst); %(op_src_decl)s; %(op_rd)s; + %(set_vlenb)s; constexpr uint8_t elem_size = sizeof(Vd[0]); %(ea_code)s; // ea_code depends on elem_size @@ -877,7 +910,7 @@ Fault } uint32_t mem_size = elem_size; - size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + size_t ei = this->regIdx * vlenb / elem_size + this->microIdx; bool need_load = machInst.vm || elem_mask(v0, ei); const std::vector byte_enable(mem_size, need_load); fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, byte_enable); @@ -894,6 +927,7 @@ Fault { %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; STATUS status = xc->readMiscReg(MISCREG_STATUS); status.vs = VPUStatus::DIRTY; @@ -920,12 +954,12 @@ Fault memcpy(Vd, old_Vd, microVl * elem_size); // treat vta as vtu // if (machInst.vtype8.vta == 0) - memcpy(Vd + microVl, old_Vd + microVl, VLENB - microVl * elem_size); + memcpy(Vd + microVl, old_Vd + microVl, vlenb - microVl * elem_size); } else { - memcpy(Vd, old_Vd, VLENB); + memcpy(Vd, old_Vd, vlenb); } - size_t ei = this->regIdx * VLENB / sizeof(Vd[0]) + this->microIdx; + size_t ei = this->regIdx * vlenb / sizeof(Vd[0]) + this->microIdx; if (machInst.vm || elem_mask(v0, ei)) { memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); %(memacc_code)s; /* Vd[this->microIdx] = Mem[0]; */ @@ -939,13 +973,13 @@ Fault def template VsStrideConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; - const int32_t num_elems_per_vreg = VLEN / width_EEW(_machInst.width); + const int32_t num_elems_per_vreg = vlen / width_EEW(_machInst.width); int32_t remaining_vl = this->vl; // Num of elems in one vreg int32_t micro_vl = std::min(remaining_vl, num_elems_per_vreg); @@ -983,7 +1017,7 @@ private: RegId destRegIdxArr[0]; public: %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, - uint8_t _microVl) + uint32_t _microVl) : %(base_class)s("%(mnemonic)s""_micro", _machInst, %(op_class)s, _regIdx, _microIdx, _microVl) { @@ -1025,6 +1059,7 @@ Fault return std::make_shared("VILL is set", machInst); %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; constexpr uint8_t elem_size = sizeof(Vs3[0]); %(ea_code)s; @@ -1038,7 +1073,7 @@ Fault uint32_t mem_size = elem_size; const std::vector byte_enable(mem_size, true); - size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + size_t ei = this->regIdx * vlenb / elem_size + this->microIdx; if (machInst.vm || elem_mask(v0, ei)) { %(memacc_code)s; fault = xc->writeMem(Mem.as(), mem_size, EA, @@ -1074,11 +1109,13 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; constexpr uint8_t elem_size = sizeof(Vs3[0]); %(ea_code)s; uint32_t mem_size = elem_size; - size_t ei = this->regIdx * VLENB / elem_size + this->microIdx; + + size_t ei = this->regIdx * vlenb / elem_size + this->microIdx; bool need_store = machInst.vm || elem_mask(v0, ei); if (need_store) { const std::vector byte_enable(mem_size, need_store); @@ -1105,8 +1142,8 @@ Fault def template VlIndexConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; @@ -1115,7 +1152,8 @@ template const uint32_t vs2_eewb = width_EEW(_machInst.width) / 8; const uint8_t vs2_split_num = (vd_eewb + vs2_eewb - 1) / vs2_eewb; const uint8_t vd_split_num = (vs2_eewb + vd_eewb - 1) / vd_eewb; - const int32_t micro_vlmax = VLENB / std::max(vd_eewb, vs2_eewb); + uint32_t vlenb = vlen >> 3; + const int32_t micro_vlmax = vlenb / std::max(vd_eewb, vs2_eewb); int32_t remaining_vl = this->vl; int32_t micro_vl = std::min(remaining_vl, micro_vlmax); StaticInstPtr microop; @@ -1212,6 +1250,7 @@ Fault %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; constexpr uint8_t elem_size = sizeof(Vd[0]); RiscvISA::vreg_t tmp_v0; @@ -1223,8 +1262,7 @@ Fault uint32_t mem_size = elem_size; const std::vector byte_enable(mem_size, true); - - size_t ei = this->vdRegIdx * VLENB / elem_size + this->vdElemIdx; + size_t ei = this->vdRegIdx * vlenb / elem_size + this->vdElemIdx; if (machInst.vm || elem_mask(v0, ei)) { fault = xc->readMem(EA, Mem.as(), mem_size, memAccessFlags, byte_enable); @@ -1259,6 +1297,7 @@ Fault return std::make_shared("VILL is set", machInst); %(op_src_decl)s; %(op_rd)s; + %(set_vlenb)s; constexpr uint8_t elem_size = sizeof(Vd[0]); %(ea_code)s; // ea_code depends on elem_size @@ -1270,7 +1309,8 @@ Fault } uint32_t mem_size = elem_size; - size_t ei = this->vdRegIdx * VLENB / elem_size + this->vdElemIdx; + + size_t ei = this->vdRegIdx * vlenb / elem_size + this->vdElemIdx; bool need_load = machInst.vm || elem_mask(v0, ei); const std::vector byte_enable(mem_size, need_load); fault = initiateMemRead(xc, EA, mem_size, memAccessFlags, byte_enable); @@ -1293,10 +1333,11 @@ Fault using vu = std::make_unsigned_t; %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; constexpr uint8_t elem_size = sizeof(Vd[0]); - RiscvISA::vreg_t old_vd; + RiscvISA::vreg_t old_vd;; decltype(Vd) old_Vd = nullptr; // We treat agnostic as undistrubed xc->getRegOperand(this, 2, &old_vd); @@ -1309,9 +1350,9 @@ Fault v0 = tmp_v0.as(); } - memcpy(Vd, old_Vd, VLENB); + memcpy(Vd, old_Vd, vlenb); - size_t ei = this->vdRegIdx * VLENB / elem_size + this->vdElemIdx; + size_t ei = this->vdRegIdx * vlenb / elem_size + this->vdElemIdx; if (machInst.vm || elem_mask(v0, ei)) { memcpy(Mem.as(), pkt->getPtr(), pkt->getSize()); %(memacc_code)s; /* Vd[this->microIdx] = Mem[0]; */ @@ -1326,8 +1367,8 @@ Fault def template VsIndexConstructor {{ template -%(class_name)s::%(class_name)s(ExtMachInst _machInst) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vlen) { %(set_reg_idx_arr)s; %(constructor)s; @@ -1336,7 +1377,8 @@ template const uint32_t vs2_eewb = width_EEW(_machInst.width) / 8; const uint8_t vs2_split_num = (vs3_eewb + vs2_eewb - 1) / vs2_eewb; const uint8_t vs3_split_num = (vs2_eewb + vs3_eewb - 1) / vs3_eewb; - const int32_t micro_vlmax = VLENB / std::max(vs3_eewb, vs2_eewb); + uint32_t vlenb = vlen >> 3; + const int32_t micro_vlmax = vlenb / std::max(vs3_eewb, vs2_eewb); int32_t remaining_vl = this->vl; int32_t micro_vl = std::min(remaining_vl, micro_vlmax); StaticInstPtr microop; @@ -1426,6 +1468,7 @@ Fault return std::make_shared("VILL is set", machInst); %(op_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; constexpr uint8_t elem_size = sizeof(Vs3[0]); RiscvISA::vreg_t tmp_v0; @@ -1438,7 +1481,7 @@ Fault uint32_t mem_size = elem_size; const std::vector byte_enable(mem_size, true); - size_t ei = this->vs3RegIdx * VLENB / elem_size + this->vs3ElemIdx; + size_t ei = this->vs3RegIdx * vlenb / elem_size + this->vs3ElemIdx; if (machInst.vm || elem_mask(v0, ei)) { %(memacc_code)s; /* Mem[0] = Vs3[this->vs3ElemIdx] */ fault = xc->writeMem(Mem.as(), mem_size, EA, @@ -1469,6 +1512,7 @@ Fault return std::make_shared("VILL is set", machInst); %(op_src_decl)s; %(op_rd)s; + %(set_vlenb)s; %(ea_code)s; constexpr uint8_t elem_size = sizeof(Vs3[0]); RiscvISA::vreg_t tmp_v0; @@ -1481,7 +1525,7 @@ Fault constexpr uint8_t mem_size = elem_size; const std::vector byte_enable(mem_size, true); - size_t ei = this->vs3RegIdx * VLENB / elem_size + this->vs3ElemIdx; + size_t ei = this->vs3RegIdx * vlenb / elem_size + this->vs3ElemIdx; if (machInst.vm || elem_mask(v0, ei)) { %(memacc_code)s; /* Mem[0] = Vs3[this->vs3ElemIdx] */ fault = xc->writeMem(Mem.as(), mem_size, EA, @@ -1504,6 +1548,10 @@ Fault }}; +def template VMemBaseDecodeBlock {{ + return new %(class_name)s(machInst, vlen); +}}; + def template VMemTemplateDecodeBlock {{ switch(machInst.vtype8.vsew) { @@ -1523,3 +1571,23 @@ switch(machInst.vtype8.vsew) { } }}; + +def template VMemSplitTemplateDecodeBlock {{ + +switch(machInst.vtype8.vsew) { + case 0b000: { + return new %(class_name)s(machInst, vlen); + } + case 0b001: { + return new %(class_name)s(machInst, vlen); + } + case 0b010: { + return new %(class_name)s(machInst, vlen); + } + case 0b011: { + return new %(class_name)s(machInst, vlen); + } + default: GEM5_UNREACHABLE; +} + +}}; diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh index 03a7fc415f..91fb507034 100644 --- a/src/arch/riscv/pcstate.hh +++ b/src/arch/riscv/pcstate.hh @@ -62,7 +62,7 @@ class PCState : public GenericISA::UPCState<4> bool _compressed = false; RiscvType _rvType = RV64; - uint64_t _vlenb = 256; + uint64_t _vlenb = 32; VTYPE _vtype = (1ULL << 63); // vtype.vill = 1 at initial; uint32_t _vl = 0; diff --git a/src/arch/riscv/types.hh b/src/arch/riscv/types.hh index 01c600d148..c7edffc2f7 100644 --- a/src/arch/riscv/types.hh +++ b/src/arch/riscv/types.hh @@ -42,7 +42,6 @@ #ifndef __ARCH_RISCV_TYPES_HH__ #define __ARCH_RISCV_TYPES_HH__ -#include "arch/riscv/pcstate.hh" #include "base/bitunion.hh" namespace gem5 diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh index 40054aec0f..bac499e523 100644 --- a/src/arch/riscv/utility.hh +++ b/src/arch/riscv/utility.hh @@ -268,12 +268,13 @@ vtype_SEW(const uint64_t vtype) * Ref: https://github.com/qemu/qemu/blob/5e9d14f2/target/riscv/cpu.h */ inline uint64_t -vtype_VLMAX(const uint64_t vtype, const bool per_reg = false) +vtype_VLMAX(const uint64_t vtype, const uint64_t vlen, + const bool per_reg = false) { int64_t lmul = (int64_t)sext<3>(bits(vtype, 2, 0)); lmul = per_reg ? std::min(0, lmul) : lmul; int64_t vsew = bits(vtype, 5, 3); - return gem5::RiscvISA::VLEN >> (vsew + 3 - lmul); + return vlen >> (vsew + 3 - lmul); } inline int64_t From 52219e5e6ff227517e7d50c7eacddc3764ccb636 Mon Sep 17 00:00:00 2001 From: Alvaro Moreno Date: Sat, 23 Sep 2023 21:42:08 +0200 Subject: [PATCH 479/693] arch-riscv: Add elen configuration to vector config instructions This patch adds elen as a member of vector configuration instructions so it can be used with the especulative execution Change-Id: Iaf79015717a006374c5198aaa36e050edde40cee --- src/arch/riscv/decoder.cc | 1 + src/arch/riscv/decoder.hh | 1 + src/arch/riscv/insts/vector.hh | 7 +++++-- src/arch/riscv/isa/formats/vector_conf.isa | 23 +++++++++++++++++----- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index 3c199b3210..ee5d313587 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -43,6 +43,7 @@ Decoder::Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst) { ISA *isa = dynamic_cast(p.isa); vlen = isa->getVecLenInBits(); + elen = isa->getVecElemLenInBits(); reset(); } diff --git a/src/arch/riscv/decoder.hh b/src/arch/riscv/decoder.hh index b53c48445d..bf863fda22 100644 --- a/src/arch/riscv/decoder.hh +++ b/src/arch/riscv/decoder.hh @@ -61,6 +61,7 @@ class Decoder : public InstDecoder uint32_t machInst; uint32_t vlen; + uint32_t elen; virtual StaticInstPtr decodeInst(ExtMachInst mach_inst); diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index 58a76e0ab1..c986c99c72 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -69,12 +69,15 @@ class VConfOp : public RiscvStaticInst uint64_t zimm10; uint64_t zimm11; uint64_t uimm; - VConfOp(const char *mnem, ExtMachInst _extMachInst, OpClass __opClass) + uint32_t elen; + VConfOp(const char *mnem, ExtMachInst _extMachInst, + uint32_t _elen, OpClass __opClass) : RiscvStaticInst(mnem, _extMachInst, __opClass), bit30(_extMachInst.bit30), bit31(_extMachInst.bit31), zimm10(_extMachInst.zimm_vsetivli), zimm11(_extMachInst.zimm_vsetvli), - uimm(_extMachInst.uimm_vsetivli) + uimm(_extMachInst.uimm_vsetivli), + elen(_elen) { this->flags[IsVector] = true; } diff --git a/src/arch/riscv/isa/formats/vector_conf.isa b/src/arch/riscv/isa/formats/vector_conf.isa index b997dbec97..6280e5679b 100644 --- a/src/arch/riscv/isa/formats/vector_conf.isa +++ b/src/arch/riscv/isa/formats/vector_conf.isa @@ -42,8 +42,8 @@ def format VConfOp(code, write_code, declare_class, branch_class, *flags) {{ branchTargetTemplate = eval(branch_class) header_output = declareTemplate.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecode.subst(iop) + decoder_output = VConfConstructor.subst(iop) + decode_block = VConfDecodeBlock.subst(iop) exec_output = VConfExecute.subst(iop) + branchTargetTemplate.subst(iop) }}; @@ -61,7 +61,7 @@ def template VSetVlDeclare {{ public: /// Constructor. - %(class_name)s(ExtMachInst machInst); + %(class_name)s(ExtMachInst machInst, uint32_t elen); Fault execute(ExecContext *, trace::InstRecord *) const override; std::unique_ptr branchTarget( ThreadContext *tc) const override; @@ -86,7 +86,7 @@ def template VSetiVliDeclare {{ public: /// Constructor. - %(class_name)s(ExtMachInst machInst); + %(class_name)s(ExtMachInst machInst, uint32_t elen); Fault execute(ExecContext *, trace::InstRecord *) const override; std::unique_ptr branchTarget( const PCStateBase &branch_pc) const override; @@ -97,6 +97,19 @@ def template VSetiVliDeclare {{ }; }}; +def template VConfConstructor {{ +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _elen) + : %(base_class)s("%(mnemonic)s", _machInst, _elen, %(op_class)s) + { + %(set_reg_idx_arr)s; + %(constructor)s; + } +}}; + +def template VConfDecodeBlock {{ + return new %(class_name)s(machInst,elen); +}}; + def template VConfExecute {{ VTYPE %(class_name)s::getNewVtype( @@ -112,7 +125,7 @@ def template VConfExecute {{ uint32_t newVill = !(vflmul >= 0.125 && vflmul <= 8) || - sew > std::min(vflmul, 1.0f) * ELEN || + sew > std::min(vflmul, 1.0f) * elen || bits(reqVtype, 62, 8) != 0; if (newVill) { newVtype = 0; From bfb295ac3f047301d5557a75c7b93cdb7179cd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= Date: Wed, 4 Oct 2023 14:49:01 +0200 Subject: [PATCH 480/693] util: cpt_upgrader fix vregs size for #PR171 * Make cpt_upgrader set vregs of size MaxVecLenInBytes Change-Id: Ie7e00d9bf42b705a0fb30c9d203933fc2e9bdcd9 --- util/cpt_upgraders/riscv-dyn-vlen.py | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 util/cpt_upgraders/riscv-dyn-vlen.py diff --git a/util/cpt_upgraders/riscv-dyn-vlen.py b/util/cpt_upgraders/riscv-dyn-vlen.py new file mode 100644 index 0000000000..ea2de9d19d --- /dev/null +++ b/util/cpt_upgraders/riscv-dyn-vlen.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023 Barcelona Supercomputing Center (BSC) +# 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. + + +def upgrader(cpt): + """ + Update the checkpoint to support initial RVV implemtation. + The updater is taking the following steps. + + Set vector registers to occupy 327680 bytes (40regs * 8192bytes). + Vector registers now ocupy this space regardless of VLEN as the + VecRegContainer is always MaxVecLenInBytes. + """ + + for sec in cpt.sections(): + import re + + # Search for all XC sections + + if re.search(r".*processor.*\.core.*\.xc.*", sec): + # Updating RVV vector registers (dummy values) + mr = cpt.get(sec, "regs.vector").split() + if len(mr) != 327680: + cpt.set( + sec, "regs.vector", " ".join("0" for i in range(327680)) + ) From edf1d692572ba682457806c38be54dcbbe43eed7 Mon Sep 17 00:00:00 2001 From: Alvaro Moreno Date: Thu, 12 Oct 2023 20:02:41 +0200 Subject: [PATCH 481/693] arch-riscv: Define vlwhole/vswhole mem acceses using vlen. This patch fixes the size of the memory acceses in vswhole and vlwhole instructions to the maximum vector length. Change-Id: Ib86b5356d9f1dfa277cb4b367893e3b08242f93e --- src/arch/generic/memhelpers.hh | 81 +++++++++++++++++++++ src/arch/riscv/isa/templates/vector_mem.isa | 10 ++- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/src/arch/generic/memhelpers.hh b/src/arch/generic/memhelpers.hh index d5684a6af9..9cdd2a56eb 100644 --- a/src/arch/generic/memhelpers.hh +++ b/src/arch/generic/memhelpers.hh @@ -124,6 +124,24 @@ readMemAtomic(XC *xc, trace::InstRecord *traceData, Addr addr, MemT &mem, return fault; } +/// Read from memory in atomic mode. +template +Fault +readMemAtomic(XC *xc, trace::InstRecord *traceData, Addr addr, MemT &mem, + size_t size, Request::Flags flags) +{ + memset(&mem, 0, size); + static const std::vector byte_enable(size, true); + Fault fault = readMemAtomic(xc, addr, (uint8_t*)&mem, + size, flags, byte_enable); + if (fault == NoFault) { + mem = gtoh(mem, Order); + if (traceData) + traceData->setData(mem); + } + return fault; +} + template Fault readMemAtomicLE(XC *xc, trace::InstRecord *traceData, Addr addr, MemT &mem, @@ -133,6 +151,16 @@ readMemAtomicLE(XC *xc, trace::InstRecord *traceData, Addr addr, MemT &mem, xc, traceData, addr, mem, flags); } +template +Fault +readMemAtomicLE(XC *xc, trace::InstRecord *traceData, Addr addr, MemT &mem, + size_t size, Request::Flags flags) +{ + return readMemAtomic( + xc, traceData, addr, mem, size, flags); +} + + template Fault readMemAtomicBE(XC *xc, trace::InstRecord *traceData, Addr addr, MemT &mem, @@ -165,6 +193,20 @@ writeMemTiming(XC *xc, trace::InstRecord *traceData, MemT mem, Addr addr, sizeof(MemT), flags, res, byte_enable); } +template +Fault +writeMemTiming(XC *xc, trace::InstRecord *traceData, MemT mem, Addr addr, + size_t size, Request::Flags flags, uint64_t *res) +{ + if (traceData) { + traceData->setData(mem); + } + mem = htog(mem, Order); + static const std::vector byte_enable(size, true); + return writeMemTiming(xc, (uint8_t*)&mem, addr, + size, flags, res, byte_enable); +} + template Fault writeMemTimingLE(XC *xc, trace::InstRecord *traceData, MemT mem, Addr addr, @@ -174,6 +216,15 @@ writeMemTimingLE(XC *xc, trace::InstRecord *traceData, MemT mem, Addr addr, xc, traceData, mem, addr, flags, res); } +template +Fault +writeMemTimingLE(XC *xc, trace::InstRecord *traceData, MemT mem, Addr addr, + size_t size, Request::Flags flags, uint64_t *res) +{ + return writeMemTiming( + xc, traceData, mem, addr, size, flags, res); +} + template Fault writeMemTimingBE(XC *xc, trace::InstRecord *traceData, MemT mem, Addr addr, @@ -214,6 +265,27 @@ writeMemAtomic(XC *xc, trace::InstRecord *traceData, const MemT &mem, return fault; } +template +Fault +writeMemAtomic(XC *xc, trace::InstRecord *traceData, const MemT &mem, + Addr addr, size_t size, Request::Flags flags, uint64_t *res) +{ + if (traceData) { + traceData->setData(mem); + } + MemT host_mem = htog(mem, Order); + static const std::vector byte_enable(size, true); + Fault fault = writeMemAtomic(xc, (uint8_t*)&host_mem, + addr, size, flags, res, byte_enable); + if (fault == NoFault && res != NULL) { + if (flags & Request::MEM_SWAP || flags & Request::MEM_SWAP_COND) + *(MemT *)res = gtoh(*(MemT *)res, Order); + else + *res = gtoh(*res, Order); + } + return fault; +} + template Fault writeMemAtomicLE(XC *xc, trace::InstRecord *traceData, const MemT &mem, @@ -223,6 +295,15 @@ writeMemAtomicLE(XC *xc, trace::InstRecord *traceData, const MemT &mem, xc, traceData, mem, addr, flags, res); } +template +Fault +writeMemAtomicLE(XC *xc, trace::InstRecord *traceData, const MemT &mem, + size_t size, Addr addr, Request::Flags flags, uint64_t *res) +{ + return writeMemAtomic( + xc, traceData, mem, addr, size, flags, res); +} + template Fault writeMemAtomicBE(XC *xc, trace::InstRecord *traceData, const MemT &mem, diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index fc1b93548c..8cbab044ec 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -562,7 +562,7 @@ Fault } Fault fault = writeMemAtomicLE(xc, traceData, *(vreg_t::Container*)(&Mem), - EA, memAccessFlags, nullptr); + vlenb, EA, memAccessFlags, nullptr); return fault; } @@ -592,7 +592,7 @@ Fault } Fault fault = writeMemTimingLE(xc, traceData, *(vreg_t::Container*)(&Mem), - EA, memAccessFlags, nullptr); + EA, vlenb, memAccessFlags, nullptr); return fault; } @@ -689,7 +689,8 @@ Fault %(ea_code)s; Fault fault = readMemAtomicLE(xc, traceData, EA, - *(vreg_t::Container*)(&Mem), memAccessFlags); + *(vreg_t::Container*)(&Mem), vlenb, + memAccessFlags); if (fault != NoFault) return fault; @@ -722,7 +723,8 @@ Fault %(set_vlenb)s; %(ea_code)s; - Fault fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); + const std::vector byte_enable(vlenb, true); + Fault fault = initiateMemRead(xc, EA, vlenb, memAccessFlags, byte_enable); return fault; } From 34314b3f929fc0d9b199dc09b06b23b08d698d5d Mon Sep 17 00:00:00 2001 From: Melissa Jost <50555529+mkjost0@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:14:39 -0700 Subject: [PATCH 482/693] misc: Add LULESH GPU tests (#256) Adds the LULESH GPU Tests to our GitHub Actions infrastructure Co-authored-by: Bobby R. Bruce Co-authored-by: Harshil Patel --- .github/workflows/gpu-tests.yaml | 39 ++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index fe6df5eb1e..4b49b34945 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -1,7 +1,9 @@ --- -# This workflow runs all of the very-long tests within main.py +# This workflow runs all the Weekly GPU Tests. +# For now this file is kept separate as we are still developing and testing +# this workflow. It will eventually be merged with "weekly-tests.yaml" -name: Weekly Tests +name: Weekly Tests (GPU) on: # Runs every Sunday from 7AM UTC @@ -29,6 +31,39 @@ jobs: retention-days: 5 - run: echo "This job's status is ${{ job.status }}." + LULESH-tests: + runs-on: [self-hosted, linux, x64] + container: ghcr.io/gem5-test/gcn-gpu:latest + needs: build-gem5 + timeout-minutes: 480 # 8 hours + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + + - name: Download build/GCN3_X86/gem5.opt + uses: actions/download-artifact@v3 + with: + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 + path: build/GCN3_X86 + # `download-artifact` does not preserve permissions so we need to set + # them again. + - run: chmod u+x build/GCN3_X86/gem5.opt + + - name: Obtain LULESH + working-directory: ${{ github.workspace }}/lulesh + # Obtains the latest LULESH compatible with this version of gem5 via + # gem5 Resources. + run: build/GCN3_X86/gem5.opt util/obtain-resource.py lulesh -p lulesh + + - name: Run LULUESH tests + working-directory: ${{ github.workspace }} + run: | + build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --mem-size=8GB --reg-alloc-policy=dynamic --benchmark-root="lulesh" -c \ + lulesh 0.01 2 + HACC-tests: runs-on: [self-hosted, linux, x64] container: ghcr.io/gem5/gcn-gpu:latest From 531067fffa26ab6722f7de4b68a5896372b99afe Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 19 Oct 2023 15:38:38 -0700 Subject: [PATCH 483/693] mem,tests: Set Ruby Mem Test atomic percent to 0 (#489) Fixes https://github.com/gem5/gem5/issues/450 (https://github.com/gem5/gem5/pull/477 fixes non-ruby memtests, so only a partial fix). --- configs/example/ruby_mem_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/example/ruby_mem_test.py b/configs/example/ruby_mem_test.py index 27751376fc..9ad6a1b7ad 100644 --- a/configs/example/ruby_mem_test.py +++ b/configs/example/ruby_mem_test.py @@ -65,7 +65,7 @@ parser.add_argument( parser.add_argument( "--atomic", type=int, - default=30, + default=0, help="percentage of accesses that should be atomic", ) parser.add_argument( From fe20f4ada60388ceb65b1a503c132bd0e2326ec5 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Fri, 20 Oct 2023 11:10:25 +0800 Subject: [PATCH 484/693] scons: Explicit the config option HAVE_DEPRECATED_NAMESPACE type bool Currently the type of HAVE_DEPRECATED_NAMESPACE is used to detect if the compiler support gnu::deprecated feature. The return type of conf.TryCompile is int, but HAVE_DEPRECATED_NAMESPACE is used as boolean type. The CL is add bool type caster to ensure the type of it is boolean. Change-Id: Ife7d9716e485a8be8722d58776f064e7c2268a30 --- src/base/SConsopts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/base/SConsopts b/src/base/SConsopts index 8e0661203f..68e40587b9 100644 --- a/src/base/SConsopts +++ b/src/base/SConsopts @@ -69,11 +69,13 @@ werror_env.Append(CCFLAGS=['-Werror']) with gem5_scons.Configure(werror_env) as conf: # Store result in the main environment - main['CONF']['HAVE_DEPRECATED_NAMESPACE'] = conf.TryCompile(''' - int main() {return 0;} - namespace [[gnu::deprecated("Test namespace deprecation")]] - test_deprecated_namespace {} - ''', '.cc') + main['CONF']['HAVE_DEPRECATED_NAMESPACE'] = bool( + conf.TryCompile(''' + int main() {return 0;} + namespace [[gnu::deprecated("Test namespace deprecation")]] + test_deprecated_namespace {} + ''', '.cc') + ) if not main['CONF']['HAVE_DEPRECATED_NAMESPACE']: warning("Deprecated namespaces are not supported by this compiler.\n" From 1a7014c653430786e1e08861311dfbe6f25216da Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Fri, 20 Oct 2023 11:37:59 +0800 Subject: [PATCH 485/693] scons: Explicit the config option HAVE_PKG_CONFIG type boolean The scons function Detect will return the program name if the program is exists in the system. However, the HAVE_PKG_CONFIG is used to check the pkg-config program is exists and it should be the boolean type. Change-Id: I18c4813d36eea68b8851a41db41777bdb2a80b7b --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 32e0c36e09..e7fa4b53b7 100755 --- a/SConstruct +++ b/SConstruct @@ -636,7 +636,7 @@ for variant_path in variant_paths: LINKFLAGS=['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']) - env['HAVE_PKG_CONFIG'] = env.Detect('pkg-config') + env['HAVE_PKG_CONFIG'] = env.Detect('pkg-config') == 'pkg-config' with gem5_scons.Configure(env) as conf: # On Solaris you need to use libsocket for socket ops From 069baed9711a0eff27d2bc6dd7f2308ec62e2cc6 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Fri, 20 Oct 2023 11:40:24 +0800 Subject: [PATCH 486/693] scons: Explicit the config option HAVE_PROTOBUF type boolean Ensure the type of HAVE_PROTOBUF is boolean Change-Id: I9cf18c52ac290000168f5228b7f4ba3621225a85 --- src/proto/SConsopts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/proto/SConsopts b/src/proto/SConsopts index fab29bc235..6cc4a48642 100644 --- a/src/proto/SConsopts +++ b/src/proto/SConsopts @@ -57,11 +57,13 @@ with gem5_scons.Configure(main) as conf: # automatically added to the LIBS environment variable. After # this, we can use the HAVE_PROTOBUF flag to determine if we have # got both protoc and libprotobuf available. - conf.env['CONF']['HAVE_PROTOBUF'] = conf.env['HAVE_PROTOC'] and ( - (conf.env['HAVE_PKG_CONFIG'] and - conf.CheckPkgConfig('protobuf', '--cflags', '--libs')) or - conf.CheckLibWithHeader('protobuf', 'google/protobuf/message.h', - 'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;')) + conf.env['CONF']['HAVE_PROTOBUF'] = bool( + conf.env['HAVE_PROTOC'] and ( + (conf.env['HAVE_PKG_CONFIG'] and + conf.CheckPkgConfig('protobuf', '--cflags', '--libs')) or + conf.CheckLibWithHeader('protobuf', 'google/protobuf/message.h', + 'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;')) + ) # If we have the compiler but not the library, print another warning. if main['HAVE_PROTOC'] and not main['CONF']['HAVE_PROTOBUF']: From 2d85707a754122ab940cc1b7c0dd07c3c3f28df7 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 08:59:43 +0100 Subject: [PATCH 487/693] sim: Define an InstructionDisassembler SimObject We want to be able to configure from python the disassembler used by an instruction tracer. The default/base version will reuse existing instruction logic and it will simply call the StaticInst::disassemble method. Change-Id: Ieb16f059a436757c5892dcc82882f6d42090927f Signed-off-by: Giacomo Travaglini --- src/sim/InstTracer.py | 22 ++++++++++++++++++++++ src/sim/SConscript | 2 +- src/sim/insttracer.hh | 43 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/sim/InstTracer.py b/src/sim/InstTracer.py index 34c97dd43e..c8b3673d47 100644 --- a/src/sim/InstTracer.py +++ b/src/sim/InstTracer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2023 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) 2007 The Regents of The University of Michigan # All rights reserved. # @@ -28,8 +40,18 @@ from m5.SimObject import SimObject from m5.params import * +class InstDisassembler(SimObject): + type = "InstDisassembler" + cxx_header = "sim/insttracer.hh" + cxx_class = "gem5::trace::InstDisassembler" + + class InstTracer(SimObject): type = "InstTracer" cxx_header = "sim/insttracer.hh" cxx_class = "gem5::trace::InstTracer" abstract = True + + disassembler = Param.InstDisassembler( + InstDisassembler(), "Instruction Disassembler" + ) diff --git a/src/sim/SConscript b/src/sim/SConscript index e26676c00a..78b06c5b1d 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -105,7 +105,7 @@ GTest('proxy_ptr.test', 'proxy_ptr.test.cc') GTest('serialize.test', 'serialize.test.cc', with_tag('gem5 serialize')) GTest('serialize_handlers.test', 'serialize_handlers.test.cc') -SimObject('InstTracer.py', sim_objects=['InstTracer']) +SimObject('InstTracer.py', sim_objects=['InstTracer', 'InstDisassembler']) SimObject('Process.py', sim_objects=['Process', 'EmulatedDriver']) Source('faults.cc') Source('process.cc') diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh index 9c9bca7692..37e29756a2 100644 --- a/src/sim/insttracer.hh +++ b/src/sim/insttracer.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, 2020 ARM Limited + * Copyright (c) 2014, 2017, 2020, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -48,6 +48,7 @@ #include "cpu/inst_res.hh" #include "cpu/inst_seq.hh" #include "cpu/static_inst.hh" +#include "params/InstTracer.hh" #include "sim/sim_object.hh" namespace gem5 @@ -286,10 +287,37 @@ class InstRecord bool getFaulting() const { return faulting; } }; +/** + * The base InstDisassembler class provides a one-API interface + * to disassemble the instruction passed as a first argument. + * It also provides a base implementation which is + * simply calling the StaticInst::disassemble method, which + * is the usual interface for disassembling + * a gem5 instruction. + */ +class InstDisassembler : public SimObject +{ + public: + InstDisassembler(const SimObjectParams ¶ms) + : SimObject(params) + {} + + virtual std::string + disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab) const + { + return inst->disassemble(pc.instAddr(), symtab); + } +}; + class InstTracer : public SimObject { public: - InstTracer(const Params &p) : SimObject(p) {} + PARAMS(InstTracer); + InstTracer(const Params &p) + : SimObject(p), disassembler(p.disassembler) + {} virtual ~InstTracer() {} @@ -297,6 +325,17 @@ class InstTracer : public SimObject getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, const PCStateBase &pc, const StaticInstPtr macroStaticInst=nullptr) = 0; + + std::string + disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab=nullptr) const + { + return disassembler->disassemble(inst, pc, symtab); + } + + private: + InstDisassembler *disassembler; }; } // namespace trace From 952c4f5eead8af33bfbff7c63cb0ebe934ebbc5d Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 09:01:09 +0100 Subject: [PATCH 488/693] cpu: Pass a reference of the parent tracer to the ExeTracerRecord Change-Id: I3576df2b7bee1289db60bb6072bd9c90038ca8ce Signed-off-by: Giacomo Travaglini --- src/cpu/exetrace.hh | 21 +++++++++++++++++++-- src/cpu/nativetrace.cc | 23 +++++++++++++++++++++++ src/cpu/nativetrace.hh | 26 +++++++++++++++++--------- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 143cfa0eb3..3fbeb98bc3 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 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) 2001-2005 The Regents of The University of Michigan * All rights reserved. * @@ -49,14 +61,19 @@ class ExeTracerRecord : public InstRecord public: ExeTracerRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, const PCStateBase &_pc, + const ExeTracer &_tracer, const StaticInstPtr _macroStaticInst = NULL) - : InstRecord(_when, _thread, _staticInst, _pc, _macroStaticInst) + : InstRecord(_when, _thread, _staticInst, _pc, _macroStaticInst), + tracer(_tracer) { } void traceInst(const StaticInstPtr &inst, bool ran); void dump(); + + protected: + const ExeTracer &tracer; }; class ExeTracer : public InstTracer @@ -75,7 +92,7 @@ class ExeTracer : public InstTracer return NULL; return new ExeTracerRecord(when, tc, - staticInst, pc, macroStaticInst); + staticInst, pc, *this, macroStaticInst); } }; diff --git a/src/cpu/nativetrace.cc b/src/cpu/nativetrace.cc index 3070205b9f..60efc791de 100644 --- a/src/cpu/nativetrace.cc +++ b/src/cpu/nativetrace.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 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) 2006-2009 The Regents of The University of Michigan * All rights reserved. * @@ -49,6 +61,17 @@ NativeTrace::NativeTrace(const Params &p) fd = native_listener->accept(); } +NativeTraceRecord::NativeTraceRecord( + NativeTrace *_parent, + Tick _when, ThreadContext *_thread, + const StaticInstPtr _staticInst, const PCStateBase &_pc, + const StaticInstPtr _macroStaticInst) + : ExeTracerRecord(_when, _thread, _staticInst, _pc, + *_parent, _macroStaticInst), + parent(_parent) +{ +} + void NativeTraceRecord::dump() { diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh index a19acaca3f..a0866e130f 100644 --- a/src/cpu/nativetrace.hh +++ b/src/cpu/nativetrace.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 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) 2006-2009 The Regents of The University of Michigan * All rights reserved. * @@ -50,20 +62,16 @@ class NativeTrace; class NativeTraceRecord : public ExeTracerRecord { - protected: - NativeTrace * parent; - public: - NativeTraceRecord(NativeTrace * _parent, + NativeTraceRecord(NativeTrace *_parent, Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, const PCStateBase &_pc, - const StaticInstPtr _macroStaticInst=nullptr) - : ExeTracerRecord(_when, _thread, _staticInst, _pc, _macroStaticInst), - parent(_parent) - { - } + const StaticInstPtr _macroStaticInst=nullptr); void dump(); + + private: + NativeTrace *parent; }; class NativeTrace : public ExeTracer From 237bbf0e42ab3b7f43d582566e021604794e5462 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 09:05:45 +0100 Subject: [PATCH 489/693] cpu: Disassemble through the InstDisassembler in the ExeTracer Change-Id: I4a0c585b9b8824a0694066bef0ee004f68407111 Signed-off-by: Giacomo Travaglini --- src/cpu/exetrace.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 22d0d4be69..6cd5269fa7 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019 ARM Limited + * Copyright (c) 2017, 2019, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -101,7 +101,7 @@ ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran) // outs << std::setw(26) << std::left; - outs << inst->disassemble(cur_pc, &loader::debugSymbolTable); + outs << tracer.disassemble(inst, *pc, &loader::debugSymbolTable); if (ran) { outs << " : "; From 81b6e296dd79969ceed9314cf5398c55cab3ba5e Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 12:48:14 +0100 Subject: [PATCH 490/693] arch-arm: disassemble member variable not used by TarmacParser We move it to the child class which is what the TarmacTracer actually uses. Change-Id: Ia30892723d2e1f7306dae87c6c9c1d69d00ad73d Signed-off-by: Giacomo Travaglini --- src/arch/arm/tracers/tarmac_base.cc | 6 ------ src/arch/arm/tracers/tarmac_base.hh | 1 - src/arch/arm/tracers/tarmac_record.cc | 8 +++++++- src/arch/arm/tracers/tarmac_record.hh | 3 +++ 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/arch/arm/tracers/tarmac_base.cc b/src/arch/arm/tracers/tarmac_base.cc index 25524d24b6..01add3037a 100644 --- a/src/arch/arm/tracers/tarmac_base.cc +++ b/src/arch/arm/tracers/tarmac_base.cc @@ -68,7 +68,6 @@ TarmacBaseRecord::InstEntry::InstEntry( : taken(predicate) , addr(pc.instAddr()) , opcode(staticInst->getEMI() & 0xffffffff), - disassemble(staticInst->disassemble(addr)), isetstate(pcToISetState(pc)), mode(MODE_USER) { @@ -76,11 +75,6 @@ TarmacBaseRecord::InstEntry::InstEntry( // Operating mode gained by reading the architectural register (CPSR) const CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR); mode = (OperatingMode) (uint8_t)cpsr.mode; - - // In Tarmac, instruction names are printed in capital - // letters. - std::for_each(disassemble.begin(), disassemble.end(), - [](char& c) { c = toupper(c); }); } TarmacBaseRecord::RegEntry::RegEntry(const PCStateBase &pc) diff --git a/src/arch/arm/tracers/tarmac_base.hh b/src/arch/arm/tracers/tarmac_base.hh index 501eb1b008..9e80f6d1f1 100644 --- a/src/arch/arm/tracers/tarmac_base.hh +++ b/src/arch/arm/tracers/tarmac_base.hh @@ -93,7 +93,6 @@ class TarmacBaseRecord : public InstRecord bool taken; Addr addr; ArmISA::MachInst opcode; - std::string disassemble; ISetState isetstate; ArmISA::OperatingMode mode; }; diff --git a/src/arch/arm/tracers/tarmac_record.cc b/src/arch/arm/tracers/tarmac_record.cc index 59d6a18b39..23e751112d 100644 --- a/src/arch/arm/tracers/tarmac_record.cc +++ b/src/arch/arm/tracers/tarmac_record.cc @@ -123,7 +123,8 @@ TarmacTracerRecord::TarmacTracerRecord(Tick _when, ThreadContext *_thread, TarmacTracerRecord::TraceInstEntry::TraceInstEntry( const TarmacContext& tarmCtx, bool predicate) - : InstEntry(tarmCtx.thread, *tarmCtx.pc, tarmCtx.staticInst, predicate) + : InstEntry(tarmCtx.thread, *tarmCtx.pc, tarmCtx.staticInst, predicate), + disassemble(tarmCtx.staticInst->disassemble(addr)) { secureMode = isSecure(tarmCtx.thread); @@ -140,6 +141,11 @@ TarmacTracerRecord::TraceInstEntry::TraceInstEntry( // for 16bit (Thumb) instruction. opcode = arm_inst->encoding(); + // In Tarmac, instruction names are printed in capital + // letters. + std::for_each(disassemble.begin(), disassemble.end(), + [](char& c) { c = toupper(c); }); + // Update the instruction count: number of executed // instructions. instCount++; diff --git a/src/arch/arm/tracers/tarmac_record.hh b/src/arch/arm/tracers/tarmac_record.hh index 009df5db29..d80121b1b9 100644 --- a/src/arch/arm/tracers/tarmac_record.hh +++ b/src/arch/arm/tracers/tarmac_record.hh @@ -115,6 +115,9 @@ class TarmacTracerRecord : public TarmacBaseRecord * 32 otherwise (ARM and BigThumb) */ uint8_t instSize; + + /** Instruction disassembly */ + std::string disassemble; }; /** Register Entry */ From 27ce721ad32aff21ce4c494cac4114c5eaf27f19 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 12:56:22 +0100 Subject: [PATCH 491/693] arch-arm: Pass a reference of the parent tracer to TarmacContext Change-Id: I7ab0442353a8b5854bb6b50bd54dac89f83ecc1d Signed-off-by: Giacomo Travaglini --- src/arch/arm/tracers/tarmac_record.cc | 1 + src/arch/arm/tracers/tarmac_tracer.hh | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/tracers/tarmac_record.cc b/src/arch/arm/tracers/tarmac_record.cc index 23e751112d..53a9d4c459 100644 --- a/src/arch/arm/tracers/tarmac_record.cc +++ b/src/arch/arm/tracers/tarmac_record.cc @@ -338,6 +338,7 @@ TarmacTracerRecord::dump() auto ®Queue = tracer.regQueue; const TarmacContext tarmCtx( + tracer, thread, staticInst->isMicroop()? macroStaticInst : staticInst, *pc diff --git a/src/arch/arm/tracers/tarmac_tracer.hh b/src/arch/arm/tracers/tarmac_tracer.hh index f8c7b5ca53..71207b3860 100644 --- a/src/arch/arm/tracers/tarmac_tracer.hh +++ b/src/arch/arm/tracers/tarmac_tracer.hh @@ -58,6 +58,8 @@ class OutputStream; namespace trace { +class TarmacTracer; + /** * This object type is encapsulating the informations needed by * a Tarmac record to generate it's own entries. @@ -65,15 +67,18 @@ namespace trace { class TarmacContext { public: - TarmacContext(ThreadContext* _thread, + TarmacContext(const TarmacTracer &_tracer, + ThreadContext* _thread, const StaticInstPtr _staticInst, const PCStateBase &_pc) - : thread(_thread), staticInst(_staticInst), pc(_pc.clone()) + : tracer(_tracer), thread(_thread), staticInst(_staticInst), + pc(_pc.clone()) {} std::string tarmacCpuName() const; public: + const TarmacTracer &tracer; ThreadContext* thread; const StaticInstPtr staticInst; std::unique_ptr pc; From 34336208b7f2ee917a55d8e43cefd30c1c0929c3 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 22 Sep 2023 13:05:10 +0100 Subject: [PATCH 492/693] arch-arm: Disassemble through InstDisassembler in TarmacTracer Change-Id: I5407338501084c016522749be697dd688ca51735 Signed-off-by: Giacomo Travaglini --- src/arch/arm/tracers/tarmac_record.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/arm/tracers/tarmac_record.cc b/src/arch/arm/tracers/tarmac_record.cc index 53a9d4c459..5aa1f7e957 100644 --- a/src/arch/arm/tracers/tarmac_record.cc +++ b/src/arch/arm/tracers/tarmac_record.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited + * Copyright (c) 2017-2019, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -124,7 +124,7 @@ TarmacTracerRecord::TraceInstEntry::TraceInstEntry( const TarmacContext& tarmCtx, bool predicate) : InstEntry(tarmCtx.thread, *tarmCtx.pc, tarmCtx.staticInst, predicate), - disassemble(tarmCtx.staticInst->disassemble(addr)) + disassemble(tarmCtx.tracer.disassemble(tarmCtx.staticInst, *tarmCtx.pc)) { secureMode = isSecure(tarmCtx.thread); From 82675648c874d6f9d00b3cb46c896dda618c4961 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 9 Oct 2023 18:23:40 +0100 Subject: [PATCH 493/693] cpu: Implement a CapstoneDisassembler Capstone is an open source disassembler [1] already used by other projects (like QEMU). gem5 is already capable of disassembling instructions. Every StaticInst is supposed to define a generateDisassembly method which returns the instruction mnemonic (opcode + operand list) as a string. This "distributed" implementation of a disassembler relies on the developer to properly populate the metadata fields of the base instruction class. The growing complexity of the ISA code and the massive reuse of base classes beyond their intended use has led to a disassembling logic which contains several bugs. By allowing a tracer to rely on a third party disassembler, we fill the intruction trace with a more trustworthy instruction stream. This will make any trace parsing tool to work better and it will also allow us to spot/fix our own bugs by comparing instruction traces with native vs custom disassembler [1]: http://www.capstone-engine.org/ Change-Id: I3c4db5072c03d2731265d0398d3863c101dcb180 Signed-off-by: Giacomo Travaglini --- src/cpu/Capstone.py | 45 +++++++++++++++++++ src/cpu/SConscript | 5 ++- src/cpu/SConsopts | 50 ++++++++++++++++++++++ src/cpu/capstone.cc | 90 ++++++++++++++++++++++++++++++++++++++ src/cpu/capstone.hh | 102 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 src/cpu/Capstone.py create mode 100644 src/cpu/SConsopts create mode 100644 src/cpu/capstone.cc create mode 100644 src/cpu/capstone.hh diff --git a/src/cpu/Capstone.py b/src/cpu/Capstone.py new file mode 100644 index 0000000000..4b6b5fd84a --- /dev/null +++ b/src/cpu/Capstone.py @@ -0,0 +1,45 @@ +# Copyright (c) 2023 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. +# +# 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.SimObject import SimObject +from m5.params import * +from m5.objects.InstTracer import InstDisassembler + + +class CapstoneDisassembler(InstDisassembler): + type = "CapstoneDisassembler" + cxx_class = "gem5::trace::CapstoneDisassembler" + cxx_header = "cpu/capstone.hh" + abstract = True diff --git a/src/cpu/SConscript b/src/cpu/SConscript index d6dcd2f6ea..03ba7b924d 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2020 ARM Limited +# Copyright (c) 2020, 2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -115,6 +115,9 @@ Source('simple_thread.cc') Source('thread_context.cc') Source('thread_state.cc') Source('timing_expr.cc') +SourceLib('capstone', tags='capstone') +Source('capstone.cc', tags='capstone') +SimObject('Capstone.py', sim_objects=['CapstoneDisassembler'], tags='capstone') SimObject('DummyChecker.py', sim_objects=['DummyChecker']) Source('checker/cpu.cc') diff --git a/src/cpu/SConsopts b/src/cpu/SConsopts new file mode 100644 index 0000000000..94e55ece32 --- /dev/null +++ b/src/cpu/SConsopts @@ -0,0 +1,50 @@ +# Copyright (c) 2023 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. +# +# 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. + +Import('*') + +from gem5_scons import warning + +import gem5_scons + +with gem5_scons.Configure(main) as conf: + # Check for + conf.env['CONF']['HAVE_CAPSTONE'] = conf.CheckHeader('capstone/capstone.h', '<>') + + if conf.env['CONF']['HAVE_CAPSTONE']: + conf.env.TagImplies('capstone', 'gem5 lib') + else: + warning("Header file not found.\n" + "This host has no capstone library installed.") diff --git a/src/cpu/capstone.cc b/src/cpu/capstone.cc new file mode 100644 index 0000000000..4c2896312d --- /dev/null +++ b/src/cpu/capstone.cc @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + +#include "cpu/capstone.hh" + +#include "base/output.hh" + +namespace gem5 +{ + +namespace trace +{ + +std::string +CapstoneDisassembler::disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab) const +{ + std::string inst_dist; + if (inst->isPseudo() || inst->isMicroop()) { + // Capstone doesn't have any visibility over microops nor over + // gem5 pseudo ops. Use native disassembler instead + inst_dist = InstDisassembler::disassemble(inst, pc, symtab); + } else { + // Stripping the extended fields from the ExtMachInst + auto mach_inst = inst->getEMI() & mask(inst->size() * 8); + + cs_insn *insn; + // capstone disassembler + if (const csh *curr_handle = currHandle(pc); curr_handle != nullptr) { + size_t count = cs_disasm(*curr_handle, (uint8_t*)&mach_inst, + inst->size(), 0, 0, &insn); + + // As we are passing only one instruction, we are expecting one instruction only + // being disassembled + assert(count <= 1); + + for (int idx = 0; idx < count; idx++) { + inst_dist += csprintf(" %s %s", insn[idx].mnemonic, insn[idx].op_str); + } + } else { + // No valid handle; return an invalid string + inst_dist += " capstone failure"; + } + } + + return inst_dist; +} + +CapstoneDisassembler::CapstoneDisassembler(const Params &p) + : InstDisassembler(p) +{ +} + +} // namespace trace +} // namespace gem5 diff --git a/src/cpu/capstone.hh b/src/cpu/capstone.hh new file mode 100644 index 0000000000..1a197e5086 --- /dev/null +++ b/src/cpu/capstone.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + +#ifndef __CPU_CAPSTONE_HH__ +#define __CPU_CAPSTONE_HH__ + +#include + +#include "params/CapstoneDisassembler.hh" +#include "sim/insttracer.hh" + +namespace gem5 +{ + +class ThreadContext; + +namespace trace { + +/** + * Capstone Disassembler: + * The disassembler relies on the capstone library to convert + * the StaticInst encoding into the disassembled string. + * + * One thing to keep in mind is that the disassembled + * instruction might not coincide with the instruction being + * decoded + executed in gem5. This could be the case if + * there was a bug in either gem5 or in capstone itself. + * This scenatio is not possible with the native gem5 disassembler + * as the instruction mnemonic is tightly coupled with the + * decoded(=generated) instruction (you print what you decode) + * + * The Capstone dispatches to the native disassembler in + * two cases: + * + * a) m5 pseudo ops + * b) micro-ops + */ +class CapstoneDisassembler : public InstDisassembler +{ + public: + PARAMS(CapstoneDisassembler); + CapstoneDisassembler(const Params &p); + + std::string + disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab) const override; + + protected: + + /** + * Return a pointer to the current capstone handle (csh). + * + * Any ISA extension of the Capstone disassembler should + * initialize (with cs_open) one or more capstone handles + * at construcion time. + * (You might need more than one handle in case the ISA + * has more than one mode of operation, e.g. arm and arm64) + * The current handle in use should be returned every time + * the currHandle is called. + */ + virtual const csh* currHandle(const PCStateBase &pc) const = 0; +}; + +} // namespace trace +} // namespace gem5 + +#endif // __CPU_CAPSTONE_HH__ From 8233aa8a9b7cf0b2028d67f9689fa6e05d2a9e13 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 21 Sep 2023 15:01:42 +0100 Subject: [PATCH 494/693] arch-arm: Implement a CapstoneDisassembler for Arm Change-Id: Id3135bda065efa9b4f3ab36972957fd00c05a53c Signed-off-by: Giacomo Travaglini --- src/arch/arm/tracers/ArmCapstone.py | 44 +++++++++++++++++ src/arch/arm/tracers/SConscript | 7 ++- src/arch/arm/tracers/capstone.cc | 75 +++++++++++++++++++++++++++++ src/arch/arm/tracers/capstone.hh | 69 ++++++++++++++++++++++++++ 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 src/arch/arm/tracers/ArmCapstone.py create mode 100644 src/arch/arm/tracers/capstone.cc create mode 100644 src/arch/arm/tracers/capstone.hh diff --git a/src/arch/arm/tracers/ArmCapstone.py b/src/arch/arm/tracers/ArmCapstone.py new file mode 100644 index 0000000000..7f1b6a9e8a --- /dev/null +++ b/src/arch/arm/tracers/ArmCapstone.py @@ -0,0 +1,44 @@ +# Copyright (c) 2023 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. +# +# 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.SimObject import SimObject +from m5.params import * +from m5.objects.Capstone import CapstoneDisassembler + + +class ArmCapstoneDisassembler(CapstoneDisassembler): + type = "ArmCapstoneDisassembler" + cxx_class = "gem5::trace::ArmCapstoneDisassembler" + cxx_header = "arch/arm/tracers/capstone.hh" diff --git a/src/arch/arm/tracers/SConscript b/src/arch/arm/tracers/SConscript index 15945a4ac4..ca012c5c2e 100644 --- a/src/arch/arm/tracers/SConscript +++ b/src/arch/arm/tracers/SConscript @@ -1,4 +1,4 @@ -# Copyright (c) 2018 ARM Limited +# Copyright (c) 2018, 2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -42,3 +42,8 @@ Source('tarmac_parser.cc', tags='arm isa') Source('tarmac_tracer.cc', tags='arm isa') Source('tarmac_record.cc', tags='arm isa') Source('tarmac_record_v8.cc', tags='arm isa') + +if env['CONF']['HAVE_CAPSTONE']: + SimObject('ArmCapstone.py', sim_objects=['ArmCapstoneDisassembler'], + tags=['capstone', 'arm isa']) + Source('capstone.cc', tags=['capstone', 'arm isa']) diff --git a/src/arch/arm/tracers/capstone.cc b/src/arch/arm/tracers/capstone.cc new file mode 100644 index 0000000000..469dc46568 --- /dev/null +++ b/src/arch/arm/tracers/capstone.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + +#include "arch/arm/tracers/capstone.hh" + +#include "arch/arm/insts/static_inst.hh" +#include "base/output.hh" + +namespace gem5 +{ + +namespace trace +{ + +using namespace ArmISA; + +ArmCapstoneDisassembler::ArmCapstoneDisassembler(const Params &p) + : CapstoneDisassembler(p) +{ + if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &arm64Handle) != CS_ERR_OK) + panic("Unable to open capstone for arm64 disassembly"); + + if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &armHandle) != CS_ERR_OK) + panic("Unable to open capstone for arm disassembly"); +} + +const csh* +ArmCapstoneDisassembler::currHandle(const PCStateBase &_pc) const +{ + auto pc = _pc.as(); + if (pc.aarch64()) { + return &arm64Handle; + } else { + auto mode = pc.thumb() ? CS_MODE_THUMB : CS_MODE_ARM; + cs_option(armHandle, CS_OPT_MODE, mode); + return &armHandle; + } +} + +} // namespace trace +} // namespace gem5 diff --git a/src/arch/arm/tracers/capstone.hh b/src/arch/arm/tracers/capstone.hh new file mode 100644 index 0000000000..929fbad6f5 --- /dev/null +++ b/src/arch/arm/tracers/capstone.hh @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + +#ifndef __ARCH_ARM_TRACERS_CAPSTONE_HH__ +#define __ARCH_ARM_TRACERS_CAPSTONE_HH__ + +#include "cpu/capstone.hh" +#include "params/ArmCapstoneDisassembler.hh" + +namespace gem5 +{ + +class ThreadContext; + +namespace trace +{ + +class ArmCapstoneDisassembler : public CapstoneDisassembler +{ + public: + PARAMS(ArmCapstoneDisassembler); + ArmCapstoneDisassembler(const Params &p); + + protected: + const csh* currHandle(const PCStateBase &pc) const override; + + protected: + csh arm64Handle; + csh armHandle; +}; + +} // namespace trace +} // namespace gem5 + +#endif // __ARCH_ARM_TRACERS_CAPSTONE_HH__ From cb56c67a8bc87b0fbc347662443b8b140b296184 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 20 Oct 2023 09:39:12 -0700 Subject: [PATCH 495/693] misc: Fix weekly-tests.yaml container uris (#488) --- .github/workflows/gpu-tests.yaml | 2 +- .github/workflows/weekly-tests.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index 4b49b34945..836bace7d7 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -33,7 +33,7 @@ jobs: LULESH-tests: runs-on: [self-hosted, linux, x64] - container: ghcr.io/gem5-test/gcn-gpu:latest + container: ghcr.io/gem5/gcn-gpu:latest needs: build-gem5 timeout-minutes: 480 # 8 hours steps: diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 17f111fc42..8e00df5e75 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -13,7 +13,7 @@ on: jobs: build-gem5: runs-on: [self-hosted, linux, x64] - container: ghcr.io/gem5-test/ubuntu-22.04_all-dependencies:latest + container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest outputs: build-name: ${{ steps.artifact-name.outputs.name }} steps: From 6ddf8c94ee1368f8a573fc7f782dcf6a8534293b Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 20 Oct 2023 19:30:19 +0100 Subject: [PATCH 496/693] arch-arm: Fix KVM Failed to set register (0x603000000013808c) (#486) Some debug registers were incorrectly tagged (e.g. as being writeable). This was causing a bug in some gem5-KVM runs where gem5 was trying to initialize the state of those registers (OSLSR_EL1) [1] but KVM was returning an error (as the registers were RO). [1]: https://github.com/gem5/gem5/blob/stable/\ src/arch/arm/kvm/armv8_cpu.cc#L408 --- src/arch/arm/regs/misc.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index f00fc09f2d..e768edeee3 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -3916,18 +3916,18 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_MDCCINT_EL1) .fault(EL1, faultMdccsrEL1) .fault(EL2, faultMdccsrEL2) - .allPrivileges(); + .allPrivileges().exceptUserMode(); InitReg(MISCREG_OSDTRRX_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGDTRRXext); InitReg(MISCREG_MDSCR_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGDSCRext); InitReg(MISCREG_OSDTRTX_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGDTRTXext); InitReg(MISCREG_OSECCR_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGOSECCR); InitReg(MISCREG_DBGBVR0_EL1) .allPrivileges().exceptUserMode() @@ -4266,28 +4266,28 @@ ISA::initializeMiscRegMetadata() .fault(EL2, faultDebugEL2) .mapsTo(MISCREG_DBGVCR); InitReg(MISCREG_MDRAR_EL1) - .allPrivileges().monSecureWrite(0).monNonSecureWrite(0) + .allPrivileges().exceptUserMode().writes(0) .mapsTo(MISCREG_DBGDRAR); InitReg(MISCREG_OSLAR_EL1) - .allPrivileges().monSecureRead(0).monNonSecureRead(0) + .allPrivileges().exceptUserMode().reads(0) .mapsTo(MISCREG_DBGOSLAR); InitReg(MISCREG_OSLSR_EL1) - .allPrivileges().monSecureWrite(0).monNonSecureWrite(0) + .allPrivileges().exceptUserMode().writes(0) .mapsTo(MISCREG_DBGOSLSR); InitReg(MISCREG_OSDLR_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGOSDLR); InitReg(MISCREG_DBGPRCR_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGPRCR); InitReg(MISCREG_DBGCLAIMSET_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGCLAIMSET); InitReg(MISCREG_DBGCLAIMCLR_EL1) - .allPrivileges() + .allPrivileges().exceptUserMode() .mapsTo(MISCREG_DBGCLAIMCLR); InitReg(MISCREG_DBGAUTHSTATUS_EL1) - .allPrivileges().monSecureWrite(0).monNonSecureWrite(0) + .allPrivileges().exceptUserMode().writes(0) .mapsTo(MISCREG_DBGAUTHSTATUS); InitReg(MISCREG_TEECR32_EL1); InitReg(MISCREG_TEEHBR32_EL1); From ccbb85c67fbf5ace280763b4e668b098a0ee9b3a Mon Sep 17 00:00:00 2001 From: David Schall Date: Tue, 17 Oct 2023 15:16:54 +0000 Subject: [PATCH 497/693] cpu: Branch Predictor Refactoring Major refactoring of the branch predictor unit. - Clearer control flow of the main branch predictor - Remove `uncondBranch` and `btbUpdate` functions in favour of a common `historyUpdate` function. There is now only one lookup function for conditional branches and the new `historyUpdate` for speculative history update. - Added a new *target provider* class. - More expressive statistics depending on the different branch types. - Cleanup the branch history management Change-Id: I21fa555b5663e4abad7c836fc1d41a9c8b205263 Signed-off-by: David Schall --- src/cpu/pred/2bit_local.cc | 26 +- src/cpu/pred/2bit_local.hh | 35 +- src/cpu/pred/BranchPredictor.py | 9 + src/cpu/pred/SConscript | 2 +- src/cpu/pred/bi_mode.cc | 53 +- src/cpu/pred/bi_mode.hh | 26 +- src/cpu/pred/bpred_unit.cc | 691 +++++++++++------- src/cpu/pred/bpred_unit.hh | 316 +++++--- src/cpu/pred/loop_predictor.cc | 25 +- src/cpu/pred/loop_predictor.hh | 13 +- src/cpu/pred/ltage.cc | 33 +- src/cpu/pred/ltage.hh | 21 +- src/cpu/pred/multiperspective_perceptron.cc | 43 +- src/cpu/pred/multiperspective_perceptron.hh | 28 +- .../pred/multiperspective_perceptron_tage.cc | 67 +- .../pred/multiperspective_perceptron_tage.hh | 26 +- src/cpu/pred/tage.cc | 64 +- src/cpu/pred/tage.hh | 26 +- src/cpu/pred/tage_sc_l.cc | 47 +- src/cpu/pred/tage_sc_l.hh | 21 +- src/cpu/pred/tournament.cc | 111 ++- src/cpu/pred/tournament.hh | 76 +- 22 files changed, 1079 insertions(+), 680 deletions(-) diff --git a/src/cpu/pred/2bit_local.cc b/src/cpu/pred/2bit_local.cc index c9aa714ed1..00baf92882 100644 --- a/src/cpu/pred/2bit_local.cc +++ b/src/cpu/pred/2bit_local.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2004-2006 The Regents of The University of Michigan * All rights reserved. * @@ -67,10 +79,10 @@ LocalBP::LocalBP(const LocalBPParams ¶ms) } void -LocalBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history) +LocalBP::updateHistories(ThreadID tid, Addr pc, bool uncond, + bool taken, Addr target, void * &bp_history) { -// Place holder for a function that is called to update predictor history when -// a BTB entry is invalid or not found. +// Place holder for a function that is called to update predictor history } @@ -94,8 +106,8 @@ LocalBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) } void -LocalBP::update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget) +LocalBP::update(ThreadID tid, Addr branch_addr, bool taken, void *&bp_history, + bool squashed, const StaticInstPtr & inst, Addr target) { assert(bp_history == NULL); unsigned local_predictor_idx; @@ -135,10 +147,6 @@ LocalBP::getLocalIndex(Addr &branch_addr) return (branch_addr >> instShiftAmt) & indexMask; } -void -LocalBP::uncondBranch(ThreadID tid, Addr pc, void *&bp_history) -{ -} } // namespace branch_prediction } // namespace gem5 diff --git a/src/cpu/pred/2bit_local.hh b/src/cpu/pred/2bit_local.hh index 55f45ca55c..9bdb1131fd 100644 --- a/src/cpu/pred/2bit_local.hh +++ b/src/cpu/pred/2bit_local.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011, 2014 ARM Limited + * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -69,35 +70,17 @@ class LocalBP : public BPredUnit */ LocalBP(const LocalBPParams ¶ms); - virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); + // Overriding interface functions + bool lookup(ThreadID tid, Addr pc, void * &bp_history) override; - /** - * Looks up the given address in the branch predictor and returns - * a true/false value as to whether it is taken. - * @param branch_addr The address of the branch to look up. - * @param bp_history Pointer to any bp history state. - * @return Whether or not the branch is taken. - */ - bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history); + void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, + Addr target, void * &bp_history) override; - /** - * Updates the branch predictor to Not Taken if a BTB entry is - * invalid or not found. - * @param branch_addr The address of the branch to look up. - * @param bp_history Pointer to any bp history state. - * @return Whether or not the branch is taken. - */ - void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history); + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; - /** - * Updates the branch predictor with the actual result of a branch. - * @param branch_addr The address of the branch to update. - * @param taken Whether or not the branch was taken. - */ - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget); - - void squash(ThreadID tid, void *bp_history) + void squash(ThreadID tid, void * &bp_history) override { assert(bp_history == NULL); } private: diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index 5ae4ee8963..8589fe5d51 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -57,6 +57,15 @@ class BranchType(Enum): ] +class TargetProvider(Enum): + vals = [ + "NoTarget", + "BTB", + "RAS", + "Indirect", + ] + + class ReturnAddrStack(SimObject): type = "ReturnAddrStack" cxx_class = "gem5::branch_prediction::ReturnAddrStack" diff --git a/src/cpu/pred/SConscript b/src/cpu/pred/SConscript index c6c2a94cc8..ec3102cada 100644 --- a/src/cpu/pred/SConscript +++ b/src/cpu/pred/SConscript @@ -59,7 +59,7 @@ SimObject('BranchPredictor.py', 'MultiperspectivePerceptronTAGE64KB', 'MPP_TAGE_8KB', 'MPP_LoopPredictor_8KB', 'MPP_StatisticalCorrector_8KB', 'MultiperspectivePerceptronTAGE8KB'], - enums=['BranchType']) + enums=['BranchType', 'TargetProvider']) Source('bpred_unit.cc') Source('2bit_local.cc') diff --git a/src/cpu/pred/bi_mode.cc b/src/cpu/pred/bi_mode.cc index 40dcbad7db..e55237f6d8 100644 --- a/src/cpu/pred/bi_mode.cc +++ b/src/cpu/pred/bi_mode.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The Regents of The University of Michigan * All rights reserved. * @@ -73,7 +85,7 @@ BiModeBP::BiModeBP(const BiModeBPParams ¶ms) * chooses the taken array and the taken array predicts taken. */ void -BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory) +BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history) { BPHistory *history = new BPHistory; history->globalHistoryReg = globalHistoryReg[tid]; @@ -81,17 +93,29 @@ BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory) history->takenPred = true; history->notTakenPred = true; history->finalPred = true; - bpHistory = static_cast(history); - updateGlobalHistReg(tid, true); + bp_history = static_cast(history); } void -BiModeBP::squash(ThreadID tid, void *bpHistory) +BiModeBP::updateHistories(ThreadID tid, Addr pc, bool uncond, + bool taken, Addr target, void * &bp_history) { - BPHistory *history = static_cast(bpHistory); + assert(uncond || bp_history); + if (uncond) { + uncondBranch(tid, pc, bp_history); + } + updateGlobalHistReg(tid, taken); +} + + +void +BiModeBP::squash(ThreadID tid, void * &bp_history) +{ + BPHistory *history = static_cast(bp_history); globalHistoryReg[tid] = history->globalHistoryReg; delete history; + bp_history = nullptr; } /* @@ -104,7 +128,7 @@ BiModeBP::squash(ThreadID tid, void *bpHistory) * direction predictors for the final branch prediction. */ bool -BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory) +BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bp_history) { unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt) & choiceHistoryMask); @@ -136,17 +160,11 @@ BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory) } history->finalPred = finalPrediction; - bpHistory = static_cast(history); - updateGlobalHistReg(tid, finalPrediction); + bp_history = static_cast(history); return finalPrediction; } -void -BiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory) -{ - globalHistoryReg[tid] &= (historyRegisterMask & ~1ULL); -} /* Only the selected direction predictor will be updated with the final * outcome; the status of the unselected one will not be altered. The choice @@ -155,12 +173,12 @@ BiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory) * the direction predictors makes a correct final prediction. */ void -BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory, - bool squashed, const StaticInstPtr & inst, Addr corrTarget) +BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken,void * &bp_history, + bool squashed, const StaticInstPtr & inst, Addr target) { - assert(bpHistory); + assert(bp_history); - BPHistory *history = static_cast(bpHistory); + BPHistory *history = static_cast(bp_history); // We do not update the counters speculatively on a squash. // We just restore the global history register. @@ -222,6 +240,7 @@ BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory, } delete history; + bp_history = nullptr; } void diff --git a/src/cpu/pred/bi_mode.hh b/src/cpu/pred/bi_mode.hh index 721d21b79a..46c3cc2b69 100644 --- a/src/cpu/pred/bi_mode.hh +++ b/src/cpu/pred/bi_mode.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The Regents of The University of Michigan * All rights reserved. * @@ -61,15 +73,17 @@ class BiModeBP : public BPredUnit { public: BiModeBP(const BiModeBPParams ¶ms); - void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); - void squash(ThreadID tid, void *bp_history); - bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history); - void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history); - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget); + bool lookup(ThreadID tid, Addr pc, void * &bp_history) override; + void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, + Addr target, void * &bp_history) override; + void squash(ThreadID tid, void * &bp_history) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; private: void updateGlobalHistReg(ThreadID tid, bool taken); + void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); struct BPHistory { diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index a338cbdafd..f705b93b71 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -58,45 +58,15 @@ namespace branch_prediction BPredUnit::BPredUnit(const Params ¶ms) : SimObject(params), numThreads(params.numThreads), + instShiftAmt(params.instShiftAmt), predHist(numThreads), btb(params.btb), ras(params.ras), iPred(params.indirectBranchPred), - stats(this), - instShiftAmt(params.instShiftAmt) + stats(this) { } -BPredUnit::BPredUnitStats::BPredUnitStats(statistics::Group *parent) - : statistics::Group(parent), - ADD_STAT(lookups, statistics::units::Count::get(), - "Number of BP lookups"), - ADD_STAT(condPredicted, statistics::units::Count::get(), - "Number of conditional branches predicted"), - ADD_STAT(condIncorrect, statistics::units::Count::get(), - "Number of conditional branches incorrect"), - ADD_STAT(BTBLookups, statistics::units::Count::get(), - "Number of BTB lookups"), - ADD_STAT(BTBUpdates, statistics::units::Count::get(), - "Number of BTB updates"), - ADD_STAT(BTBHits, statistics::units::Count::get(), "Number of BTB hits"), - ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(), "BTB Hit Ratio", - BTBHits / BTBLookups), - ADD_STAT(RASUsed, statistics::units::Count::get(), - "Number of times the RAS was used to get a target."), - ADD_STAT(RASIncorrect, statistics::units::Count::get(), - "Number of incorrect RAS predictions."), - ADD_STAT(indirectLookups, statistics::units::Count::get(), - "Number of indirect predictor lookups."), - ADD_STAT(indirectHits, statistics::units::Count::get(), - "Number of indirect target hits."), - ADD_STAT(indirectMisses, statistics::units::Count::get(), - "Number of indirect misses."), - ADD_STAT(indirectMispredicted, statistics::units::Count::get(), - "Number of mispredicted indirect branches.") -{ - BTBHitRatio.precision(6); -} probing::PMUUPtr BPredUnit::pmuProbePoint(const char *name) @@ -123,246 +93,350 @@ BPredUnit::drainSanityCheck() const assert(ph.empty()); } + bool BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, PCStateBase &pc, ThreadID tid) { + /** Perform the prediction. */ + PredictorHistory* bpu_history = nullptr; + bool taken = predict(inst, seqNum, pc, tid, bpu_history); + + assert(bpu_history!=nullptr); + + /** Push the record into the history buffer */ + predHist[tid].push_front(bpu_history); + + DPRINTF(Branch, "[tid:%i] [sn:%llu] History entry added. " + "predHist.size(): %i\n", tid, seqNum, predHist[tid].size()); + + return taken; +} + + + + +bool +BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, + PCStateBase &pc, ThreadID tid, PredictorHistory* &hist) +{ + assert(hist == nullptr); + + // See if branch predictor predicts taken. // If so, get its target addr either from the BTB or the RAS. - // Save off record of branch stuff so the RAS can be fixed - // up once it's done. + // Save off branch stuff into `hist` so we can correct the predictor + // if prediction was wrong. - bool pred_taken = false; - std::unique_ptr target(pc.clone()); + BranchType brType = getBranchType(inst); + hist = new PredictorHistory(tid, seqNum, pc.instAddr(), inst); - ++stats.lookups; + stats.lookups[tid][brType]++; ppBranches->notify(1); - void *bp_history = NULL; - void *indirect_history = NULL; + + /* ----------------------------------------------- + * Get branch direction + * ----------------------------------------------- + * Lookup the direction predictor for every + * conditional branch. For unconditional branches + * the direction is always taken + */ if (inst->isUncondCtrl()) { - DPRINTF(Branch, "[tid:%i] [sn:%llu] Unconditional control\n", - tid,seqNum); - pred_taken = true; - // Tell the BP there was an unconditional branch. - uncondBranch(tid, pc.instAddr(), bp_history); + // Unconditional branches ----- + hist->condPred = true; } else { + // Conditional branches ------- ++stats.condPredicted; - pred_taken = lookup(tid, pc.instAddr(), bp_history); + hist->condPred = lookup(tid, pc.instAddr(), hist->bpHistory); - DPRINTF(Branch, "[tid:%i] [sn:%llu] " - "Branch predictor predicted %i for PC %s\n", - tid, seqNum, pred_taken, pc); + if (hist->condPred) { + ++stats.condPredictedTaken; + } } - + hist->predTaken = hist->condPred; DPRINTF(Branch, - "[tid:%i] [sn:%llu] Creating prediction history for PC %s\n", - tid, seqNum, pc); + "[tid:%i, sn:%llu] Branch predictor predicted %i for PC:%#x %s\n", + tid, seqNum, hist->condPred, hist->pc, toString(brType)); - PredictorHistory predict_record(seqNum, pc.instAddr(), pred_taken, - bp_history, indirect_history, tid, inst); - // Now lookup in the BTB or RAS. - if (pred_taken) { - // Note: The RAS may be both popped and pushed to - // support coroutines. - if (inst->isReturn()) { - ++stats.RASUsed; - // If it's a return from a function call, then look up the - // RETURN address in the RAS. - const PCStateBase *return_addr = ras->pop(tid, - predict_record.rasHistory); - if (return_addr) - set(target, return_addr); + // The direction is done now get the target address + // from BTB, RAS or indirect predictor. + hist->targetProvider = TargetProvider::NoTarget; - DPRINTF(Branch, "[tid:%i] [sn:%llu] Instruction %s is a return, " - "RAS predicted target: %s, RAS index: %i\n", - tid, seqNum, pc, *target, predict_record.RASIndex); + /* ----------------------------------------------- + * Branch Target Buffer (BTB) + * ----------------------------------------------- + * The BTB will be checked for all branches. + */ + stats.BTBLookups++; + const PCStateBase * btb_target = btb->lookup(tid, pc.instAddr(), brType); + if (btb_target) { + stats.BTBHits++; + hist->btbHit = true; + + if (hist->predTaken) { + hist->targetProvider = TargetProvider::BTB; + set(hist->target, btb_target); } + } + DPRINTF(Branch, "[tid:%i, sn:%llu] PC:%#x BTB:%s\n", + tid, seqNum, hist->pc, (hist->btbHit) ? "hit" : "miss"); + + + /* ----------------------------------------------- + * Return Address Stack (RAS) + * ----------------------------------------------- + * Perform RAS operations for calls and returns. + * Calls: push their RETURN address onto + * the RAS. + * Return: pop the the return address from the + * top of the RAS. + */ + if (ras) { if (inst->isCall()) { // In case of a call build the return address and // push it to the RAS. auto return_addr = inst->buildRetPC(pc, pc); - ras->push(tid, *return_addr, predict_record.rasHistory); + ras->push(tid, *return_addr, hist->rasHistory); - // Record that it was a call so that the top RAS entry can - // be popped off if the speculation is incorrect. DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s was " "a call, push return address %s onto the RAS\n", tid, seqNum, pc, *return_addr); } + else if (inst->isReturn()) { - // The target address is not predicted by RAS. - // Thus, BTB/IndirectBranch Predictor is employed. - if (!inst->isReturn()) { - if (inst->isDirectCtrl() || !iPred) { - ++stats.BTBLookups; - // Check BTB on direct branches - const PCStateBase * btb_target = btb->lookup(tid, - pc.instAddr(), - getBranchType(inst)); - if (btb_target) { - ++stats.BTBHits; - // If it's not a return, use the BTB to get target addr. - set(target, btb_target); - DPRINTF(Branch, - "[tid:%i] [sn:%llu] Instruction %s predicted " - "target is %s\n", - tid, seqNum, pc, *target); - } else { - DPRINTF(Branch, "[tid:%i] [sn:%llu] BTB doesn't have a " - "valid entry\n", tid, seqNum); - pred_taken = false; - predict_record.predTaken = pred_taken; - // The Direction of the branch predictor is altered - // because the BTB did not have an entry - // The predictor needs to be updated accordingly - if (!inst->isCall() && !inst->isReturn()) { - btbUpdate(tid, pc.instAddr(), bp_history); - DPRINTF(Branch, - "[tid:%i] [sn:%llu] btbUpdate " - "called for %s\n", - tid, seqNum, pc); - } else if (inst->isCall() && !inst->isUncondCtrl()) { - ras->squash(tid, predict_record.rasHistory); - predict_record.pushedRAS = false; - } - inst->advancePC(*target); - } - } else { - predict_record.wasIndirect = true; - ++stats.indirectLookups; - //Consult indirect predictor on indirect control - const PCStateBase *itarget = iPred->lookup(tid, - seqNum, pc.instAddr(), - predict_record.indirectHistory); - if (itarget) { - // Indirect predictor hit - ++stats.indirectHits; - set(target, *itarget); + // If it's a return from a function call, then look up the + // RETURN address in the RAS. + const PCStateBase *return_addr = ras->pop(tid, hist->rasHistory); + if (return_addr) { - DPRINTF(Branch, - "[tid:%i, sn:%llu] Instruction %s predicted " - "indirect target is %s\n", - tid, seqNum, pc, *target); - } else { - ++stats.indirectMisses; - pred_taken = false; - predict_record.predTaken = pred_taken; - DPRINTF(Branch, - "[tid:%i, sn:%llu] PC:%#x no indirect target\n", - tid, seqNum, pc.instAddr()); + // Set the target to the return address + set(hist->target, *return_addr); + hist->targetProvider = TargetProvider::RAS; - if (!inst->isCall() && !inst->isReturn()) { - - } else if (inst->isCall() && !inst->isUncondCtrl()) { - ras->squash(tid, predict_record.rasHistory); - } - inst->advancePC(*target); - } + DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s is a " + "return, RAS poped return addr: %s\n", + tid, seqNum, pc, *hist->target); } } - } else { - inst->advancePC(*target); } - predict_record.target = target->instAddr(); - set(pc, *target); + + /* ----------------------------------------------- + * Indirect Predictor + * ----------------------------------------------- + * For indirect branches/calls check the indirect + * predictor if one is available. Not for returns. + * Note that depending on the implementation a + * indirect predictor might only return a target + * for an indirect branch with a changing target. + * As most indirect branches have a static target + * using the target from the BTB is the optimal + * to save space in the indirect predictor itself. + */ + if (iPred && hist->predTaken && + inst->isIndirectCtrl() && !inst->isReturn()) { + + ++stats.indirectLookups; + + const PCStateBase *itarget = iPred->lookup(tid, seqNum, + pc.instAddr(), + hist->indirectHistory); + + if (itarget) { + // Indirect predictor hit + ++stats.indirectHits; + hist->targetProvider = TargetProvider::Indirect; + set(hist->target, *itarget); + + DPRINTF(Branch, + "[tid:%i, sn:%llu] Instruction %s predicted " + "indirect target is %s\n", + tid, seqNum, pc, *hist->target); + } else { + ++stats.indirectMisses; + DPRINTF(Branch, + "[tid:%i, sn:%llu] PC:%#x no indirect target\n", + tid, seqNum, pc.instAddr()); + } + } + + + /** ---------------------------------------------- + * Fallthrough + * ----------------------------------------------- + * All the target predictors did their job. + * If there is no target its either not taken or + * a BTB miss. In that case we just fallthrough. + * */ + if (hist->targetProvider == TargetProvider::NoTarget) { + set(hist->target, pc); + inst->advancePC(*hist->target); + hist->predTaken = false; + } + stats.targetProvider[tid][hist->targetProvider]++; + + // The actual prediction is done. + // For now the BPU assume its correct. The update + // functions will correct the branch if needed. + // If prediction and actual direction are the same + // at commit the prediction was correct. + hist->actuallyTaken = hist->predTaken; + set(pc, *hist->target); + + DPRINTF(Branch, "%s(tid:%i, sn:%i, PC:%#x, %s) -> taken:%i, target:%s " + "provider:%s\n", __func__, tid, seqNum, hist->pc, + toString(brType), hist->predTaken, *hist->target, + enums::TargetProviderStrings[hist->targetProvider]); + + + /** ---------------------------------------------- + * Speculative history update + * ----------------------------------------------- + * Now that the prediction is done the predictor + * may update its histories speculative. (local + * and global path). A later squash will revert + * the history update if needed. + * The actual prediction tables will updated once + * we know the correct direction. + **/ + updateHistories(tid, hist->pc, hist->uncond, hist->predTaken, + hist->target->instAddr(), hist->bpHistory); + if (iPred) { // Update the indirect predictor with the direction prediction - iPred->update(tid, seqNum, predict_record.pc, false, - predict_record.predTaken, *target, - getBranchType(inst), - predict_record.indirectHistory); + iPred->update(tid, seqNum, hist->pc, false, hist->predTaken, + *hist->target, brType, hist->indirectHistory); } - predHist[tid].push_front(predict_record); - - DPRINTF(Branch, - "[tid:%i] [sn:%llu] History entry added. " - "predHist.size(): %i\n", - tid, seqNum, predHist[tid].size()); - - return pred_taken; + return hist->predTaken; } + void BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) { DPRINTF(Branch, "[tid:%i] Committing branches until " - "sn:%llu]\n", tid, done_sn); + "[sn:%llu]\n", tid, done_sn); while (!predHist[tid].empty() && - predHist[tid].back().seqNum <= done_sn) { - // Update the branch predictor with the correct results. - update(tid, predHist[tid].back().pc, - predHist[tid].back().predTaken, - predHist[tid].back().bpHistory, false, - predHist[tid].back().inst, - predHist[tid].back().target); + predHist[tid].back()->seqNum <= done_sn) { - // Commite also Indirect predictor and RAS - if (iPred) { - iPred->commit(tid, predHist[tid].back().seqNum, - predHist[tid].back().indirectHistory); - } - - if (ras) { - ras->commit(tid, predHist[tid].back().mispredict, - getBranchType(predHist[tid].back().inst), - predHist[tid].back().rasHistory); - } + // Iterate from the back to front. Least recent + // sequence number until the most recent done number + commitBranch(tid, *predHist[tid].rbegin()); + delete predHist[tid].back(); predHist[tid].pop_back(); + DPRINTF(Branch, "[tid:%i] [commit sn:%llu] pred_hist.size(): %i\n", + tid, done_sn, predHist[tid].size()); } } +void +BPredUnit::commitBranch(ThreadID tid, PredictorHistory* &hist) +{ + + stats.committed[tid][hist->type]++; + if (hist->mispredict) { + stats.mispredicted[tid][hist->type]++; + } + + + DPRINTF(Branch, "Commit branch: sn:%llu, PC:%#x %s, " + "pred:%i, taken:%i, target:%#x\n", + hist->seqNum, hist->pc, toString(hist->type), + hist->predTaken, hist->actuallyTaken, + hist->target->instAddr()); + + // Update the branch predictor with the correct results. + update(tid, hist->pc, + hist->actuallyTaken, + hist->bpHistory, false, + hist->inst, + hist->target->instAddr()); + + // Commite also Indirect predictor and RAS + if (iPred) { + iPred->commit(tid, hist->seqNum, + hist->indirectHistory); + } + + if (ras) { + ras->commit(tid, hist->mispredict, + hist->type, + hist->rasHistory); + } +} + + + void BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) { - History &pred_hist = predHist[tid]; - while (!pred_hist.empty() && - pred_hist.front().seqNum > squashed_sn) { + while (!predHist[tid].empty() && + predHist[tid].front()->seqNum > squashed_sn) { - if (pred_hist.front().rasHistory) { - assert(ras); + auto hist = predHist[tid].front(); - DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect call/return " - "PC %#x. Fix RAS.\n", tid, pred_hist.front().seqNum, - pred_hist.front().pc); + squashHistory(tid, hist); - ras->squash(tid, pred_hist.front().rasHistory); - } + DPRINTF(Branch, "[tid:%i, squash sn:%llu] Removing history for " + "sn:%llu, PC:%#x\n", tid, squashed_sn, hist->seqNum, + hist->pc); - // This call should delete the bpHistory. - squash(tid, pred_hist.front().bpHistory); - if (iPred) { - iPred->squash(tid, pred_hist.front().seqNum, - pred_hist.front().indirectHistory); - } - DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " - "Removing history for [sn:%llu] " - "PC %#x\n", tid, squashed_sn, pred_hist.front().seqNum, - pred_hist.front().pc); + delete predHist[tid].front(); + predHist[tid].pop_front(); - pred_hist.pop_front(); - - DPRINTF(Branch, "[tid:%i] [squash sn:%llu] predHist.size(): %i\n", + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] pred_hist.size(): %i\n", tid, squashed_sn, predHist[tid].size()); } } + + +void +BPredUnit::squashHistory(ThreadID tid, PredictorHistory* &history) +{ + + stats.squashes[tid][history->type]++; + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect: %s\n", + tid, history->seqNum, + toString(history->type)); + + + if (history->rasHistory) { + assert(ras); + + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect call/return " + "PC %#x. Fix RAS.\n", tid, history->seqNum, + history->pc); + + ras->squash(tid, history->rasHistory); + } + + if (iPred) { + iPred->squash(tid, history->seqNum, + history->indirectHistory); + } + + // This call should delete the bpHistory. + squash(tid, history->bpHistory); +} + + void BPredUnit::squash(const InstSeqNum &squashed_sn, const PCStateBase &corr_target, - bool actually_taken, ThreadID tid) + bool actually_taken, ThreadID tid, bool from_commit) { // Now that we know that a branch was mispredicted, we need to undo // all the branches that have been seen up until this branch and @@ -380,10 +454,15 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ++stats.condIncorrect; ppMisses->notify(1); - DPRINTF(Branch, "[tid:%i] Squashing from sequence number %i, " - "setting target to %s\n", tid, squashed_sn, corr_target); + + DPRINTF(Branch, "[tid:%i] Squash from %s start from sequence number %i, " + "setting target to %s\n", tid, from_commit ? "commit" : "decode", + squashed_sn, corr_target); + + // dump(); // Squash All Branches AFTER this mispredicted branch + // First the Prefetch history then the main history. squash(squashed_sn, tid); // If there's a squash due to a syscall, there may not be an entry @@ -391,25 +470,32 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, // fix up the entry. if (!pred_hist.empty()) { - auto hist_it = pred_hist.begin(); - //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(), - // squashed_sn); + PredictorHistory* const hist = pred_hist.front(); - //assert(hist_it != pred_hist.end()); - if (pred_hist.front().seqNum != squashed_sn) { - DPRINTF(Branch, "Front sn %i != Squash sn %i\n", - pred_hist.front().seqNum, squashed_sn); + DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Mispredicted: %s, PC:%#x\n", + tid, squashed_sn, toString(hist->type), hist->pc); - assert(pred_hist.front().seqNum == squashed_sn); + // Update stats + stats.corrected[tid][hist->type]++; + if (hist->target && + (hist->target->instAddr() != corr_target.instAddr())) { + stats.targetWrong[tid][hist->targetProvider]++; } - if ((*hist_it).rasHistory) { - ++stats.RASIncorrect; - DPRINTF(Branch, - "[tid:%i] [squash sn:%llu] Incorrect RAS [sn:%llu]\n", - tid, squashed_sn, hist_it->seqNum); + // If the squash is comming from decode it can be + // redirected earlier. Note that this branch might never get + // committed as a preceeding branch was mispredicted + if (!from_commit) { + stats.earlyResteers[tid][hist->type]++; } + if (actually_taken) { + ++stats.NotTakenMispredicted; + } else { + ++stats.TakenMispredicted; + } + + // There are separate functions for in-order and out-of-order // branch prediction, but not for update. Therefore, this // call should take into account that the mispredicted branch may @@ -419,99 +505,109 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, // local/global histories. The counter tables will be updated when // the branch actually commits. - // Remember the correct direction for the update at commit. - pred_hist.front().predTaken = actually_taken; - pred_hist.front().target = corr_target.instAddr(); - pred_hist.front().mispredict = true; + // Remember the correct direction and target for the update at commit. + hist->mispredict = true; + hist->actuallyTaken = actually_taken; + set(hist->target, corr_target); + + // Correct Direction predictor ------------------ + update(tid, hist->pc, actually_taken, hist->bpHistory, + true, hist->inst, corr_target.instAddr()); - update(tid, (*hist_it).pc, actually_taken, - pred_hist.front().bpHistory, true, pred_hist.front().inst, - corr_target.instAddr()); // Correct Indirect predictor ------------------- if (iPred) { - iPred->update(tid, squashed_sn, (*hist_it).pc, + iPred->update(tid, squashed_sn, hist->pc, true, actually_taken, corr_target, - getBranchType(pred_hist.front().inst), - (*hist_it).indirectHistory); - + hist->type, hist->indirectHistory); } // Correct RAS --------------------------------- if (ras) { // The branch was taken and the RAS was not updated. // In case of call or return that needs to be fixed. - if (actually_taken && (hist_it->rasHistory == nullptr)) { + if (actually_taken && (hist->rasHistory == nullptr)) { // A return has not poped the RAS. - if (hist_it->inst->isReturn()) { + if (hist->type == BranchType::Return) { DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " "Incorrectly predicted return [sn:%llu] PC: %#x\n", - tid, squashed_sn, hist_it->seqNum, hist_it->pc); + tid, squashed_sn, hist->seqNum, hist->pc); - ras->pop(tid, hist_it->rasHistory); + ras->pop(tid, hist->rasHistory); } // A call has not pushed a return address to the RAS. - if (hist_it->inst->isCall()) { + if (hist->call) { // In case of a call build the return address and // push it to the RAS. - auto return_addr = hist_it->inst->buildRetPC( + auto return_addr = hist->inst->buildRetPC( corr_target, corr_target); DPRINTF(Branch, "[tid:%i] [squash sn:%llu] " "Incorrectly predicted call: [sn:%llu,PC:%#x] " " Push return address %s onto RAS\n", tid, - squashed_sn, hist_it->seqNum, hist_it->pc, + squashed_sn, hist->seqNum, hist->pc, *return_addr); - ras->push(tid, *return_addr, hist_it->rasHistory); + ras->push(tid, *return_addr, hist->rasHistory); } // The branch was not taken but the RAS modified. - } else if (!actually_taken && (hist_it->rasHistory != nullptr)) { + } else if (!actually_taken && (hist->rasHistory != nullptr)) { // The branch was not taken but the RAS was modified. // Needs to be fixed. - ras->squash(tid, hist_it->rasHistory); + ras->squash(tid, hist->rasHistory); } } + // Correct BTB --------------------------------------------------- + // Check if the misprediction happened was because of a BTB miss + // or incorrect indirect predictor if (actually_taken) { - if (hist_it->wasIndirect) { + if (hist->inst->isIndirectCtrl() && !hist->inst->isReturn()) { ++stats.indirectMispredicted; } else { - DPRINTF(Branch,"[tid:%i] [squash sn:%llu] " - "BTB Update called for [sn:%llu] " - "PC %#x\n", tid, squashed_sn, - hist_it->seqNum, hist_it->pc); ++stats.BTBUpdates; - btb->update(tid, hist_it->pc, corr_target, - getBranchType(hist_it->inst)); + btb->update(tid, hist->pc, corr_target, + getBranchType(hist->inst)); + + ++stats.BTBMispredicted; + if (hist->condPred) + ++stats.predTakenBTBMiss; + + btb->incorrectTarget(hist->pc, hist->type); + + DPRINTF(Branch,"[tid:%i] [squash sn:%llu] " + "BTB miss PC %#x %s \n", tid, squashed_sn, + hist->pc, toString(hist->type)); } } + } else { DPRINTF(Branch, "[tid:%i] [sn:%llu] pred_hist empty, can't " "update\n", tid, squashed_sn); } } + void BPredUnit::dump() { int i = 0; for (const auto& ph : predHist) { if (!ph.empty()) { - auto pred_hist_it = ph.begin(); + auto hist = ph.begin(); cprintf("predHist[%i].size(): %i\n", i++, ph.size()); - while (pred_hist_it != ph.end()) { + while (hist != ph.end()) { cprintf("sn:%llu], PC:%#x, tid:%i, predTaken:%i, " - "bpHistory:%#x\n", - pred_hist_it->seqNum, pred_hist_it->pc, - pred_hist_it->tid, pred_hist_it->predTaken, - pred_hist_it->bpHistory); - pred_hist_it++; + "bpHistory:%#x, rasHistory:%#x\n", + (*hist)->seqNum, (*hist)->pc, + (*hist)->tid, (*hist)->predTaken, + (*hist)->bpHistory, (*hist)->rasHistory); + hist++; } cprintf("\n"); @@ -519,5 +615,108 @@ BPredUnit::dump() } } + +BPredUnit::BPredUnitStats::BPredUnitStats(BPredUnit *bp) + : statistics::Group(bp), + ADD_STAT(lookups, statistics::units::Count::get(), + "Number of BP lookups"), + ADD_STAT(squashes, statistics::units::Count::get(), + "Number of branches that got squashed (completely removed) as " + "an earlier branch was mispredicted."), + ADD_STAT(corrected, statistics::units::Count::get(), + "Number of branches that got corrected but not yet commited. " + "Branches get corrected by decode or after execute. Also a " + "branch misprediction can be detected out-of-order. Therefore, " + "a corrected branch might not end up beeing committed in case " + "an even earlier branch was mispredicted"), + ADD_STAT(earlyResteers, statistics::units::Count::get(), + "Number of branches that got redirected after decode."), + ADD_STAT(committed, statistics::units::Count::get(), + "Number of branches finally committed "), + ADD_STAT(mispredicted, statistics::units::Count::get(), + "Number of committed branches that were mispredicted."), + ADD_STAT(targetProvider, statistics::units::Count::get(), + "The component providing the target for taken branches"), + ADD_STAT(targetWrong, statistics::units::Count::get(), + "Number of branches where the target was incorrect or not " + "available at prediction time."), + ADD_STAT(condPredicted, statistics::units::Count::get(), + "Number of conditional branches predicted"), + ADD_STAT(condPredictedTaken, statistics::units::Count::get(), + "Number of conditional branches predicted as taken"), + ADD_STAT(condIncorrect, statistics::units::Count::get(), + "Number of conditional branches incorrect"), + ADD_STAT(predTakenBTBMiss, statistics::units::Count::get(), + "Number of branches predicted taken but missed in BTB"), + ADD_STAT(NotTakenMispredicted, statistics::units::Count::get(), + "Number branches predicted 'not taken' but turned out " + "to be taken"), + ADD_STAT(TakenMispredicted, statistics::units::Count::get(), + "Number branches predicted taken but are actually not taken"), + ADD_STAT(BTBLookups, statistics::units::Count::get(), + "Number of BTB lookups"), + ADD_STAT(BTBUpdates, statistics::units::Count::get(), + "Number of BTB updates"), + ADD_STAT(BTBHits, statistics::units::Count::get(), + "Number of BTB hits"), + ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(), "BTB Hit Ratio", + BTBHits / BTBLookups), + ADD_STAT(BTBMispredicted, statistics::units::Count::get(), + "Number BTB mispredictions. No target found or target wrong"), + ADD_STAT(indirectLookups, statistics::units::Count::get(), + "Number of indirect predictor lookups."), + ADD_STAT(indirectHits, statistics::units::Count::get(), + "Number of indirect target hits."), + ADD_STAT(indirectMisses, statistics::units::Count::get(), + "Number of indirect misses."), + ADD_STAT(indirectMispredicted, statistics::units::Count::get(), + "Number of mispredicted indirect branches.") + +{ + using namespace statistics; + BTBHitRatio.precision(6); + + lookups + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + lookups.ysubnames(enums::BranchTypeStrings); + + squashes + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + squashes.ysubnames(enums::BranchTypeStrings); + + corrected + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + corrected.ysubnames(enums::BranchTypeStrings); + + earlyResteers + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + earlyResteers.ysubnames(enums::BranchTypeStrings); + + committed + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + committed.ysubnames(enums::BranchTypeStrings); + + mispredicted + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + mispredicted.ysubnames(enums::BranchTypeStrings); + + targetProvider + .init(bp->numThreads, enums::Num_TargetProvider) + .flags(total | pdf); + targetProvider.ysubnames(enums::TargetProviderStrings); + + targetWrong + .init(bp->numThreads, enums::Num_BranchType) + .flags(total | pdf); + targetWrong.ysubnames(enums::BranchTypeStrings); + +} + } // namespace branch_prediction } // namespace gem5 diff --git a/src/cpu/pred/bpred_unit.hh b/src/cpu/pred/bpred_unit.hh index 18f3f562cb..6aaec616c6 100644 --- a/src/cpu/pred/bpred_unit.hh +++ b/src/cpu/pred/bpred_unit.hh @@ -46,12 +46,13 @@ #include "base/statistics.hh" #include "base/types.hh" +#include "cpu/inst_seq.hh" #include "cpu/pred/branch_type.hh" #include "cpu/pred/btb.hh" #include "cpu/pred/indirect.hh" #include "cpu/pred/ras.hh" -#include "cpu/inst_seq.hh" #include "cpu/static_inst.hh" +#include "enums/TargetProvider.hh" #include "params/BranchPredictor.hh" #include "sim/probe/pmu.hh" #include "sim/sim_object.hh" @@ -68,8 +69,14 @@ namespace branch_prediction */ class BPredUnit : public SimObject { + typedef BranchPredictorParams Params; + typedef enums::TargetProvider TargetProvider; + + /** Branch Predictor Unit (BPU) interface functions */ public: - typedef BranchPredictorParams Params; + + + /** * @param params The params object, that has the size of the BP and BTB. */ @@ -91,9 +98,6 @@ class BPredUnit : public SimObject bool predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, PCStateBase &pc, ThreadID tid); - // @todo: Rename this function. - virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) = 0; - /** * Tells the branch predictor to commit any updates until the given * sequence number. @@ -118,38 +122,75 @@ class BPredUnit : public SimObject * @param corr_target The correct branch target. * @param actually_taken The correct branch direction. * @param tid The thread id. + * @param from_commit Indicate whether the squash is comming from commit + * or from decode. Its optional and used for statistics. */ - void squash(const InstSeqNum &squashed_sn, - const PCStateBase &corr_target, - bool actually_taken, ThreadID tid); + void squash(const InstSeqNum &squashed_sn, const PCStateBase &corr_target, + bool actually_taken, ThreadID tid, bool from_commit=true); + + protected: + + /** ******************************************************* + * Interface functions to the conditional branch predictor + * + */ /** - * @param bp_history Pointer to the history object. The predictor - * will need to update any state and delete the object. - */ - virtual void squash(ThreadID tid, void *bp_history) = 0; - - /** - * Looks up a given PC in the BP to see if it is taken or not taken. - * @param inst_PC The PC to look up. + * Looks up a given conditional branch PC of in the BP to see if it + * is taken or not taken. + * @param pc The PC to look up. * @param bp_history Pointer that will be set to an object that * has the branch predictor state associated with the lookup. * @return Whether the branch is taken or not taken. */ - virtual bool lookup(ThreadID tid, Addr instPC, void * &bp_history) = 0; + virtual bool lookup(ThreadID tid, Addr pc, void * &bp_history) = 0; - /** - * If a branch is not taken, because the BTB address is invalid or missing, - * this function sets the appropriate counter in the global and local - * predictors to not taken. - * @param inst_PC The PC to look up the local predictor. + /** + * Ones done with the prediction this function updates the + * path and global history. All branches call this function + * including unconditional once. + * @param tid The thread id. + * @param PC The branch's PC that will be updated. + * @param uncond Wheather or not this branch is an unconditional branch. + * @param taken Whether or not the branch was taken + * @param target The final target of branch. Some modern + * predictors use the target in their history. * @param bp_history Pointer that will be set to an object that * has the branch predictor state associated with the lookup. */ - virtual void btbUpdate(ThreadID tid, Addr instPC, void * &bp_history) = 0; + virtual void updateHistories(ThreadID tid, Addr pc, bool uncond, + bool taken, Addr target, void * &bp_history) = 0; + + /** + * @param tid The thread id. + * @param bp_history Pointer to the history object. The predictor + * will need to update any state and delete the object. + */ + virtual void squash(ThreadID tid, void * &bp_history) = 0; + + + /** + * Updates the BP with taken/not taken information. + * @param tid The thread id. + * @param PC The branch's PC that will be updated. + * @param taken Whether the branch was taken or not taken. + * @param bp_history Pointer to the branch predictor state that is + * associated with the branch lookup that is being updated. + * @param squashed Set to true when this function is called during a + * squash operation. + * @param inst Static instruction information + * @param target The resolved target of the branch (only needed + * for squashed branches) + * @todo Make this update flexible enough to handle a global predictor. + */ + virtual void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr &inst, Addr target) = 0; + /** * Looks up a given PC in the BTB to see if a matching entry exists. + * @param tid The thread id. * @param inst_PC The PC to look up. * @return Whether the BTB contains the given PC. */ @@ -157,15 +198,12 @@ class BPredUnit : public SimObject { return btb->valid(tid, instPC); } - bool BTBValid(ThreadID tid, PCStateBase &instPC) - { - return BTBValid(tid, instPC.instAddr()); - } /** * Looks up a given PC in the BTB to get the predicted target. The PC may * be changed or deleted in the future, so it needs to be used immediately, * and/or copied for use later. + * @param tid The thread id. * @param inst_PC The PC to look up. * @return The address of the target of the branch. */ @@ -176,21 +214,21 @@ class BPredUnit : public SimObject } /** - * Updates the BP with taken/not taken information. - * @param inst_PC The branch's PC that will be updated. - * @param taken Whether the branch was taken or not taken. - * @param bp_history Pointer to the branch predictor state that is - * associated with the branch lookup that is being updated. - * @param squashed Set to true when this function is called during a - * squash operation. - * @param inst Static instruction information - * @param corrTarget The resolved target of the branch (only needed - * for squashed branches) - * @todo Make this update flexible enough to handle a global predictor. + * Looks up a given PC in the BTB to get current static instruction + * information. This is necessary in a decoupled frontend as + * the information does not usually exist at that this point. + * Only for instructions (branches) that hit in the BTB this information + * is available as the BTB stores them together with the target. + * + * @param inst_PC The PC to look up. + * @return The static instruction info of the given PC if existant. */ - virtual void update(ThreadID tid, Addr instPC, bool taken, - void *bp_history, bool squashed, - const StaticInstPtr &inst, Addr corrTarget) = 0; + const StaticInstPtr + BTBGetInst(ThreadID tid, Addr instPC) + { + return btb->getInst(tid, instPC); + } + /** * Updates the BTB with the target of a branch. * @param inst_PC The branch's PC that will be updated. @@ -213,28 +251,28 @@ class BPredUnit : public SimObject * Makes a predictor history struct that contains any * information needed to update the predictor, BTB, and RAS. */ - PredictorHistory(const InstSeqNum &seq_num, Addr instPC, - bool pred_taken, void *bp_history, - void *indirect_history, ThreadID _tid, + PredictorHistory(ThreadID _tid, InstSeqNum sn, Addr _pc, const StaticInstPtr & inst) - : seqNum(seq_num), pc(instPC), bpHistory(bp_history), - indirectHistory(indirect_history), rasHistory(nullptr), - tid(_tid), - predTaken(pred_taken), inst(inst) - {} + : seqNum(sn), tid(_tid), pc(_pc), + inst(inst), type(getBranchType(inst)), + call(inst->isCall()), uncond(inst->isUncondCtrl()), + predTaken(false), actuallyTaken(false), condPred(false), + btbHit(false), targetProvider(TargetProvider::NoTarget), + resteered(false), mispredict(false), target(nullptr), + bpHistory(nullptr), + indirectHistory(nullptr), rasHistory(nullptr) + { } - PredictorHistory(const PredictorHistory &other) : - seqNum(other.seqNum), pc(other.pc), bpHistory(other.bpHistory), - indirectHistory(other.indirectHistory), - rasHistory(other.rasHistory), RASIndex(other.RASIndex), - tid(other.tid), predTaken(other.predTaken), usedRAS(other.usedRAS), - pushedRAS(other.pushedRAS), wasIndirect(other.wasIndirect), - target(other.target), inst(other.inst), - mispredict(other.mispredict) + ~PredictorHistory() { - set(RASTarget, other.RASTarget); + assert(bpHistory == nullptr); + assert(indirectHistory == nullptr); + assert(rasHistory == nullptr); } + PredictorHistory (const PredictorHistory&) = delete; + PredictorHistory& operator= (const PredictorHistory&) = delete; + bool operator==(const PredictorHistory &entry) const { @@ -242,14 +280,55 @@ class BPredUnit : public SimObject } /** The sequence number for the predictor history entry. */ - InstSeqNum seqNum; + const InstSeqNum seqNum; + + /** The thread id. */ + const ThreadID tid; /** The PC associated with the sequence number. */ - Addr pc; + const Addr pc; - /** Pointer to the history object passed back from the branch - * predictor. It is used to update or restore state of the - * branch predictor. + /** The branch instrction */ + const StaticInstPtr inst; + + /** The type of the branch */ + const BranchType type; + + /** Whether or not the instruction was a call. */ + const bool call; + + /** Was unconditional control */ + const bool uncond; + + /** Whether or not it was predicted taken. */ + bool predTaken; + + /** To record the actual outcome of the branch */ + bool actuallyTaken; + + /** The prediction of the conditional predictor */ + bool condPred; + + /** Was BTB hit at prediction time */ + bool btbHit; + + /** Which component provided the target */ + TargetProvider targetProvider; + + /** Resteered */ + bool resteered; + + /** The branch was corrected hence was mispredicted. */ + bool mispredict; + + /** The predicted target */ + std::unique_ptr target; + + /** + * Pointer to the history objects passed back from the branch + * predictor subcomponents. + * It is used to update or restore state. + * Respectively for conditional, indirect and RAS. */ void *bpHistory = nullptr; @@ -257,44 +336,40 @@ class BPredUnit : public SimObject void *rasHistory = nullptr; - /** The RAS target (only valid if a return). */ - std::unique_ptr RASTarget; - - /** The RAS index of the instruction (only valid if a call). */ - unsigned RASIndex = 0; - - /** The thread id. */ - ThreadID tid; - - /** Whether or not it was predicted taken. */ - bool predTaken; - - /** Whether or not the RAS was used. */ - bool usedRAS = false; - - /* Whether or not the RAS was pushed */ - bool pushedRAS = false; - - /** Wether this instruction was an indirect branch */ - bool wasIndirect = false; - - /** Target of the branch. First it is predicted, and fixed later - * if necessary - */ - Addr target = MaxAddr; - - /** The branch instrction */ - const StaticInstPtr inst; - - /** Whether this branch was mispredicted */ - bool mispredict = false; }; - typedef std::deque History; + typedef std::deque History; + + /** + * Internal prediction function. + */ + bool predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, + PCStateBase &pc, ThreadID tid, PredictorHistory* &bpu_history); + + /** + * Squashes a particular branch instance + * @param tid The thread id. + * @param bpu_history The history to be squashed. + */ + void squashHistory(ThreadID tid, PredictorHistory* &bpu_history); + + + /** + * Commit a particular branch + * @param tid The thread id. + * @param bpu_history The history of the branch to be commited. + */ + void commitBranch(ThreadID tid, PredictorHistory* &bpu_history); + + + + protected: /** Number of the threads for which the branch history is maintained. */ const unsigned numThreads; + /** Number of bits to shift instructions by for predictor addresses. */ + const unsigned instShiftAmt; /** * The per-thread predictor history. This is used to update the predictor @@ -312,42 +387,47 @@ class BPredUnit : public SimObject /** The indirect target predictor. */ IndirectPredictor * iPred; + /** Statistics */ struct BPredUnitStats : public statistics::Group { - BPredUnitStats(statistics::Group *parent); + BPredUnitStats(BPredUnit *bp); - /** Stat for number of BP lookups. */ - statistics::Scalar lookups; - /** Stat for number of conditional branches predicted. */ + /** Stats per branch type */ + statistics::Vector2d lookups; + statistics::Vector2d squashes; + statistics::Vector2d corrected; + statistics::Vector2d earlyResteers; + statistics::Vector2d committed; + statistics::Vector2d mispredicted; + + /** Target prediction per branch type */ + statistics::Vector2d targetProvider; + statistics::Vector2d targetWrong; + + /** Additional scalar stats for conditional branches */ statistics::Scalar condPredicted; - /** Stat for number of conditional branches predicted incorrectly. */ + statistics::Scalar condPredictedTaken; statistics::Scalar condIncorrect; - /** Stat for number of BTB lookups. */ - statistics::Scalar BTBLookups; - /** Stat for number of BTB updates. */ - statistics::Scalar BTBUpdates; - /** Stat for number of BTB hits. */ - statistics::Scalar BTBHits; - /** Stat for the ratio between BTB hits and BTB lookups. */ - statistics::Formula BTBHitRatio; - /** Stat for number of times the RAS is used to get a target. */ - statistics::Scalar RASUsed; - /** Stat for number of times the RAS is incorrect. */ - statistics::Scalar RASIncorrect; + statistics::Scalar predTakenBTBMiss; + statistics::Scalar NotTakenMispredicted; + statistics::Scalar TakenMispredicted; - /** Stat for the number of indirect target lookups.*/ + /** BTB stats. */ + statistics::Scalar BTBLookups; + statistics::Scalar BTBUpdates; + statistics::Scalar BTBHits; + statistics::Formula BTBHitRatio; + statistics::Scalar BTBMispredicted; + + /** Indirect stats */ statistics::Scalar indirectLookups; - /** Stat for the number of indirect target hits.*/ statistics::Scalar indirectHits; - /** Stat for the number of indirect target misses.*/ statistics::Scalar indirectMisses; - /** Stat for the number of indirect target mispredictions.*/ statistics::Scalar indirectMispredicted; + } stats; protected: - /** Number of bits to shift instructions by for predictor addresses. */ - const unsigned instShiftAmt; /** * @{ diff --git a/src/cpu/pred/loop_predictor.cc b/src/cpu/pred/loop_predictor.cc index 6574d61bb1..9e34e5141a 100644 --- a/src/cpu/pred/loop_predictor.cc +++ b/src/cpu/pred/loop_predictor.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The University of Wisconsin * * Copyright (c) 2006 INRIA (Institut National de Recherche en @@ -320,10 +332,13 @@ LoopPredictor::squashLoop(BranchInfo* bi) void LoopPredictor::updateStats(bool taken, BranchInfo* bi) { - if (taken == bi->loopPred) { - stats.correct++; - } else { - stats.wrong++; + if (bi->loopPredUsed) { + stats.used++; + if (taken == bi->loopPred) { + stats.correct++; + } else { + stats.wrong++; + } } } @@ -354,6 +369,8 @@ LoopPredictor::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, LoopPredictor::LoopPredictorStats::LoopPredictorStats( statistics::Group *parent) : statistics::Group(parent), + ADD_STAT(used, statistics::units::Count::get(), + "Number of times the loop predictor is the provider."), ADD_STAT(correct, statistics::units::Count::get(), "Number of times the loop predictor is the provider and the " "prediction is correct"), diff --git a/src/cpu/pred/loop_predictor.hh b/src/cpu/pred/loop_predictor.hh index 44d75aba35..333cb3b34e 100644 --- a/src/cpu/pred/loop_predictor.hh +++ b/src/cpu/pred/loop_predictor.hh @@ -1,5 +1,15 @@ /* - * Copyright (c) 2014 The University of Wisconsin + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2006 INRIA (Institut National de Recherche en * Informatique et en Automatique / French National Research Institute @@ -92,6 +102,7 @@ class LoopPredictor : public SimObject struct LoopPredictorStats : public statistics::Group { LoopPredictorStats(statistics::Group *parent); + statistics::Scalar used; statistics::Scalar correct; statistics::Scalar wrong; } stats; diff --git a/src/cpu/pred/ltage.cc b/src/cpu/pred/ltage.cc index 930d6bf44a..3da443d20d 100644 --- a/src/cpu/pred/ltage.cc +++ b/src/cpu/pred/ltage.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The University of Wisconsin * * Copyright (c) 2006 INRIA (Institut National de Recherche en @@ -94,8 +106,8 @@ LTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) // PREDICTOR UPDATE void -LTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget) +LTAGE::update(ThreadID tid, Addr pc, bool taken, void * &bp_history, + bool squashed, const StaticInstPtr & inst, Addr target) { assert(bp_history); @@ -105,7 +117,7 @@ LTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, if (tage->isSpeculativeUpdateEnabled()) { // This restores the global history, then update it // and recomputes the folded histories. - tage->squash(tid, taken, bi->tageBranchInfo, corrTarget); + tage->squash(tid, taken, bi->tageBranchInfo, target); if (bi->tageBranchInfo->condBranch) { loopPredictor->squashLoop(bi->lpBranchInfo); @@ -117,26 +129,27 @@ LTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, int nrand = random_mt.random() & 3; if (bi->tageBranchInfo->condBranch) { DPRINTF(LTage, "Updating tables for branch:%lx; taken?:%d\n", - branch_pc, taken); + pc, taken); tage->updateStats(taken, bi->tageBranchInfo); loopPredictor->updateStats(taken, bi->lpBranchInfo); - loopPredictor->condBranchUpdate(tid, branch_pc, taken, + loopPredictor->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt); - tage->condBranchUpdate(tid, branch_pc, taken, bi->tageBranchInfo, - nrand, corrTarget, bi->lpBranchInfo->predTaken); + tage->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo, + nrand, target, bi->lpBranchInfo->predTaken); } - tage->updateHistories(tid, branch_pc, taken, bi->tageBranchInfo, false, - inst, corrTarget); + tage->updateHistories(tid, pc, taken, bi->tageBranchInfo, false, + inst, target); delete bi; + bp_history = nullptr; } void -LTAGE::squash(ThreadID tid, void *bp_history) +LTAGE::squash(ThreadID tid, void * &bp_history) { LTageBranchInfo* bi = (LTageBranchInfo*)(bp_history); diff --git a/src/cpu/pred/ltage.hh b/src/cpu/pred/ltage.hh index 7deaa2bc04..92d1fd25d7 100644 --- a/src/cpu/pred/ltage.hh +++ b/src/cpu/pred/ltage.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The University of Wisconsin * * Copyright (c) 2006 INRIA (Institut National de Recherche en @@ -69,10 +81,10 @@ class LTAGE : public TAGE LTAGE(const LTAGEParams ¶ms); // Base class methods. - void squash(ThreadID tid, void *bp_history) override; - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, - Addr corrTarget) override; + void squash(ThreadID tid, void * &bp_history) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; void init() override; @@ -98,6 +110,7 @@ class LTAGE : public TAGE virtual ~LTageBranchInfo() { delete lpBranchInfo; + lpBranchInfo = nullptr; } }; diff --git a/src/cpu/pred/multiperspective_perceptron.cc b/src/cpu/pred/multiperspective_perceptron.cc index 25b4d7d39a..fd54ec8163 100644 --- a/src/cpu/pred/multiperspective_perceptron.cc +++ b/src/cpu/pred/multiperspective_perceptron.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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 2019 Texas A&M University * * Redistribution and use in source and binary forms, with or without @@ -547,10 +559,19 @@ MultiperspectivePerceptron::train(ThreadID tid, MPPBranchInfo &bi, bool taken) } } + void -MultiperspectivePerceptron::uncondBranch(ThreadID tid, Addr pc, - void * &bp_history) +MultiperspectivePerceptron::updateHistories(ThreadID tid, Addr pc, + bool uncond, bool taken, Addr target, void * &bp_history) { + assert(uncond || bp_history); + + // For perceptron there is no speculative history correction. + // Conditional branches are done. + if (!uncond) + return; + + // For uncondition branches create branch info. MPPBranchInfo *bi = new MPPBranchInfo(pc, pcshift, false); std::vector &ghist_words = threadData[tid]->ghist_words; @@ -613,10 +634,10 @@ MultiperspectivePerceptron::lookup(ThreadID tid, Addr instPC, } void -MultiperspectivePerceptron::update(ThreadID tid, Addr instPC, bool taken, - void *bp_history, bool squashed, +MultiperspectivePerceptron::update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, const StaticInstPtr & inst, - Addr corrTarget) + Addr target) { assert(bp_history); MPPBranchInfo *bi = static_cast(bp_history); @@ -627,6 +648,7 @@ MultiperspectivePerceptron::update(ThreadID tid, Addr instPC, bool taken, if (bi->isUnconditional()) { delete bi; + bp_history = nullptr; return; } @@ -693,7 +715,6 @@ MultiperspectivePerceptron::update(ThreadID tid, Addr instPC, bool taken, // four different styles of IMLI if (!bi->filtered || (record_mask & Imli)) { - unsigned int target = corrTarget; if (target < bi->getPC()) { if (taken) { threadData[tid]->imli_counter[0] += 1; @@ -813,20 +834,16 @@ MultiperspectivePerceptron::update(ThreadID tid, Addr instPC, bool taken, threadData[tid]->last_ghist_bit = taken; delete bi; + bp_history = nullptr; } void -MultiperspectivePerceptron::btbUpdate(ThreadID tid, Addr branch_pc, - void* &bp_history) -{ -} - -void -MultiperspectivePerceptron::squash(ThreadID tid, void *bp_history) +MultiperspectivePerceptron::squash(ThreadID tid, void * &bp_history) { assert(bp_history); MPPBranchInfo *bi = static_cast(bp_history); delete bi; + bp_history = nullptr; } } // namespace branch_prediction diff --git a/src/cpu/pred/multiperspective_perceptron.hh b/src/cpu/pred/multiperspective_perceptron.hh index 68ab5f1a23..f761607a29 100644 --- a/src/cpu/pred/multiperspective_perceptron.hh +++ b/src/cpu/pred/multiperspective_perceptron.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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 2019 Texas A&M University * * Redistribution and use in source and binary forms, with or without @@ -1048,14 +1060,14 @@ class MultiperspectivePerceptron : public BPredUnit void init() override; - void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) override; - void squash(ThreadID tid, void *bp_history) override; - bool lookup(ThreadID tid, Addr instPC, void * &bp_history) override; - void update(ThreadID tid, Addr instPC, bool taken, - void *bp_history, bool squashed, - const StaticInstPtr & inst, - Addr corrTarget) override; - void btbUpdate(ThreadID tid, Addr branch_addr, void* &bp_history) override; + // Base class methods. + bool lookup(ThreadID tid, Addr branch_addr, void* &bp_history) override; + void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, + Addr target, void * &bp_history) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; + void squash(ThreadID tid, void * &bp_history) override; }; } // namespace branch_prediction diff --git a/src/cpu/pred/multiperspective_perceptron_tage.cc b/src/cpu/pred/multiperspective_perceptron_tage.cc index 6176d9ccb2..1075f9d04f 100644 --- a/src/cpu/pred/multiperspective_perceptron_tage.cc +++ b/src/cpu/pred/multiperspective_perceptron_tage.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 The University of Edinburgh + * 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 2019 Texas A&M University * * Redistribution and use in source and binary forms, with or without @@ -548,7 +560,7 @@ MultiperspectivePerceptronTAGE::lookup(ThreadID tid, Addr instPC, void MPP_StatisticalCorrector::condBranchUpdate(ThreadID tid, Addr branch_pc, - bool taken, StatisticalCorrector::BranchInfo *bi, Addr corrTarget, + bool taken, StatisticalCorrector::BranchInfo *bi, Addr target, bool bias_bit, int hitBank, int altBank, int64_t phist) { bool scPred = (bi->lsum >= 0); @@ -588,10 +600,10 @@ MPP_StatisticalCorrector::condBranchUpdate(ThreadID tid, Addr branch_pc, } void -MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, - void *bp_history, bool squashed, +MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, const StaticInstPtr & inst, - Addr corrTarget) + Addr target) { assert(bp_history); MPPTAGEBranchInfo *bi = static_cast(bp_history); @@ -600,7 +612,7 @@ MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, if (tage->isSpeculativeUpdateEnabled()) { // This restores the global history, then update it // and recomputes the folded histories. - tage->squash(tid, taken, bi->tageBranchInfo, corrTarget); + tage->squash(tid, taken, bi->tageBranchInfo, target); if (bi->tageBranchInfo->condBranch) { loopPredictor->squashLoop(bi->lpBranchInfo); } @@ -609,16 +621,16 @@ MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, } if (bi->isUnconditional()) { - statisticalCorrector->scHistoryUpdate(instPC, inst, taken, - bi->scBranchInfo, corrTarget); - tage->updateHistories(tid, instPC, taken, bi->tageBranchInfo, false, - inst, corrTarget); + statisticalCorrector->scHistoryUpdate(pc, inst, taken, + bi->scBranchInfo, target); + tage->updateHistories(tid, pc, taken, bi->tageBranchInfo, false, + inst, target); } else { tage->updateStats(taken, bi->tageBranchInfo); loopPredictor->updateStats(taken, bi->lpBranchInfo); statisticalCorrector->updateStats(taken, bi->scBranchInfo); - loopPredictor->condBranchUpdate(tid, instPC, taken, + loopPredictor->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt); bool scPred = (bi->scBranchInfo->lsum >= 0); @@ -626,13 +638,13 @@ MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, ((abs(bi->scBranchInfo->lsum) < bi->scBranchInfo->thres))) { updatePartial(tid, *bi, taken); } - statisticalCorrector->condBranchUpdate(tid, instPC, taken, - bi->scBranchInfo, corrTarget, false /* bias_bit: unused */, + statisticalCorrector->condBranchUpdate(tid, pc, taken, + bi->scBranchInfo, target, false /* bias_bit: unused */, 0 /* hitBank: unused */, 0 /* altBank: unused*/, tage->getPathHist(tid)); - tage->condBranchUpdate(tid, instPC, taken, bi->tageBranchInfo, - random_mt.random(), corrTarget, + tage->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo, + random_mt.random(), target, bi->predictedTaken, true); updateHistories(tid, *bi, taken); @@ -640,8 +652,8 @@ MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, if (!tage->isSpeculativeUpdateEnabled()) { if (inst->isCondCtrl() && inst->isDirectCtrl() && !inst->isCall() && !inst->isReturn()) { - uint32_t truncated_target = corrTarget; - uint32_t truncated_pc = instPC; + uint32_t truncated_target = target; + uint32_t truncated_pc = pc; if (truncated_target < truncated_pc) { if (!taken) { threadData[tid]->imli_counter[0] = 0; @@ -657,20 +669,28 @@ MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, } } - statisticalCorrector->scHistoryUpdate(instPC, inst, taken, - bi->scBranchInfo, corrTarget); + statisticalCorrector->scHistoryUpdate(pc, inst, taken, + bi->scBranchInfo, target); - tage->updateHistories(tid, instPC, taken, bi->tageBranchInfo, - false, inst, corrTarget); + tage->updateHistories(tid, pc, taken, bi->tageBranchInfo, + false, inst, target); } } delete bi; + bp_history = nullptr; } void -MultiperspectivePerceptronTAGE::uncondBranch(ThreadID tid, Addr pc, - void * &bp_history) +MultiperspectivePerceptronTAGE::updateHistories(ThreadID tid, Addr pc, + bool uncond, bool taken, + Addr target, void * &bp_history) { + assert(uncond || bp_history); + + // For perceptron there is no speculative history correction. + // Conditional branches are done. + if (!uncond) return; + MPPTAGEBranchInfo *bi = new MPPTAGEBranchInfo(pc, pcshift, false, *tage, *loopPredictor, *statisticalCorrector); @@ -678,11 +698,12 @@ MultiperspectivePerceptronTAGE::uncondBranch(ThreadID tid, Addr pc, } void -MultiperspectivePerceptronTAGE::squash(ThreadID tid, void *bp_history) +MultiperspectivePerceptronTAGE::squash(ThreadID tid, void * &bp_history) { assert(bp_history); MPPTAGEBranchInfo *bi = static_cast(bp_history); delete bi; + bp_history = nullptr; } } // namespace branch_prediction diff --git a/src/cpu/pred/multiperspective_perceptron_tage.hh b/src/cpu/pred/multiperspective_perceptron_tage.hh index 3a92e3cf07..9c7ee3556f 100644 --- a/src/cpu/pred/multiperspective_perceptron_tage.hh +++ b/src/cpu/pred/multiperspective_perceptron_tage.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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 2019 Texas A&M University * * Redistribution and use in source and binary forms, with or without @@ -178,7 +190,7 @@ class MPP_StatisticalCorrector : public StatisticalCorrector void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, StatisticalCorrector::BranchInfo *bi, - Addr corrTarget, bool b, int hitBank, int altBank, + Addr target, bool b, int hitBank, int altBank, int64_t phist) override; virtual void getBiasLSUM(Addr branch_pc, @@ -236,12 +248,12 @@ class MultiperspectivePerceptronTAGE : public MultiperspectivePerceptron bool lookup(ThreadID tid, Addr instPC, void * &bp_history) override; - void update(ThreadID tid, Addr instPC, bool taken, - void *bp_history, bool squashed, - const StaticInstPtr & inst, - Addr corrTarget) override; - void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) override; - void squash(ThreadID tid, void *bp_history) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; + void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, + Addr target, void * &bp_history) override; + void squash(ThreadID tid, void * &bp_history) override; }; diff --git a/src/cpu/pred/tage.cc b/src/cpu/pred/tage.cc index 1ba52e27c7..35c0d75352 100644 --- a/src/cpu/pred/tage.cc +++ b/src/cpu/pred/tage.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The University of Wisconsin * * Copyright (c) 2006 INRIA (Institut National de Recherche en @@ -56,8 +68,8 @@ TAGE::TAGE(const TAGEParams ¶ms) : BPredUnit(params), tage(params.tage) // PREDICTOR UPDATE void -TAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget) +TAGE::update(ThreadID tid, Addr pc, bool taken, void * &bp_history, + bool squashed, const StaticInstPtr & inst, Addr target) { assert(bp_history); @@ -67,69 +79,65 @@ TAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, if (squashed) { // This restores the global history, then update it // and recomputes the folded histories. - tage->squash(tid, taken, tage_bi, corrTarget); + tage->squash(tid, taken, tage_bi, target); return; } int nrand = random_mt.random() & 3; if (bi->tageBranchInfo->condBranch) { DPRINTF(Tage, "Updating tables for branch:%lx; taken?:%d\n", - branch_pc, taken); + pc, taken); tage->updateStats(taken, bi->tageBranchInfo); - tage->condBranchUpdate(tid, branch_pc, taken, tage_bi, nrand, - corrTarget, bi->tageBranchInfo->tagePred); + tage->condBranchUpdate(tid, pc, taken, tage_bi, nrand, + target, bi->tageBranchInfo->tagePred); } // optional non speculative update of the histories - tage->updateHistories(tid, branch_pc, taken, tage_bi, false, inst, - corrTarget); + tage->updateHistories(tid, pc, taken, tage_bi, false, inst, target); delete bi; + bp_history = nullptr; } void -TAGE::squash(ThreadID tid, void *bp_history) +TAGE::squash(ThreadID tid, void * &bp_history) { TageBranchInfo *bi = static_cast(bp_history); DPRINTF(Tage, "Deleting branch info: %lx\n", bi->tageBranchInfo->branchPC); delete bi; + bp_history = nullptr; } bool -TAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) +TAGE::predict(ThreadID tid, Addr pc, bool cond_branch, void* &b) { TageBranchInfo *bi = new TageBranchInfo(*tage);//nHistoryTables+1); b = (void*)(bi); - return tage->tagePredict(tid, branch_pc, cond_branch, bi->tageBranchInfo); + return tage->tagePredict(tid, pc, cond_branch, bi->tageBranchInfo); } bool -TAGE::lookup(ThreadID tid, Addr branch_pc, void* &bp_history) +TAGE::lookup(ThreadID tid, Addr pc, void* &bp_history) { - bool retval = predict(tid, branch_pc, true, bp_history); + bool retval = predict(tid, pc, true, bp_history); - TageBranchInfo *bi = static_cast(bp_history); - - DPRINTF(Tage, "Lookup branch: %lx; predict:%d\n", branch_pc, retval); - - tage->updateHistories(tid, branch_pc, retval, bi->tageBranchInfo, true); + DPRINTF(Tage, "Lookup branch: %lx; predict:%d\n", pc, retval); return retval; } void -TAGE::btbUpdate(ThreadID tid, Addr branch_pc, void* &bp_history) +TAGE::updateHistories(ThreadID tid, Addr pc, bool uncond, + bool taken, Addr target, void * &bp_history) { - TageBranchInfo *bi = static_cast(bp_history); - tage->btbUpdate(tid, branch_pc, bi->tageBranchInfo); -} + assert(uncond || bp_history); + if (uncond) { + DPRINTF(Tage, "UnConditionalBranch: %lx\n", pc); + predict(tid, pc, false, bp_history); + } -void -TAGE::uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history) -{ - DPRINTF(Tage, "UnConditionalBranch: %lx\n", br_pc); - predict(tid, br_pc, false, bp_history); + // Update the global history for all branches TageBranchInfo *bi = static_cast(bp_history); - tage->updateHistories(tid, br_pc, true, bi->tageBranchInfo, true); + tage->updateHistories(tid, pc, taken, bi->tageBranchInfo, true); } } // namespace branch_prediction diff --git a/src/cpu/pred/tage.hh b/src/cpu/pred/tage.hh index 568f07bf9e..6d4151cb11 100644 --- a/src/cpu/pred/tage.hh +++ b/src/cpu/pred/tage.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2014 The University of Wisconsin * * Copyright (c) 2006 INRIA (Institut National de Recherche en @@ -87,13 +99,13 @@ class TAGE: public BPredUnit TAGE(const TAGEParams ¶ms); // Base class methods. - void uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history) override; - bool lookup(ThreadID tid, Addr branch_addr, void* &bp_history) override; - void btbUpdate(ThreadID tid, Addr branch_addr, void* &bp_history) override; - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, - Addr corrTarget) override; - virtual void squash(ThreadID tid, void *bp_history) override; + bool lookup(ThreadID tid, Addr pc, void* &bp_history) override; + void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, + Addr target, void * &bp_history) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; + virtual void squash(ThreadID tid, void * &bp_history) override; }; } // namespace branch_prediction diff --git a/src/cpu/pred/tage_sc_l.cc b/src/cpu/pred/tage_sc_l.cc index 615c6230c8..a178ba6fc6 100644 --- a/src/cpu/pred/tage_sc_l.cc +++ b/src/cpu/pred/tage_sc_l.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2018 Metempsy Technology Consulting * All rights reserved. * @@ -362,16 +374,16 @@ TAGE_SC_L_TAGE::extraAltCalc(TAGEBase::BranchInfo* bi) } bool -TAGE_SC_L::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) +TAGE_SC_L::predict(ThreadID tid, Addr pc, bool cond_branch, void* &b) { TageSCLBranchInfo *bi = new TageSCLBranchInfo(*tage, *statisticalCorrector, *loopPredictor); b = (void*)(bi); - bool pred_taken = tage->tagePredict(tid, branch_pc, cond_branch, + bool pred_taken = tage->tagePredict(tid, pc, cond_branch, bi->tageBranchInfo); - pred_taken = loopPredictor->loopPredict(tid, branch_pc, cond_branch, + pred_taken = loopPredictor->loopPredict(tid, pc, cond_branch, bi->lpBranchInfo, pred_taken, instShiftAmt); @@ -394,7 +406,7 @@ TAGE_SC_L::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) bool bias = (bi->tageBranchInfo->longestMatchPred != bi->tageBranchInfo->altTaken); - pred_taken = statisticalCorrector->scPredict(tid, branch_pc, cond_branch, + pred_taken = statisticalCorrector->scPredict(tid, pc, cond_branch, bi->scBranchInfo, pred_taken, bias, use_tage_ctr, tage_ctr, tage->getTageCtrBits(), bi->tageBranchInfo->hitBank, bi->tageBranchInfo->altBank, tage->getPathHist(tid)); @@ -410,8 +422,8 @@ TAGE_SC_L::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) } void -TAGE_SC_L::update(ThreadID tid, Addr branch_pc, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget) +TAGE_SC_L::update(ThreadID tid, Addr pc, bool taken, void *&bp_history, + bool squashed, const StaticInstPtr & inst, Addr target) { assert(bp_history); @@ -423,7 +435,7 @@ TAGE_SC_L::update(ThreadID tid, Addr branch_pc, bool taken, void *bp_history, if (tage->isSpeculativeUpdateEnabled()) { // This restores the global history, then update it // and recomputes the folded histories. - tage->squash(tid, taken, tage_bi, corrTarget); + tage->squash(tid, taken, tage_bi, target); if (bi->tageBranchInfo->condBranch) { loopPredictor->squashLoop(bi->lpBranchInfo); } @@ -434,7 +446,7 @@ TAGE_SC_L::update(ThreadID tid, Addr branch_pc, bool taken, void *bp_history, int nrand = random_mt.random() & 3; if (tage_bi->condBranch) { DPRINTF(TageSCL, "Updating tables for branch:%lx; taken?:%d\n", - branch_pc, taken); + pc, taken); tage->updateStats(taken, bi->tageBranchInfo); loopPredictor->updateStats(taken, bi->lpBranchInfo); @@ -443,26 +455,27 @@ TAGE_SC_L::update(ThreadID tid, Addr branch_pc, bool taken, void *bp_history, bool bias = (bi->tageBranchInfo->longestMatchPred != bi->tageBranchInfo->altTaken); - statisticalCorrector->condBranchUpdate(tid, branch_pc, taken, - bi->scBranchInfo, corrTarget, bias, bi->tageBranchInfo->hitBank, + statisticalCorrector->condBranchUpdate(tid, pc, taken, + bi->scBranchInfo, target, bias, bi->tageBranchInfo->hitBank, bi->tageBranchInfo->altBank, tage->getPathHist(tid)); - loopPredictor->condBranchUpdate(tid, branch_pc, taken, + loopPredictor->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt); - tage->condBranchUpdate(tid, branch_pc, taken, bi->tageBranchInfo, - nrand, corrTarget, bi->lpBranchInfo->predTaken); + tage->condBranchUpdate(tid, pc, taken, bi->tageBranchInfo, + nrand, target, bi->lpBranchInfo->predTaken); } if (!tage->isSpeculativeUpdateEnabled()) { - statisticalCorrector->scHistoryUpdate(branch_pc, inst, taken, - bi->scBranchInfo, corrTarget); + statisticalCorrector->scHistoryUpdate(pc, inst, taken, + bi->scBranchInfo, target); - tage->updateHistories(tid, branch_pc, taken, bi->tageBranchInfo, false, - inst, corrTarget); + tage->updateHistories(tid, pc, taken, bi->tageBranchInfo, false, + inst, target); } delete bi; + bp_history = nullptr; } } // namespace branch_prediction diff --git a/src/cpu/pred/tage_sc_l.hh b/src/cpu/pred/tage_sc_l.hh index 7dead58363..6c56e69982 100644 --- a/src/cpu/pred/tage_sc_l.hh +++ b/src/cpu/pred/tage_sc_l.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2022-2023 The University of Edinburgh + * 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) 2018 Metempsy Technology Consulting * All rights reserved. * @@ -159,12 +171,11 @@ class TAGE_SC_L: public LTAGE public: TAGE_SC_L(const TAGE_SC_LParams ¶ms); - bool predict( - ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) override; + bool predict(ThreadID tid, Addr pc, bool cond_branch, void* &b) override; - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, - Addr corrTarget) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; protected: diff --git a/src/cpu/pred/tournament.cc b/src/cpu/pred/tournament.cc index b3a55313b7..a480497c0a 100644 --- a/src/cpu/pred/tournament.cc +++ b/src/cpu/pred/tournament.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2011, 2014 ARM Limited + * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -134,50 +135,22 @@ TournamentBP::calcLocHistIdx(Addr &branch_addr) inline void -TournamentBP::updateGlobalHistTaken(ThreadID tid) +TournamentBP::updateGlobalHist(ThreadID tid, bool taken) { - globalHistory[tid] = (globalHistory[tid] << 1) | 1; + globalHistory[tid] = (globalHistory[tid] << 1) | taken; globalHistory[tid] = globalHistory[tid] & historyRegisterMask; } inline void -TournamentBP::updateGlobalHistNotTaken(ThreadID tid) -{ - globalHistory[tid] = (globalHistory[tid] << 1); - globalHistory[tid] = globalHistory[tid] & historyRegisterMask; -} - -inline -void -TournamentBP::updateLocalHistTaken(unsigned local_history_idx) +TournamentBP::updateLocalHist(unsigned local_history_idx, bool taken) { localHistoryTable[local_history_idx] = - (localHistoryTable[local_history_idx] << 1) | 1; -} - -inline -void -TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx) -{ - localHistoryTable[local_history_idx] = - (localHistoryTable[local_history_idx] << 1); -} - - -void -TournamentBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history) -{ - unsigned local_history_idx = calcLocHistIdx(branch_addr); - //Update Global History to Not Taken (clear LSB) - globalHistory[tid] &= (historyRegisterMask & ~1ULL); - //Update Local History to Not Taken - localHistoryTable[local_history_idx] = - localHistoryTable[local_history_idx] & (localPredictorMask & ~1ULL); + (localHistoryTable[local_history_idx] << 1) | taken; } bool -TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) +TournamentBP::lookup(ThreadID tid, Addr pc, void * &bp_history) { bool local_prediction; unsigned local_history_idx; @@ -187,7 +160,7 @@ TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) bool choice_prediction; //Lookup in the local predictor to get its branch prediction - local_history_idx = calcLocHistIdx(branch_addr); + local_history_idx = calcLocHistIdx(pc); local_predictor_idx = localHistoryTable[local_history_idx] & localPredictorMask; local_prediction = localCtrs[local_predictor_idx] > localThreshold; @@ -212,57 +185,53 @@ TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) assert(local_history_idx < localHistoryTableSize); - // Speculative update of the global history and the - // selected local history. + // Select and return the prediction + // History update will be happen in the next function if (choice_prediction) { - if (global_prediction) { - updateGlobalHistTaken(tid); - updateLocalHistTaken(local_history_idx); - return true; - } else { - updateGlobalHistNotTaken(tid); - updateLocalHistNotTaken(local_history_idx); - return false; - } + return global_prediction; } else { - if (local_prediction) { - updateGlobalHistTaken(tid); - updateLocalHistTaken(local_history_idx); - return true; - } else { - updateGlobalHistNotTaken(tid); - updateLocalHistNotTaken(local_history_idx); - return false; - } + return local_prediction; } } void -TournamentBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history) +TournamentBP::updateHistories(ThreadID tid, Addr pc, bool uncond, + bool taken, Addr target, void * &bp_history) { - // Create BPHistory and pass it back to be recorded. - BPHistory *history = new BPHistory; - history->globalHistory = globalHistory[tid]; - history->localPredTaken = true; - history->globalPredTaken = true; - history->globalUsed = true; - history->localHistoryIdx = invalidPredictorIndex; - history->localHistory = invalidPredictorIndex; - bp_history = static_cast(history); + assert(uncond || bp_history); + if (uncond) { + // Create BPHistory and pass it back to be recorded. + BPHistory *history = new BPHistory; + history->globalHistory = globalHistory[tid]; + history->localPredTaken = true; + history->globalPredTaken = true; + history->globalUsed = true; + history->localHistoryIdx = invalidPredictorIndex; + history->localHistory = invalidPredictorIndex; + bp_history = static_cast(history); + } - updateGlobalHistTaken(tid); + // Update the global history for all branches + updateGlobalHist(tid, taken); + + // Update the local history only for conditional branches + if (!uncond) { + auto history = static_cast(bp_history); + updateLocalHist(history->localHistoryIdx, taken); + } } + void -TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken, - void *bp_history, bool squashed, - const StaticInstPtr & inst, Addr corrTarget) +TournamentBP::update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) { assert(bp_history); BPHistory *history = static_cast(bp_history); - unsigned local_history_idx = calcLocHistIdx(branch_addr); + unsigned local_history_idx = calcLocHistIdx(pc); assert(local_history_idx < localHistoryTableSize); @@ -330,10 +299,11 @@ TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken, // We're done with this history, now delete it. delete history; + bp_history = nullptr; } void -TournamentBP::squash(ThreadID tid, void *bp_history) +TournamentBP::squash(ThreadID tid, void * &bp_history) { BPHistory *history = static_cast(bp_history); @@ -347,6 +317,7 @@ TournamentBP::squash(ThreadID tid, void *bp_history) // Delete this BPHistory now that we're done with it. delete history; + bp_history = nullptr; } #ifdef GEM5_DEBUG diff --git a/src/cpu/pred/tournament.hh b/src/cpu/pred/tournament.hh index 018d6756e4..1f404c1cce 100644 --- a/src/cpu/pred/tournament.hh +++ b/src/cpu/pred/tournament.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2011, 2014 ARM Limited + * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -70,52 +71,14 @@ class TournamentBP : public BPredUnit */ TournamentBP(const TournamentBPParams ¶ms); - /** - * Looks up the given address in the branch predictor and returns - * a true/false value as to whether it is taken. Also creates a - * BPHistory object to store any state it will need on squash/update. - * @param branch_addr The address of the branch to look up. - * @param bp_history Pointer that will be set to the BPHistory object. - * @return Whether or not the branch is taken. - */ - bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history); - - /** - * Records that there was an unconditional branch, and modifies - * the bp history to point to an object that has the previous - * global history stored in it. - * @param bp_history Pointer that will be set to the BPHistory object. - */ - void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); - /** - * Updates the branch predictor to Not Taken if a BTB entry is - * invalid or not found. - * @param branch_addr The address of the branch to look up. - * @param bp_history Pointer to any bp history state. - * @return Whether or not the branch is taken. - */ - void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history); - /** - * Updates the branch predictor with the actual result of a branch. - * @param branch_addr The address of the branch to update. - * @param taken Whether or not the branch was taken. - * @param bp_history Pointer to the BPHistory object that was created - * when the branch was predicted. - * @param squashed is set when this function is called during a squash - * operation. - * @param inst Static instruction information - * @param corrTarget Resolved target of the branch (only needed if - * squashed) - */ - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed, const StaticInstPtr & inst, Addr corrTarget); - - /** - * Restores the global branch history on a squash. - * @param bp_history Pointer to the BPHistory object that has the - * previous global branch history in it. - */ - void squash(ThreadID tid, void *bp_history); + // Base class methods. + bool lookup(ThreadID tid, Addr pc, void* &bp_history) override; + void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, + Addr target, void * &bp_history) override; + void update(ThreadID tid, Addr pc, bool taken, + void * &bp_history, bool squashed, + const StaticInstPtr & inst, Addr target) override; + void squash(ThreadID tid, void * &bp_history) override; private: /** @@ -131,25 +94,18 @@ class TournamentBP : public BPredUnit */ inline unsigned calcLocHistIdx(Addr &branch_addr); - /** Updates global history as taken. */ - inline void updateGlobalHistTaken(ThreadID tid); - - /** Updates global history as not taken. */ - inline void updateGlobalHistNotTaken(ThreadID tid); + /** Updates global history with the given direction + * @param taken Whether or not the branch was taken + */ + inline void updateGlobalHist(ThreadID tid, bool taken); /** - * Updates local histories as taken. + * Updates local histories. * @param local_history_idx The local history table entry that * will be updated. + * @param taken Whether or not the branch was taken. */ - inline void updateLocalHistTaken(unsigned local_history_idx); - - /** - * Updates local histories as not taken. - * @param local_history_idx The local history table entry that - * will be updated. - */ - inline void updateLocalHistNotTaken(unsigned local_history_idx); + inline void updateLocalHist(unsigned local_history_idx, bool taken); /** * The branch history information that is created upon predicting From b670ed9fba7c99092830e59e573d5a33e27dde00 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 24 Oct 2023 14:51:19 -0700 Subject: [PATCH 498/693] util: Add 'sudo' to rm WORK_DIR command (#496) Unfortunately Actions uses docker contaienrs to create files on the system with root permissions. The 'vagrant' user which we login to run the Actions Runner, can't remove these files. However, 'vagrant' is part of the sudo group and can therefore use sudo to remove these files. I don't like this, but it works. --- util/github-runners-vagrant/action-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/github-runners-vagrant/action-run.sh b/util/github-runners-vagrant/action-run.sh index b3c343e495..e280b2f03a 100755 --- a/util/github-runners-vagrant/action-run.sh +++ b/util/github-runners-vagrant/action-run.sh @@ -76,6 +76,6 @@ while true; do ./run.sh # This will complete with the runner being destroyed # 4. Cleanup the machine - rm -rf "${WORK_DIR}" + sudo rm -rf "${WORK_DIR}" docker system prune --force --volumes --all done From b6ce2d0db891a2dee0bace10222dec06cb4c175b Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 24 Oct 2023 14:51:31 -0700 Subject: [PATCH 499/693] misc: Add GitHub Runner API rate limiting (#497) This stops the 'action-run.sh' from exhausting the GitHub API by adding sleeps. --- util/github-runners-vagrant/action-run.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/github-runners-vagrant/action-run.sh b/util/github-runners-vagrant/action-run.sh index e280b2f03a..67cc6f3cf8 100755 --- a/util/github-runners-vagrant/action-run.sh +++ b/util/github-runners-vagrant/action-run.sh @@ -62,6 +62,15 @@ while true; do token=$(echo ${token_curl} | jq -r '.token') + if [[ "${token}" == "null" ]]; + then + # If "null" is returned, this can be because the GitHub API rate limit + # has been exceeded. To be safe we wait for 15 mintues before + # continuing. + sleep 900 # 15 minutes. + continue + fi + # 2. Configure the runner. ./config.sh --unattended \ --url https://github.com/${GITHUB_ORG} \ @@ -78,4 +87,9 @@ while true; do # 4. Cleanup the machine sudo rm -rf "${WORK_DIR}" docker system prune --force --volumes --all + + # 5. Sleep for a few minutes + # GitHub has a api rate limit. This sleep ensures we dont ping GitHub + # too frequently. + sleep 180 # 3 minutes. done From a47ca9dadcf2fec62d20097fad1a80fca7fd927d Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 15 Oct 2023 19:29:01 -0700 Subject: [PATCH 500/693] arch-riscv: Add a function generating the ISA string Currently, we are hardcoding the ISA string in the device tree generator. The ISA string from the device tree affects which ISA extensions will be used by the bootloader/kernel. This function allows generating the ISA string from the gem5's ISA object rather than using hardcoded values. Change-Id: I2f3720fb6da24347f38f26d9a49939484b11d3bb Signed-off-by: Hoa Nguyen --- src/arch/riscv/RiscvISA.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index 3f123405e9..62dcffb5d8 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -13,6 +13,7 @@ # # Copyright (c) 2016 RISC-V Foundation # Copyright (c) 2016 The University of Virginia +# Copyright (c) 2023 The Regents of the University of California # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -94,3 +95,18 @@ class RiscvISA(BaseISA): "Length of each vector element in bits. \ ELEN in Ch. 2 of RISC-V vector spec", ) + + def get_isa_string(self): + isa_extensions = [] + # check for the base ISA type + if self.riscv_type.value == "RV32": + isa_extensions.append("rv32") + elif self.riscv_type.value == "RV64": + isa_extensions.append("rv64") + # use imafdc by default + isa_extensions.extend(["i", "m", "a", "f", "d", "c"]) + # check for the vector extension + if self.enable_rvv.value == True: + isa_extensions.append("v") + isa_string = "".join(isa_extensions) + return isa_string From 4f72f6172ac6e44b770a590a5cfbab063ce36412 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 15 Oct 2023 19:36:20 -0700 Subject: [PATCH 501/693] stdlib: Use the ISA string generator in the RiscvBoard Current hardcoded value does not support vector instructions. The new ISA string generator function allows the flexibility of using or not using the vector extension. Change-Id: Ic78c4b6629ad3813fc172f700d77ea956552e613 Signed-off-by: Hoa Nguyen --- src/python/gem5/components/boards/riscv_board.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 450fcb7866..9b0d6454e1 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -280,7 +280,11 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): node.append(FdtPropertyWords("reg", state.CPUAddrCells(i))) node.append(FdtPropertyStrings("mmu-type", "riscv,sv48")) node.append(FdtPropertyStrings("status", "okay")) - node.append(FdtPropertyStrings("riscv,isa", "rv64imafdc")) + node.append( + FdtPropertyStrings( + "riscv,isa", core.core.isa[0].get_isa_string() + ) + ) # TODO: Should probably get this from the core. freq = self.clk_domain.clock[0].frequency node.append(FdtPropertyWords("clock-frequency", freq)) From dce8d07703d0a799959b7bce79c43790775b0323 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 15 Oct 2023 19:42:35 -0700 Subject: [PATCH 502/693] stdlib: Turn off RVV for U74 core The U74 core doesn't support vector instructions. Change-Id: Iadfb6b43ef8c62dcad23391e468a43b908e4a22c Signed-off-by: Hoa Nguyen --- src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py index 22ec29e59d..19dc2f2e8c 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py @@ -214,3 +214,4 @@ class U74Core(BaseCPUCore): core_id, ): super().__init__(core=U74CPU(cpu_id=core_id), isa=ISA.RISCV) + self.core.isa[0].enable_rvv = False From 50196863a4148d50421b6228bf0b8362d811d0eb Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 15 Oct 2023 19:54:22 -0700 Subject: [PATCH 503/693] stdlib,dev: Fix several hardcoded RISC-V ISA strings The "s" and "u" letters are not recognized by the Linux kernel as RISC-V extensions [1]. [1] https://elixir.bootlin.com/linux/v6.5.7/source/arch/riscv/kernel/cpufeature.c#L170 Change-Id: I2a99557482cde6e6d6160626b3995275c41b1577 Signed-off-by: Hoa Nguyen --- src/dev/riscv/HiFive.py | 2 +- src/python/gem5/components/boards/experimental/lupv_board.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dev/riscv/HiFive.py b/src/dev/riscv/HiFive.py index 5bd6363363..c3d51aa5e7 100755 --- a/src/dev/riscv/HiFive.py +++ b/src/dev/riscv/HiFive.py @@ -251,7 +251,7 @@ class HiFive(HiFiveBase): def annotateCpuDeviceNode(self, cpu, state): cpu.append(FdtPropertyStrings("mmu-type", "riscv,sv48")) cpu.append(FdtPropertyStrings("status", "okay")) - cpu.append(FdtPropertyStrings("riscv,isa", "rv64imafdcsu")) + cpu.append(FdtPropertyStrings("riscv,isa", "rv64imafdc")) cpu.appendCompatible(["riscv"]) int_node = FdtNode("interrupt-controller") diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index a0ec89eafb..85843b89e2 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -316,7 +316,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): node.append(FdtPropertyWords("reg", state.CPUAddrCells(i))) node.append(FdtPropertyStrings("mmu-type", "riscv,sv48")) node.append(FdtPropertyStrings("status", "okay")) - node.append(FdtPropertyStrings("riscv,isa", "rv64imafdcsu")) + node.append(FdtPropertyStrings("riscv,isa", "rv64imafdc")) # TODO: Should probably get this from the core. freq = self.clk_domain.clock[0].frequency node.appendCompatible(["riscv"]) From 605ec6899e6b2983e4ec9ea8e257447b19eb9a7a Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 29 Aug 2023 19:53:26 +0800 Subject: [PATCH 504/693] arch-riscv: Move VMem implementation from header to source Move the VMem implementation from header_output to decoder_output and exec_output respectively. Change-Id: I699e197f37f22a59ecb9f92a64b5e296d2e9f5fa --- src/arch/riscv/isa/formats/vector_mem.isa | 28 +- src/arch/riscv/isa/includes.isa | 2 - src/arch/riscv/isa/templates/vector_mem.isa | 322 ++++++++++++-------- 3 files changed, 216 insertions(+), 136 deletions(-) diff --git a/src/arch/riscv/isa/formats/vector_mem.isa b/src/arch/riscv/isa/formats/vector_mem.isa index da53d80d0a..3b3309797c 100644 --- a/src/arch/riscv/isa/formats/vector_mem.isa +++ b/src/arch/riscv/isa/formats/vector_mem.isa @@ -34,6 +34,14 @@ def setVlen(): def setVlenb(): return "uint32_t vlenb = VlenbBits;\n" +def declareVMemTemplate(class_name): + return f''' + template class {class_name}; + template class {class_name}; + template class {class_name}; + template class {class_name}; + ''' + def VMemBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, base_class, postacc_code='', declare_template_base=VMemMacroDeclare, @@ -47,22 +55,20 @@ def VMemBase(name, Name, ea_code, memacc_code, mem_flags, iop = InstObjParams(name, Name, base_class, {'ea_code': ea_code, 'memacc_code': memacc_code, - 'postacc_code': postacc_code }, + 'postacc_code': postacc_code, + 'declare_vmem_template': declareVMemTemplate(Name)}, inst_flags) constructTemplate = eval(exec_template_base + 'Constructor') header_output = declare_template_base.subst(iop) - decoder_output = '' - if declare_template_base is not VMemTemplateMacroDeclare: - decoder_output += constructTemplate.subst(iop) - else: - header_output += constructTemplate.subst(iop) + decoder_output = constructTemplate.subst(iop) decode_block = decode_template.subst(iop) exec_output = '' if not is_macroop: return (header_output, decoder_output, decode_block, exec_output) + micro_class_name = exec_template_base + 'MicroInst' microiop = InstObjParams(name + '_micro', Name + 'Micro', exec_template_base + 'MicroInst', @@ -70,7 +76,8 @@ def VMemBase(name, Name, ea_code, memacc_code, mem_flags, 'memacc_code': memacc_code, 'postacc_code': postacc_code, 'set_vlenb': setVlenb(), - 'set_vlen': setVlen()}, + 'set_vlen': setVlen(), + 'declare_vmem_template': declareVMemTemplate(Name + 'Micro')}, inst_flags) if mem_flags: @@ -79,17 +86,16 @@ def VMemBase(name, Name, ea_code, memacc_code, mem_flags, microiop.constructor += s microDeclTemplate = eval(exec_template_base + 'Micro' + 'Declare') + microConsTemplate = eval(exec_template_base + 'Micro' + 'Constructor') microExecTemplate = eval(exec_template_base + 'Micro' + 'Execute') microInitTemplate = eval(exec_template_base + 'Micro' + 'InitiateAcc') microCompTemplate = eval(exec_template_base + 'Micro' + 'CompleteAcc') header_output = microDeclTemplate.subst(microiop) + header_output + decoder_output = microConsTemplate.subst(microiop) + decoder_output micro_exec_output = (microExecTemplate.subst(microiop) + microInitTemplate.subst(microiop) + microCompTemplate.subst(microiop)) - if declare_template_base is not VMemTemplateMacroDeclare: - exec_output += micro_exec_output - else: - header_output += micro_exec_output + exec_output += micro_exec_output return (header_output, decoder_output, decode_block, exec_output) diff --git a/src/arch/riscv/isa/includes.isa b/src/arch/riscv/isa/includes.isa index 76f2388faf..b37e62bca8 100644 --- a/src/arch/riscv/isa/includes.isa +++ b/src/arch/riscv/isa/includes.isa @@ -46,8 +46,6 @@ output header {{ #include #include -#include "arch/generic/memhelpers.hh" -#include "arch/riscv/decoder.hh" #include "arch/riscv/insts/amo.hh" #include "arch/riscv/insts/bs.hh" #include "arch/riscv/insts/compressed.hh" diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index 8cbab044ec..84cee9af73 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -96,22 +96,8 @@ private: RegId srcRegIdxArr[3]; RegId destRegIdxArr[1]; public: - %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx, uint32_t _vlen) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _microVl, _microIdx, _vlen) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); - _numTypedDestRegs[VecRegClass]++; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _microIdx]); - if (!_machInst.vm) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); - } - } + %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx, uint32_t _vlen); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -123,6 +109,27 @@ public: }}; +def template VleMicroConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint8_t _microVl, + uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s( + "%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _microIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } +} + +}}; + def template VleMicroExecute {{ Fault @@ -293,21 +300,7 @@ private: RegId destRegIdxArr[0]; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _microVl, _microIdx, _vlen) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _microIdx]); - if (!_machInst.vm) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); - } - this->flags[IsVector] = true; - this->flags[IsStore] = true; - } + uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -318,6 +311,27 @@ public: }}; +def template VseMicroConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s( + "%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _microIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsVector] = true; + this->flags[IsStore] = true; +} + +}}; + def template VseMicroExecute {{ Fault @@ -518,18 +532,8 @@ private: RegId srcRegIdxArr[2]; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) - : %(base_class)s("%(mnemonic)s", _machInst, - %(op_class)s, _microVl, _microIdx, _vlen) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _microIdx]); - this->flags[IsVector] = true; - this->flags[IsStore] = true; - } + uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen); + Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, @@ -539,6 +543,24 @@ public: }}; +def template VsWholeMicroConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s( + "%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _microIdx]); + this->flags[IsVector] = true; + this->flags[IsStore] = true; +} + +}}; + def template VsWholeMicroExecute {{ Fault @@ -644,19 +666,8 @@ private: RegId srcRegIdxArr[1]; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) - : %(base_class)s("%(mnemonic)s_micro", _machInst, - %(op_class)s, _microVl, _microIdx, _vlen) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); - _numTypedDestRegs[VecRegClass]++; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - this->flags[IsVector] = true; - this->flags[IsLoad] = true; - } + uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen); + Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; Fault completeAcc(PacketPtr, ExecContext *, @@ -666,6 +677,25 @@ public: }}; +def template VlWholeMicroConstructor {{ + +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen) + : %(base_class)s("%(mnemonic)s_micro", _machInst, %(op_class)s, _microVl, + _microIdx, _vlen) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _microIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + this->flags[IsVector] = true; + this->flags[IsLoad] = true; +} + +}}; + def template VlWholeMicroExecute {{ Fault @@ -803,24 +833,7 @@ private: RegId destRegIdxArr[1]; public: %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, - uint32_t _microVl) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _regIdx, _microIdx, _microVl) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _regIdx]); - _numTypedDestRegs[VecRegClass]++; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs2]); - // We treat agnostic as undistrubed - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _regIdx]); - if (!_machInst.vm) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); - } - this->flags[IsLoad] = true; - } + uint32_t _microVl); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -831,6 +844,31 @@ public: }}; +def template VlStrideMicroConstructor {{ + +%(class_name)s::%(class_name)s( + ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + uint32_t _microVl) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _regIdx, _microIdx, _microVl) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _regIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs2]); + // We treat agnostic as undistrubed + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _regIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsLoad] = true; +} + +}}; + def template VlStrideMicroExecute {{ Fault @@ -1019,21 +1057,7 @@ private: RegId destRegIdxArr[0]; public: %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, - uint32_t _microVl) - : %(base_class)s("%(mnemonic)s""_micro", _machInst, %(op_class)s, - _regIdx, _microIdx, _microVl) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs2]); - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _regIdx]); - if (!_machInst.vm) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); - } - this->flags[IsStore] = true; - } + uint32_t _microVl); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -1044,6 +1068,28 @@ public: }}; +def template VsStrideMicroConstructor {{ + +%(class_name)s::%(class_name)s( + ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + uint32_t _microVl) + : %(base_class)s("%(mnemonic)s""_micro", _machInst, %(op_class)s, + _regIdx, _microIdx, _microVl) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs2]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _regIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsStore] = true; +} + +}}; + def template VsStrideMicroExecute {{ Fault @@ -1185,6 +1231,8 @@ template this->flags[IsVector] = true; } +%(declare_vmem_template)s; + }}; def template VlIndexMicroDeclare {{ @@ -1199,24 +1247,7 @@ private: public: %(class_name)s(ExtMachInst _machInst, uint8_t _vdRegIdx, uint8_t _vdElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _vdRegIdx, _vdElemIdx, _vs2RegIdx, _vs2ElemIdx) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _vdRegIdx]); - _numTypedDestRegs[VecRegClass]++; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _vs2RegIdx]); - // We treat agnostic as undistrubed - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _vdRegIdx]); - if (!_machInst.vm) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); - } - this->flags[IsLoad] = true; - } + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -1227,6 +1258,34 @@ public: }}; +def template VlIndexMicroConstructor {{ + +template +%(class_name)s::%(class_name)s( + ExtMachInst _machInst,uint8_t _vdRegIdx, uint8_t _vdElemIdx, + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _vdRegIdx, _vdElemIdx, _vs2RegIdx, _vs2ElemIdx) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setDestRegIdx(_numDestRegs++, vecRegClass[_machInst.vd + _vdRegIdx]); + _numTypedDestRegs[VecRegClass]++; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _vs2RegIdx]); + // We treat agnostic as undistrubed + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vd + _vdRegIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsLoad] = true; +} + +%(declare_vmem_template)s; + +}}; + def template VlIndexMicroExecute {{ template @@ -1364,6 +1423,8 @@ Fault return NoFault; } +%(declare_vmem_template)s; + }}; def template VsIndexConstructor {{ @@ -1410,6 +1471,8 @@ template this->flags[IsVector] = true; } +%(declare_vmem_template)s; + }}; def template VsIndexMicroDeclare {{ @@ -1424,22 +1487,7 @@ private: public: %(class_name)s(ExtMachInst _machInst, uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) - : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, - _vs3RegIdx, _vs3ElemIdx, _vs2RegIdx, _vs2ElemIdx) - { - %(set_reg_idx_arr)s; - _numSrcRegs = 0; - _numDestRegs = 0; - setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _vs2RegIdx]); - // We treat agnostic as undistrubed - setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _vs3RegIdx]); - if (!_machInst.vm) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); - } - this->flags[IsStore] = true; - } + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -1450,6 +1498,32 @@ public: }}; +def template VsIndexMicroConstructor {{ + +template +%(class_name)s::%(class_name)s(ExtMachInst _machInst, + uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, + uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, + _vs3RegIdx, _vs3ElemIdx, _vs2RegIdx, _vs2ElemIdx) +{ + %(set_reg_idx_arr)s; + _numSrcRegs = 0; + _numDestRegs = 0; + setSrcRegIdx(_numSrcRegs++, intRegClass[_machInst.rs1]); + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2 + _vs2RegIdx]); + // We treat agnostic as undistrubed + setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs3 + _vs3RegIdx]); + if (!_machInst.vm) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[0]); + } + this->flags[IsStore] = true; +} + +%(declare_vmem_template)s; + +}}; + def template VsIndexMicroExecute {{ template @@ -1548,6 +1622,8 @@ Fault return NoFault; } +%(declare_vmem_template)s; + }}; def template VMemBaseDecodeBlock {{ From 62af678d5c51b1fa15ec40c5d4ff4e36971e34f1 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 24 Oct 2023 14:47:04 +0800 Subject: [PATCH 505/693] arch-riscv: Move VArith implementations from header to source Move VArith implementations from heaher_output to decoder_output and exec_output respectively Change-Id: I406eedbd9dd625aa939ec0e20aa29ef4f18ba79c --- src/arch/riscv/isa/formats/vector_arith.isa | 564 +++++++++++------- src/arch/riscv/isa/templates/vector_arith.isa | 145 ++++- 2 files changed, 487 insertions(+), 222 deletions(-) diff --git a/src/arch/riscv/isa/formats/vector_arith.isa b/src/arch/riscv/isa/formats/vector_arith.isa index 0d5055ea8f..1ddf323f04 100644 --- a/src/arch/riscv/isa/formats/vector_arith.isa +++ b/src/arch/riscv/isa/formats/vector_arith.isa @@ -121,6 +121,28 @@ let {{ softfloat_exceptionFlags = 0; xc->setMiscReg(MISCREG_FFLAGS, FFLAGS); ''' + + def declareVArithTemplate( + class_name, type_name='uint', min_size=8, max_size=64): + sizes = [8, 16, 32, 64] + code = '' + for size in sizes: + if size < min_size or size > max_size: + continue + code += f'template class {class_name}<{type_name}{size}_t>;\n' + return code + + def declareGatherTemplate(class_name, index_type): + sizes = [8, 16, 32, 64] + code = '' + for size in sizes: + if index_type == 'elem_type': + idx_type = f'uint{size}_t' + else: + idx_type = index_type + code += ('template class' + f' {class_name};\n') + return code }}; @@ -132,8 +154,14 @@ def format VectorIntFormat(code, category, *flags) {{ macroop_class_name = 'VectorVMUNARY0MacroInst' microp_class_name = 'VectorVMUNARY0MicroInst' - iop = InstObjParams(name, Name, macroop_class_name, {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + macroop_class_name, + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) v0_required = inst_name not in ["vmv"] mask_cond = v0_required and (inst_suffix not in ['vvm', 'vxm', 'vim']) @@ -192,25 +220,30 @@ def format VectorIntFormat(code, category, *flags) {{ 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb' : set_vlenb, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': declareVArithTemplate(Name + "Micro")}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntMicroDeclare.subst(microiop) + \ + VectorIntMacroDeclare.subst(iop) + decoder_output = \ VectorIntMicroConstructor.subst(microiop) + \ - VectorIntMicroExecute.subst(microiop) + \ - VectorIntMacroDeclare.subst(iop) + \ VectorIntMacroConstructor.subst(iop) - + exec_output = VectorIntMicroExecute.subst(microiop) decode_block = VectorIntDecodeBlock.subst(iop) }}; def format VectorIntExtFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) ext_div = int(inst_suffix[-1]) @@ -245,24 +278,31 @@ def format VectorIntExtFormat(code, category, *flags) {{ 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx), - 'ext_div': ext_div}, + 'ext_div': ext_div, + 'declare_varith_template': declareVArithTemplate(Name + "Micro")}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntExtMicroDeclare.subst(microiop) + \ + VectorIntExtMacroDeclare.subst(iop) + decoder_output = \ VectorIntMicroConstructor.subst(microiop) + \ - VectorIntExtMicroExecute.subst(microiop) + \ - VectorIntExtMacroDeclare.subst(iop) + \ VectorIntMacroConstructor.subst(iop) - + exec_output = \ + VectorIntExtMicroExecute.subst(microiop) + \ + VectorIntExtMacroExecute.subst(iop) decode_block = VectorIntDecodeBlock.subst(iop) }}; def format VectorIntWideningFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, max_size=32)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) v0_required = True mask_cond = v0_required @@ -308,6 +348,7 @@ def format VectorIntWideningFormat(code, category, *flags) {{ set_vlenb = setVlenb(); set_vlen = setVlen(); + varith_micro_declare = declareVArithTemplate(Name + "Micro", max_size=32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -317,24 +358,29 @@ def format VectorIntWideningFormat(code, category, *flags) {{ 'set_vlenb': set_vlenb, 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntWideningMicroDeclare.subst(microiop) + \ + VectorIntWideningMacroDeclare.subst(iop) + decoder_output = \ VectorIntWideningMicroConstructor.subst(microiop) + \ - VectorIntWideningMicroExecute.subst(microiop) + \ - VectorIntWideningMacroDeclare.subst(iop) + \ VectorIntWideningMacroConstructor.subst(iop) - + exec_output = VectorIntWideningMicroExecute.subst(microiop) decode_block = VectorIntWideningDecodeBlock.subst(iop) }}; def format VectorIntNarrowingFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, max_size=32)}, + flags + ) mask_cond = True need_elem_idx = True @@ -368,6 +414,7 @@ def format VectorIntNarrowingFormat(code, category, *flags) {{ set_vlenb = setVlenb(); set_vlen = setVlen(); + varith_micro_declare = declareVArithTemplate(Name + "Micro", max_size=32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -378,18 +425,17 @@ def format VectorIntNarrowingFormat(code, category, *flags) {{ 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx), - }, + 'declare_varith_template': varith_micro_declare + }, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntWideningMicroDeclare.subst(microiop) + \ + VectorIntWideningMacroDeclare.subst(iop) + decoder_output = \ VectorIntWideningMicroConstructor.subst(microiop) + \ - VectorIntNarrowingMicroExecute.subst(microiop) + \ - VectorIntWideningMacroDeclare.subst(iop) + \ VectorIntWideningMacroConstructor.subst(iop) - + exec_output = VectorIntNarrowingMicroExecute.subst(microiop) decode_block = VectorIntWideningDecodeBlock.subst(iop) }}; @@ -397,7 +443,8 @@ def format VectorIntMaskFormat(code, category, *flags) {{ iop = InstObjParams(name, Name, 'VectorArithMacroInst', - {'code': code}, + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name)}, flags) inst_name, inst_suffix = name.split("_", maxsplit=1) v0_required = not (inst_name in ["vmadc", "vmsbc"] \ @@ -448,17 +495,17 @@ def format VectorIntMaskFormat(code, category, *flags) {{ 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': declareVArithTemplate(Name + "Micro")}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntMaskMicroDeclare.subst(microiop) + \ + VectorIntMaskMacroDeclare.subst(iop) + decoder_output = \ VectorIntMaskMicroConstructor.subst(microiop) + \ - VectorIntMaskMicroExecute.subst(microiop) + \ - VectorIntMaskMacroDeclare.subst(iop) + \ VectorIntMaskMacroConstructor.subst(iop) + exec_output = VectorIntMaskMicroExecute.subst(microiop) decode_block = VectorIntDecodeBlock.subst(iop) }}; @@ -470,7 +517,8 @@ def format VectorGatherFormat(code, category, *flags) {{ idx_type = "elem_type" iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'idx_type': idx_type, - 'code': code}, + 'code': code, + 'declare_varith_template': declareGatherTemplate(Name, idx_type)}, flags) old_vd_idx = 2 dest_reg_id = "vecRegClass[_machInst.vd + vd_idx]" @@ -502,6 +550,7 @@ def format VectorGatherFormat(code, category, *flags) {{ set_vlenb = setVlenb(); set_vlen = setVlen(); + varith_micro_declare = declareGatherTemplate(Name + "Micro", idx_type) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -512,25 +561,30 @@ def format VectorGatherFormat(code, category, *flags) {{ 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'copy_old_vd': copyOldVd(old_vd_idx), - 'idx_type': idx_type}, + 'idx_type': idx_type, + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorGatherMicroDeclare.subst(microiop) + \ + VectorGatherMacroDeclare.subst(iop) + decoder_output = \ VectorGatherMicroConstructor.subst(microiop) + \ - VectorGatherMicroExecute.subst(microiop) + \ - VectorGatherMacroDeclare.subst(iop) + \ VectorGatherMacroConstructor.subst(iop) - + exec_output = VectorGatherMicroExecute.subst(microiop) decode_block = VectorGatherDecodeBlock.subst(iop) }}; def format VectorFloatFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, 'float', 32)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) v0_required = inst_name not in ["vfmv"] mask_cond = v0_required and (inst_suffix not in ['vvm', 'vfm']) @@ -569,6 +623,7 @@ def format VectorFloatFormat(code, category, *flags) {{ set_vlenb = setVlenb(); + varith_micro_declare = declareVArithTemplate(Name + "Micro", 'float', 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -577,24 +632,29 @@ def format VectorFloatFormat(code, category, *flags) {{ 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorFloatMicroDeclare.subst(microiop) + \ + VectorFloatMacroDeclare.subst(iop) + decoder_output = \ VectorFloatMicroConstructor.subst(microiop) + \ - VectorFloatMicroExecute.subst(microiop) + \ - VectorFloatMacroDeclare.subst(iop) + \ VectorFloatMacroConstructor.subst(iop) - + exec_output = VectorFloatMicroExecute.subst(microiop) decode_block = VectorFloatDecodeBlock.subst(iop) }}; def format VectorFloatCvtFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, 'float', 32)}, + flags + ) old_vd_idx = 1 dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" @@ -616,6 +676,7 @@ def format VectorFloatCvtFormat(code, category, *flags) {{ set_vlenb = setVlenb(); + varith_micro_declare = declareVArithTemplate(Name + "Micro", 'float', 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -624,24 +685,30 @@ def format VectorFloatCvtFormat(code, category, *flags) {{ 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorFloatCvtMicroDeclare.subst(microiop) + \ + VectorFloatCvtMacroDeclare.subst(iop) + decoder_output = \ VectorFloatMicroConstructor.subst(microiop) + \ - VectorFloatMicroExecute.subst(microiop) + \ - VectorFloatCvtMacroDeclare.subst(iop) + \ VectorFloatMacroConstructor.subst(iop) - + exec_output = VectorFloatMicroExecute.subst(microiop) decode_block = VectorFloatDecodeBlock.subst(iop) }}; def format VectorFloatWideningFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + varith_macro_declare = declareVArithTemplate(Name, 'float', 32, 32) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': varith_macro_declare}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) v0_required = True mask_cond = v0_required @@ -688,6 +755,8 @@ def format VectorFloatWideningFormat(code, category, *flags) {{ set_vlenb = setVlenb(); set_vlen = setVlen(); + varith_micro_declare = declareVArithTemplate( + Name + "Micro", 'float', 32, 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -697,24 +766,30 @@ def format VectorFloatWideningFormat(code, category, *flags) {{ 'set_vlenb': set_vlenb, 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntWideningMicroDeclare.subst(microiop) + \ + VectorIntWideningMacroDeclare.subst(iop) + decoder_output = \ VectorIntWideningMicroConstructor.subst(microiop) + \ - VectorFloatWideningMicroExecute.subst(microiop) + \ - VectorIntWideningMacroDeclare.subst(iop) + \ VectorIntWideningMacroConstructor.subst(iop) - + exec_output = VectorFloatWideningMicroExecute.subst(microiop) decode_block = VectorFloatWideningDecodeBlock.subst(iop) }}; def format VectorFloatWideningCvtFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + varith_macro_declare = declareVArithTemplate(Name, 'float', 32, 32) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': varith_macro_declare}, + flags + ) old_vd_idx = 1 dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" @@ -737,6 +812,8 @@ def format VectorFloatWideningCvtFormat(code, category, *flags) {{ set_vlenb = setVlenb(); set_vlen = setVlen(); + varith_micro_declare = declareVArithTemplate( + Name + "Micro", 'float', 32, 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -746,24 +823,30 @@ def format VectorFloatWideningCvtFormat(code, category, *flags) {{ 'set_vlenb': set_vlenb, 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorFloatCvtMicroDeclare.subst(microiop) + \ + VectorFloatCvtMacroDeclare.subst(iop) + decoder_output = \ VectorFloatMicroConstructor.subst(microiop) + \ - VectorFloatWideningMicroExecute.subst(microiop) + \ - VectorFloatCvtMacroDeclare.subst(iop) + \ VectorIntWideningMacroConstructor.subst(iop) - + exec_output = VectorFloatWideningMicroExecute.subst(microiop) decode_block = VectorFloatWideningDecodeBlock.subst(iop) }}; def format VectorFloatNarrowingCvtFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + varith_macro_declare = declareVArithTemplate(Name, 'float', 32, 32) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': varith_macro_declare}, + flags + ) old_vd_idx = 1 dest_reg_id = "vecRegClass[_machInst.vd + _microIdx / 2]" @@ -787,6 +870,8 @@ def format VectorFloatNarrowingCvtFormat(code, category, *flags) {{ set_vlenb = setVlenb(); set_vlen = setVlen(); + varith_micro_declare = declareVArithTemplate( + Name + "Micro", 'float', 32, 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -796,18 +881,17 @@ def format VectorFloatNarrowingCvtFormat(code, category, *flags) {{ 'set_vlenb': set_vlenb, 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorFloatCvtMicroDeclare.subst(microiop) + \ + VectorFloatCvtMacroDeclare.subst(iop) + decoder_output = \ VectorFloatMicroConstructor.subst(microiop) + \ - VectorFloatNarrowingMicroExecute.subst(microiop) + \ - VectorFloatCvtMacroDeclare.subst(iop) + \ VectorIntWideningMacroConstructor.subst(iop) - + exec_output = VectorFloatNarrowingMicroExecute.subst(microiop) decode_block = VectorFloatWideningDecodeBlock.subst(iop) }}; @@ -815,8 +899,10 @@ def format VectorFloatMaskFormat(code, category, *flags) {{ iop = InstObjParams(name, Name, 'VectorArithMacroInst', - {'code': code}, - flags) + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, 'float', 32)}, + flags + ) dest_reg_id = "vecRegClass[VecMemInternalReg0 + _microIdx]" src1_reg_id = "" if category == "OPFVV": @@ -841,6 +927,7 @@ def format VectorFloatMaskFormat(code, category, *flags) {{ code = loopWrapper(code) code = fflags_wrapper(code) + varith_micro_declare = declareVArithTemplate(Name + "Micro", 'float', 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -849,17 +936,17 @@ def format VectorFloatMaskFormat(code, category, *flags) {{ 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorFloatMaskMicroDeclare.subst(microiop) + \ + VectorFloatMaskMacroDeclare.subst(iop) + decoder_output = \ VectorFloatMaskMicroConstructor.subst(microiop) + \ - VectorFloatMaskMicroExecute.subst(microiop) + \ - VectorFloatMaskMacroDeclare.subst(iop) + \ VectorFloatMaskMacroConstructor.subst(iop) + exec_output = VectorFloatMaskMicroExecute.subst(microiop) decode_block = VectorFloatDecodeBlock.subst(iop) }}; @@ -884,8 +971,14 @@ def format VMvWholeFormat(code, category, *flags) {{ }}; def format ViotaFormat(code, category, *flags){{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" @@ -912,17 +1005,17 @@ def format ViotaFormat(code, category, *flags){{ 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'set_vm_idx': set_vm_idx, - 'copy_old_vd': copyOldVd(1)}, + 'copy_old_vd': copyOldVd(1), + 'declare_varith_template': declareVArithTemplate(Name + "Micro")}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. + header_output = \ ViotaMicroDeclare.subst(microiop) + \ + ViotaMacroDeclare.subst(iop) + decoder_output = \ ViotaMicroConstructor.subst(microiop) + \ - ViotaMicroExecute.subst(microiop)+\ - ViotaMacroDeclare.subst(iop) + \ ViotaMacroConstructor.subst(iop) - + exec_output = ViotaMicroExecute.subst(microiop) decode_block = VectorIntDecodeBlock.subst(iop) }}; @@ -951,15 +1044,14 @@ def format Vector1Vs1VdMaskFormat(code, category, *flags){{ 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, 'set_vm_idx': set_vm_idx, - 'copy_old_vd': copyOldVd(1)}, + 'copy_old_vd': copyOldVd(1), + 'declare_varith_template': declareVArithTemplate(Name, 'uint', 8, 8), + }, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. - header_output = \ - Vector1Vs1RdMaskDeclare.subst(iop) + \ - Vector1Vs1VdMaskConstructor.subst(iop) + \ - Vector1Vs1VdMaskExecute.subst(iop) + header_output = Vector1Vs1RdMaskDeclare.subst(iop) + decoder_output = Vector1Vs1VdMaskConstructor.subst(iop) + exec_output = Vector1Vs1VdMaskExecute.subst(iop) decode_block = VectorMaskDecodeBlock.subst(iop) }}; @@ -972,15 +1064,14 @@ def format Vector1Vs1RdMaskFormat(code, category, *flags){{ 'VectorNonSplitInst', {'code': code, 'vm_decl_rd': vm_decl_rd, - 'set_vm_idx': set_vm_idx}, + 'set_vm_idx': set_vm_idx, + 'declare_varith_template': declareVArithTemplate(Name, 'uint', 8, 8) + }, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. - header_output = \ - Vector1Vs1RdMaskDeclare.subst(iop) + \ - Vector1Vs1RdMaskConstructor.subst(iop) + \ - Vector1Vs1RdMaskExecute.subst(iop) + header_output = Vector1Vs1RdMaskDeclare.subst(iop) + decoder_output = Vector1Vs1RdMaskConstructor.subst(iop) + exec_output = Vector1Vs1RdMaskExecute.subst(iop) decode_block = VectorMaskDecodeBlock.subst(iop) }}; @@ -993,31 +1084,36 @@ def format VectorNonSplitFormat(code, category, *flags) {{ if inst_name == "vfmv" : code = fflags_wrapper(code) - iop = InstObjParams(name, - Name, - 'VectorNonSplitInst', - {'code': code, - 'vm_decl_rd': vm_decl_rd, - 'set_vm_idx': set_vm_idx}, - flags) - - if inst_name == "vfmv" : - execute_block = VectorFloatNonSplitExecute.subst(iop) + varith_template = declareVArithTemplate(Name, 'float', 32) + iop = InstObjParams(name, + Name, + 'VectorNonSplitInst', + {'code': code, + 'vm_decl_rd': vm_decl_rd, + 'set_vm_idx': set_vm_idx, + 'declare_varith_template': varith_template}, + flags) + header_output = VectorNonSplitDeclare.subst(iop) + decoder_output = VectorNonSplitConstructor.subst(iop) + exec_output = VectorFloatNonSplitExecute.subst(iop) decode_block = VectorFloatNonSplitDecodeBlock.subst(iop) elif inst_name == "vmv" : - execute_block = VectorIntNonSplitExecute.subst(iop) + iop = InstObjParams(name, + Name, + 'VectorNonSplitInst', + {'code': code, + 'vm_decl_rd': vm_decl_rd, + 'set_vm_idx': set_vm_idx, + 'declare_varith_template': declareVArithTemplate(Name)}, + flags) + header_output = VectorNonSplitDeclare.subst(iop) + decoder_output = VectorNonSplitConstructor.subst(iop) + exec_output = VectorIntNonSplitExecute.subst(iop) decode_block = VectorIntNonSplitDecodeBlock.subst(iop) else : error("Unsupported inst for VectorNonSplitFormat: %s" % inst_name) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. - header_output = \ - VectorNonSplitDeclare.subst(iop) + \ - VectorNonSplitConstructor.subst(iop) + \ - execute_block - }}; def format VectorMaskFormat(code, category, *flags) {{ @@ -1053,21 +1149,26 @@ def format VectorMaskFormat(code, category, *flags) {{ 'set_dest_reg_idx': set_dest_reg_idx, 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb': set_vlenb, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': declareVArithTemplate(Name, 'uint', 8, 8) + }, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. - header_output = \ - VectorMaskDeclare.subst(iop) + \ - VectorMaskConstructor.subst(iop) + \ - VectorMaskExecute.subst(iop) + header_output = VectorMaskDeclare.subst(iop) + decoder_output = VectorMaskConstructor.subst(iop) + exec_output = VectorMaskExecute.subst(iop) decode_block = VectorMaskDecodeBlock.subst(iop) }}; def format VectorReduceIntFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) dest_reg_id = "vecRegClass[_machInst.vd]" src1_reg_id = "vecRegClass[_machInst.vs1]" @@ -1098,23 +1199,29 @@ def format VectorReduceIntFormat(code, category, *flags) {{ 'set_vlen' : set_vlen, 'vm_decl_rd': vm_decl_rd, 'type_def': type_def, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': declareVArithTemplate(Name + "Micro")}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + decoder_output = \ VectorReduceMicroConstructor.subst(microiop) + \ - VectorReduceIntMicroExecute.subst(microiop) + \ - VectorReduceMacroDeclare.subst(iop) + \ VectorReduceMacroConstructor.subst(iop) + exec_output = VectorReduceIntMicroExecute.subst(microiop) decode_block = VectorIntDecodeBlock.subst(iop) }}; def format VectorReduceFloatFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, 'float', 32)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) dest_reg_id = "vecRegClass[_machInst.vd]" src1_reg_id = "vecRegClass[_machInst.vs1]" @@ -1138,6 +1245,7 @@ def format VectorReduceFloatFormat(code, category, *flags) {{ code = fflags_wrapper(code) + varith_micro_declare = declareVArithTemplate(Name + "Micro", 'float', 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -1148,23 +1256,30 @@ def format VectorReduceFloatFormat(code, category, *flags) {{ 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'type_def': type_def, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + decoder_output = \ VectorReduceMicroConstructor.subst(microiop) + \ - VectorReduceFloatMicroExecute.subst(microiop) + \ - VectorReduceMacroDeclare.subst(iop) + \ VectorReduceMacroConstructor.subst(iop) + exec_output = VectorReduceFloatMicroExecute.subst(microiop) decode_block = VectorFloatDecodeBlock.subst(iop) }}; def format VectorReduceFloatWideningFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + varith_macro_declare = declareVArithTemplate(Name, 'float', 32, 32) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': varith_macro_declare}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) dest_reg_id = "vecRegClass[_machInst.vd]" src1_reg_id = "vecRegClass[_machInst.vs1]" @@ -1186,6 +1301,9 @@ def format VectorReduceFloatWideningFormat(code, category, *flags) {{ using ewt = typename double_width::type; using vwu = decltype(ewt::v); ''' + + varith_micro_declare = declareVArithTemplate( + Name + "Micro", 'float', 32, 32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -1196,23 +1314,29 @@ def format VectorReduceFloatWideningFormat(code, category, *flags) {{ 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, 'type_def': type_def, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + decoder_output = \ VectorReduceMicroConstructor.subst(microiop) + \ - VectorReduceFloatWideningMicroExecute.subst(microiop) + \ - VectorReduceMacroDeclare.subst(iop) + \ VectorReduceMacroConstructor.subst(iop) + exec_output = VectorReduceFloatWideningMicroExecute.subst(microiop) decode_block = VectorFloatWideningDecodeBlock.subst(iop) }}; def format VectorIntVxsatFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) old_vd_idx = 2 dest_reg_id = "vecRegClass[_machInst.vd + _microIdx]" @@ -1251,24 +1375,29 @@ def format VectorIntVxsatFormat(code, category, *flags) {{ 'set_src_reg_idx': set_src_reg_idx, 'set_vlenb': set_vlenb, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': declareVArithTemplate(Name + "Micro")}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorIntVxsatMicroDeclare.subst(microiop) + \ + VectorIntVxsatMacroDeclare.subst(iop) + decoder_output = \ VectorIntVxsatMicroConstructor.subst(microiop) + \ - VectorIntMicroExecute.subst(microiop) + \ - VectorIntVxsatMacroDeclare.subst(iop) + \ VectorIntVxsatMacroConstructor.subst(iop) - + exec_output = VectorIntMicroExecute.subst(microiop) decode_block = VectorIntDecodeBlock.subst(iop) }}; def format VectorReduceIntWideningFormat(code, category, *flags) {{ - iop = InstObjParams(name, Name, 'VectorArithMacroInst', {'code': code}, - flags) + iop = InstObjParams( + name, + Name, + 'VectorArithMacroInst', + {'code': code, + 'declare_varith_template': declareVArithTemplate(Name, max_size=32)}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) dest_reg_id = "vecRegClass[_machInst.vd]" src1_reg_id = "vecRegClass[_machInst.vs1]" @@ -1284,6 +1413,8 @@ def format VectorReduceIntWideningFormat(code, category, *flags) {{ vm_decl_rd = vmDeclAndReadData() set_vlenb = setVlenb() set_vlen = setVlen() + + varith_micro_declare = declareVArithTemplate(Name + "Micro", max_size=32) microiop = InstObjParams(name + "_micro", Name + "Micro", 'VectorArithMicroInst', @@ -1293,17 +1424,17 @@ def format VectorReduceIntWideningFormat(code, category, *flags) {{ 'set_vlenb': set_vlenb, 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(2)}, + 'copy_old_vd': copyOldVd(2), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. header_output = \ VectorReduceMicroDeclare.subst(microiop) + \ + VectorReduceMacroDeclare.subst(iop) + decoder_output = \ VectorReduceMicroConstructor.subst(microiop) + \ - VectorReduceIntWideningMicroExecute.subst(microiop) + \ - VectorReduceMacroDeclare.subst(iop) + \ VectorReduceMacroConstructor.subst(iop) + exec_output = VectorReduceIntWideningMicroExecute.subst(microiop) decode_block = VectorIntWideningDecodeBlock.subst(iop) }}; @@ -1315,8 +1446,20 @@ def VectorSlideBase(name, Name, category, code, flags, macro_construtor, microop_class_name = 'VectorSlideMicroInst' # Make sure flags are in lists (convert to lists if not). flags = makeList(flags) - iop = InstObjParams(name, Name, macroop_class_name, {'code': code}, - flags) + + if decode_template is VectorIntDecodeBlock: + varith_macro_declare = declareVArithTemplate(Name) + elif decode_template is VectorFloatDecodeBlock: + varith_macro_declare = declareVArithTemplate(Name, 'float', 32) + + iop = InstObjParams( + name, + Name, + macroop_class_name, + {'code': code, + 'declare_varith_template': varith_macro_declare}, + flags + ) inst_name, inst_suffix = name.split("_", maxsplit=1) dest_reg_id = "vecRegClass[_machInst.vd + vdIdx]" src2_reg_id = "vecRegClass[_machInst.vs2 + vs2Idx]" @@ -1345,6 +1488,13 @@ def VectorSlideBase(name, Name, category, code, flags, macro_construtor, set_src_reg_idx += setSrcVm() set_vlenb = setVlenb() set_vlen = setVlen() + + if decode_template is VectorIntDecodeBlock: + varith_micro_declare = declareVArithTemplate(Name + "Micro") + elif decode_template is VectorFloatDecodeBlock: + varith_micro_declare = declareVArithTemplate( + Name + "Micro", 'float', 32) + microiop = InstObjParams(name + "_micro", Name + "Micro", microop_class_name, @@ -1354,52 +1504,54 @@ def VectorSlideBase(name, Name, category, code, flags, macro_construtor, 'set_vlenb': set_vlenb, 'set_vlen': set_vlen, 'vm_decl_rd': vm_decl_rd, - 'copy_old_vd': copyOldVd(old_vd_idx)}, + 'copy_old_vd': copyOldVd(old_vd_idx), + 'declare_varith_template': varith_micro_declare}, flags) - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. - # Because of the use of templates, we had to put all parts in header to - # keep the compiler happy. + header_output = \ VectorSlideMicroDeclare.subst(microiop) + \ + VectorSlideMacroDeclare.subst(iop) + decoder_output = \ VectorSlideMicroConstructor.subst(microiop) + \ - micro_execute_template.subst(microiop) + \ - VectorSlideMacroDeclare.subst(iop) + \ macro_construtor.subst(iop) - + exec_output = micro_execute_template.subst(microiop) decode_block = decode_template.subst(iop) - return (header_output, decode_block) + return (header_output, decoder_output, decode_block, exec_output) }}; def format VectorSlideUpFormat(code, category, *flags) {{ - (header_output, decode_block) = VectorSlideBase(name, Name, category, code, - flags, - macro_construtor = VectorSlideUpMacroConstructor, - decode_template = VectorIntDecodeBlock, - micro_execute_template = VectorSlideMicroExecute) + (header_output, decoder_output, decode_block, exec_output) = \ + VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideUpMacroConstructor, + decode_template = VectorIntDecodeBlock, + micro_execute_template = VectorSlideMicroExecute) }}; def format VectorSlideDownFormat(code, category, *flags) {{ - (header_output, decode_block) = VectorSlideBase(name, Name, category, code, - flags, - macro_construtor = VectorSlideDownMacroConstructor, - decode_template = VectorIntDecodeBlock, - micro_execute_template = VectorSlideMicroExecute) + (header_output, decoder_output, decode_block, exec_output) = \ + VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideDownMacroConstructor, + decode_template = VectorIntDecodeBlock, + micro_execute_template = VectorSlideMicroExecute) }}; def format VectorFloatSlideUpFormat(code, category, *flags) {{ - (header_output, decode_block) = VectorSlideBase(name, Name, category, code, - flags, - macro_construtor = VectorSlideUpMacroConstructor, - decode_template = VectorFloatDecodeBlock, - micro_execute_template = VectorFloatSlideMicroExecute) + (header_output, decoder_output, decode_block, exec_output) = \ + VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideUpMacroConstructor, + decode_template = VectorFloatDecodeBlock, + micro_execute_template = VectorFloatSlideMicroExecute) }}; def format VectorFloatSlideDownFormat(code, category, *flags) {{ - (header_output, decode_block) = VectorSlideBase(name, Name, category, code, - flags, - macro_construtor = VectorSlideDownMacroConstructor, - decode_template = VectorFloatDecodeBlock, - micro_execute_template = VectorFloatSlideMicroExecute) + (header_output, decoder_output, decode_block, exec_output) = \ + VectorSlideBase(name, Name, category, code, + flags, + macro_construtor = VectorSlideDownMacroConstructor, + decode_template = VectorFloatDecodeBlock, + micro_execute_template = VectorFloatSlideMicroExecute) }}; diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa index 306b1c53f1..3a528f1198 100644 --- a/src/arch/riscv/isa/templates/vector_arith.isa +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -107,6 +107,9 @@ template this->microops.front()->setFirstMicroop(); this->microops.back()->setLastMicroop(); } + +%(declare_varith_template)s; + }}; def template VectorIntMicroDeclare {{ @@ -145,6 +148,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorIntMicroExecute {{ @@ -182,6 +187,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorIntExtMacroDeclare {{ @@ -193,14 +200,7 @@ private: public: %(class_name)s(ExtMachInst _machInst, uint32_t _vlen); std::string generateDisassembly(Addr pc, - const loader::SymbolTable *symtab) const override - { - std::stringstream ss; - ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " - << registerName(srcRegIdx(0)); - if (machInst.vm == 0) ss << ", v0.t"; - return ss.str(); - } + const loader::SymbolTable *symtab) const override; }; }}; @@ -219,14 +219,7 @@ public: uint8_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; std::string generateDisassembly(Addr pc, - const loader::SymbolTable *symtab) const override - { - std::stringstream ss; - ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " - << registerName(srcRegIdx(0)); - if (machInst.vm == 0) ss << ", v0.t"; - return ss.str(); - } + const loader::SymbolTable *symtab) const override; }; }}; @@ -303,6 +296,38 @@ Fault return NoFault; } +template +std::string +%(class_name)s::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +%(declare_varith_template)s; + +}}; + +def template VectorIntExtMacroExecute {{ + +template +std::string +%(class_name)s::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " + << registerName(srcRegIdx(0)); + if (machInst.vm == 0) ss << ", v0.t"; + return ss.str(); +} + +%(declare_varith_template)s; + }}; def template VectorIntDecodeBlock {{ @@ -365,6 +390,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorIntWideningMicroDeclare {{ @@ -402,6 +429,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorIntWideningMicroExecute {{ @@ -447,6 +476,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorIntNarrowingMicroExecute {{ @@ -493,6 +524,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorIntWideningDecodeBlock {{ @@ -546,6 +579,9 @@ template this->microops.front()->setFirstMicroop(); this->microops.back()->setLastMicroop(); } + +%(declare_varith_template)s; + }}; def template VectorFloatMicroDeclare {{ @@ -582,6 +618,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorFloatMicroExecute {{ @@ -620,6 +658,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorFloatDecodeBlock {{ @@ -725,6 +765,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorFloatNarrowingMicroExecute {{ @@ -772,6 +814,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorFloatWideningDecodeBlock {{ @@ -826,6 +870,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template ViotaMicroDeclare {{ @@ -865,6 +911,8 @@ template setSrcRegIdx(_numSrcRegs++, vecRegClass[_machInst.vs2]); } +%(declare_varith_template)s; + }}; def template ViotaMicroExecute {{ @@ -899,6 +947,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; @@ -915,6 +965,8 @@ template %(set_vm_idx)s; } +%(declare_varith_template)s; + }}; def template Vector1Vs1VdMaskExecute {{ @@ -948,6 +1000,8 @@ Fault return NoFault; }; +%(declare_varith_template)s; + }}; def template Vector1Vs1RdMaskDeclare {{ @@ -978,6 +1032,8 @@ template %(set_vm_idx)s; } +%(declare_varith_template)s; + }}; def template Vector1Vs1RdMaskExecute {{ @@ -1010,6 +1066,8 @@ Fault return NoFault; }; +%(declare_varith_template)s; + }}; def template VectorIntMaskMacroDeclare {{ @@ -1057,6 +1115,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorIntMaskMicroDeclare {{ @@ -1095,6 +1155,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorIntMaskMicroExecute {{ @@ -1133,6 +1195,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorFloatMaskMacroDeclare {{ @@ -1180,6 +1244,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorFloatMaskMicroDeclare {{ @@ -1217,6 +1283,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorFloatMaskMicroExecute {{ @@ -1255,6 +1323,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VMvWholeMacroDeclare {{ @@ -1381,6 +1451,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorMaskExecute {{ @@ -1415,6 +1487,8 @@ Fault return NoFault; }; +%(declare_varith_template)s; + }}; def template VectorMaskDecodeBlock {{ @@ -1449,6 +1523,8 @@ template %(set_vm_idx)s; } +%(declare_varith_template)s; + }}; def template VectorIntNonSplitExecute {{ @@ -1481,6 +1557,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorFloatNonSplitExecute {{ @@ -1513,6 +1591,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorFloatNonSplitDecodeBlock {{ @@ -1578,6 +1658,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorReduceMicroDeclare {{ @@ -1615,6 +1697,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorReduceIntMicroExecute {{ @@ -1664,6 +1748,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorReduceFloatMicroExecute {{ @@ -1715,6 +1801,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorReduceFloatWideningMicroExecute {{ @@ -1765,6 +1853,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorGatherMacroDeclare {{ @@ -1824,6 +1914,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorGatherMicroDeclare {{ @@ -1873,6 +1965,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorGatherMicroExecute {{ @@ -1930,6 +2024,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorGatherDecodeBlock {{ @@ -2003,6 +2099,9 @@ template this->microops.front()->setFirstMicroop(); this->microops.back()->setLastMicroop(); } + +%(declare_varith_template)s; + }}; def template VectorIntVxsatMicroDeclare {{ @@ -2041,6 +2140,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorReduceIntWideningMicroExecute {{ @@ -2094,6 +2195,8 @@ Fault return NoFault; } +%(declare_varith_template)s; + }}; def template VectorSlideMacroDeclare {{ @@ -2142,6 +2245,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorSlideDownMacroConstructor {{ @@ -2177,6 +2282,8 @@ template this->microops.back()->setLastMicroop(); } +%(declare_varith_template)s; + }}; def template VectorSlideMicroDeclare {{ @@ -2215,6 +2322,8 @@ template %(set_src_reg_idx)s; } +%(declare_varith_template)s; + }}; def template VectorSlideMicroExecute {{ @@ -2254,6 +2363,8 @@ Fault return NoFault; }; +%(declare_varith_template)s; + }}; def template VectorFloatSlideMicroExecute {{ @@ -2293,4 +2404,6 @@ Fault return NoFault; }; +%(declare_varith_template)s; + }}; From e561f3b6f149f45f291c8ad7b310f157bfcba154 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 24 Oct 2023 15:29:40 +0800 Subject: [PATCH 506/693] arch-riscv: Move insts/vector from header to source Move the implemention of following classes - VMaskMergeMicroInst - VxsatMicroInst Change-Id: I42ec45681064a0f599c3b2313c2125da7cfc849b --- src/arch/riscv/insts/vector.cc | 93 ++++++++++++++++++ src/arch/riscv/insts/vector.hh | 94 ++----------------- src/arch/riscv/isa/templates/vector_arith.isa | 8 +- 3 files changed, 106 insertions(+), 89 deletions(-) diff --git a/src/arch/riscv/insts/vector.cc b/src/arch/riscv/insts/vector.cc index c99e806e9b..7f17bb055e 100644 --- a/src/arch/riscv/insts/vector.cc +++ b/src/arch/riscv/insts/vector.cc @@ -32,6 +32,9 @@ #include #include "arch/riscv/insts/static_inst.hh" +#include "arch/riscv/isa.hh" +#include "arch/riscv/regs/misc.hh" +#include "arch/riscv/regs/vector.hh" #include "arch/riscv/utility.hh" #include "cpu/static_inst.hh" @@ -408,5 +411,95 @@ VMvWholeMicroInst::generateDisassembly(Addr pc, return ss.str(); } +VMaskMergeMicroInst::VMaskMergeMicroInst(ExtMachInst extMachInst, + uint8_t _dstReg, uint8_t _numSrcs, uint32_t _vlen, size_t _elemSize) + : VectorArithMicroInst("vmask_mv_micro", extMachInst, + VectorIntegerArithOp, 0, 0), + vlen(_vlen), + elemSize(_elemSize) +{ + setRegIdxArrays( + reinterpret_cast( + &std::remove_pointer_t::srcRegIdxArr), + reinterpret_cast( + &std::remove_pointer_t::destRegIdxArr)); + + _numSrcRegs = 0; + _numDestRegs = 0; + + setDestRegIdx(_numDestRegs++, vecRegClass[_dstReg]); + _numTypedDestRegs[VecRegClass]++; + for (uint8_t i=0; i<_numSrcs; i++) { + setSrcRegIdx(_numSrcRegs++, vecRegClass[VecMemInternalReg0 + i]); + } +} + +Fault +VMaskMergeMicroInst::execute(ExecContext* xc, + trace::InstRecord* traceData) const +{ + vreg_t& tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); + PCStateBase *pc_ptr = xc->tcBase()->pcState().clone(); + auto Vd = tmp_d0.as(); + uint32_t vlenb = pc_ptr->as().vlenb(); + const uint32_t elems_per_vreg = vlenb / elemSize; + size_t bit_cnt = elems_per_vreg; + vreg_t tmp_s; + xc->getRegOperand(this, 0, &tmp_s); + auto s = tmp_s.as(); + // cp the first result and tail + memcpy(Vd, s, vlenb); + for (uint8_t i = 1; i < this->_numSrcRegs; i++) { + xc->getRegOperand(this, i, &tmp_s); + s = tmp_s.as(); + if (elems_per_vreg < 8) { + const uint32_t m = (1 << elems_per_vreg) - 1; + const uint32_t mask = m << (i * elems_per_vreg % 8); + // clr & ext bits + Vd[bit_cnt/8] ^= Vd[bit_cnt/8] & mask; + Vd[bit_cnt/8] |= s[bit_cnt/8] & mask; + bit_cnt += elems_per_vreg; + } else { + const uint32_t byte_offset = elems_per_vreg / 8; + memcpy(Vd + i * byte_offset, s + i * byte_offset, byte_offset); + } + } + if (traceData) + traceData->setData(vecRegClass, &tmp_d0); + return NoFault; +} + +std::string +VMaskMergeMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)); + for (uint8_t i = 0; i < this->_numSrcRegs; i++) { + ss << ", " << registerName(srcRegIdx(i)); + } + unsigned vlenb = vlen >> 3; + ss << ", offset:" << vlenb / elemSize; + return ss.str(); +} + +Fault +VxsatMicroInst::execute(ExecContext* xc, trace::InstRecord* traceData) const +{ + xc->setMiscReg(MISCREG_VXSAT, *vxsat); + auto vcsr = xc->readMiscReg(MISCREG_VCSR); + xc->setMiscReg(MISCREG_VCSR, ((vcsr&~1)|*vxsat)); + return NoFault; +} + +std::string +VxsatMicroInst::generateDisassembly(Addr pc, + const loader::SymbolTable *symtab) const +{ + std::stringstream ss; + ss << mnemonic << ' ' << "VXSAT" << ", " << (*vxsat ? "0x1" : "0x0"); + return ss.str(); +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index c986c99c72..4127060e4a 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -34,7 +34,6 @@ #include "arch/riscv/insts/static_inst.hh" #include "arch/riscv/isa.hh" #include "arch/riscv/regs/misc.hh" -#include "arch/riscv/regs/vector.hh" #include "arch/riscv/utility.hh" #include "cpu/exec_context.hh" #include "cpu/static_inst.hh" @@ -539,7 +538,7 @@ class VMvWholeMicroInst : public VectorArithMicroInst Addr pc, const loader::SymbolTable *symtab) const override; }; -template + class VMaskMergeMicroInst : public VectorArithMicroInst { private: @@ -548,75 +547,12 @@ class VMaskMergeMicroInst : public VectorArithMicroInst public: uint32_t vlen; + size_t elemSize; VMaskMergeMicroInst(ExtMachInst extMachInst, - uint8_t _dstReg, uint8_t _numSrcs, uint32_t _vlen) - : VectorArithMicroInst("vmask_mv_micro", extMachInst, - VectorIntegerArithOp, 0, 0), - vlen(_vlen) - { - setRegIdxArrays( - reinterpret_cast( - &std::remove_pointer_t::srcRegIdxArr), - reinterpret_cast( - &std::remove_pointer_t::destRegIdxArr)); - - _numSrcRegs = 0; - _numDestRegs = 0; - - setDestRegIdx(_numDestRegs++, vecRegClass[_dstReg]); - _numTypedDestRegs[VecRegClass]++; - for (uint8_t i=0; i<_numSrcs; i++) { - setSrcRegIdx(_numSrcRegs++, vecRegClass[VecMemInternalReg0 + i]); - } - } - - Fault - execute(ExecContext* xc, trace::InstRecord* traceData) const override - { - vreg_t& tmp_d0 = *(vreg_t *)xc->getWritableRegOperand(this, 0); - PCStateBase *pc_ptr = xc->tcBase()->pcState().clone(); - auto Vd = tmp_d0.as(); - uint32_t vlenb = pc_ptr->as().vlenb(); - const uint32_t elems_per_vreg = vlenb / sizeof(ElemType); - size_t bit_cnt = elems_per_vreg; - vreg_t tmp_s; - xc->getRegOperand(this, 0, &tmp_s); - auto s = tmp_s.as(); - // cp the first result and tail - memcpy(Vd, s, vlenb); - for (uint8_t i = 1; i < this->_numSrcRegs; i++) { - xc->getRegOperand(this, i, &tmp_s); - s = tmp_s.as(); - if (elems_per_vreg < 8) { - const uint32_t m = (1 << elems_per_vreg) - 1; - const uint32_t mask = m << (i * elems_per_vreg % 8); - // clr & ext bits - Vd[bit_cnt/8] ^= Vd[bit_cnt/8] & mask; - Vd[bit_cnt/8] |= s[bit_cnt/8] & mask; - bit_cnt += elems_per_vreg; - } else { - const uint32_t byte_offset = elems_per_vreg / 8; - memcpy(Vd + i * byte_offset, s + i * byte_offset, byte_offset); - } - } - if (traceData) - traceData->setData(vecRegClass, &tmp_d0); - return NoFault; - } - - std::string - generateDisassembly(Addr pc, const loader::SymbolTable *symtab) - const override - { - std::stringstream ss; - ss << mnemonic << ' ' << registerName(destRegIdx(0)); - for (uint8_t i = 0; i < this->_numSrcRegs; i++) { - ss << ", " << registerName(srcRegIdx(i)); - } - unsigned vlenb = vlen >> 3; - ss << ", offset:" << vlenb / sizeof(ElemType); - return ss.str(); - } + uint8_t _dstReg, uint8_t _numSrcs, uint32_t _vlen, size_t _elemSize); + Fault execute(ExecContext *, trace::InstRecord *) const override; + std::string generateDisassembly(Addr, + const loader::SymbolTable *) const override; }; class VxsatMicroInst : public VectorArithMicroInst @@ -630,21 +566,9 @@ class VxsatMicroInst : public VectorArithMicroInst { vxsat = Vxsat; } - Fault - execute(ExecContext* xc, trace::InstRecord* traceData) const override - { - xc->setMiscReg(MISCREG_VXSAT,*vxsat); - auto vcsr = xc->readMiscReg(MISCREG_VCSR); - xc->setMiscReg(MISCREG_VCSR, ((vcsr&~1)|*vxsat)); - return NoFault; - } - std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) - const override - { - std::stringstream ss; - ss << mnemonic << ' ' << "VXSAT" << ", " << (*vxsat ? "0x1" : "0x0"); - return ss.str(); - } + Fault execute(ExecContext *, trace::InstRecord *) const override; + std::string generateDisassembly(Addr, const loader::SymbolTable *) + const override; }; } // namespace RiscvISA diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa index 3a528f1198..364639a716 100644 --- a/src/arch/riscv/isa/templates/vector_arith.isa +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -1107,8 +1107,8 @@ template this->microops.push_back(microop); micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); } - microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, - this->microops.size(), _vlen); + microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, + this->microops.size(), _vlen, sizeof(ElemType)); this->microops.push_back(microop); this->microops.front()->setFirstMicroop(); @@ -1236,8 +1236,8 @@ template this->microops.push_back(microop); micro_vl = std::min(tmp_vl -= micro_vlmax, micro_vlmax); } - microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, - this->microops.size(), _vlen); + microop = new VMaskMergeMicroInst(_machInst, _machInst.vd, + this->microops.size(), _vlen, sizeof(ElemType)); this->microops.push_back(microop); this->microops.front()->setFirstMicroop(); From ecc248c3c18c0144fb8976a589f9a27f0d26cfc0 Mon Sep 17 00:00:00 2001 From: Ivana Mitrovic Date: Thu, 26 Oct 2023 08:27:32 -0700 Subject: [PATCH 507/693] misc: Fix spelling error in MAINTAINERS.yaml (#475) --- MAINTAINERS.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS.yaml b/MAINTAINERS.yaml index 6636f11e26..ebf5e3a5e7 100644 --- a/MAINTAINERS.yaml +++ b/MAINTAINERS.yaml @@ -55,13 +55,13 @@ arch-gcn3: status: maintained maintainers: - Matt Sinclair - - Matt Porema + - Matt Poremba arch-vega: status: maintained maintainers: - Matt Sinclair - - Matt Porema + - Matt Poremba arch-mips: status: orphaned From e496d29171c0dac56432fde3a7bc76bb92350ca2 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 18 Oct 2023 15:18:43 +0100 Subject: [PATCH 508/693] stdlib: Explicitly set alloc_on_atomic for the CHI example gem5 will otherwise fatal with the error message: fatal: ... alloc_on_atomic without default or user set value See github issue [1] for further details [1]: https://github.com/gem5/gem5/issues/449 Change-Id: I0bb8fccf0ac6d60fc6c1229436a35e91b2fb45cd Signed-off-by: Giacomo Travaglini --- .../gem5/components/cachehierarchies/chi/nodes/directory.py | 1 + .../gem5/components/cachehierarchies/chi/nodes/dma_requestor.py | 1 + .../cachehierarchies/chi/nodes/private_l1_moesi_cache.py | 1 + 3 files changed, 3 insertions(+) diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py index 3488435d56..b93112a620 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py @@ -72,6 +72,7 @@ class SimpleDirectory(AbstractNode): self.alloc_on_readunique = False self.alloc_on_readonce = False self.alloc_on_writeback = False + self.alloc_on_atomic = False self.dealloc_on_unique = False self.dealloc_on_shared = False self.dealloc_backinv_unique = 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 index ccac6cae91..f6b63e0649 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py @@ -56,6 +56,7 @@ class DMARequestor(AbstractNode): self.alloc_on_readunique = False self.alloc_on_readonce = False self.alloc_on_writeback = False + self.alloc_on_atomic = False self.dealloc_on_unique = False self.dealloc_on_shared = False self.dealloc_backinv_unique = True 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 index 3e38c9038f..2f618491ca 100644 --- 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 @@ -66,6 +66,7 @@ class PrivateL1MOESICache(AbstractNode): self.alloc_on_readunique = True self.alloc_on_readonce = True self.alloc_on_writeback = False # Should never happen in an L1 + self.alloc_on_atomic = False self.dealloc_on_unique = False self.dealloc_on_shared = False self.dealloc_backinv_unique = True From 1b05c0050bdee2024d89b4a083b793af7ae1fbd9 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Sat, 28 Oct 2023 22:59:51 +0100 Subject: [PATCH 509/693] mem-ruby: Clear the atomic log from the DataBlock in CHI The new far atomics implementation [1] didn't take into consideration it was supposed to manually clear the atomic log. This caused a memory leak where the log queue was getting bigger and bigger as no cleaning was happening [1]: https://github.com/gem5/gem5/pull/177 Change-Id: I4a74fbf15d21e35caec69c29117e2d98cc86d5ff Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 4c9498423c..ffa57cb03b 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -2299,6 +2299,7 @@ action(UpdateDataState_FromADataResp, desc="") { tbe.oldDataBlk := tbe.dataBlk; tbe.dataBlk.atomicPartial(tbe.dataBlk, tbe.atomic_op); + tbe.dataBlk.clearAtomicLogEntries(); tbe.dataDirty := true; DPRINTF(RubySlicc, "Atomic after %s\n", tbe.dataBlk); @@ -3424,6 +3425,7 @@ action(Callback_AtomicHit, desc="") { DataBlock oldDataBlk; oldDataBlk := tbe.dataBlk; tbe.dataBlk.atomicPartial(tbe.dataBlk, tbe.atomic_op); + tbe.dataBlk.clearAtomicLogEntries(); sequencer.atomicCallback(tbe.addr, oldDataBlk, false); DPRINTF(RubySlicc, "Atomic after %s\n", tbe.dataBlk); @@ -3490,6 +3492,7 @@ action(Callback_Miss, desc="") { DataBlock oldDataBlk; oldDataBlk := tbe.dataBlk; tbe.dataBlk.atomicPartial(tbe.dataBlk, tbe.atomic_op); + tbe.dataBlk.clearAtomicLogEntries(); sequencer.atomicCallback(tbe.addr, oldDataBlk, false); DPRINTF(RubySlicc, "Atomic after %s\n", tbe.dataBlk); From 108704169810fa0b444d7eedae070a8621a55760 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Sun, 29 Oct 2023 08:27:19 +0000 Subject: [PATCH 510/693] stdlib: Use near atomics in the CHI component nodes This is a temporary solution to fix daily tests. We could revert to the default (policy_type = 1) once the problem is properly fixed Change-Id: Ia80af9a7d84d5c777ddeb441110a91a1680c1030 Signed-off-by: Giacomo Travaglini --- .../components/cachehierarchies/chi/nodes/abstract_node.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py index 746c66eb01..ed8c3e0d5a 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py @@ -85,6 +85,9 @@ class AbstractNode(Cache_Controller): # Use 32-byte channels (two flits per message) self.data_channel_size = 32 + # Use near atomics (see: https://github.com/gem5/gem5/issues/449) + self.policy_type = 0 + self.connectQueues(network) def getBlockSizeBits(self): From d131ff488e4b5f88c019c3473ab8f76af41f3b2a Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 30 Oct 2023 10:43:22 +0000 Subject: [PATCH 511/693] arch-arm: Set UNCACHEABLE flag in Request in SE mode (#515) As pointed out by [1], Arm doesn't seem to respect the cacheability attribute when mapping uncacheable memory. This is because the request is not tagged as uncacheable during SE translation With this patch we are checking for the cacheability attribute before finalizing translation [1]: https://github.com/gem5/gem5/issues/509 Change-Id: I42df0e119af61763971d5766ae764a540055781b Signed-off-by: Giacomo Travaglini --- src/arch/arm/mmu.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/arch/arm/mmu.cc b/src/arch/arm/mmu.cc index 824974ab21..956f95d3b3 100644 --- a/src/arch/arm/mmu.cc +++ b/src/arch/arm/mmu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013, 2016-2022 Arm Limited + * Copyright (c) 2010-2013, 2016-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -263,14 +263,17 @@ MMU::translateSe(const RequestPtr &req, ThreadContext *tc, Mode mode, } } - Addr paddr; Process *p = tc->getProcessPtr(); - - if (!p->pTable->translate(vaddr, paddr)) + if (const auto pte = p->pTable->lookup(vaddr); !pte) { return std::make_shared(vaddr_tainted); - req->setPaddr(paddr); + } else { + req->setPaddr(pte->paddr + p->pTable->pageOffset(vaddr)); - return finalizePhysical(req, tc, mode); + if (pte->flags & EmulationPageTable::Uncacheable) + req->setFlags(Request::UNCACHEABLE); + + return finalizePhysical(req, tc, mode); + } } Fault From 0218103162b2f530ba2b50f105387b408a5fa7c7 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 30 Oct 2023 09:56:10 -0700 Subject: [PATCH 512/693] arch-riscv: Correct BootloaderKernelWorkload symbol table (#511) Currently, the kernel's symbols are shifted by `kernel_paddr_offset`, which is where the kernel is located in the physcial address space. However, the symbols are mapped to virtual addresses, which stay the same even though the physical address space is shifted. This patch removes the offset for the kernel's symbols virtual addresses. Change-Id: I7c35f925777220f56bd8c69bba14c267d2048ade Signed-off-by: Hoa Nguyen --- src/arch/riscv/linux/fs_workload.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index 8bb35ccd17..0933df6cfb 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -96,11 +96,10 @@ void BootloaderKernelWorkload::loadKernelSymbolTable() { if (params().kernel_filename != "") { - Addr kernel_paddr_offset = params().kernel_addr; kernel = loader::createObjectFile(params().kernel_filename); kernelSymbolTable = kernel->symtab(); auto renamedKernelSymbolTable = \ - kernelSymbolTable.offset(kernel_paddr_offset)->rename( + kernelSymbolTable.rename( [](std::string &name) { name = "kernel." + name; } From 697cab05443266b98c23323b3364c0520af3692a Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 29 Oct 2023 03:20:47 +0000 Subject: [PATCH 513/693] base,sim: Add the SymbolType field to the Symbol object Symbol type is part of the info provided by an ELF object's symtab. It indicates whether a symbol is a file symbol, or a function symbol, etc. Change-Id: I827e79f8439c47ac9e889734aaf354c653aff530 Signed-off-by: Hoa Nguyen --- src/base/loader/elf_object.cc | 21 ++ src/base/loader/symtab.cc | 6 +- src/base/loader/symtab.hh | 12 ++ src/base/loader/symtab.test.cc | 358 +++++++++++++++++++++++---------- src/sim/pseudo_inst.cc | 15 +- 5 files changed, 305 insertions(+), 107 deletions(-) diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 4b1467acf0..5eef4cb44c 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -196,6 +196,27 @@ ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd) continue; } + switch (GELF_ST_TYPE(sym.st_info)) { + case STT_NOTYPE: + symbol.type = loader::Symbol::SymbolType::NoType; + break; + case STT_OBJECT: + symbol.type = loader::Symbol::SymbolType::Object; + break; + case STT_FUNC: + symbol.type = loader::Symbol::SymbolType::Function; + break; + case STT_SECTION: + symbol.type = loader::Symbol::SymbolType::Section; + break; + case STT_FILE: + symbol.type = loader::Symbol::SymbolType::File; + break; + default: + symbol.type = loader::Symbol::SymbolType::Other; + break; + } + if (_symtab.insert(symbol)) { DPRINTF(Loader, "Symbol: %-40s value %#x.\n", symbol.name, symbol.address); diff --git a/src/base/loader/symtab.cc b/src/base/loader/symtab.cc index 041476bf7d..cd7bec3d56 100644 --- a/src/base/loader/symtab.cc +++ b/src/base/loader/symtab.cc @@ -101,6 +101,7 @@ SymbolTable::serialize(const std::string &base, CheckpointOut &cp) const paramOut(cp, csprintf("%s.addr_%d", base, i), symbol.address); paramOut(cp, csprintf("%s.symbol_%d", base, i), symbol.name); paramOut(cp, csprintf("%s.binding_%d", base, i), (int)symbol.binding); + paramOut(cp, csprintf("%s.type_%d", base, i), (int)symbol.type); i++; } } @@ -116,12 +117,15 @@ SymbolTable::unserialize(const std::string &base, CheckpointIn &cp, Addr address; std::string name; Symbol::Binding binding = default_binding; + Symbol::SymbolType type = Symbol::SymbolType::Other; paramIn(cp, csprintf("%s.addr_%d", base, i), address); paramIn(cp, csprintf("%s.symbol_%d", base, i), name); if (!optParamIn(cp, csprintf("%s.binding_%d", base, i), binding)) binding = default_binding; - insert({binding, name, address}); + if (!optParamIn(cp, csprintf("%s.type_%d", base, i), type)) + type = Symbol::SymbolType::Other; + insert({binding, type, name, address}); } } diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 2e50523c32..45e55fcee7 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -56,7 +56,19 @@ struct Symbol Weak }; + // The ELF64_ST_TYPE field of gelf's st_info + enum class SymbolType + { + NoType, + Object, + Function, + Section, + File, + Other + }; + Binding binding; + SymbolType type; std::string name; Addr address; }; diff --git a/src/base/loader/symtab.test.cc b/src/base/loader/symtab.test.cc index 313055392a..1705a4165c 100644 --- a/src/base/loader/symtab.test.cc +++ b/src/base/loader/symtab.test.cc @@ -58,6 +58,12 @@ getSymbolError(const loader::Symbol& symbol, const loader::Symbol& expected) (int)expected.binding << "`.\n"; } + if (symbol.type != expected.type) { + ss << " symbols' types do not match: seen `" << + (int)symbol.type << "`, expected `" << + (int)expected.type << "`.\n"; + } + if (symbol.name != expected.name) { ss << " symbols' names do not match: seen `" << symbol.name << "`, expected `" << expected.name << "`.\n"; @@ -136,7 +142,9 @@ TEST(LoaderSymtabTest, InsertSymbolNoName) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "", 0x10}; ASSERT_FALSE(symtab.insert(symbol)); ASSERT_TRUE(checkTable(symtab, {})); } @@ -146,7 +154,9 @@ TEST(LoaderSymtabTest, InsertOneSymbol) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "symbol", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}; ASSERT_TRUE(symtab.insert(symbol)); ASSERT_FALSE(symtab.empty()); @@ -160,8 +170,10 @@ TEST(LoaderSymtabTest, InsertSymbolExistingName) const std::string name = "symbol"; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, name, 0x10}, - {loader::Symbol::Binding::Local, name, 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + name, 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + name, 0x20}, }; ASSERT_TRUE(symtab.insert(symbols[0])); ASSERT_FALSE(symtab.insert(symbols[1])); @@ -177,8 +189,10 @@ TEST(LoaderSymtabTest, InsertSymbolExistingAddress) const Addr addr = 0x10; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", addr}, - {loader::Symbol::Binding::Local, "symbol2", addr}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", addr}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", addr}, }; ASSERT_TRUE(symtab.insert(symbols[0])); ASSERT_TRUE(symtab.insert(symbols[1])); @@ -193,9 +207,12 @@ TEST(LoaderSymtabTest, InsertMultipleSymbols) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -212,9 +229,12 @@ TEST(LoaderSymtabTest, ClearMultiple) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -234,9 +254,12 @@ TEST(LoaderSymtabTest, Offset) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -250,9 +273,12 @@ TEST(LoaderSymtabTest, Offset) // Check that the new table is offset loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].name, symbols[0].address + offset}, - {symbols[1].binding, symbols[1].name, symbols[1].address + offset}, - {symbols[2].binding, symbols[2].name, symbols[2].address + offset}, + {symbols[0].binding, symbols[0].type, symbols[0].name, + symbols[0].address + offset}, + {symbols[1].binding, symbols[1].type, symbols[1].name, + symbols[1].address + offset}, + {symbols[2].binding, symbols[2].type, symbols[2].name, + symbols[2].address + offset}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2]})); @@ -267,10 +293,14 @@ TEST(LoaderSymtabTest, Mask) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x1310}, - {loader::Symbol::Binding::Local, "symbol2", 0x2810}, - {loader::Symbol::Binding::Local, "symbol3", 0x2920}, - {loader::Symbol::Binding::Local, "symbol4", 0x3C20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x1310}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x2810}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x2920}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol4", 0x3C20}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -286,10 +316,14 @@ TEST(LoaderSymtabTest, Mask) // Check that the new table is masked loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].name, symbols[0].address & mask}, - {symbols[1].binding, symbols[1].name, symbols[1].address & mask}, - {symbols[2].binding, symbols[2].name, symbols[2].address & mask}, - {symbols[3].binding, symbols[3].name, symbols[3].address & mask}, + {symbols[0].binding, symbols[0].type, symbols[0].name, + symbols[0].address & mask}, + {symbols[1].binding, symbols[1].type, symbols[1].name, + symbols[1].address & mask}, + {symbols[2].binding, symbols[2].type, symbols[2].name, + symbols[2].address & mask}, + {symbols[3].binding, symbols[3].type, symbols[3].name, + symbols[3].address & mask}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2], expected_symbols[3]})); @@ -304,10 +338,14 @@ TEST(LoaderSymtabTest, Rename) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Local, "symbol4", 0x40}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -323,10 +361,14 @@ TEST(LoaderSymtabTest, Rename) // Check that the new table's symbols have been renamed loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].name + "_suffix", symbols[0].address}, - {symbols[1].binding, symbols[1].name + "_suffix", symbols[1].address}, - {symbols[2].binding, symbols[2].name + "_suffix", symbols[2].address}, - {symbols[3].binding, symbols[3].name + "_suffix", symbols[3].address}, + {symbols[0].binding, symbols[0].type, symbols[0].name + "_suffix", + symbols[0].address}, + {symbols[1].binding, symbols[1].type, symbols[1].name + "_suffix", + symbols[1].address}, + {symbols[2].binding, symbols[2].type, symbols[2].name + "_suffix", + symbols[2].address}, + {symbols[3].binding, symbols[3].type, symbols[3].name + "_suffix", + symbols[3].address}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2], expected_symbols[3]})); @@ -341,10 +383,14 @@ TEST(LoaderSymtabTest, RenameNonUnique) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Local, "symbol4", 0x40}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -366,9 +412,12 @@ TEST(LoaderSymtabTest, RenameNonUnique) // Check that the new table's symbols have been renamed, yet it does not // contain the symbols with duplicated names loader::Symbol expected_symbols[] = { - {symbols[0].binding, "NonUniqueName", symbols[0].address}, - {symbols[1].binding, symbols[1].name, symbols[1].address}, - {symbols[3].binding, symbols[3].name, symbols[3].address}, + {symbols[0].binding, symbols[0].type, "NonUniqueName", + symbols[0].address}, + {symbols[1].binding, symbols[1].type, symbols[1].name, + symbols[1].address}, + {symbols[3].binding, symbols[3].type, symbols[3].name, + symbols[3].address}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2]})); @@ -383,11 +432,16 @@ TEST(LoaderSymtabTest, Globals) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Global, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Weak, "symbol4", 0x40}, - {loader::Symbol::Binding::Weak, "symbol5", 0x50} + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol5", 0x50} }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -414,11 +468,16 @@ TEST(LoaderSymtabTest, Locals) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Global, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Weak, "symbol4", 0x40}, - {loader::Symbol::Binding::Weak, "symbol5", 0x50} + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol5", 0x50} }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -445,11 +504,16 @@ TEST(LoaderSymtabTest, Weaks) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Global, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Weak, "symbol4", 0x40}, - {loader::Symbol::Binding::Weak, "symbol5", 0x50} + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol5", 0x50} }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -467,12 +531,50 @@ TEST(LoaderSymtabTest, Weaks) ASSERT_TRUE(checkTable(*symtab_new, {symbols[3], symbols[4]})); } +/** + * Test the creation of a new filtered table containing only function symbols + * of the original table. Also verifies if the original table is kept the same. + */ +TEST(LoaderSymtabTest, FunctionSymbols) +{ + loader::SymbolTable symtab; + + loader::Symbol symbols[] = { + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::NoType, + "symbol", 0x10}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::File, + "symbol2", 0x20}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Function, + "symbol3", 0x30}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Object, + "symbol4", 0x40}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Function, + "symbol5", 0x50} + }; + EXPECT_TRUE(symtab.insert(symbols[0])); + EXPECT_TRUE(symtab.insert(symbols[1])); + EXPECT_TRUE(symtab.insert(symbols[2])); + EXPECT_TRUE(symtab.insert(symbols[3])); + EXPECT_TRUE(symtab.insert(symbols[4])); + + const auto symtab_new = symtab.functionSymbols(); + + // Check that the original table is not modified + ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2], + symbols[3], symbols[4]})); + + // Check that the new table only contains function symbols + ASSERT_TRUE(checkTable(*symtab_new, {symbols[2], symbols[4]})); +} + /** Test searching for a non-existent address. */ TEST(LoaderSymtabTest, FindNonExistentAddress) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "symbol", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); ASSERT_EQ(symtab.find(0x0), symtab.end()); @@ -484,9 +586,12 @@ TEST(LoaderSymtabTest, FindUniqueAddress) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -506,9 +611,12 @@ TEST(LoaderSymtabTest, FindNonUniqueAddress) const Addr addr = 0x20; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", addr}, - {loader::Symbol::Binding::Local, "symbol3", addr}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", addr}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", addr}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -524,7 +632,9 @@ TEST(LoaderSymtabTest, FindNonExistentName) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "symbol", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); const auto it = symtab.find("symbol2"); @@ -537,9 +647,12 @@ TEST(LoaderSymtabTest, FindExistingName) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -556,8 +669,10 @@ TEST(LoaderSymtabTest, FindNearestExact) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -575,7 +690,9 @@ TEST(LoaderSymtabTest, FindNearestRound) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "symbol", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); const auto it = symtab.findNearest(symbol.address + 0x1); @@ -593,8 +710,10 @@ TEST(LoaderSymtabTest, FindNearestRoundWithNext) loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -615,7 +734,9 @@ TEST(LoaderSymtabTest, FindNearestRoundWithNextNonExistent) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "symbol", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); Addr next_addr; @@ -633,7 +754,9 @@ TEST(LoaderSymtabTest, FindNearestNonExistent) { loader::SymbolTable symtab; - loader::Symbol symbol = {loader::Symbol::Binding::Local, "symbol", 0x10}; + loader::Symbol symbol = \ + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); const auto it = symtab.findNearest(symbol.address - 0x1); @@ -648,12 +771,17 @@ TEST(LoaderSymtabTest, InsertTableConflicting) { const std::string name = "symbol"; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, name, 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Local, "symbol4", 0x40}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + name, 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, // Introduce name conflict - {loader::Symbol::Binding::Local, name, 0x50}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + name, 0x50}, }; // Populate table 1 @@ -682,11 +810,16 @@ TEST(LoaderSymtabTest, InsertTableConflicting) TEST(LoaderSymtabTest, InsertTable) { loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, - {loader::Symbol::Binding::Local, "symbol4", 0x40}, - {loader::Symbol::Binding::Local, "symbol5", 0x50}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol4", 0x40}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol5", 0x50}, }; // Populate table 1 @@ -719,9 +852,12 @@ TEST_F(LoaderSymtabSerializationFixture, Serialization) // Populate the table loader::SymbolTable symtab; loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); @@ -735,22 +871,31 @@ TEST_F(LoaderSymtabSerializationFixture, Serialization) // Verify the output ASSERT_THAT(cp.str(), ::testing::StrEq("\n[Section1]\ntest.size=3\n" "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n" + "test.type_0=5\n" "test.addr_1=32\ntest.symbol_1=symbol2\ntest.binding_1=1\n" - "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n")); + "test.type_1=5\n" + "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n" + "test.type_2=5\n")); } /** Test unserialization. */ TEST_F(LoaderSymtabSerializationFixture, Unserialization) { loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Local, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; simulateSerialization("\n[Section1]\ntest.size=3\n" "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n" + "test.type_0=5\n" "test.addr_1=32\ntest.symbol_1=symbol2\ntest.binding_1=1\n" - "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"); + "test.type_1=5\n" + "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n" + "test.type_2=5\n"); loader::SymbolTable unserialized_symtab; CheckpointIn cp(getDirName()); @@ -771,14 +916,19 @@ TEST_F(LoaderSymtabSerializationFixture, Unserialization) TEST_F(LoaderSymtabSerializationFixture, UnserializationMissingBinding) { loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Global, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; simulateSerialization("\n[Section1]\ntest.size=3\n" "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n" - "test.addr_1=32\ntest.symbol_1=symbol2\n" - "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"); + "test.type_0=5\n" + "test.addr_1=32\ntest.symbol_1=symbol2\ntest.type_1=5\n" + "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n" + "test.type_2=5\n"); loader::SymbolTable unserialized_symtab; CheckpointIn cp(getDirName()); @@ -801,14 +951,20 @@ TEST_F(LoaderSymtabSerializationFixture, UnserializationMissingBindingChangeDefault) { loader::Symbol symbols[] = { - {loader::Symbol::Binding::Local, "symbol", 0x10}, - {loader::Symbol::Binding::Weak, "symbol2", 0x20}, - {loader::Symbol::Binding::Local, "symbol3", 0x30}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol", 0x10}, + {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other, + "symbol2", 0x20}, + {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other, + "symbol3", 0x30}, }; simulateSerialization("\n[Section1]\ntest.size=3\n" "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n" + "test.type_0=5\n" "test.addr_1=32\ntest.symbol_1=symbol2\n" - "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"); + "test.type_1=5\n" + "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n" + "test.type_2=5\n"); loader::SymbolTable unserialized_symtab; CheckpointIn cp(getDirName()); diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 55e44c7adc..29caba6661 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -244,9 +244,10 @@ loadsymbol(ThreadContext *tc) continue; if (!tc->getSystemPtr()->workload->insertSymbol( - { loader::Symbol::Binding::Global, symbol, addr })) { - continue; - } + { loader::Symbol::Binding::Global, + loader::Symbol::SymbolType::Function, symbol, addr })) { + continue; + } DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); @@ -270,9 +271,13 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); tc->getSystemPtr()->workload->insertSymbol( - { loader::Symbol::Binding::Global, symbol, addr }); + { loader::Symbol::Binding::Global, + loader::Symbol::SymbolType::Function, symbol, addr } + ); loader::debugSymbolTable.insert( - { loader::Symbol::Binding::Global, symbol, addr }); + { loader::Symbol::Binding::Global, + loader::Symbol::SymbolType::Function, symbol, addr } + ); } uint64_t From 6eca83d0fb85897b9575a5c53beae8d0b22dd676 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 29 Oct 2023 03:29:30 +0000 Subject: [PATCH 514/693] base: Add ability to generate SymbolTable by filtering SymbolType This allows filtering out non function symbols. Change-Id: I518c2842a6f04c4475240126ad64070a6de09df9 Signed-off-by: Hoa Nguyen --- src/base/loader/symtab.hh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 45e55fcee7..654064c9db 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -176,6 +176,22 @@ class SymbolTable return filter(filt); } + /** + * Generate a new table by applying a filter that only accepts the symbols + * whose type matches the given symbol type. + * + * @param The type that must be matched. + * @return A new table, filtered by type. + */ + SymbolTablePtr + filterBySymbolType(const Symbol::SymbolType& symbol_type) const + { + auto filt = [symbol_type](const Symbol &symbol) { + return symbol.type == symbol_type; + }; + return filter(filt); + } + public: typedef SymbolVector::iterator iterator; typedef SymbolVector::const_iterator const_iterator; @@ -302,6 +318,17 @@ class SymbolTable return filterByBinding(Symbol::Binding::Weak); } + /** + * Generates a new symbol table containing only function symbols. + * + * @return The new table. + */ + SymbolTablePtr + functionSymbols() const + { + return filterBySymbolType(Symbol::SymbolType::Function); + } + /** * Serialize the table's contents. * From 4fdfb96cadd5cb6e0bccec469dc1a699507fe5bb Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 29 Oct 2023 03:47:40 +0000 Subject: [PATCH 515/693] arch-riscv: Load function symbols for BootloaderKernelWorkload Change-Id: Iade91b2cdf6701ed3fe6f5583127c8c3d669d695 Signed-off-by: Hoa Nguyen --- src/arch/riscv/linux/fs_workload.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index 0933df6cfb..2946d6c324 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -83,7 +83,9 @@ BootloaderKernelWorkload::loadBootloaderSymbolTable() bootloader = loader::createObjectFile(params().bootloader_filename); bootloaderSymbolTable = bootloader->symtab(); auto renamedBootloaderSymbolTable = \ - bootloaderSymbolTable.offset(bootloader_paddr_offset)->rename( + bootloaderSymbolTable.offset( + bootloader_paddr_offset + )->functionSymbols()->rename( [](std::string &name) { name = "bootloader." + name; } @@ -99,7 +101,7 @@ BootloaderKernelWorkload::loadKernelSymbolTable() kernel = loader::createObjectFile(params().kernel_filename); kernelSymbolTable = kernel->symtab(); auto renamedKernelSymbolTable = \ - kernelSymbolTable.rename( + kernelSymbolTable.functionSymbols()->rename( [](std::string &name) { name = "kernel." + name; } From 2521ba066475ae0884d80ef0285efbd327767380 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 30 Oct 2023 02:07:04 +0000 Subject: [PATCH 516/693] arch-riscv: Fix implementation of CMO extension instructions This change introduces a template for store instruction's mem access. The new template is called CacheBlockBasedStore. The reasons for not reusing the current Store's mem access template are as follows, - The CMO extension instructions operate on cache block size granularity, while regular load/store instructions operate on data of size 64 bits or fewer. - The writeMemAtomicLE/writeMemTimingLE interfaces do not allow passing nullptr as data. However, CPUs in gem5 rely on (data == NULL) to detect CACHE_BLOCK_ZERO instructions. Setting `Mem = 0;` to `uint64_t Mem;` does not solve the problem as the reference is allocated and thus, it's always true that `&Mem != NULL`. This change uses the writeMemAtomic/writeMemTiming interfaces instead. - Per CMO v1.0.1, the instructions in the spec do not generate address misaligned faults. - The CMO extension instructions do not use IMM. Change-Id: I323615639a4ba882fe40a55ed32c7632e0251421 Signed-off-by: Hoa Nguyen --- src/arch/riscv/isa/formats/mem.isa | 69 ++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/arch/riscv/isa/formats/mem.isa b/src/arch/riscv/isa/formats/mem.isa index 7cec113ba1..53de4af8b4 100644 --- a/src/arch/riscv/isa/formats/mem.isa +++ b/src/arch/riscv/isa/formats/mem.isa @@ -228,6 +228,69 @@ def template StoreCompleteAcc {{ } }}; +def template CacheBlockBasedStoreExecute {{ + Fault + %(class_name)s::execute(ExecContext *xc, + trace::InstRecord *traceData) const + { + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + Addr cacheBlockSize = xc->tcBase()->getCpuPtr()->cacheLineSize(); + uint64_t numOffsetBits = floorLog2(cacheBlockSize); + EA = (EA >> numOffsetBits) << numOffsetBits; + + { + Fault fault = + writeMemAtomic(xc, nullptr, EA, cacheBlockSize, memAccessFlags, + nullptr, std::vector(cacheBlockSize, true)); + if (fault != NoFault) + return fault; + } + + return NoFault; + } +}}; + +def template CacheBlockBasedStoreInitiateAcc {{ + Fault + %(class_name)s::initiateAcc(ExecContext *xc, + trace::InstRecord *traceData) const + { + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + Addr cacheBlockSize = xc->tcBase()->getCpuPtr()->cacheLineSize(); + uint64_t numOffsetBits = floorLog2(cacheBlockSize); + EA = (EA >> numOffsetBits) << numOffsetBits; + + { + Fault fault = + writeMemTiming(xc, nullptr, EA, cacheBlockSize, memAccessFlags, + nullptr, std::vector(cacheBlockSize, true)); + if (fault != NoFault) + return fault; + } + + return NoFault; + } +}}; + +def template CacheBlockBasedStoreCompleteAcc {{ + Fault + %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, + trace::InstRecord *traceData) const + { + return NoFault; + } +}}; + def format Load(memacc_code, ea_code = {{EA = rvZext(Rs1 + offset);}}, offset_code={{offset = sext<12>(IMM12);}}, mem_flags=[], inst_flags=[]) {{ @@ -244,9 +307,9 @@ def format Store(memacc_code, ea_code={{EA = rvZext(Rs1 + offset);}}, inst_flags, 'Store', exec_template_base='Store') }}; -def format CBMOp(memacc_code, ea_code={{EA = rvZext(Rs1 + offset);}}, - offset_code={{offset = 0;}}, mem_flags=[], inst_flags=[]) {{ +def format CBMOp(memacc_code, ea_code={{EA = rvZext(Rs1);}}, + offset_code={{;}}, mem_flags=[], inst_flags=[]) {{ (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags, - inst_flags, 'Store', exec_template_base='Store') + inst_flags, 'Store', exec_template_base='CacheBlockBasedStore') }}; From f615ee4cd43fb968397b24946257eb12fd0f3395 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 30 Oct 2023 02:18:29 +0000 Subject: [PATCH 517/693] arch-riscv: Fix generateDisassembly for Store with 1 source reg Currently, store instructions are assumed to have two source registers. However, since we are supporting the RISC-V CMO instructions, which are Store instructions in gem5 but they only have one source register. This change allows printing disassembly of Store instructions with one source register. Change-Id: I4dd7818c9ac8a89d5e10e77db72248942a25e938 Signed-off-by: Hoa Nguyen --- src/arch/riscv/insts/mem.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/insts/mem.cc b/src/arch/riscv/insts/mem.cc index 5f58a68a57..8ebda7406d 100644 --- a/src/arch/riscv/insts/mem.cc +++ b/src/arch/riscv/insts/mem.cc @@ -55,8 +55,13 @@ std::string Store::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const { std::stringstream ss; - ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " << - offset << '(' << registerName(srcRegIdx(0)) << ')'; + if (_numSrcRegs == 1) { + ss << mnemonic << ' ' << offset << '(' << registerName(srcRegIdx(0)) + << ")"; + } else { + ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " << + offset << '(' << registerName(srcRegIdx(0)) << ')'; + } return ss.str(); } From 7c6fcb38386cce2121e699e2eab75e01ea98d97d Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 30 Oct 2023 02:36:24 +0000 Subject: [PATCH 518/693] arch-riscv: Add all supporting Z extensions to RISC-V isa string Change-Id: I809744fc546bc5c0e27380f9b75bdf99f8520583 Signed-off-by: Hoa Nguyen --- src/arch/riscv/RiscvISA.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index 62dcffb5d8..ca533bef0e 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -109,4 +109,15 @@ class RiscvISA(BaseISA): if self.enable_rvv.value == True: isa_extensions.append("v") isa_string = "".join(isa_extensions) + + isa_string += "_Zicbom" # Cache-block Management Instructions + isa_string += "_Zicboz" # Cache-block Zero Instruction + isa_string += "_Zicntr" # Performance Couter Spec + isa_string += "_Zicsr" # RMW CSR Instructions (Privileged Spec) + isa_string += "_Zifencei" # FENCE.I Instruction (Unprivileged Spec) + isa_string += "_Zihpm" # Performance Couter Spec + isa_string += "_Zba" # Address Generation + isa_string += "_Zbb" # Basic Bit Manipulation + isa_string += "_Zbs" # Single-bit Instructions + return isa_string From 68287604ee3364747c6ef54bef38a8fc08245896 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 30 Oct 2023 02:41:26 +0000 Subject: [PATCH 519/693] arch-riscv: Make Zicbom/Zicboz extensions optional in FS mode Currently, we're enable Zicbom/Zicboz by default. Since those extensions might be buggy as they are not well-tested, making those entensions optional allows running simulation where the performance implication of the instructions do not matter. Effectively, by turning off the extensions, we simply remove those extensions from the device tree, so the OS would not use them. It doesn't prohibit the userspace application to use those instructions, however. Change-Id: Ib30e98c4c39f741dec5f7d31bd7b832391686840 Signed-off-by: Hoa Nguyen --- src/arch/riscv/RiscvISA.py | 9 +++++++-- src/python/gem5/components/boards/riscv_board.py | 12 ++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index ca533bef0e..bce7f2497f 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -96,6 +96,9 @@ class RiscvISA(BaseISA): ELEN in Ch. 2 of RISC-V vector spec", ) + enable_Zicbom_fs = Param.Bool(True, "Enable Zicbom extension in FS mode") + enable_Zicboz_fs = Param.Bool(True, "Enable Zicboz extension in FS mode") + def get_isa_string(self): isa_extensions = [] # check for the base ISA type @@ -110,8 +113,10 @@ class RiscvISA(BaseISA): isa_extensions.append("v") isa_string = "".join(isa_extensions) - isa_string += "_Zicbom" # Cache-block Management Instructions - isa_string += "_Zicboz" # Cache-block Zero Instruction + if self.enable_Zicbom_fs.value: + isa_string += "_Zicbom" # Cache-block Management Instructions + if self.enable_Zicboz_fs.value: + isa_string += "_Zicboz" # Cache-block Zero Instruction isa_string += "_Zicntr" # Performance Couter Spec isa_string += "_Zicsr" # RMW CSR Instructions (Privileged Spec) isa_string += "_Zifencei" # FENCE.I Instruction (Unprivileged Spec) diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 9b0d6454e1..5e5af815a4 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -279,6 +279,18 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): node.append(FdtPropertyStrings("device_type", "cpu")) node.append(FdtPropertyWords("reg", state.CPUAddrCells(i))) node.append(FdtPropertyStrings("mmu-type", "riscv,sv48")) + if core.core.isa[0].enable_Zicbom_fs.value: + node.append( + FdtPropertyWords( + "riscv,cbom-block-size", self.get_cache_line_size() + ) + ) + if core.core.isa[0].enable_Zicboz_fs.value: + node.append( + FdtPropertyWords( + "riscv,cboz-block-size", self.get_cache_line_size() + ) + ) node.append(FdtPropertyStrings("status", "okay")) node.append( FdtPropertyStrings( From d05433b3f65af251e0e4b98266f50a5ab1b8a503 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sat, 21 Oct 2023 12:36:35 -0500 Subject: [PATCH 520/693] gpu-compute,dev-hsa: Send vendor packet completion signal gem5 does not currently implement any vendor-specific HSA packets. Starting in ROCm 5.5, vendor packets appear to end with a completion signal. Not sending this completion causes gem5 to hang. Since these packets are not documented anywhere and need to be reverse engineered we send the completion signal, if non-zero, and finish the packet as is the current behavior. Testing: HIP examples working on most recent ROCm release (5.7.1). Change-Id: Id0841407bec564c84f590c943f0609b17e01e14c --- src/dev/hsa/hsa_packet.hh | 8 ++++++++ src/gpu-compute/gpu_command_processor.cc | 23 ++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/dev/hsa/hsa_packet.hh b/src/dev/hsa/hsa_packet.hh index 8c7d694431..8eab8385a6 100644 --- a/src/dev/hsa/hsa_packet.hh +++ b/src/dev/hsa/hsa_packet.hh @@ -100,6 +100,14 @@ struct _hsa_barrier_or_packet_t uint64_t completion_signal; }; +struct _hsa_generic_vendor_pkt +{ + uint32_t padding[14]; + Addr completion_signal; +}; +// All HSA AQL packets are 64 bytes. Confirm that here. +static_assert(sizeof(_hsa_generic_vendor_pkt) == 64); + } // namespace gem5 #endif // __DEV_HSA_HSA_PACKET_HH__ diff --git a/src/gpu-compute/gpu_command_processor.cc b/src/gpu-compute/gpu_command_processor.cc index ecc5f1d98b..5bed04b9dd 100644 --- a/src/gpu-compute/gpu_command_processor.cc +++ b/src/gpu-compute/gpu_command_processor.cc @@ -473,18 +473,27 @@ GPUCommandProcessor::driver() */ /** - * TODO: For now we simply tell the HSAPP to finish the packet, - * however a future patch will update this method to provide - * the proper handling of any required vendor-specific packets. - * In the version of ROCm that is currently supported (1.6) - * the runtime will send packets that direct the CP to - * invalidate the GPUs caches. We do this automatically on - * each kernel launch in the CU, so this is safe for now. + * TODO: For now we simply tell the HSAPP to finish the packet and write a + * completion signal, if any. However, in the future proper handing may be + * required for vendor specific packets. + * + * In the version of ROCm that is currently supported the runtime will send + * packets that direct the CP to invalidate the GPU caches. We do this + * automatically on each kernel launch in the CU, so that situation is safe + * for now. */ void GPUCommandProcessor::submitVendorPkt(void *raw_pkt, uint32_t queue_id, Addr host_pkt_addr) { + auto vendor_pkt = (_hsa_generic_vendor_pkt *)raw_pkt; + + if (vendor_pkt->completion_signal) { + sendCompletionSignal(vendor_pkt->completion_signal); + } + + warn("Ignoring vendor packet\n"); + hsaPP->finishPkt(raw_pkt, queue_id); } From 37da1c45f328e45fc1e07ea55197742bae007d7d Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 13 Oct 2023 14:59:56 -0500 Subject: [PATCH 521/693] dev-amdgpu: Better handling for queue remapping The amdgpu driver can, at *any* time, tell the device to unmap a queue to force the queue descriptor to be written back to main memory in the form of a memory queue descriptor (MQD). It will then immediately remap the queue and continue writing the doorbell to the queue. It is possible that the doorbell write occurs after the queue is unmapped but before it is remapped. In this situation, we need to check the updated value of the doorbell for the queue and write that to the queue after it is mapped. To handle this, a pending doorbell packet map is created to hold a packet to replay when the queue is mapped. Because PCI in gem5 implements only the atomic protocol port, we cannot use the original packet as it must respond in the same Tick. This patch fixes issues with the doorbell maps not being cleared on unmapping to ensure the doorbell is not found in writeDoorbell and places in the pending doorbell map. This includes fixing the doorbell offset value in the doorbell to VMID map which was is now multiplied by four as it is a dword address. This was tested using tensorflow 2.0's MNIST example which was seeing this issue consistently. With this patch it now makes progress and does issue pending doorbell writes. Change-Id: Ic6b401d3fe7fc46b7bcbf19a769cdea6814e7d1e --- src/dev/amdgpu/amdgpu_device.cc | 31 +++++++++++++++++++++++++- src/dev/amdgpu/amdgpu_device.hh | 2 ++ src/dev/amdgpu/pm4_packet_processor.cc | 10 ++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc index 1b81c4d0b2..b25ffbf79f 100644 --- a/src/dev/amdgpu/amdgpu_device.cc +++ b/src/dev/amdgpu/amdgpu_device.cc @@ -466,7 +466,17 @@ AMDGPUDevice::writeDoorbell(PacketPtr pkt, Addr offset) panic("Write to unkown queue type!"); } } else { - warn("Unknown doorbell offset: %lx\n", offset); + warn("Unknown doorbell offset: %lx. Saving to pending doorbells.\n", + offset); + + // We have to ACK the PCI packet immediately, so create a copy of the + // packet here to send again. + RequestPtr pending_req(pkt->req); + PacketPtr pending_pkt = Packet::createWrite(pending_req); + uint8_t *pending_data = new uint8_t[pkt->getSize()]; + pending_pkt->dataDynamic(pending_data); + + pendingDoorbellPkts.emplace(offset, pending_pkt); } } @@ -589,6 +599,17 @@ AMDGPUDevice::write(PacketPtr pkt) return pioDelay; } +void +AMDGPUDevice::processPendingDoorbells(uint32_t offset) +{ + if (pendingDoorbellPkts.count(offset)) { + DPRINTF(AMDGPUDevice, "Sending pending doorbell %x\n", offset); + writeDoorbell(pendingDoorbellPkts[offset], offset); + delete pendingDoorbellPkts[offset]; + pendingDoorbellPkts.erase(offset); + } +} + bool AMDGPUDevice::haveRegVal(uint32_t addr) { @@ -812,6 +833,14 @@ AMDGPUDevice::deallocateAllQueues() for (auto& it : sdmaEngs) { it.second->deallocateRLCQueues(); } + + // "All" queues implicitly refers to all user queues. User queues begin at + // doorbell address 0x4000, so unmap any queue at or above that address. + for (auto [offset, vmid] : doorbellVMIDMap) { + if (offset >= 0x4000) { + doorbells.erase(offset); + } + } } void diff --git a/src/dev/amdgpu/amdgpu_device.hh b/src/dev/amdgpu/amdgpu_device.hh index 7f69ec19f6..b6b6e2a81a 100644 --- a/src/dev/amdgpu/amdgpu_device.hh +++ b/src/dev/amdgpu/amdgpu_device.hh @@ -90,6 +90,7 @@ class AMDGPUDevice : public PciDevice using GPURegMap = std::unordered_map; GPURegMap regs; std::unordered_map doorbells; + std::unordered_map pendingDoorbellPkts; /** * VGA ROM methods @@ -187,6 +188,7 @@ class AMDGPUDevice : public PciDevice * Set handles to GPU blocks. */ void setDoorbellType(uint32_t offset, QueueType qt); + void processPendingDoorbells(uint32_t offset); void setSDMAEngine(Addr offset, SDMAEngine *eng); /** diff --git a/src/dev/amdgpu/pm4_packet_processor.cc b/src/dev/amdgpu/pm4_packet_processor.cc index fdb6f9d7ce..352af400b0 100644 --- a/src/dev/amdgpu/pm4_packet_processor.cc +++ b/src/dev/amdgpu/pm4_packet_processor.cc @@ -384,7 +384,10 @@ PM4PacketProcessor::mapQueues(PM4Queue *q, PM4MapQueues *pkt) "Mapping mqd from %p %p (vmid %d - last vmid %d).\n", addr, pkt->mqdAddr, pkt->vmid, gpuDevice->lastVMID()); - gpuDevice->mapDoorbellToVMID(pkt->doorbellOffset, + // The doorbellOffset is a dword address. We shift by two / multiply + // by four to get the byte address to match doorbell addresses in + // the GPU device. + gpuDevice->mapDoorbellToVMID(pkt->doorbellOffset << 2, gpuDevice->lastVMID()); QueueDesc *mqd = new QueueDesc(); @@ -444,6 +447,8 @@ PM4PacketProcessor::processMQD(PM4MapQueues *pkt, PM4Queue *q, Addr addr, DPRINTF(PM4PacketProcessor, "PM4 mqd read completed, base %p, mqd %p, " "hqdAQL %d.\n", mqd->base, mqd->mqdBase, mqd->aql); + + gpuDevice->processPendingDoorbells(offset); } void @@ -472,6 +477,8 @@ PM4PacketProcessor::processSDMAMQD(PM4MapQueues *pkt, PM4Queue *q, Addr addr, // Register doorbell with GPU device gpuDevice->setSDMAEngine(pkt->doorbellOffset << 2, sdma_eng); gpuDevice->setDoorbellType(pkt->doorbellOffset << 2, RLC); + + gpuDevice->processPendingDoorbells(pkt->doorbellOffset << 2); } void @@ -576,6 +583,7 @@ PM4PacketProcessor::unmapQueues(PM4Queue *q, PM4UnmapQueues *pkt) gpuDevice->deallocatePasid(pkt->pasid); break; case 2: + panic("Unmapping queue selection 2 unimplemented\n"); break; case 3: { auto &hsa_pp = gpuDevice->CP()->hsaPacketProc(); From f07e0e7f5d38f56d147ac07f03757e0b89094e49 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 20 Oct 2023 16:30:43 -0500 Subject: [PATCH 522/693] gpu-compute: Read dispatch packet with timing DMA This fixes occasional readBlob fatals caused by the functional read of system memory, seen often with the KVM CPU. Change-Id: Ifccee666f62faa5b2fcf0a64a9d77c8cf95b3add --- src/gpu-compute/gpu_command_processor.cc | 155 ++++++++++++++--------- src/gpu-compute/gpu_command_processor.hh | 5 + 2 files changed, 99 insertions(+), 61 deletions(-) diff --git a/src/gpu-compute/gpu_command_processor.cc b/src/gpu-compute/gpu_command_processor.cc index 5bed04b9dd..05c9a95eed 100644 --- a/src/gpu-compute/gpu_command_processor.cc +++ b/src/gpu-compute/gpu_command_processor.cc @@ -116,28 +116,52 @@ void GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, Addr host_pkt_addr) { - static int dynamic_task_id = 0; _hsa_dispatch_packet_t *disp_pkt = (_hsa_dispatch_packet_t*)raw_pkt; assert(!(disp_pkt->kernel_object & (system()->cacheLineSize() - 1))); /** - * we need to read a pointer in the application's address - * space to pull out the kernel code descriptor. + * Need to use a raw pointer for DmaVirtDevice API. This is deleted + * in the dispatchKernelObject method. */ - auto *tc = sys->threads[0]; - - TranslatingPortProxy fs_proxy(tc); - SETranslatingPortProxy se_proxy(tc); - PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; + AMDKernelCode *akc = new AMDKernelCode; /** - * In full system mode, the page table entry may point to a system page - * or a device page. System pages use the proxy as normal, but a device - * page needs to be read from device memory. Check what type it is here. + * The kernel_object is a pointer to the machine code, whose entry + * point is an 'amd_kernel_code_t' type, which is included in the + * kernel binary, and describes various aspects of the kernel. The + * desired entry is the 'kernel_code_entry_byte_offset' field, + * which provides the byte offset (positive or negative) from the + * address of the amd_kernel_code_t to the start of the machine + * instructions. + * + * For SE mode we can read from the port proxy. In FS mode, we may need + * to wait for the guest OS to setup translations, especially when using + * the KVM CPU, so it is preferred to read the code object using a timing + * DMA request. */ - bool is_system_page = true; - Addr phys_addr = disp_pkt->kernel_object; - if (FullSystem) { + if (!FullSystem) { + /** + * we need to read a pointer in the application's address + * space to pull out the kernel code descriptor. + */ + auto *tc = sys->threads[0]; + SETranslatingPortProxy virt_proxy(tc); + + DPRINTF(GPUCommandProc, "reading kernel_object using proxy\n"); + virt_proxy.readBlob(disp_pkt->kernel_object, (uint8_t*)akc, + sizeof(AMDKernelCode)); + + dispatchKernelObject(akc, raw_pkt, queue_id, host_pkt_addr); + } else { + /** + * In full system mode, the page table entry may point to a system + * page or a device page. System pages use the proxy as normal, but + * a device page needs to be read from device memory. Check what type + * it is here. + */ + bool is_system_page = true; + Addr phys_addr = disp_pkt->kernel_object; + /** * Full system currently only supports running on single VMID (one * virtual memory space), i.e., one application running on GPU at a @@ -149,61 +173,68 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, walker->startFunctional(gpuDevice->getVM().getPageTableBase(vmid), phys_addr, tmp_bytes, BaseMMU::Mode::Read, is_system_page); - } - DPRINTF(GPUCommandProc, "kernobj vaddr %#lx paddr %#lx size %d s:%d\n", - disp_pkt->kernel_object, phys_addr, sizeof(AMDKernelCode), - is_system_page); + DPRINTF(GPUCommandProc, "kernel_object vaddr %#lx paddr %#lx size %d" + " s:%d\n", disp_pkt->kernel_object, phys_addr, + sizeof(AMDKernelCode), is_system_page); - /** - * The kernel_object is a pointer to the machine code, whose entry - * point is an 'amd_kernel_code_t' type, which is included in the - * kernel binary, and describes various aspects of the kernel. The - * desired entry is the 'kernel_code_entry_byte_offset' field, - * which provides the byte offset (positive or negative) from the - * address of the amd_kernel_code_t to the start of the machine - * instructions. - */ - AMDKernelCode akc; - if (is_system_page) { - DPRINTF(GPUCommandProc, "kernel_object in system, using proxy\n"); - virt_proxy.readBlob(disp_pkt->kernel_object, (uint8_t*)&akc, - sizeof(AMDKernelCode)); - } else { - assert(FullSystem); - DPRINTF(GPUCommandProc, "kernel_object in device, using device mem\n"); + /** + * System objects use DMA device. Device objects need to use device + * memory. + */ + if (is_system_page) { + DPRINTF(GPUCommandProc, + "sending system DMA read for kernel_object\n"); - // Read from GPU memory manager one cache line at a time to prevent - // rare cases where the AKC spans two memory pages. - ChunkGenerator gen(disp_pkt->kernel_object, sizeof(AMDKernelCode), - system()->cacheLineSize()); - for (; !gen.done(); gen.next()) { - Addr chunk_addr = gen.addr(); - int vmid = 1; - unsigned dummy; - walker->startFunctional(gpuDevice->getVM().getPageTableBase(vmid), - chunk_addr, dummy, BaseMMU::Mode::Read, - is_system_page); + auto dma_callback = new DmaVirtCallback( + [=](const uint32_t&) { + dispatchKernelObject(akc, raw_pkt, queue_id, host_pkt_addr); + }); - Request::Flags flags = Request::PHYSICAL; - RequestPtr request = std::make_shared(chunk_addr, - system()->cacheLineSize(), flags, walker->getDevRequestor()); - Packet *readPkt = new Packet(request, MemCmd::ReadReq); - readPkt->dataStatic((uint8_t *)&akc + gen.complete()); - system()->getDeviceMemory(readPkt)->access(readPkt); - delete readPkt; + dmaReadVirt(disp_pkt->kernel_object, sizeof(AMDKernelCode), + dma_callback, (void *)akc); + } else { + DPRINTF(GPUCommandProc, + "kernel_object in device, using device mem\n"); + + // Read from GPU memory manager one cache line at a time to prevent + // rare cases where the AKC spans two memory pages. + ChunkGenerator gen(disp_pkt->kernel_object, sizeof(AMDKernelCode), + system()->cacheLineSize()); + for (; !gen.done(); gen.next()) { + Addr chunk_addr = gen.addr(); + int vmid = 1; + unsigned dummy; + walker->startFunctional( + gpuDevice->getVM().getPageTableBase(vmid), chunk_addr, + dummy, BaseMMU::Mode::Read, is_system_page); + + Request::Flags flags = Request::PHYSICAL; + RequestPtr request = std::make_shared(chunk_addr, + system()->cacheLineSize(), flags, + walker->getDevRequestor()); + Packet *readPkt = new Packet(request, MemCmd::ReadReq); + readPkt->dataStatic((uint8_t *)akc + gen.complete()); + system()->getDeviceMemory(readPkt)->access(readPkt); + delete readPkt; + } + + dispatchKernelObject(akc, raw_pkt, queue_id, host_pkt_addr); } } +} + +void +GPUCommandProcessor::dispatchKernelObject(AMDKernelCode *akc, void *raw_pkt, + uint32_t queue_id, Addr host_pkt_addr) +{ + _hsa_dispatch_packet_t *disp_pkt = (_hsa_dispatch_packet_t*)raw_pkt; DPRINTF(GPUCommandProc, "GPU machine code is %lli bytes from start of the " - "kernel object\n", akc.kernel_code_entry_byte_offset); - - DPRINTF(GPUCommandProc,"GPUCommandProc: Sending dispatch pkt to %lu\n", - (uint64_t)tc->cpuId()); - + "kernel object\n", akc->kernel_code_entry_byte_offset); Addr machine_code_addr = (Addr)disp_pkt->kernel_object - + akc.kernel_code_entry_byte_offset; + + akc->kernel_code_entry_byte_offset; DPRINTF(GPUCommandProc, "Machine code starts at addr: %#x\n", machine_code_addr); @@ -219,7 +250,7 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, * APUs to implement asynchronous memcopy operations from 2 pointers in * host memory. I have no idea what BLIT stands for. * */ - if (akc.runtime_loader_kernel_symbol) { + if (akc->runtime_loader_kernel_symbol) { kernel_name = "Some kernel"; } else { kernel_name = "Blit kernel"; @@ -230,7 +261,7 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, GfxVersion gfxVersion = FullSystem ? gpuDevice->getGfxVersion() : driver()->getGfxVersion(); HSAQueueEntry *task = new HSAQueueEntry(kernel_name, queue_id, - dynamic_task_id, raw_pkt, &akc, host_pkt_addr, machine_code_addr, + dynamic_task_id, raw_pkt, akc, host_pkt_addr, machine_code_addr, gfxVersion); DPRINTF(GPUCommandProc, "Task ID: %i Got AQL: wg size (%dx%dx%d), " @@ -252,6 +283,8 @@ GPUCommandProcessor::submitDispatchPkt(void *raw_pkt, uint32_t queue_id, // The driver expects the start time to be in ns Tick start_ts = curTick() / sim_clock::as_int::ns; dispatchStartTime.insert({disp_pkt->completion_signal, start_ts}); + + delete akc; } void diff --git a/src/gpu-compute/gpu_command_processor.hh b/src/gpu-compute/gpu_command_processor.hh index f6783834eb..85b2a44494 100644 --- a/src/gpu-compute/gpu_command_processor.hh +++ b/src/gpu-compute/gpu_command_processor.hh @@ -99,6 +99,8 @@ class GPUCommandProcessor : public DmaVirtDevice Addr host_pkt_addr); void attachDriver(GPUComputeDriver *driver); + void dispatchKernelObject(AMDKernelCode *akc, void *raw_pkt, + uint32_t queue_id, Addr host_pkt_addr); void dispatchPkt(HSAQueueEntry *task); void signalWakeupEvent(uint32_t event_id); @@ -149,6 +151,9 @@ class GPUCommandProcessor : public DmaVirtDevice HSAPacketProcessor *hsaPP; TranslationGenPtr translate(Addr vaddr, Addr size) override; + // Running counter of dispatched tasks + int dynamic_task_id = 0; + // Keep track of start times for task dispatches. std::unordered_map dispatchStartTime; From e362310f3d72a45dea7fc6855e5cff3b675b47a1 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Fri, 27 Oct 2023 13:20:56 -0500 Subject: [PATCH 523/693] gpu-compute: Update GPR allocation counts GPR allocation is using fields in the AMD kernel code structure which are not backwards compatible and are not populated in more recent compiler versions. Use the granulated fields instead which is enfored to be backwards compatible. Change-Id: I718716226f5dbeb08369d5365d5e85b029027932 --- src/gpu-compute/hsa_queue_entry.hh | 58 ++++++++++++++---------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/src/gpu-compute/hsa_queue_entry.hh b/src/gpu-compute/hsa_queue_entry.hh index 4083c1c85a..84ae139127 100644 --- a/src/gpu-compute/hsa_queue_entry.hh +++ b/src/gpu-compute/hsa_queue_entry.hh @@ -70,8 +70,6 @@ class HSAQueueEntry _gridSize{{(int)((_hsa_dispatch_packet_t*)disp_pkt)->grid_size_x, (int)((_hsa_dispatch_packet_t*)disp_pkt)->grid_size_y, (int)((_hsa_dispatch_packet_t*)disp_pkt)->grid_size_z}}, - numVgprs(akc->workitem_vgpr_count), - numSgprs(akc->wavefront_sgpr_count), _queueId(queue_id), _dispatchId(dispatch_id), dispPkt(disp_pkt), _hostDispPktAddr(host_pkt_addr), _completionSignal(((_hsa_dispatch_packet_t*)disp_pkt) @@ -88,40 +86,36 @@ class HSAQueueEntry _globalWgId(0), dispatchComplete(false) { - // Precompiled BLIT kernels actually violate the spec a bit - // and don't set many of the required akc fields. For these kernels, - // we need to rip register usage from the resource registers. - // - // We can't get an exact number of registers from the resource - // registers because they round, but we can get an upper bound on it. - // We determine the number of registers by solving for "vgprs_used" - // in the LLVM docs: https://www.llvm.org/docs/AMDGPUUsage.html + // Use the resource descriptors to determine number of GPRs. This will + // round up in some cases, however the exact number field in the AMD + // kernel code struct is not backwards compatible and that field is + // not populated in newer compiles. The resource descriptor dword must + // be backwards compatible, so use that always. + // LLVM docs: https://www.llvm.org/docs/AMDGPUUsage.html // #code-object-v3-kernel-descriptor + // // Currently, the only supported gfx version in gem5 that computes - // this differently is gfx90a. - if (!numVgprs) { - if (gfx_version == GfxVersion::gfx90a) { - numVgprs = (akc->granulated_workitem_vgpr_count + 1) * 8; - } else { - numVgprs = (akc->granulated_workitem_vgpr_count + 1) * 4; - } + // VGPR count differently is gfx90a. + if (gfx_version == GfxVersion::gfx90a) { + numVgprs = (akc->granulated_workitem_vgpr_count + 1) * 8; + } else { + numVgprs = (akc->granulated_workitem_vgpr_count + 1) * 4; } - if (!numSgprs || numSgprs == - std::numeric_limitswavefront_sgpr_count)>::max()) { - // Supported major generation numbers: 0 (BLIT kernels), 8, and 9 - uint16_t version = akc->amd_machine_version_major; - assert((version == 0) || (version == 8) || (version == 9)); - // SGPR allocation granularies: - // - GFX8: 8 - // - GFX9: 16 - // Source: https://llvm.org/docs/AMDGPUUsage.html - if ((version == 0) || (version == 8)) { - // We assume that BLIT kernels use the same granularity as GFX8 - numSgprs = (akc->granulated_wavefront_sgpr_count + 1) * 8; - } else if (version == 9) { - numSgprs = ((akc->granulated_wavefront_sgpr_count + 1) * 16)/2; - } + // SGPR allocation granularies: + // - GFX8: 8 + // - GFX9: 16 + // Source: https://llvm.org/docs/.html + if (gfx_version == GfxVersion::gfx801 || + gfx_version == GfxVersion::gfx803) { + numSgprs = (akc->granulated_wavefront_sgpr_count + 1) * 8; + } else if (gfx_version == GfxVersion::gfx900 || + gfx_version == GfxVersion::gfx902 || + gfx_version == GfxVersion::gfx908 || + gfx_version == GfxVersion::gfx90a) { + numSgprs = ((akc->granulated_wavefront_sgpr_count + 1) * 16)/2; + } else { + panic("Saw unknown gfx version setting up GPR counts\n"); } initialVgprState.reset(); From 42fd7ff894f5ed689fbfe44dc7e33bc8900b73ca Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 3 Nov 2023 13:54:30 -0700 Subject: [PATCH 524/693] stdlib, resources: Update JSON data in workload - resources field in workload now supports a dict with resources id and version. - Older workload JSON are still supported but added a deprecation waring Change-Id: I137dbb99799a5294e84ce7d5d914f05e4cfe9e00 --- src/python/gem5/resources/resource.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 96cb5cf19d..ae9ff668ca 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -964,10 +964,22 @@ def obtain_resource( for key in resource_json["resources"].keys(): assert isinstance(key, str) value = resource_json["resources"][key] - assert isinstance(value, str) - params[key] = obtain_resource( - value, - ) + + if isinstance(value, str): + warn( + "Deprecation warning: resources field in workloads has changed" + "from { category: id } to" + "{ category: { id: id, resource_version: resource_version } }" + "Please update your resource.json file to reflect this change." + ) + params[key] = obtain_resource( + value, + ) + elif isinstance(value, dict): + params[key] = obtain_resource( + value["id"], + resource_version=value["resource_version"], + ) if "additional_params" in resource_json: for key in resource_json["additional_params"].keys(): assert isinstance(key, str) From e4cdd73a595b348a869ab5d039ba78667c88d626 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Tue, 7 Nov 2023 02:26:08 +0800 Subject: [PATCH 525/693] arch-riscv: Fix line length of CSRData declaration (#519) The length of CSRData declaration must less than 79 characters Change-Id: I3767b069664690d7b4498a73536880cfa491c6e5 --- src/arch/riscv/regs/misc.hh | 690 ++++++++++++++++++++++++------------ 1 file changed, 461 insertions(+), 229 deletions(-) diff --git a/src/arch/riscv/regs/misc.hh b/src/arch/riscv/regs/misc.hh index 64072c97e2..d36776d7ef 100644 --- a/src/arch/riscv/regs/misc.hh +++ b/src/arch/riscv/regs/misc.hh @@ -508,241 +508,473 @@ constexpr uint64_t rvTypeFlags(T... args) { } const std::unordered_map CSRData = { - {CSR_USTATUS, {"ustatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, - {CSR_UIE, {"uie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, - {CSR_UTVEC, {"utvec", MISCREG_UTVEC, rvTypeFlags(RV64, RV32)}}, - {CSR_USCRATCH, {"uscratch", MISCREG_USCRATCH, rvTypeFlags(RV64, RV32)}}, - {CSR_UEPC, {"uepc", MISCREG_UEPC, rvTypeFlags(RV64, RV32)}}, - {CSR_UCAUSE, {"ucause", MISCREG_UCAUSE, rvTypeFlags(RV64, RV32)}}, - {CSR_UTVAL, {"utval", MISCREG_UTVAL, rvTypeFlags(RV64, RV32)}}, - {CSR_UIP, {"uip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, - {CSR_FFLAGS, {"fflags", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32)}}, - {CSR_FRM, {"frm", MISCREG_FRM, rvTypeFlags(RV64, RV32)}}, - {CSR_FCSR, {"fcsr", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32)}}, // Actually FRM << 5 | FFLAGS - {CSR_CYCLE, {"cycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32)}}, - {CSR_TIME, {"time", MISCREG_TIME, rvTypeFlags(RV64, RV32)}}, - {CSR_INSTRET, {"instret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER03, {"hpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER04, {"hpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER05, {"hpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER06, {"hpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER07, {"hpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER08, {"hpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER09, {"hpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER10, {"hpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER11, {"hpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER12, {"hpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER13, {"hpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER14, {"hpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER15, {"hpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER16, {"hpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER17, {"hpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER18, {"hpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER19, {"hpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER20, {"hpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER21, {"hpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER22, {"hpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER23, {"hpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER24, {"hpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER25, {"hpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER26, {"hpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER27, {"hpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER28, {"hpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER29, {"hpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER30, {"hpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32)}}, - {CSR_HPMCOUNTER31, {"hpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32)}}, - {CSR_CYCLEH, {"cycleh", MISCREG_CYCLEH, rvTypeFlags(RV32)}}, - {CSR_TIMEH, {"timeh", MISCREG_TIMEH, rvTypeFlags(RV32)}}, - {CSR_INSTRETH, {"instreth", MISCREG_INSTRETH, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER03H, {"hpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER04H, {"hpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER05H, {"hpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER06H, {"hpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER07H, {"hpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER08H, {"hpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER09H, {"hpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER10H, {"hpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER11H, {"hpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER12H, {"hpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER13H, {"hpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER14H, {"hpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER15H, {"hpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER16H, {"hpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER17H, {"hpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER18H, {"hpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER19H, {"hpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER20H, {"hpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER21H, {"hpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER22H, {"hpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER23H, {"hpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER24H, {"hpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER25H, {"hpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER26H, {"hpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER27H, {"hpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER28H, {"hpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER29H, {"hpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER30H, {"hpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32)}}, - {CSR_HPMCOUNTER31H, {"hpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32)}}, + {CSR_USTATUS, + {"ustatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, + {CSR_UIE, + {"uie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, + {CSR_UTVEC, + {"utvec", MISCREG_UTVEC, rvTypeFlags(RV64, RV32)}}, + {CSR_USCRATCH, + {"uscratch", MISCREG_USCRATCH, rvTypeFlags(RV64, RV32)}}, + {CSR_UEPC, + {"uepc", MISCREG_UEPC, rvTypeFlags(RV64, RV32)}}, + {CSR_UCAUSE, + {"ucause", MISCREG_UCAUSE, rvTypeFlags(RV64, RV32)}}, + {CSR_UTVAL, + {"utval", MISCREG_UTVAL, rvTypeFlags(RV64, RV32)}}, + {CSR_UIP, + {"uip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, + {CSR_FFLAGS, + {"fflags", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32)}}, + {CSR_FRM, + {"frm", MISCREG_FRM, rvTypeFlags(RV64, RV32)}}, + // Actually FRM << 5 | FFLAGS + {CSR_FCSR, + {"fcsr", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32)}}, + {CSR_CYCLE, + {"cycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32)}}, + {CSR_TIME, + {"time", MISCREG_TIME, rvTypeFlags(RV64, RV32)}}, + {CSR_INSTRET, + {"instret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER03, + {"hpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER04, + {"hpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER05, + {"hpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER06, + {"hpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER07, + {"hpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER08, + {"hpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER09, + {"hpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER10, + {"hpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER11, + {"hpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER12, + {"hpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER13, + {"hpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER14, + {"hpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER15, + {"hpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER16, + {"hpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER17, + {"hpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER18, + {"hpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER19, + {"hpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER20, + {"hpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER21, + {"hpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER22, + {"hpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER23, + {"hpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER24, + {"hpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER25, + {"hpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER26, + {"hpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER27, + {"hpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER28, + {"hpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER29, + {"hpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER30, + {"hpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32)}}, + {CSR_HPMCOUNTER31, + {"hpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32)}}, + {CSR_CYCLEH, + {"cycleh", MISCREG_CYCLEH, rvTypeFlags(RV32)}}, + {CSR_TIMEH, + {"timeh", MISCREG_TIMEH, rvTypeFlags(RV32)}}, + {CSR_INSTRETH, + {"instreth", MISCREG_INSTRETH, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER03H, + {"hpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER04H, + {"hpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER05H, + {"hpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER06H, + {"hpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER07H, + {"hpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER08H, + {"hpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER09H, + {"hpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER10H, + {"hpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER11H, + {"hpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER12H, + {"hpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER13H, + {"hpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER14H, + {"hpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER15H, + {"hpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER16H, + {"hpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER17H, + {"hpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER18H, + {"hpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER19H, + {"hpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER20H, + {"hpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER21H, + {"hpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER22H, + {"hpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER23H, + {"hpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER24H, + {"hpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER25H, + {"hpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER26H, + {"hpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER27H, + {"hpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER28H, + {"hpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER29H, + {"hpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER30H, + {"hpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32)}}, + {CSR_HPMCOUNTER31H, + {"hpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32)}}, - {CSR_SSTATUS, {"sstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, - {CSR_SEDELEG, {"sedeleg", MISCREG_SEDELEG, rvTypeFlags(RV64, RV32)}}, - {CSR_SIDELEG, {"sideleg", MISCREG_SIDELEG, rvTypeFlags(RV64, RV32)}}, - {CSR_SIE, {"sie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, - {CSR_STVEC, {"stvec", MISCREG_STVEC, rvTypeFlags(RV64, RV32)}}, - {CSR_SCOUNTEREN, {"scounteren", MISCREG_SCOUNTEREN, rvTypeFlags(RV64, RV32)}}, - {CSR_SSCRATCH, {"sscratch", MISCREG_SSCRATCH, rvTypeFlags(RV64, RV32)}}, - {CSR_SEPC, {"sepc", MISCREG_SEPC, rvTypeFlags(RV64, RV32)}}, - {CSR_SCAUSE, {"scause", MISCREG_SCAUSE, rvTypeFlags(RV64, RV32)}}, - {CSR_STVAL, {"stval", MISCREG_STVAL, rvTypeFlags(RV64, RV32)}}, - {CSR_SIP, {"sip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, - {CSR_SATP, {"satp", MISCREG_SATP, rvTypeFlags(RV64, RV32)}}, + {CSR_SSTATUS, + {"sstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, + {CSR_SEDELEG, + {"sedeleg", MISCREG_SEDELEG, rvTypeFlags(RV64, RV32)}}, + {CSR_SIDELEG, + {"sideleg", MISCREG_SIDELEG, rvTypeFlags(RV64, RV32)}}, + {CSR_SIE, + {"sie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, + {CSR_STVEC, + {"stvec", MISCREG_STVEC, rvTypeFlags(RV64, RV32)}}, + {CSR_SCOUNTEREN, + {"scounteren", MISCREG_SCOUNTEREN, rvTypeFlags(RV64, RV32)}}, + {CSR_SSCRATCH, + {"sscratch", MISCREG_SSCRATCH, rvTypeFlags(RV64, RV32)}}, + {CSR_SEPC, + {"sepc", MISCREG_SEPC, rvTypeFlags(RV64, RV32)}}, + {CSR_SCAUSE, + {"scause", MISCREG_SCAUSE, rvTypeFlags(RV64, RV32)}}, + {CSR_STVAL, + {"stval", MISCREG_STVAL, rvTypeFlags(RV64, RV32)}}, + {CSR_SIP, + {"sip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, + {CSR_SATP, + {"satp", MISCREG_SATP, rvTypeFlags(RV64, RV32)}}, - {CSR_MVENDORID, {"mvendorid", MISCREG_VENDORID, rvTypeFlags(RV64, RV32)}}, - {CSR_MARCHID, {"marchid", MISCREG_ARCHID, rvTypeFlags(RV64, RV32)}}, - {CSR_MIMPID, {"mimpid", MISCREG_IMPID, rvTypeFlags(RV64, RV32)}}, - {CSR_MHARTID, {"mhartid", MISCREG_HARTID, rvTypeFlags(RV64, RV32)}}, - {CSR_MSTATUS, {"mstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, - {CSR_MISA, {"misa", MISCREG_ISA, rvTypeFlags(RV64, RV32)}}, - {CSR_MEDELEG, {"medeleg", MISCREG_MEDELEG, rvTypeFlags(RV64, RV32)}}, - {CSR_MIDELEG, {"mideleg", MISCREG_MIDELEG, rvTypeFlags(RV64, RV32)}}, - {CSR_MIE, {"mie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, - {CSR_MTVEC, {"mtvec", MISCREG_MTVEC, rvTypeFlags(RV64, RV32)}}, - {CSR_MCOUNTEREN, {"mcounteren", MISCREG_MCOUNTEREN, rvTypeFlags(RV64, RV32)}}, - {CSR_MSTATUSH, {"mstatush", MISCREG_MSTATUSH, rvTypeFlags(RV32)}}, - {CSR_MSCRATCH, {"mscratch", MISCREG_MSCRATCH, rvTypeFlags(RV64, RV32)}}, - {CSR_MEPC, {"mepc", MISCREG_MEPC, rvTypeFlags(RV64, RV32)}}, - {CSR_MCAUSE, {"mcause", MISCREG_MCAUSE, rvTypeFlags(RV64, RV32)}}, - {CSR_MTVAL, {"mtval", MISCREG_MTVAL, rvTypeFlags(RV64, RV32)}}, - {CSR_MIP, {"mip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPCFG0, {"pmpcfg0", MISCREG_PMPCFG0, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPCFG1, {"pmpcfg1", MISCREG_PMPCFG1, rvTypeFlags(RV32)}}, // pmpcfg1 rv32 only - {CSR_PMPCFG2, {"pmpcfg2", MISCREG_PMPCFG2, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPCFG3, {"pmpcfg3", MISCREG_PMPCFG3, rvTypeFlags(RV32)}}, // pmpcfg3 rv32 only - {CSR_PMPADDR00, {"pmpaddr0", MISCREG_PMPADDR00, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR01, {"pmpaddr1", MISCREG_PMPADDR01, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR02, {"pmpaddr2", MISCREG_PMPADDR02, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR03, {"pmpaddr3", MISCREG_PMPADDR03, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR04, {"pmpaddr4", MISCREG_PMPADDR04, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR05, {"pmpaddr5", MISCREG_PMPADDR05, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR06, {"pmpaddr6", MISCREG_PMPADDR06, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR07, {"pmpaddr7", MISCREG_PMPADDR07, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR08, {"pmpaddr8", MISCREG_PMPADDR08, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR09, {"pmpaddr9", MISCREG_PMPADDR09, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR10, {"pmpaddr10", MISCREG_PMPADDR10, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR11, {"pmpaddr11", MISCREG_PMPADDR11, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR12, {"pmpaddr12", MISCREG_PMPADDR12, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR13, {"pmpaddr13", MISCREG_PMPADDR13, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR14, {"pmpaddr14", MISCREG_PMPADDR14, rvTypeFlags(RV64, RV32)}}, - {CSR_PMPADDR15, {"pmpaddr15", MISCREG_PMPADDR15, rvTypeFlags(RV64, RV32)}}, - {CSR_MCYCLE, {"mcycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32)}}, - {CSR_MINSTRET, {"minstret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER03, {"mhpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER04, {"mhpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER05, {"mhpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER06, {"mhpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER07, {"mhpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER08, {"mhpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER09, {"mhpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER10, {"mhpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER11, {"mhpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER12, {"mhpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER13, {"mhpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER14, {"mhpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER15, {"mhpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER16, {"mhpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER17, {"mhpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER18, {"mhpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER19, {"mhpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER20, {"mhpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER21, {"mhpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER22, {"mhpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER23, {"mhpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER24, {"mhpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER25, {"mhpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER26, {"mhpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER27, {"mhpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER28, {"mhpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER29, {"mhpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER30, {"mhpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMCOUNTER31, {"mhpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32)}}, + {CSR_MVENDORID, + {"mvendorid", MISCREG_VENDORID, rvTypeFlags(RV64, RV32)}}, + {CSR_MARCHID, + {"marchid", MISCREG_ARCHID, rvTypeFlags(RV64, RV32)}}, + {CSR_MIMPID, + {"mimpid", MISCREG_IMPID, rvTypeFlags(RV64, RV32)}}, + {CSR_MHARTID, + {"mhartid", MISCREG_HARTID, rvTypeFlags(RV64, RV32)}}, + {CSR_MSTATUS, + {"mstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, + {CSR_MISA, + {"misa", MISCREG_ISA, rvTypeFlags(RV64, RV32)}}, + {CSR_MEDELEG, + {"medeleg", MISCREG_MEDELEG, rvTypeFlags(RV64, RV32)}}, + {CSR_MIDELEG, + {"mideleg", MISCREG_MIDELEG, rvTypeFlags(RV64, RV32)}}, + {CSR_MIE, + {"mie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, + {CSR_MTVEC, + {"mtvec", MISCREG_MTVEC, rvTypeFlags(RV64, RV32)}}, + {CSR_MCOUNTEREN, + {"mcounteren", MISCREG_MCOUNTEREN, rvTypeFlags(RV64, RV32)}}, + {CSR_MSTATUSH, + {"mstatush", MISCREG_MSTATUSH, rvTypeFlags(RV32)}}, + {CSR_MSCRATCH, + {"mscratch", MISCREG_MSCRATCH, rvTypeFlags(RV64, RV32)}}, + {CSR_MEPC, + {"mepc", MISCREG_MEPC, rvTypeFlags(RV64, RV32)}}, + {CSR_MCAUSE, + {"mcause", MISCREG_MCAUSE, rvTypeFlags(RV64, RV32)}}, + {CSR_MTVAL, + {"mtval", MISCREG_MTVAL, rvTypeFlags(RV64, RV32)}}, + {CSR_MIP, + {"mip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPCFG0, + {"pmpcfg0", MISCREG_PMPCFG0, rvTypeFlags(RV64, RV32)}}, + // pmpcfg1 rv32 only + {CSR_PMPCFG1, + {"pmpcfg1", MISCREG_PMPCFG1, rvTypeFlags(RV32)}}, + {CSR_PMPCFG2, + {"pmpcfg2", MISCREG_PMPCFG2, rvTypeFlags(RV64, RV32)}}, + // pmpcfg3 rv32 only + {CSR_PMPCFG3, + {"pmpcfg3", MISCREG_PMPCFG3, rvTypeFlags(RV32)}}, + {CSR_PMPADDR00, + {"pmpaddr0", MISCREG_PMPADDR00, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR01, + {"pmpaddr1", MISCREG_PMPADDR01, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR02, + {"pmpaddr2", MISCREG_PMPADDR02, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR03, + {"pmpaddr3", MISCREG_PMPADDR03, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR04, + {"pmpaddr4", MISCREG_PMPADDR04, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR05, + {"pmpaddr5", MISCREG_PMPADDR05, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR06, + {"pmpaddr6", MISCREG_PMPADDR06, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR07, + {"pmpaddr7", MISCREG_PMPADDR07, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR08, + {"pmpaddr8", MISCREG_PMPADDR08, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR09, + {"pmpaddr9", MISCREG_PMPADDR09, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR10, + {"pmpaddr10", MISCREG_PMPADDR10, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR11, + {"pmpaddr11", MISCREG_PMPADDR11, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR12, + {"pmpaddr12", MISCREG_PMPADDR12, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR13, + {"pmpaddr13", MISCREG_PMPADDR13, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR14, + {"pmpaddr14", MISCREG_PMPADDR14, rvTypeFlags(RV64, RV32)}}, + {CSR_PMPADDR15, + {"pmpaddr15", MISCREG_PMPADDR15, rvTypeFlags(RV64, RV32)}}, + {CSR_MCYCLE, + {"mcycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32)}}, + {CSR_MINSTRET, + {"minstret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER03, + {"mhpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER04, + {"mhpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER05, + {"mhpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER06, + {"mhpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER07, + {"mhpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER08, + {"mhpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER09, + {"mhpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER10, + {"mhpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER11, + {"mhpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER12, + {"mhpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER13, + {"mhpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER14, + {"mhpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER15, + {"mhpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER16, + {"mhpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER17, + {"mhpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER18, + {"mhpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER19, + {"mhpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER20, + {"mhpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER21, + {"mhpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER22, + {"mhpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER23, + {"mhpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER24, + {"mhpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER25, + {"mhpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER26, + {"mhpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER27, + {"mhpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER28, + {"mhpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER29, + {"mhpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER30, + {"mhpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMCOUNTER31, + {"mhpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32)}}, - {CSR_MCYCLEH, {"mcycleh", MISCREG_CYCLEH, rvTypeFlags(RV32)}}, - {CSR_MINSTRETH, {"minstreth", MISCREG_INSTRETH, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER03H, {"mhpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER04H, {"mhpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER05H, {"mhpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER06H, {"mhpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER07H, {"mhpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER08H, {"mhpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER09H, {"mhpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER10H, {"mhpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER11H, {"mhpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER12H, {"mhpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER13H, {"mhpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER14H, {"mhpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER15H, {"mhpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER16H, {"mhpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER17H, {"mhpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER18H, {"mhpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER19H, {"mhpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER20H, {"mhpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER21H, {"mhpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER22H, {"mhpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER23H, {"mhpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER24H, {"mhpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER25H, {"mhpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER26H, {"mhpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER27H, {"mhpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER28H, {"mhpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER29H, {"mhpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER30H, {"mhpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32)}}, - {CSR_MHPMCOUNTER31H, {"mhpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32)}}, + {CSR_MCYCLEH, + {"mcycleh", MISCREG_CYCLEH, rvTypeFlags(RV32)}}, + {CSR_MINSTRETH, + {"minstreth", MISCREG_INSTRETH, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER03H, + {"mhpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER04H, + {"mhpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER05H, + {"mhpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER06H, + {"mhpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER07H, + {"mhpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER08H, + {"mhpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER09H, + {"mhpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER10H, + {"mhpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER11H, + {"mhpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER12H, + {"mhpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER13H, + {"mhpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER14H, + {"mhpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER15H, + {"mhpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER16H, + {"mhpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER17H, + {"mhpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER18H, + {"mhpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER19H, + {"mhpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER20H, + {"mhpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER21H, + {"mhpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER22H, + {"mhpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER23H, + {"mhpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER24H, + {"mhpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER25H, + {"mhpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER26H, + {"mhpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER27H, + {"mhpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER28H, + {"mhpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER29H, + {"mhpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER30H, + {"mhpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32)}}, + {CSR_MHPMCOUNTER31H, + {"mhpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32)}}, - {CSR_MHPMEVENT03, {"mhpmevent03", MISCREG_HPMEVENT03, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT04, {"mhpmevent04", MISCREG_HPMEVENT04, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT05, {"mhpmevent05", MISCREG_HPMEVENT05, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT06, {"mhpmevent06", MISCREG_HPMEVENT06, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT07, {"mhpmevent07", MISCREG_HPMEVENT07, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT08, {"mhpmevent08", MISCREG_HPMEVENT08, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT09, {"mhpmevent09", MISCREG_HPMEVENT09, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT10, {"mhpmevent10", MISCREG_HPMEVENT10, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT11, {"mhpmevent11", MISCREG_HPMEVENT11, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT12, {"mhpmevent12", MISCREG_HPMEVENT12, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT13, {"mhpmevent13", MISCREG_HPMEVENT13, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT14, {"mhpmevent14", MISCREG_HPMEVENT14, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT15, {"mhpmevent15", MISCREG_HPMEVENT15, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT16, {"mhpmevent16", MISCREG_HPMEVENT16, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT17, {"mhpmevent17", MISCREG_HPMEVENT17, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT18, {"mhpmevent18", MISCREG_HPMEVENT18, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT19, {"mhpmevent19", MISCREG_HPMEVENT19, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT20, {"mhpmevent20", MISCREG_HPMEVENT20, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT21, {"mhpmevent21", MISCREG_HPMEVENT21, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT22, {"mhpmevent22", MISCREG_HPMEVENT22, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT23, {"mhpmevent23", MISCREG_HPMEVENT23, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT24, {"mhpmevent24", MISCREG_HPMEVENT24, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT25, {"mhpmevent25", MISCREG_HPMEVENT25, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT26, {"mhpmevent26", MISCREG_HPMEVENT26, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT27, {"mhpmevent27", MISCREG_HPMEVENT27, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT28, {"mhpmevent28", MISCREG_HPMEVENT28, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT29, {"mhpmevent29", MISCREG_HPMEVENT29, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT30, {"mhpmevent30", MISCREG_HPMEVENT30, rvTypeFlags(RV64, RV32)}}, - {CSR_MHPMEVENT31, {"mhpmevent31", MISCREG_HPMEVENT31, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT03, + {"mhpmevent03", MISCREG_HPMEVENT03, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT04, + {"mhpmevent04", MISCREG_HPMEVENT04, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT05, + {"mhpmevent05", MISCREG_HPMEVENT05, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT06, + {"mhpmevent06", MISCREG_HPMEVENT06, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT07, + {"mhpmevent07", MISCREG_HPMEVENT07, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT08, + {"mhpmevent08", MISCREG_HPMEVENT08, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT09, + {"mhpmevent09", MISCREG_HPMEVENT09, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT10, + {"mhpmevent10", MISCREG_HPMEVENT10, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT11, + {"mhpmevent11", MISCREG_HPMEVENT11, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT12, + {"mhpmevent12", MISCREG_HPMEVENT12, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT13, + {"mhpmevent13", MISCREG_HPMEVENT13, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT14, + {"mhpmevent14", MISCREG_HPMEVENT14, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT15, + {"mhpmevent15", MISCREG_HPMEVENT15, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT16, + {"mhpmevent16", MISCREG_HPMEVENT16, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT17, + {"mhpmevent17", MISCREG_HPMEVENT17, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT18, + {"mhpmevent18", MISCREG_HPMEVENT18, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT19, + {"mhpmevent19", MISCREG_HPMEVENT19, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT20, + {"mhpmevent20", MISCREG_HPMEVENT20, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT21, + {"mhpmevent21", MISCREG_HPMEVENT21, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT22, + {"mhpmevent22", MISCREG_HPMEVENT22, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT23, + {"mhpmevent23", MISCREG_HPMEVENT23, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT24, + {"mhpmevent24", MISCREG_HPMEVENT24, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT25, + {"mhpmevent25", MISCREG_HPMEVENT25, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT26, + {"mhpmevent26", MISCREG_HPMEVENT26, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT27, + {"mhpmevent27", MISCREG_HPMEVENT27, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT28, + {"mhpmevent28", MISCREG_HPMEVENT28, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT29, + {"mhpmevent29", MISCREG_HPMEVENT29, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT30, + {"mhpmevent30", MISCREG_HPMEVENT30, rvTypeFlags(RV64, RV32)}}, + {CSR_MHPMEVENT31, + {"mhpmevent31", MISCREG_HPMEVENT31, rvTypeFlags(RV64, RV32)}}, - {CSR_TSELECT, {"tselect", MISCREG_TSELECT, rvTypeFlags(RV64, RV32)}}, - {CSR_TDATA1, {"tdata1", MISCREG_TDATA1, rvTypeFlags(RV64, RV32)}}, - {CSR_TDATA2, {"tdata2", MISCREG_TDATA2, rvTypeFlags(RV64, RV32)}}, - {CSR_TDATA3, {"tdata3", MISCREG_TDATA3, rvTypeFlags(RV64, RV32)}}, - {CSR_DCSR, {"dcsr", MISCREG_DCSR, rvTypeFlags(RV64, RV32)}}, - {CSR_DPC, {"dpc", MISCREG_DPC, rvTypeFlags(RV64, RV32)}}, - {CSR_DSCRATCH, {"dscratch", MISCREG_DSCRATCH, rvTypeFlags(RV64, RV32)}}, + {CSR_TSELECT, + {"tselect", MISCREG_TSELECT, rvTypeFlags(RV64, RV32)}}, + {CSR_TDATA1, + {"tdata1", MISCREG_TDATA1, rvTypeFlags(RV64, RV32)}}, + {CSR_TDATA2, + {"tdata2", MISCREG_TDATA2, rvTypeFlags(RV64, RV32)}}, + {CSR_TDATA3, + {"tdata3", MISCREG_TDATA3, rvTypeFlags(RV64, RV32)}}, + {CSR_DCSR, + {"dcsr", MISCREG_DCSR, rvTypeFlags(RV64, RV32)}}, + {CSR_DPC, + {"dpc", MISCREG_DPC, rvTypeFlags(RV64, RV32)}}, + {CSR_DSCRATCH, + {"dscratch", MISCREG_DSCRATCH, rvTypeFlags(RV64, RV32)}}, - {CSR_VSTART, {"vstart", MISCREG_VSTART, rvTypeFlags(RV64, RV32)}}, - {CSR_VXSAT, {"vxsat" , MISCREG_VXSAT, rvTypeFlags(RV64, RV32)}}, - {CSR_VXRM, {"vxrm" , MISCREG_VXRM, rvTypeFlags(RV64, RV32)}}, - {CSR_VCSR, {"vcsr" , MISCREG_VCSR, rvTypeFlags(RV64, RV32)}}, - {CSR_VL, {"vl" , MISCREG_VL, rvTypeFlags(RV64, RV32)}}, - {CSR_VTYPE, {"vtype" , MISCREG_VTYPE, rvTypeFlags(RV64, RV32)}}, - {CSR_VLENB, {"VLENB" , MISCREG_VLENB, rvTypeFlags(RV64, RV32)}} + {CSR_VSTART, + {"vstart", MISCREG_VSTART, rvTypeFlags(RV64, RV32)}}, + {CSR_VXSAT, + {"vxsat", MISCREG_VXSAT, rvTypeFlags(RV64, RV32)}}, + {CSR_VXRM, + {"vxrm", MISCREG_VXRM, rvTypeFlags(RV64, RV32)}}, + {CSR_VCSR, + {"vcsr", MISCREG_VCSR, rvTypeFlags(RV64, RV32)}}, + {CSR_VL, + {"vl", MISCREG_VL, rvTypeFlags(RV64, RV32)}}, + {CSR_VTYPE, + {"vtype", MISCREG_VTYPE, rvTypeFlags(RV64, RV32)}}, + {CSR_VLENB, + {"VLENB", MISCREG_VLENB, rvTypeFlags(RV64, RV32)}} }; /** From 2c229aa2ff0a24db4b6b9581dc64ed070e8aff1f Mon Sep 17 00:00:00 2001 From: Kaustav Goswami Date: Wed, 25 Oct 2023 13:59:51 -0700 Subject: [PATCH 526/693] configs,ext: gem5 SST bridge calls m5.instantiate() in gem5 This change updates the gem5 SST bridge to call m5.instantiate() in the gem5 config script instead of in the SST component. This allows more flexibility for the gem5-SST setup, as we can now write traffic generators using the bridge. Change-Id: I510a8c15f8fb00bdbdd60dafa2d9f5ad011e48f2 Signed-off-by: Kaustav Goswami --- configs/example/sst/arm_fs.py | 1 + configs/example/sst/riscv_fs.py | 1 + ext/sst/gem5.cc | 8 +------- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/configs/example/sst/arm_fs.py b/configs/example/sst/arm_fs.py index 14dd7c4743..b8fcb68e37 100644 --- a/configs/example/sst/arm_fs.py +++ b/configs/example/sst/arm_fs.py @@ -185,3 +185,4 @@ for cpu in system.cpu: cpu.createInterruptController() root = Root(full_system=True, system=system) +m5.instantiate() diff --git a/configs/example/sst/riscv_fs.py b/configs/example/sst/riscv_fs.py index 46754debf5..c82ad9a6b9 100644 --- a/configs/example/sst/riscv_fs.py +++ b/configs/example/sst/riscv_fs.py @@ -175,3 +175,4 @@ for cpu in system.cpu: cpu.createInterruptController() root = Root(full_system=True, system=system) +m5.instantiate() diff --git a/ext/sst/gem5.cc b/ext/sst/gem5.cc index 8c845f329e..3ea6127ecd 100644 --- a/ext/sst/gem5.cc +++ b/ext/sst/gem5.cc @@ -204,13 +204,7 @@ gem5Component::init(unsigned phase) if (phase == 0) { initPython(args.size(), &args[0]); - - const std::vector m5_instantiate_commands = { - "import m5", - "m5.instantiate()" - }; - execPythonCommands(m5_instantiate_commands); - + // m5.instantiate() was moved to the gem5 script. // calling SimObject.startup() const std::vector simobject_setup_commands = { "import atexit", From e109076357b71e105f8e8739d195a1932bdd4847 Mon Sep 17 00:00:00 2001 From: Kaustav Goswami Date: Thu, 26 Oct 2023 18:46:01 -0700 Subject: [PATCH 527/693] ext: removed SST deprecation notice from SimpleMem SST SimpleMem will be deprecated in SST 14. PR 396 updated the bridge to use StandardMem, which is the new memory interface in SST. This change removes all references to SimpleMem. Change-Id: I6e4d645317d95ebb610e3dfc93a30d53b91b6b5d Signed-off-by: Kaustav Goswami --- ext/sst/gem5.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/sst/gem5.hh b/ext/sst/gem5.hh index fd00b1504e..f9f00beabd 100644 --- a/ext/sst/gem5.hh +++ b/ext/sst/gem5.hh @@ -80,7 +80,6 @@ #include #include -#include #include From 76279fef59117abe566772cb2ddb124fb52940ec Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Sun, 5 Nov 2023 02:21:47 -0600 Subject: [PATCH 528/693] mem-ruby: update RubyRequest print to include GPU fields The print function used for RubyRequests did not include the GPU specific fields (for the GLC and SLC bits, which are cache modifiers that specify what level of the memory hierarchy a request should be performed at). This causes confusion when the GPU Ruby SLICC code prints out RubyRequest messages, since important fields are missing. Thus this commit adds that support. Since these fields are already part of the RubyRequest class, and are always 0 for non-GPU requests, it should not affect other components beyond slightly longer prints. Change-Id: I31c9122b82dfa2c6415ce25d225ea82cb35c7333 --- src/mem/ruby/slicc_interface/RubyRequest.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mem/ruby/slicc_interface/RubyRequest.cc b/src/mem/ruby/slicc_interface/RubyRequest.cc index c6faf2d76f..fbd211d2a8 100644 --- a/src/mem/ruby/slicc_interface/RubyRequest.cc +++ b/src/mem/ruby/slicc_interface/RubyRequest.cc @@ -61,7 +61,9 @@ RubyRequest::print(std::ostream& out) const out << " " << "AccessMode = " << m_AccessMode << " "; out << "Size = " << m_Size << " "; out << "Prefetch = " << m_Prefetch << " "; -// out << "Time = " << getTime() << " "; + out << "isGLCSet = " << m_isGLCSet << ""; + out << "isSLCSet = " << m_isSLCSet << ""; + // out << "Time = " << getTime() << " "; out << "]"; } From 10374f2f052c23e01480d9d686edf4a6e846dd67 Mon Sep 17 00:00:00 2001 From: Daniel Carvalho Date: Tue, 7 Nov 2023 13:58:32 -0300 Subject: [PATCH 529/693] Fix calculation of compressed size in bytes (#534) An integer division in the compression:Base:getSize() was being done, which led to rounding down instead of up. Signed-off-by: Daniel R. Carvalho --- src/mem/cache/compressors/base.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/cache/compressors/base.cc b/src/mem/cache/compressors/base.cc index df3020dbf8..6ab2831fc9 100644 --- a/src/mem/cache/compressors/base.cc +++ b/src/mem/cache/compressors/base.cc @@ -78,7 +78,7 @@ Base::CompressionData::getSizeBits() const std::size_t Base::CompressionData::getSize() const { - return std::ceil(_size/8); + return std::ceil(_size/(float)CHAR_BIT); } Base::Base(const Params &p) From f97adbaac7e0372083dc1037bff588b566d4771c Mon Sep 17 00:00:00 2001 From: Zixian Cai <2891235+caizixian@users.noreply.github.com> Date: Wed, 8 Nov 2023 03:59:42 +1100 Subject: [PATCH 530/693] python: Handle unicode characters in config files (#521) Previously, opening a config file (such as `configs/example/hmc_hello.py`) containing non-ASCII characters causes UnicodeDecodeError. Also switch to use more an more idiomatic context manager for handling files. Change-Id: Ia39cbe2c420e9c94f3a84af459b7e5f4d9718d14 --- src/python/m5/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/python/m5/main.py b/src/python/m5/main.py index fa73fc3e33..31eaf83690 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -632,7 +632,9 @@ def main(): if not options.P: sys.path = [os.path.dirname(sys.argv[0])] + sys.path filename = sys.argv[0] - filedata = open(filename).read() + with open(filename, "rb") as fd: + # Handle config files with unicode characters + filedata = fd.read().decode("utf-8") filecode = compile(filedata, filename, "exec") scope = {"__file__": filename, "__name__": "__m5_main__"} From 1f1e15e48f8b5178a1aac0122627a241f779f875 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 8 Nov 2023 08:35:02 +0000 Subject: [PATCH 531/693] arch-arm,kvm: Fix copy-paste error (#541) This was probably a copy paste error introduced by [1]. Luckily armv7 KVM mode has been superseeded by the armv8 one. [1]: https://gem5-review.googlesource.com/c/public/gem5/+/52059 Change-Id: I260229c94077d856510976bda58383f0564fc15b Signed-off-by: Giacomo Travaglini --- src/arch/arm/kvm/arm_cpu.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/arm/kvm/arm_cpu.hh b/src/arch/arm/kvm/arm_cpu.hh index 849aa769a5..302d40e17a 100644 --- a/src/arch/arm/kvm/arm_cpu.hh +++ b/src/arch/arm/kvm/arm_cpu.hh @@ -100,7 +100,7 @@ class ArmKvmCPU : public BaseKvmCPU void stutterPC(PCStateBase &pc) const { - pc.as().setNPC(pc->instAddr()); + pc.as().setNPC(pc->instAddr()); } /** From 86131d4323f4ec70e4f60074d4e6b13c6d1f3bf1 Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Wed, 8 Nov 2023 12:13:15 -0600 Subject: [PATCH 532/693] mem-ruby, gpu-compute: update GPU L1I$ MRU info (#530) Previously the GPU L1 I$ (SQC) was not updating the MRU information on hits in the SQC. This commit resolves that by adding support to the appropriate Ruby transition. --- src/mem/ruby/protocol/GPU_VIPER-SQC.sm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mem/ruby/protocol/GPU_VIPER-SQC.sm b/src/mem/ruby/protocol/GPU_VIPER-SQC.sm index 28bddf5ba4..6290908e1b 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-SQC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-SQC.sm @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. + * Copyright (c) 2023 Matthew D. Sinclair * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -297,6 +298,10 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") } } + action(mru_updateMRU, "mru", desc="Touch block for replacement policy") { + L1cache.setMRU(address); + } + // added for profiling action(uu_profileDataMiss, "\udm", desc="Profile SQC demand miss"){ L1cache.profileDemandMiss(); @@ -332,6 +337,7 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") // simple hit transitions transition(V, Fetch) {TagArrayRead, DataArrayRead} { l_loadDoneHit; + mru_updateMRU; uu_profileDataHit; // line was in SQC, so we hit p_popMandatoryQueue; } From 1204267fd8dc2076b4f3b6288a0040116017193d Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Thu, 9 Nov 2023 15:15:10 -0600 Subject: [PATCH 533/693] mem-ruby: SLICC Fixes to GLC Atomics in WB L2 (#397) Made the following changes to fix the behavior of GLC atomics in a WB L2: - Stored atomic write mask in TBE For GLC atomics on an invalid line that bypass to the directory, but have their atomics performed on the return path. - Replaced !presentOrAvail() check for bypassing atomics to directory (which will then be performed on return path), with check for invalid line state. - Replaced wdb_writeDirtyBytes action used when performing atomics with owm_orWriteMask action that doesn't write from invalid atomic request data block - Fixed atomic return path actions Change-Id: I6a406c313d2f9c88cd75bfe39187ef94ce84098f --- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 120 +++++++++++++++++-------- 1 file changed, 82 insertions(+), 38 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index d1905c3b96..ed7931d316 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -106,16 +106,17 @@ machine(MachineType:TCC, "TCC Cache") } structure(TBE, desc="...") { - State TBEState, desc="Transient state"; - DataBlock DataBlk, desc="data for the block"; - bool Dirty, desc="Is the data dirty?"; - bool Shared, desc="Victim hit by shared probe"; - MachineID From, desc="Waiting for writeback from..."; - NetDest Destination, desc="Data destination"; - int numAtomics, desc="number remaining atomics"; - int atomicDoneCnt, desc="number AtomicDones triggered"; - bool isGLCSet, desc="Bypass L1 Cache"; - bool isSLCSet, desc="Bypass L1 and L2 Cache"; + State TBEState, desc="Transient state"; + DataBlock DataBlk, desc="data for the block"; + bool Dirty, desc="Is the data dirty?"; + bool Shared, desc="Victim hit by shared probe"; + MachineID From, desc="Waiting for writeback from..."; + NetDest Destination, desc="Data destination"; + int numPendingDirectoryAtomics, desc="number of pending atomics to be performed in directory"; + int atomicDoneCnt, desc="number AtomicDones triggered"; + bool isGLCSet, desc="Bypass L1 Cache"; + bool isSLCSet, desc="Bypass L1 and L2 Cache"; + WriteMask atomicWriteMask, desc="Atomic write mask"; } structure(TBETable, external="yes") { @@ -265,13 +266,15 @@ machine(MachineType:TCC, "TCC Cache") TBE tbe := TBEs.lookup(in_msg.addr); Entry cache_entry := getCacheEntry(in_msg.addr); + // The trigger queue applies only to atomics performed in the directory. + // There is a possible race where multiple AtomicDone triggers can be // sent if another Atomic to the same address is issued after the // AtomicDone is triggered but before the message arrives here. For // that case we count the number of AtomicDones in flight for this // address and only call AtomicDone to deallocate the TBE when it is // the last in flight message. - if (tbe.numAtomics == 0 && tbe.atomicDoneCnt == 1) { + if (tbe.numPendingDirectoryAtomics == 0 && tbe.atomicDoneCnt == 1) { trigger(Event:AtomicDone, in_msg.addr, cache_entry, tbe); } else { trigger(Event:AtomicNotDone, in_msg.addr, cache_entry, tbe); @@ -370,7 +373,7 @@ machine(MachineType:TCC, "TCC Cache") // TCC will perform the atomic on the return path on Event:Data. // The action will invalidate the cache line if SLC is set and the address is // in the cache. - if(in_msg.isSLCSet || !WB || !presentOrAvail(in_msg.addr)) { + if(in_msg.isSLCSet || !WB) { trigger(Event:AtomicPassOn, in_msg.addr, cache_entry, tbe); } else { trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); @@ -549,7 +552,23 @@ machine(MachineType:TCC, "TCC Cache") cache_entry.DataBlk.clearAtomicLogEntries(); } - action(bar_sendBypassedAtomicResponse, "bar", desc="send bypassed Atomic Ack") { + action(baplr_sendBypassedAtomicPerformedLocallyResponse, "barplr", desc="send locally-performed bypassed Atomic Ack") { + peek(responseFromNB_in, ResponseMsg) { + enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { + out_msg.addr := address; + out_msg.Type := CoherenceResponseType:TDSysResp; + out_msg.Destination.add(in_msg.WTRequestor); + out_msg.Sender := machineID; + out_msg.MessageSize := in_msg.MessageSize; + out_msg.DataBlk := cache_entry.DataBlk; + out_msg.isGLCSet := tbe.isGLCSet; + out_msg.isSLCSet := tbe.isSLCSet; + } + } + cache_entry.DataBlk.clearAtomicLogEntries(); + } + + action(bapdr_sendBypassedAtomicPerformedInDirectoryResponse, "bapdr", desc="send bypassed Atomic Ack") { peek(responseFromNB_in, ResponseMsg) { enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { out_msg.addr := address; @@ -585,7 +604,7 @@ machine(MachineType:TCC, "TCC Cache") TBEs.allocate(address); set_tbe(TBEs.lookup(address)); tbe.Destination.clear(); - tbe.numAtomics := 0; + tbe.numPendingDirectoryAtomics := 0; tbe.atomicDoneCnt := 0; } if (coreRequestNetwork_in.isReady(clockEdge())) { @@ -595,6 +614,10 @@ machine(MachineType:TCC, "TCC Cache") } tbe.isGLCSet := in_msg.isGLCSet; tbe.isSLCSet := in_msg.isSLCSet; + if(in_msg.Type == CoherenceRequestType:Atomic){ + tbe.atomicWriteMask.clear(); + tbe.atomicWriteMask.orMask(in_msg.writeMask); + } } } } @@ -620,6 +643,20 @@ machine(MachineType:TCC, "TCC Cache") } } + action(wardb_writeAtomicResponseDirtyBytes, "wardb", desc="write data to TCC") { + peek(responseFromNB_in, ResponseMsg) { + cache_entry.DataBlk := in_msg.DataBlk; + cache_entry.writeMask.orMask(tbe.atomicWriteMask); + DPRINTF(RubySlicc, "Writing to TCC: %s\n", in_msg); + } + } + + action(owm_orWriteMask, "owm", desc="or TCCs write mask") { + peek(coreRequestNetwork_in, CPURequestMsg) { + cache_entry.writeMask.orMask(in_msg.writeMask); + } + } + action(wt_writeThrough, "wt", desc="write back data") { peek(coreRequestNetwork_in, CPURequestMsg) { enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { @@ -726,14 +763,20 @@ machine(MachineType:TCC, "TCC Cache") } - action(ina_incrementNumAtomics, "ina", desc="inc num atomics") { - tbe.numAtomics := tbe.numAtomics + 1; + action(inpa_incrementNumPendingDirectoryAtomics, "inpa", desc="inc num atomics") { + // Only increment number of atomics if they will actually be performed in directory + // That is, if the SLC bit is set or if the cache is write through + peek(coreRequestNetwork_in, CPURequestMsg) { + if (in_msg.isSLCSet || !WB) { + tbe.numPendingDirectoryAtomics := tbe.numPendingDirectoryAtomics + 1; + } + } } - action(dna_decrementNumAtomics, "dna", desc="inc num atomics") { - tbe.numAtomics := tbe.numAtomics - 1; - if (tbe.numAtomics==0) { + action(dnpa_decrementNumPendingDirectoryAtomics, "dnpa", desc="dec num atomics") { + tbe.numPendingDirectoryAtomics := tbe.numPendingDirectoryAtomics - 1; + if (tbe.numPendingDirectoryAtomics==0) { enqueue(triggerQueue_out, TriggerMsg, 1) { tbe.atomicDoneCnt := tbe.atomicDoneCnt + 1; out_msg.addr := address; @@ -876,17 +919,8 @@ machine(MachineType:TCC, "TCC Cache") transition(V, Atomic, M) {TagArrayRead, DataArrayWrite} { p_profileHit; - wdb_writeDirtyBytes; - pa_performAtomic; - ar_sendAtomicResponse; - p_popRequestQueue; - } - - transition(I, Atomic, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} { - p_profileMiss; - a_allocateBlock; ut_updateTag; - wdb_writeDirtyBytes; + owm_orWriteMask; pa_performAtomic; ar_sendAtomicResponse; p_popRequestQueue; @@ -900,9 +934,19 @@ machine(MachineType:TCC, "TCC Cache") st_stallAndWaitRequest; } - transition({M, W}, Atomic) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + transition(W, Atomic, WI) { + t_allocateTBE; + wb_writeBack; + // need to try this request again after writing back the current entry -- to + // do so, put it with other stalled requests in a buffer to reduce resource + // contention since they won't try again every cycle and will instead only + // try again once woken up + st_stallAndWaitRequest; + } + + transition(M, Atomic) {TagArrayRead, TagArrayWrite, DataArrayWrite} { p_profileHit; - wdb_writeDirtyBytes; + owm_orWriteMask; pa_performAtomic; ar_sendAtomicResponse; p_popRequestQueue; @@ -917,16 +961,16 @@ machine(MachineType:TCC, "TCC Cache") i_invL2; t_allocateTBE; at_atomicThrough; - ina_incrementNumAtomics; + inpa_incrementNumPendingDirectoryAtomics; p_popRequestQueue; } - transition(I, AtomicPassOn, A) {TagArrayRead} { + transition(I, {Atomic, AtomicPassOn}, A) {TagArrayRead} { p_profileMiss; i_invL2; t_allocateTBE; at_atomicThrough; - ina_incrementNumAtomics; + inpa_incrementNumPendingDirectoryAtomics; p_popRequestQueue; } @@ -1058,8 +1102,8 @@ machine(MachineType:TCC, "TCC Cache") } transition(A, Bypass) {TagArrayRead, TagArrayWrite, DataArrayWrite} { - bar_sendBypassedAtomicResponse; - dna_decrementNumAtomics; + bapdr_sendBypassedAtomicPerformedInDirectoryResponse; + dnpa_decrementNumPendingDirectoryAtomics; pr_popResponseQueue; } @@ -1081,9 +1125,9 @@ machine(MachineType:TCC, "TCC Cache") transition(A, Data, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} { a_allocateBlock; + wardb_writeAtomicResponseDirtyBytes; pa_performAtomic; - bar_sendBypassedAtomicResponse; - dna_decrementNumAtomics; + baplr_sendBypassedAtomicPerformedLocallyResponse; pr_popResponseQueue; } From eaec1a7146b8a630ef9ac84ea70392c033f92ff9 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 13 Nov 2023 01:03:43 -0800 Subject: [PATCH 534/693] tests: Remove GCC-9 compiler test When compiling GCC-9 gem5 the gem5 object files are near double the size than when compiling with other GCC versions. This increase in size means we need >16GB of memory available when linking. As we do not want to mandate >16GB systems for building gem5, we are going to drop GCC-9. The exact cause of this bug unknown. Change-Id: I43744d421b88b79ccb21a76badd6b525e894e973 --- .github/workflows/compiler-tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compiler-tests.yaml b/.github/workflows/compiler-tests.yaml index ac092cd3d3..4656563357 100644 --- a/.github/workflows/compiler-tests.yaml +++ b/.github/workflows/compiler-tests.yaml @@ -16,8 +16,8 @@ jobs: strategy: fail-fast: false matrix: - image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-9, gcc-version-8, clang-version-16, clang-version-15, clang-version-14, - clang-version-13, clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, + image: [gcc-version-12, gcc-version-11, gcc-version-10, gcc-version-8, clang-version-16, clang-version-15, clang-version-14, clang-version-13, + clang-version-12, clang-version-11, clang-version-10, clang-version-9, clang-version-8, clang-version-7, ubuntu-20.04_all-dependencies, ubuntu-22.04_all-dependencies, ubuntu-22.04_min-dependencies] opts: [.opt, .fast] runs-on: [self-hosted, linux, x64] From c40c4450f5674dc3e225e9a721430520b19b92e2 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 13 Nov 2023 01:29:56 -0800 Subject: [PATCH 535/693] util-docker: Remove GCC Version 9 from Dockerfiles As we are no longer testing for GCC Version 9, we no longer need to compile these Docker images. Change-Id: Ia8fc712043ce211ff46da47fdce691a67ecdbb54 --- util/dockerfiles/docker-compose.yaml | 7 ------- util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/util/dockerfiles/docker-compose.yaml b/util/dockerfiles/docker-compose.yaml index 005e415484..5c63e101ba 100644 --- a/util/dockerfiles/docker-compose.yaml +++ b/util/dockerfiles/docker-compose.yaml @@ -44,13 +44,6 @@ services: args: - version=8 image: gcr.io/gem5-test/gcc-version-8:latest - gcc-9: - build: - context: ubuntu-20.04_gcc-version - dockerfile: Dockerfile - args: - - version=9 - image: gcr.io/gem5-test/gcc-version-9:latest gcc-10: build: context: ubuntu-20.04_gcc-version diff --git a/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile b/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile index f79bcef2d9..7841635aef 100644 --- a/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_gcc-version/Dockerfile @@ -28,7 +28,7 @@ FROM --platform=${BUILDPLATFORM} ubuntu:20.04 # Valid version values: # 7 # 8 -# 9 +# 9 # Not supported. See: https://github.com/gem5/gem5/issues/555. # 10 ARG version From cb62b089891151e74a9cdbc792e212d54dad1742 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 13 Nov 2023 01:36:52 -0800 Subject: [PATCH 536/693] util-docker: Update Ubuntu 20.04 to use GCC-10 GCC-9 is no longer supported. Change-Id: I09bf8f744546908b1c06615b458b31b9b814b61a --- .../ubuntu-20.04_all-dependencies/Dockerfile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile index 449f8b1b06..8f092adc7a 100644 --- a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile @@ -32,6 +32,15 @@ RUN apt -y update && apt -y upgrade && \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev python-is-python3 doxygen libboost-all-dev \ libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config pip \ - python3-venv black + python3-venv black gcc-10 g++-10 RUN pip install mypy pre-commit + +RUN update-alternatives --install \ + /usr/bin/g++ g++ /usr/bin/g++-10 100 +RUN update-alternatives --install \ + /usr/bin/gcc gcc /usr/bin/gcc-10 100 +RUN update-alternatives --install \ + /usr/bin/c++ c++ /usr/bin/g++-10 100 +RUN update-alternatives --install \ + /usr/bin/cc cc /usr/bin/gcc-10 100 From 50c9cbf61327f0943810053d671ab1b99c6018d4 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Mon, 13 Nov 2023 14:09:13 -0800 Subject: [PATCH 537/693] stdlib, resources: Fixed deprecation warning Change-Id: I61865d9a2c08e344824a735ee5e85fb54cd489da --- src/python/gem5/resources/resource.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index ae9ff668ca..98c58cf832 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -970,7 +970,8 @@ def obtain_resource( "Deprecation warning: resources field in workloads has changed" "from { category: id } to" "{ category: { id: id, resource_version: resource_version } }" - "Please update your resource.json file to reflect this change." + "The current develop branch of gem5 supports both formats" + "but this will be removed in the 23.1 release." ) params[key] = obtain_resource( value, From 3642bc48929597ea0b4fd02f654b91ff2538d99e Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Mon, 13 Nov 2023 16:20:54 -0600 Subject: [PATCH 538/693] mem-ruby, gpu-compute: fix GPU SQC/TCP Ruby formatting (#538) mem-ruby, gpu-compute: fix GPU SQC/TCP Ruby formatting Fix several not properly indented prints and extraneous extra lines in the SLICC code for the GPU SQC (L1I$) and TCP (L1D$). --- src/mem/ruby/protocol/GPU_VIPER-SQC.sm | 2 +- src/mem/ruby/protocol/GPU_VIPER-TCP.sm | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-SQC.sm b/src/mem/ruby/protocol/GPU_VIPER-SQC.sm index 6290908e1b..000cf5b1e6 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-SQC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-SQC.sm @@ -75,7 +75,7 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") } structure(TBE, desc="...") { - State TBEState, desc="Transient state"; + State TBEState, desc="Transient state"; DataBlock DataBlk, desc="data for the block, required for concurrent writebacks"; bool Dirty, desc="Is the data dirty (different than memory)?"; int NumPendingMsgs, desc="Number of acks/data messages that this processor is waiting for"; diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm index 8244879c55..5530e6dcb3 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm @@ -52,30 +52,30 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") { state_declaration(State, desc="TCP Cache States", default="TCP_State_I") { - I, AccessPermission:Invalid, desc="Invalid"; + I, AccessPermission:Invalid, desc="Invalid"; V, AccessPermission:Read_Only, desc="Valid"; - A, AccessPermission:Invalid, desc="Waiting on Atomic"; + A, AccessPermission:Invalid, desc="Waiting on Atomic"; F, AccessPermission:Invalid, desc="Flushing; Waiting for Ack"; } enumeration(Event, desc="TCP Events") { // Core initiated - Load, desc="Load"; + Load, desc="Load"; LoadBypassEvict, desc="Bypass L1 on a load. Evict if cache block already allocated"; - Store, desc="Store to L1 (L1 is dirty)"; - StoreThrough, desc="Store directly to L2(L1 is clean)"; - Atomic, desc="Atomic"; - Flush, desc="Flush if dirty(wbL1 for Store Release)"; - Evict, desc="Evict if clean(invL1 for Load Acquire)"; + Store, desc="Store to L1 (L1 is dirty)"; + StoreThrough, desc="Store directly to L2(L1 is clean)"; + Atomic, desc="Atomic"; + Flush, desc="Flush if dirty(wbL1 for Store Release)"; + Evict, desc="Evict if clean(invL1 for Load Acquire)"; // Mem sys initiated - Repl, desc="Replacing block from cache"; + Repl, desc="Replacing block from cache"; // TCC initiated - TCC_Ack, desc="TCC Ack to Core Request"; - TCC_AckWB, desc="TCC Ack for WB"; + TCC_Ack, desc="TCC Ack to Core Request"; + TCC_AckWB, desc="TCC Ack for WB"; // Disable L1 cache - Bypass, desc="Bypass the entire L1 cache"; + Bypass, desc="Bypass the entire L1 cache"; } enumeration(RequestType, @@ -613,7 +613,6 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") L1cache.profileDemandHit(); } - // Transitions // ArrayRead/Write assumptions: // All requests read Tag Array From f3128043646859a426bf821751fbdd2bdf07069d Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Mon, 13 Nov 2023 16:34:33 -0600 Subject: [PATCH 539/693] mem-ruby: fix hex print in CacheMemory (#561) Update print in CacheMemory about clearing the lock to properly print in hex. --- src/mem/ruby/structures/CacheMemory.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/ruby/structures/CacheMemory.cc b/src/mem/ruby/structures/CacheMemory.cc index 5a5eaffa02..975bf0b775 100644 --- a/src/mem/ruby/structures/CacheMemory.cc +++ b/src/mem/ruby/structures/CacheMemory.cc @@ -288,7 +288,7 @@ CacheMemory::allocate(Addr address, AbstractCacheEntry *entry) set[i] = entry; // Init entry set[i]->m_Address = address; set[i]->m_Permission = AccessPermission_Invalid; - DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n", + DPRINTF(RubyCache, "Allocate clearing lock for addr: 0x%x\n", address); set[i]->m_locked = -1; m_tag_index[address] = i; From 75ca2c42829fa5034f450df76174bfda647b07fc Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Mon, 13 Nov 2023 16:40:27 -0600 Subject: [PATCH 540/693] gpu-compute: Fix typo with GPUTLB print (#529) gpu-compute: Fix typo with GPUTLB print Print was not properly ending in a newline, which caused confusion when looking a trace with GPUTLB enabled. This fixes that. --- src/arch/amdgpu/common/tlb_coalescer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/amdgpu/common/tlb_coalescer.cc b/src/arch/amdgpu/common/tlb_coalescer.cc index 0be1387977..0d2715fca3 100644 --- a/src/arch/amdgpu/common/tlb_coalescer.cc +++ b/src/arch/amdgpu/common/tlb_coalescer.cc @@ -482,7 +482,7 @@ TLBCoalescer::processProbeTLBEvent() stats.localqueuingCycles += (curTick() * pkt_cnt); } - DPRINTF(GPUTLB, "Successfully sent TLB request for page %#x", + DPRINTF(GPUTLB, "Successfully sent TLB request for page %#x\n", virt_page_addr); //copy coalescedReq to issuedTranslationsTable From 7d0a1fb28403e64b78bc3555a412d34b8e69a81f Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Mon, 13 Nov 2023 17:01:01 -0600 Subject: [PATCH 541/693] mem-ruby, gpu-compute: fix typo in GPU coalescer deadlock print (#535) mem-ruby, gpu-compute: fix typo in GPU coalescer deadlock print The GPU Coalescer's deadlock print did not previously print a newline at the end of each deadlock, which caused confusion when there were multiple deadlocks as each deadlock print would appear to go with the address after it. This patch fixes this issue. --- src/mem/ruby/system/GPUCoalescer.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mem/ruby/system/GPUCoalescer.cc b/src/mem/ruby/system/GPUCoalescer.cc index a70af07467..9b1b537618 100644 --- a/src/mem/ruby/system/GPUCoalescer.cc +++ b/src/mem/ruby/system/GPUCoalescer.cc @@ -344,7 +344,8 @@ GPUCoalescer::printRequestTable(std::stringstream& ss) << "\t\tIssue time: " << request->getIssueTime() * clockPeriod() << "\n" << "\t\tDifference from current tick: " - << (curCycle() - request->getIssueTime()) * clockPeriod(); + << (curCycle() - request->getIssueTime()) * clockPeriod() + << "\n"; } } From 48fde5a9c64fd5f901482dc793d9e8a903e76298 Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Mon, 13 Nov 2023 17:01:30 -0600 Subject: [PATCH 542/693] mem-ruby, gpu-compute: fix formatting of TCC (#536) mem-ruby, gpu-compute: fix formatting of TCC Fix several not properly indented prints and extraneous extra lines in the SLICC code for the GPU TCC (L2 cache). --- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 47 ++++++++++++-------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index ed7931d316..e3438fcd91 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -258,8 +258,7 @@ machine(MachineType:TCC, "TCC Cache") // request queue going to NB // - -// ** IN_PORTS ** + // ** IN_PORTS ** in_port(triggerQueue_in, TriggerMsg, triggerQueue) { if (triggerQueue_in.isReady(clockEdge())) { peek(triggerQueue_in, TriggerMsg) { @@ -283,8 +282,7 @@ machine(MachineType:TCC, "TCC Cache") } } - - + // handle responses from directory here in_port(responseFromNB_in, ResponseMsg, responseFromNB) { if (responseFromNB_in.isReady(clockEdge())) { peek(responseFromNB_in, ResponseMsg, block_on="addr") { @@ -876,9 +874,9 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } -// Transition to be called when a read request with SLC flag set arrives at -// entry in state W. It evicts and invalidates the cache entry before -// forwarding the request to global memory + // Transition to be called when a read request with SLC flag set arrives at + // entry in state W. It evicts and invalidates the cache entry before + // forwarding the request to global memory transition(W, RdBypassEvict, WIB) {TagArrayRead} { p_profileMiss; t_allocateTBE; @@ -888,9 +886,9 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } -// Transition to be called when a read request with SLC flag set arrives at -// entry in state M. It evicts and invalidates the cache entry before -// forwarding the request to global memory to main memory + // Transition to be called when a read request with SLC flag set arrives at + // entry in state M. It evicts and invalidates the cache entry before + // forwarding the request to global memory to main memory transition(M, RdBypassEvict, WIB) {TagArrayRead} { p_profileMiss; t_allocateTBE; @@ -900,9 +898,9 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } -// Transition to be called when a read request with SLC flag set arrives at -// entry in state V. It invalidates the cache entry before forwarding the -// request to global memory. + // Transition to be called when a read request with SLC flag set arrives at + // entry in state V. It invalidates the cache entry before forwarding the + // request to global memory. transition(V, RdBypassEvict, I) {TagArrayRead} { p_profileMiss; t_allocateTBE; @@ -911,8 +909,8 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } -// Transition to be called when a read request with SLC flag arrives at entry -// in transient state. The request stalls until the pending transition is complete. + // Transition to be called when a read request with SLC flag arrives at entry + // in transient state. The request stalls until the pending transition is complete. transition({WI, WIB, IV}, RdBypassEvict) { st_stallAndWaitRequest; } @@ -955,7 +953,6 @@ machine(MachineType:TCC, "TCC Cache") // The following atomic pass on actions will send the request to the directory, // and are triggered when an atomic request is received that is not in TCC, // and/or if SLC is set. - transition(V, AtomicPassOn, A) {TagArrayRead} { p_profileHit; i_invL2; @@ -1032,9 +1029,9 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } -// Transition to be called when a write request with SLC bit set arrives at an -// entry with state V. The entry has to be evicted and invalidated before the -// request is forwarded to global memory + // Transition to be called when a write request with SLC bit set arrives at an + // entry with state V. The entry has to be evicted and invalidated before the + // request is forwarded to global memory transition(V, WrVicBlkEvict, I) {TagArrayRead, TagArrayWrite, DataArrayWrite} { p_profileMiss; ut_updateTag; @@ -1044,9 +1041,9 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } -// Transition to be called when a write request with SLC bit set arrives at an -// entry with state W. The entry has to be evicted and invalidated before the -// request is forwarded to global memory. + // Transition to be called when a write request with SLC bit set arrives at an + // entry with state W. The entry has to be evicted and invalidated before the + // request is forwarded to global memory. transition(W, WrVicBlkEvict, I) {TagArrayRead, TagArrayWrite, DataArrayWrite} { p_profileMiss; ut_updateTag; @@ -1091,9 +1088,9 @@ machine(MachineType:TCC, "TCC Cache") pp_popProbeQueue; } -// Transition to be called when the response for a request with SLC bit set -// arrives. The request has to be forwarded to the core that needs it while -// making sure no entry is allocated. + // Transition to be called when the response for a request with SLC bit set + // arrives. The request has to be forwarded to the core that needs it while + // making sure no entry is allocated. transition(I, Bypass, I) { rb_bypassDone; pr_popResponseQueue; From f71450d26da63b63c90ed0b9eb7c4386a9498b64 Mon Sep 17 00:00:00 2001 From: Rajarshi Das Date: Tue, 14 Nov 2023 17:17:04 +0530 Subject: [PATCH 543/693] python,util: Fix magic number check in decode_inst_dep_trace.py (#560) The decode_inst_dep_trace.py opens the trace file in read mode, and subsequently reads the magic number from the trace file. Once the number is read, it is compared against the string 'gem5' without decoding it first. This causes the comparison to fail. The fix addresses this by calling the decode() routine on the output of the read() call. Please find the details in the associated issue #543 --- util/decode_inst_dep_trace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/decode_inst_dep_trace.py b/util/decode_inst_dep_trace.py index dcb5a7077b..9cd50a6819 100755 --- a/util/decode_inst_dep_trace.py +++ b/util/decode_inst_dep_trace.py @@ -130,7 +130,7 @@ def main(): exit(-1) # Read the magic number in 4-byte Little Endian - magic_number = proto_in.read(4) + magic_number = proto_in.read(4).decode() if magic_number != "gem5": print("Unrecognized file") From dde3d10aea9fe23dde28edecd1e80c0b381742af Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Tue, 14 Nov 2023 05:47:34 -0600 Subject: [PATCH 544/693] cpu: Remove SLC bit restraint for GPU tester (#552) This reverts gem5#133, the temporary work-around for gem5#131, allowing both SLC and GLC atomic requests to be made in the GPU tester. The underlying issues behind gem5#131 have been resolved by gem5#367 and gem5#397. --- src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc b/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc index 0fcfba7a37..ae4078ee6c 100644 --- a/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc +++ b/src/cpu/testers/gpu_ruby_test/gpu_wavefront.cc @@ -189,7 +189,6 @@ GpuWavefront::issueAtomicOps() AtomicOpFunctorPtr(amo_op)); req->setPaddr(address); req->setReqInstSeqNum(tester->getActionSeqNum()); - req->setCacheCoherenceFlags(Request::SLC_BIT); // set protocol-specific flags setExtraRequestFlags(req); From 6ac6d0c3406057b5ec19a521cf3839cbcd92478e Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 14 Nov 2023 03:53:28 -0800 Subject: [PATCH 545/693] tests,misc: Add "build/ALL/gem5.fast" Clang compilation to CI (#432) While we do run compiler tests weekly, 9/10 the issue is a strict check in clang we did not check before incorporating code into the codebase. Therefore, running a clang compilation as part of our CI would help us catch errors quicker. --- .github/workflows/ci-tests.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/ci-tests.yaml b/.github/workflows/ci-tests.yaml index 08ec318660..49928faf20 100644 --- a/.github/workflows/ci-tests.yaml +++ b/.github/workflows/ci-tests.yaml @@ -89,6 +89,22 @@ jobs: build-matrix: ${{ steps.build-matrix.outputs.build-matrix }} test-dirs-matrix: ${{ steps.dir-matrix.outputs.test-dirs-matrix }} + clang-fast-compilation: + # gem5 binaries built in `quick-gem5-builds` always use GCC. + # Clang is more strict than GCC. This job checks that gem5 compiles + # with Clang. It compiles build/ALL/gem5.fast to maximize the change + # for compilation error to be exposed. + runs-on: [self-hosted, linux, x64] + if: github.event.pull_request.draft == false + container: ghcr.io/gem5/clang-version-16:latest + needs: [pre-commit, check-for-change-id] + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: Clang Compilation + working-directory: ${{ github.workspace }} + run: scons build/ALL/gem5.fast -j $(nproc) + testlib-quick-gem5-builds: runs-on: [self-hosted, linux, x64] if: github.event.pull_request.draft == false From f11227b4a09bedcc92b961d70f47b232095dbce7 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Tue, 14 Nov 2023 19:54:35 +0800 Subject: [PATCH 546/693] systemc: Fix gcc13 systemC compilation error (#520) issue: https://github.com/gem5/gem5/issues/472 --- src/systemc/ext/core/sc_port.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/systemc/ext/core/sc_port.hh b/src/systemc/ext/core/sc_port.hh index 796950e29b..bd57553559 100644 --- a/src/systemc/ext/core/sc_port.hh +++ b/src/systemc/ext/core/sc_port.hh @@ -114,6 +114,10 @@ class sc_port_base : public sc_object virtual sc_port_policy _portPolicy() const = 0; }; +// The overloaded virtual is intended in SystemC, so we'll disable the warning. +// Please check section 9.3 of SystemC 2.3.1 release note for more details. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" template class sc_port_b : public sc_port_base { @@ -244,6 +248,7 @@ class sc_port_b : public sc_port_base sc_port_b(const sc_port_b &) {} sc_port_b &operator = (const sc_port_b &) { return *this; } }; +#pragma GCC diagnostic pop template class sc_port : public sc_port_b From 8598764a0345ec4326061d94f917597b65e25c8f Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Mon, 14 Nov 2022 12:02:10 +0000 Subject: [PATCH 547/693] mem-cache: Squash prefetch queue entries by block address. Prefetch queue entries were being squashed by comparing the address of each queued prefetch against the block address of the demand access. Only prefetches that happen to fall on a cache-line block boundary would be squashed. This patch converts the prefetch addresses to block addresses before comparison. Change-Id: I55ecb4919e94ad314b91c7795bba257c550b1528 Reviewed-by: Giacomo Travaglini --- src/mem/cache/prefetch/queued.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index 1ab34d2e9b..c67c315dad 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 ARM Limited + * Copyright (c) 2014-2015, 2022 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -178,7 +178,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi) if (queueSquash) { auto itr = pfq.begin(); while (itr != pfq.end()) { - if (itr->pfInfo.getAddr() == blk_addr && + if (blockAddress(itr->pfInfo.getAddr()) == blk_addr && itr->pfInfo.isSecure() == is_secure) { DPRINTF(HWPrefetch, "Removing pf candidate addr: %#x " "(cl: %#x), demand request going to the same addr\n", From 6416304e07a6bcbcf338d20f8852923f050afa70 Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Mon, 14 Nov 2022 10:56:36 +0000 Subject: [PATCH 548/693] mem-cache: Update default prefetch options. Update the default prefetch options to achieve out-of-the box prefetcher performance closer to that which a typical user would expect. Configurations that set these parameters explicitly will be unaffected. The new defaults were identified as part of work on gem5 prefetchers undertaken by Nikolaos Kyparissas while on internship at Arm. Change-Id: Id63868c7c8f00ee15a0b09a6550780a45ae67e55 Reviewed-by: Giacomo Travaglini --- src/mem/cache/Cache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py index d853a08cd9..501bb92682 100644 --- a/src/mem/cache/Cache.py +++ b/src/mem/cache/Cache.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2013, 2015, 2018 ARM Limited +# Copyright (c) 2012-2013, 2015, 2018, 2022 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -112,7 +112,7 @@ class BaseCache(ClockedObject): "Notify the hardware prefetcher on every access (not just misses)", ) prefetch_on_pf_hit = Param.Bool( - False, "Notify the hardware prefetcher on hit on prefetched lines" + True, "Notify the hardware prefetcher on hit on prefetched lines" ) tags = Param.BaseTags(BaseSetAssoc(), "Tag store") From 38045d7a252c46f5f57692e5eff5b18dd4fd2547 Mon Sep 17 00:00:00 2001 From: Nikolaos Kyparissas Date: Tue, 30 Aug 2022 17:14:03 +0100 Subject: [PATCH 549/693] mem-cache: Added clean eviction check for prefetchers. pkt->req->isCacheMaintenance() would not include a check for clean eviction before notifying the prefetcher, causing gem5 to crash. Change-Id: I1d082a87a3908b1ed46c5d632d45d8b09950b382 Reviewed-by: Giacomo Travaglini --- src/mem/cache/prefetch/base.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index e3e4b24cf2..25c37df323 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 ARM Limited + * Copyright (c) 2013-2014, 2022 Arm Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -245,6 +245,7 @@ Base::probeNotify(const PacketPtr &pkt, bool miss) // operations or for writes that we are coaslescing. if (pkt->cmd.isSWPrefetch()) return; if (pkt->req->isCacheMaintenance()) return; + if (pkt->isCleanEviction()) return; if (pkt->isWrite() && cache != nullptr && cache->coalesce()) return; if (!pkt->req->hasPaddr()) { panic("Request must have a physical address"); From be5c03ea9f82d43c7637488649fc1dabb1c29e7b Mon Sep 17 00:00:00 2001 From: Daniel Kouchekinia Date: Tue, 14 Nov 2023 09:48:48 -0600 Subject: [PATCH 550/693] mem-ruby,configs: Add GPU GLC Atomic Resource Constraints (#120) Added a resource constraint, AtomicALUOperation, to GLC atomics performed in the TCC. The resource constraint uses a new class, ALUFreeList array. The class assumes the following: - There are a fixed number of atomic ALU pipelines - While a new cache line can be processed in each pipeline each cycle, if a cache line is currently going through a pipeline, it can't be processed again until it's finished Two configuration parameters have been used to tune this behavior: - tcc-num-atomic-alus corresponds to the number of atomic ALU pipelines - atomic-alu-latency corresponds to the latency of atomic ALU pipelines Change-Id: I25bdde7dafc3877590bb6536efdf57b8c540a939 --- configs/ruby/GPU_VIPER.py | 11 ++ src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 15 ++- src/mem/ruby/protocol/RubySlicc_Exports.sm | 2 + src/mem/ruby/structures/ALUFreeListArray.cc | 106 ++++++++++++++++++++ src/mem/ruby/structures/ALUFreeListArray.hh | 78 ++++++++++++++ src/mem/ruby/structures/CacheMemory.cc | 24 +++++ src/mem/ruby/structures/CacheMemory.hh | 5 + src/mem/ruby/structures/RubyCache.py | 5 + src/mem/ruby/structures/SConscript | 1 + 9 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 src/mem/ruby/structures/ALUFreeListArray.cc create mode 100644 src/mem/ruby/structures/ALUFreeListArray.hh diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index b034cf76fd..665f739b4b 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -275,6 +275,8 @@ class TCC(RubyCache): def create(self, options): self.assoc = options.tcc_assoc + self.atomicLatency = options.atomic_alu_latency + self.atomicALUs = options.tcc_num_atomic_alus if hasattr(options, "bw_scalor") and options.bw_scalor > 0: s = options.num_compute_units tcc_size = s * 128 @@ -497,6 +499,15 @@ def define_options(parser): parser.add_argument( "--glc-atomic-latency", type=int, default=1, help="GLC Atomic Latency" ) + parser.add_argument( + "--atomic-alu-latency", type=int, default=0, help="Atomic ALU Latency" + ) + parser.add_argument( + "--tcc-num-atomic-alus", + type=int, + default=64, + help="Number of atomic ALUs in the TCC", + ) parser.add_argument( "--tcp-num-banks", type=int, diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index e3438fcd91..dfab0ed29a 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -93,6 +93,7 @@ machine(MachineType:TCC, "TCC Cache") DataArrayWrite, desc="Write the data array"; TagArrayRead, desc="Read the data array"; TagArrayWrite, desc="Write the data array"; + AtomicALUOperation, desc="Atomic ALU operation"; } @@ -223,6 +224,8 @@ machine(MachineType:TCC, "TCC Cache") L2cache.recordRequestType(CacheRequestType:TagArrayRead, addr); } else if (request_type == RequestType:TagArrayWrite) { L2cache.recordRequestType(CacheRequestType:TagArrayWrite, addr); + } else if (request_type == RequestType:AtomicALUOperation) { + L2cache.recordRequestType(CacheRequestType:AtomicALUOperation, addr); } } @@ -235,6 +238,8 @@ machine(MachineType:TCC, "TCC Cache") return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr); } else if (request_type == RequestType:TagArrayWrite) { return L2cache.checkResourceAvailable(CacheResourceType:TagArray, addr); + } else if (request_type == RequestType:AtomicALUOperation) { + return L2cache.checkResourceAvailable(CacheResourceType:AtomicALUArray, addr); } else { error("Invalid RequestType type in checkResourceAvailable"); return true; @@ -915,7 +920,7 @@ machine(MachineType:TCC, "TCC Cache") st_stallAndWaitRequest; } - transition(V, Atomic, M) {TagArrayRead, DataArrayWrite} { + transition(V, Atomic, M) {TagArrayRead, TagArrayWrite, DataArrayWrite, AtomicALUOperation} { p_profileHit; ut_updateTag; owm_orWriteMask; @@ -942,7 +947,7 @@ machine(MachineType:TCC, "TCC Cache") st_stallAndWaitRequest; } - transition(M, Atomic) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + transition(M, Atomic) {TagArrayRead, DataArrayWrite, AtomicALUOperation} { p_profileHit; owm_orWriteMask; pa_performAtomic; @@ -979,7 +984,7 @@ machine(MachineType:TCC, "TCC Cache") st_stallAndWaitRequest; } - transition({M, W}, AtomicPassOn, WI) {TagArrayRead} { + transition({M, W}, AtomicPassOn, WI) {TagArrayRead, DataArrayRead} { t_allocateTBE; wb_writeBack; // after writing back the current line, we need to wait for it to be done @@ -1098,7 +1103,7 @@ machine(MachineType:TCC, "TCC Cache") dt_deallocateTBE; } - transition(A, Bypass) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + transition(A, Bypass) {TagArrayRead, TagArrayWrite} { bapdr_sendBypassedAtomicPerformedInDirectoryResponse; dnpa_decrementNumPendingDirectoryAtomics; pr_popResponseQueue; @@ -1120,7 +1125,7 @@ machine(MachineType:TCC, "TCC Cache") dt_deallocateTBE; } - transition(A, Data, M) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + transition(A, Data, M) {TagArrayRead, TagArrayWrite, DataArrayWrite, AtomicALUOperation} { a_allocateBlock; wardb_writeAtomicResponseDirtyBytes; pa_performAtomic; diff --git a/src/mem/ruby/protocol/RubySlicc_Exports.sm b/src/mem/ruby/protocol/RubySlicc_Exports.sm index 2e496a8221..9ccafba41f 100644 --- a/src/mem/ruby/protocol/RubySlicc_Exports.sm +++ b/src/mem/ruby/protocol/RubySlicc_Exports.sm @@ -230,11 +230,13 @@ enumeration(CacheRequestType, desc="...", default="CacheRequestType_NULL") { DataArrayWrite, desc="Write access to the cache's data array"; TagArrayRead, desc="Read access to the cache's tag array"; TagArrayWrite, desc="Write access to the cache's tag array"; + AtomicALUOperation, desc="Atomic ALU operation"; } enumeration(CacheResourceType, desc="...", default="CacheResourceType_NULL") { DataArray, desc="Access to the cache's data array"; TagArray, desc="Access to the cache's tag array"; + AtomicALUArray, desc="Access to the cache's atomic ALU array"; } enumeration(DirectoryRequestType, desc="...", default="DirectoryRequestType_NULL") { diff --git a/src/mem/ruby/structures/ALUFreeListArray.cc b/src/mem/ruby/structures/ALUFreeListArray.cc new file mode 100644 index 0000000000..87b5cbfbd2 --- /dev/null +++ b/src/mem/ruby/structures/ALUFreeListArray.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023 The University of Wisconsin + * + * 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. + */ + +#include "mem/ruby/structures/ALUFreeListArray.hh" + +#include "base/intmath.hh" +#include "mem/ruby/system/RubySystem.hh" +#include "sim/cur_tick.hh" + +namespace gem5 +{ + +namespace ruby +{ + +/* +* +* Models num_ALUs pipelined atomic ALUs with a depth of access_latency ticks. +* Rather than reserving ALUs, this class assumes multiple requests can go +* through an ALU at the same time. As such, up to numALU new requests can +* go through at once, with the caveat that a line already being processed +* in an ALU can't start processing again until the previous request has exited +* the pipeline. +* +* ALUs aren't mapped directly to cache lines. Rather, ALUs are treated as +* a free list. +* +* Behavior: +* Requests will go through unless one/both of the following are met: +* - There have been more than [numALUs] requests in the current cycle +* - The same line has been accessed in the past accessLatency ticks +*/ + +ALUFreeListArray::ALUFreeListArray(unsigned int num_ALUs, Tick access_latency) +{ + this->numALUs = num_ALUs; + this->accessLatency = access_latency; +} + +bool ALUFreeListArray::tryAccess(Addr addr) +{ + uint32_t accesses_this_tick = 0; + + // Remove requests from the tail of the queue that occured more than + // accessLatency ticks ago + Tick oldestValidRecordStart = curTick() - this->accessLatency; + + while (accessQueue.size() > 0 && + (accessQueue.back().startTick < oldestValidRecordStart)) { + accessQueue.pop_back(); + } + + for (AccessRecord& record : accessQueue) { + // Block access if we would be using more ALUs than we have in a + // single tick + if (record.startTick == curTick() && + (++accesses_this_tick > numALUs)) { + return false; + } + + // Block access if the line is already being used + if (record.lineAddr == makeLineAddress(addr)) { + return false; + } + } + + return true; +} + +void ALUFreeListArray::reserve(Addr addr) +{ + // Only called after tryAccess, so we know queue is up to date and that + // the access is valid + + // Add record to queue + accessQueue.push_front(AccessRecord(makeLineAddress(addr), curTick())); +} + +} // namespace ruby +} // namespace gem5 diff --git a/src/mem/ruby/structures/ALUFreeListArray.hh b/src/mem/ruby/structures/ALUFreeListArray.hh new file mode 100644 index 0000000000..bed1b00b5c --- /dev/null +++ b/src/mem/ruby/structures/ALUFreeListArray.hh @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 The University of Wisconsin + * + * 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. + */ + +#ifndef __MEM_RUBY_STRUCTURES_ALUFREELISTARRAY_HH__ +#define __MEM_RUBY_STRUCTURES_ALUFREELISTARRAY_HH__ + +#include + +#include "mem/ruby/common/TypeDefines.hh" +#include "sim/cur_tick.hh" + +namespace gem5 +{ + +namespace ruby +{ + +class ALUFreeListArray +{ + private: + unsigned int numALUs; + Tick accessLatency; + + class AccessRecord + { + public: + AccessRecord(Addr line_addr, Tick start_tick) { + this->lineAddr = line_addr; + this->startTick = start_tick; + } + + Addr lineAddr; + Tick startTick; + }; + + // Queue of accesses from past accessLatency cycles + std::deque accessQueue; + + public: + ALUFreeListArray(unsigned int num_ALUs, Tick access_latency); + + bool tryAccess(Addr addr); + + void reserve(Addr addr); + + Tick getLatency() const { return accessLatency; } +}; + +} // namespace ruby +} // namespace gem5 + +#endif diff --git a/src/mem/ruby/structures/CacheMemory.cc b/src/mem/ruby/structures/CacheMemory.cc index 975bf0b775..3b97d34d18 100644 --- a/src/mem/ruby/structures/CacheMemory.cc +++ b/src/mem/ruby/structures/CacheMemory.cc @@ -73,6 +73,8 @@ CacheMemory::CacheMemory(const Params &p) p.start_index_bit, p.ruby_system), tagArray(p.tagArrayBanks, p.tagAccessLatency, p.start_index_bit, p.ruby_system), + atomicALUArray(p.atomicALUs, p.atomicLatency * + p.ruby_system->clockPeriod()), cacheMemoryStats(this) { m_cache_size = p.size; @@ -529,6 +531,8 @@ CacheMemoryStats::CacheMemoryStats(statistics::Group *parent) ADD_STAT(numTagArrayWrites, "Number of tag array writes"), ADD_STAT(numTagArrayStalls, "Number of stalls caused by tag array"), ADD_STAT(numDataArrayStalls, "Number of stalls caused by data array"), + ADD_STAT(numAtomicALUOperations, "Number of atomic ALU operations"), + ADD_STAT(numAtomicALUArrayStalls, "Number of stalls caused by atomic ALU array"), ADD_STAT(htmTransCommitReadSet, "Read set size of a committed " "transaction"), ADD_STAT(htmTransCommitWriteSet, "Write set size of a committed " @@ -564,6 +568,12 @@ CacheMemoryStats::CacheMemoryStats(statistics::Group *parent) numDataArrayStalls .flags(statistics::nozero); + numAtomicALUOperations + .flags(statistics::nozero); + + numAtomicALUArrayStalls + .flags(statistics::nozero); + htmTransCommitReadSet .init(8) .flags(statistics::pdf | statistics::dist | statistics::nozero | @@ -633,6 +643,11 @@ CacheMemory::recordRequestType(CacheRequestType requestType, Addr addr) tagArray.reserve(addressToCacheSet(addr)); cacheMemoryStats.numTagArrayWrites++; return; + case CacheRequestType_AtomicALUOperation: + if (m_resource_stalls) + atomicALUArray.reserve(addr); + cacheMemoryStats.numAtomicALUOperations++; + return; default: warn("CacheMemory access_type not found: %s", CacheRequestType_to_string(requestType)); @@ -664,6 +679,15 @@ CacheMemory::checkResourceAvailable(CacheResourceType res, Addr addr) cacheMemoryStats.numDataArrayStalls++; return false; } + } else if (res == CacheResourceType_AtomicALUArray) { + if (atomicALUArray.tryAccess(addr)) return true; + else { + DPRINTF(RubyResourceStalls, + "Atomic ALU array stall on addr %#x in line address %#x\n", + addr, makeLineAddress(addr)); + cacheMemoryStats.numAtomicALUArrayStalls++; + return false; + } } else { panic("Unrecognized cache resource type."); } diff --git a/src/mem/ruby/structures/CacheMemory.hh b/src/mem/ruby/structures/CacheMemory.hh index a63bb02748..de7c327f63 100644 --- a/src/mem/ruby/structures/CacheMemory.hh +++ b/src/mem/ruby/structures/CacheMemory.hh @@ -56,6 +56,7 @@ #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/structures/BankedArray.hh" +#include "mem/ruby/structures/ALUFreeListArray.hh" #include "mem/ruby/system/CacheRecorder.hh" #include "params/RubyCache.hh" #include "sim/sim_object.hh" @@ -186,6 +187,7 @@ class CacheMemory : public SimObject BankedArray dataArray; BankedArray tagArray; + ALUFreeListArray atomicALUArray; int m_cache_size; int m_cache_num_sets; @@ -224,6 +226,9 @@ class CacheMemory : public SimObject statistics::Scalar numTagArrayStalls; statistics::Scalar numDataArrayStalls; + statistics::Scalar numAtomicALUOperations; + statistics::Scalar numAtomicALUArrayStalls; + // hardware transactional memory statistics::Histogram htmTransCommitReadSet; statistics::Histogram htmTransCommitWriteSet; diff --git a/src/mem/ruby/structures/RubyCache.py b/src/mem/ruby/structures/RubyCache.py index f2c1b7230c..7446ac3de0 100644 --- a/src/mem/ruby/structures/RubyCache.py +++ b/src/mem/ruby/structures/RubyCache.py @@ -44,6 +44,11 @@ class RubyCache(SimObject): "0B", "block size in bytes. 0 means default RubyBlockSize" ) + # Atomic parameters only applicable to GPU atomics + # Zero atomic latency corresponds to instantanous atomic ALU operations + atomicLatency = Param.Cycles(0, "Cycles for an atomic ALU operation") + atomicALUs = Param.Int(64, "Number of atomic ALUs") + dataArrayBanks = Param.Int(1, "Number of banks for the data array") tagArrayBanks = Param.Int(1, "Number of banks for the tag array") dataAccessLatency = Param.Cycles(1, "cycles for a data array access") diff --git a/src/mem/ruby/structures/SConscript b/src/mem/ruby/structures/SConscript index cae03909c7..7baab6a4c4 100644 --- a/src/mem/ruby/structures/SConscript +++ b/src/mem/ruby/structures/SConscript @@ -55,6 +55,7 @@ Source('PersistentTable.cc') Source('RubyPrefetcher.cc') Source('TimerTable.cc') Source('BankedArray.cc') +Source('ALUFreeListArray.cc') Source('TBEStorage.cc') if env['PROTOCOL'] == 'CHI': Source('MN_TBETable.cc') From 65b44e6516096d5f812fcfa6e4946663eabda10c Mon Sep 17 00:00:00 2001 From: BujSet Date: Tue, 14 Nov 2023 09:54:42 -0600 Subject: [PATCH 551/693] mem-ruby: Fix for not creating log entries on atomic no return requests (#546) Augmenting Datablock and WriteMask to support optional arg to distinguish between return and no return. In the case of atomic no return requests, log entries should not be created when performing the atomic. Change-Id: Ic3112834742f4058a7aa155d25ccc4c014b60199a --- src/mem/ruby/common/DataBlock.cc | 5 +- src/mem/ruby/common/DataBlock.hh | 3 +- src/mem/ruby/common/WriteMask.cc | 14 ++--- src/mem/ruby/common/WriteMask.hh | 3 +- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 26 +++++++-- src/mem/ruby/protocol/GPU_VIPER-TCP.sm | 7 ++- .../protocol/MOESI_AMD_Base-Region-dir.sm | 54 ++++++++++++++++--- .../protocol/MOESI_AMD_Base-RegionBuffer.sm | 12 +++-- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 29 ++++++++-- src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm | 2 + .../protocol/MOESI_AMD_Base-probeFilter.sm | 38 ++++++++++--- src/mem/ruby/protocol/RubySlicc_Exports.sm | 1 + 12 files changed, 156 insertions(+), 38 deletions(-) diff --git a/src/mem/ruby/common/DataBlock.cc b/src/mem/ruby/common/DataBlock.cc index 70d9bc332a..8f47d0026b 100644 --- a/src/mem/ruby/common/DataBlock.cc +++ b/src/mem/ruby/common/DataBlock.cc @@ -110,12 +110,13 @@ DataBlock::copyPartial(const DataBlock &dblk, const WriteMask &mask) } void -DataBlock::atomicPartial(const DataBlock &dblk, const WriteMask &mask) +DataBlock::atomicPartial(const DataBlock &dblk, const WriteMask &mask, + bool isAtomicNoReturn) { for (int i = 0; i < RubySystem::getBlockSizeBytes(); i++) { m_data[i] = dblk.m_data[i]; } - mask.performAtomic(m_data, m_atomicLog); + mask.performAtomic(m_data, m_atomicLog, isAtomicNoReturn); } void diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index aa94f56eb8..7456a25f3f 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -96,7 +96,8 @@ class DataBlock void setData(PacketPtr pkt); void copyPartial(const DataBlock &dblk, int offset, int len); void copyPartial(const DataBlock &dblk, const WriteMask &mask); - void atomicPartial(const DataBlock & dblk, const WriteMask & mask); + void atomicPartial(const DataBlock & dblk, const WriteMask & mask, + bool isAtomicNoReturn=true); bool equal(const DataBlock& obj) const; void print(std::ostream& out) const; diff --git a/src/mem/ruby/common/WriteMask.cc b/src/mem/ruby/common/WriteMask.cc index 911262b4ba..1fa03c951e 100644 --- a/src/mem/ruby/common/WriteMask.cc +++ b/src/mem/ruby/common/WriteMask.cc @@ -57,7 +57,7 @@ WriteMask::print(std::ostream& out) const void WriteMask::performAtomic(uint8_t * p, - std::deque& log) const + std::deque& log, bool isAtomicNoReturn) const { int offset; uint8_t *block_update; @@ -65,11 +65,13 @@ WriteMask::performAtomic(uint8_t * p, // vector. This is done to match the ordering of packets // that was seen when the initial coalesced request was created. for (int i = 0; i < mAtomicOp.size(); i++) { - // Save the old value of the data block in case a - // return value is needed - block_update = new uint8_t[mSize]; - std::memcpy(block_update, p, mSize); - log.push_back(block_update); + if (!isAtomicNoReturn) { + // Save the old value of the data block in case a + // return value is needed + block_update = new uint8_t[mSize]; + std::memcpy(block_update, p, mSize); + log.push_back(block_update); + } // Perform the atomic operation offset = mAtomicOp[i].first; AtomicOpFunctor *fnctr = mAtomicOp[i].second; diff --git a/src/mem/ruby/common/WriteMask.hh b/src/mem/ruby/common/WriteMask.hh index 47ec798500..8c6b8ce976 100644 --- a/src/mem/ruby/common/WriteMask.hh +++ b/src/mem/ruby/common/WriteMask.hh @@ -230,7 +230,8 @@ class WriteMask * specific atomic operation. */ void performAtomic(uint8_t * p, - std::deque& atomicChangeLog) const; + std::deque& atomicChangeLog, + bool isAtomicNoReturn=true) const; const AtomicOpVector& getAtomicOps() const diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index dfab0ed29a..7cb3a00e26 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -369,7 +369,9 @@ machine(MachineType:TCC, "TCC Cache") } else { trigger(Event:WrVicBlk, in_msg.addr, cache_entry, tbe); } - } else if (in_msg.Type == CoherenceRequestType:Atomic) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { // If the request is system-level, if the address isn't in the cache, // or if this cache is write-through, then send the request to the // directory. Since non-SLC atomics won't be performed by the directory, @@ -612,12 +614,17 @@ machine(MachineType:TCC, "TCC Cache") } if (coreRequestNetwork_in.isReady(clockEdge())) { peek(coreRequestNetwork_in, CPURequestMsg) { - if(in_msg.Type == CoherenceRequestType:RdBlk || in_msg.Type == CoherenceRequestType:Atomic){ + if(in_msg.Type == CoherenceRequestType:RdBlk || + in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn){ tbe.Destination.add(in_msg.Requestor); } tbe.isGLCSet := in_msg.isGLCSet; tbe.isSLCSet := in_msg.isSLCSet; - if(in_msg.Type == CoherenceRequestType:Atomic){ + if(in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn){ tbe.atomicWriteMask.clear(); tbe.atomicWriteMask.orMask(in_msg.writeMask); } @@ -715,7 +722,7 @@ machine(MachineType:TCC, "TCC Cache") out_msg.WTRequestor := in_msg.Requestor; out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); out_msg.MessageSize := MessageSizeType:Data; - out_msg.Type := CoherenceRequestType:Atomic; + out_msg.Type := in_msg.Type; out_msg.Dirty := true; out_msg.writeMask.orMask(in_msg.writeMask); out_msg.isGLCSet := in_msg.isGLCSet; @@ -801,7 +808,16 @@ machine(MachineType:TCC, "TCC Cache") } action(pa_performAtomic, "pa", desc="Perform atomic") { - cache_entry.DataBlk.atomicPartial(cache_entry.DataBlk, cache_entry.writeMask); + peek(coreRequestNetwork_in, CPURequestMsg) { + if (in_msg.Type == CoherenceRequestType:AtomicReturn) { + cache_entry.DataBlk.atomicPartial(cache_entry.DataBlk, cache_entry.writeMask, false); + } else { + // Set the isAtomicNoReturn flag to ensure that logs are not + // generated erroneously + assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); + cache_entry.DataBlk.atomicPartial(cache_entry.DataBlk, cache_entry.writeMask, true); + } + } } // END ACTIONS diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm index 5530e6dcb3..ee49d859a8 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm @@ -441,10 +441,15 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") out_msg.Destination.add(mapAddressToRange(address,MachineType:TCC, TCC_select_low_bit, TCC_select_num_bits)); out_msg.MessageSize := MessageSizeType:Data; - out_msg.Type := CoherenceRequestType:Atomic; out_msg.InitialRequestTime := curCycle(); out_msg.Shared := false; peek(mandatoryQueue_in, RubyRequest) { + if (in_msg.Type == RubyRequestType:ATOMIC_RETURN) { + out_msg.Type := CoherenceRequestType:AtomicReturn; + } else { + assert(in_msg.Type == RubyRequestType:ATOMIC_NO_RETURN); + out_msg.Type := CoherenceRequestType:AtomicNoReturn; + } out_msg.instSeqNum := in_msg.instSeqNum; out_msg.isGLCSet := in_msg.isGLCSet; out_msg.isSLCSet := in_msg.isSLCSet; diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm index ec8ffe6325..2f5103f846 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm @@ -180,6 +180,9 @@ machine(MachineType:Directory, "AMD_Base-like protocol") bool MemData, desc="Got MemData?",default="false"; bool wtData, desc="Got write through data?",default="false"; bool atomicData, desc="Got Atomic op?",default="false"; + // Note, protocol invariant: atomicData = atomicDataReturn || atomicDataNoReturn; + bool atomicDataReturn, desc="Got Atomic op and need return value?",default="false"; + bool atomicDataNoReturn, desc="Got Atomic op and don't need return value?",default="false"; Cycles InitialRequestTime, desc="..."; Cycles ForwardRequestTime, desc="..."; Cycles ProbeRequestStartTime, desc="..."; @@ -436,7 +439,9 @@ machine(MachineType:Directory, "AMD_Base-like protocol") trigger(Event:RdBlkS, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:RdBlkM) { trigger(Event:RdBlkM, in_msg.addr, entry, tbe); - } else if (in_msg.Type == CoherenceRequestType:Atomic) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { trigger(Event:Atomic, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WriteThrough) { trigger(Event:WriteThrough, in_msg.addr, entry, tbe); @@ -474,7 +479,9 @@ machine(MachineType:Directory, "AMD_Base-like protocol") trigger(Event:RdBlkSP, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:RdBlkM) { trigger(Event:RdBlkMP, in_msg.addr, entry, tbe); - } else if (in_msg.Type == CoherenceRequestType:Atomic) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { trigger(Event:AtomicP, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WriteThrough) { trigger(Event:WriteThroughP, in_msg.addr, entry, tbe); @@ -670,7 +677,9 @@ machine(MachineType:Directory, "AMD_Base-like protocol") out_msg.DemandRequest := false; } } else { - assert(in_msg.Type == CoherenceRequestType:Atomic); + assert(in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn); enqueue(responseNetwork_out, ResponseMsg, response_latency) { out_msg.addr := address; out_msg.Type := CoherenceResponseType:NBSysResp; @@ -977,10 +986,18 @@ machine(MachineType:Directory, "AMD_Base-like protocol") tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } - if (in_msg.Type == CoherenceRequestType:Atomic) { + if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { tbe.writeMask.clear(); tbe.writeMask.orMask(in_msg.writeMask); tbe.atomicData := true; + if (in_msg.Type == CoherenceRequestType:AtomicReturn) { + tbe.atomicDataReturn := true; + } else { + assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); + tbe.atomicDataNoReturn := true; + } tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } @@ -1012,10 +1029,18 @@ machine(MachineType:Directory, "AMD_Base-like protocol") tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } - if (in_msg.Type == CoherenceRequestType:Atomic) { + if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { tbe.writeMask.clear(); tbe.writeMask.orMask(in_msg.writeMask); tbe.atomicData := true; + if (in_msg.Type == CoherenceRequestType:AtomicReturn) { + tbe.atomicDataReturn := true; + } else { + assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); + tbe.atomicDataNoReturn := true; + } tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } @@ -1062,8 +1087,15 @@ machine(MachineType:Directory, "AMD_Base-like protocol") tbe.DataBlkAux.copyPartial(in_msg.DataBlk,in_msg.writeMask); getDirectoryEntry(address).DataBlk := tbe.DataBlkAux; } else{ - assert(in_msg.Type == CoherenceRequestType:Atomic); - tbe.DataBlkAux.atomicPartial(getDirectoryEntry(address).DataBlk,in_msg.writeMask); + assert(in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { + if (in_msg.Type == CoherenceRequestType:AtomicReturn) { + tbe.DataBlkAux.atomicPartial(getDirectoryEntry(address).DataBlk,in_msg.writeMask, false); + } else { + assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); + tbe.DataBlkAux.atomicPartial(getDirectoryEntry(address).DataBlk,in_msg.writeMask, true); + } getDirectoryEntry(address).DataBlk := tbe.DataBlkAux; } } @@ -1076,7 +1108,12 @@ machine(MachineType:Directory, "AMD_Base-like protocol") tbe.DataBlk := tmp; getDirectoryEntry(address).DataBlk := tbe.DataBlk; } else if (tbe.atomicData) { - tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk,tbe.writeMask); + if (tbe.atomicDataReturn) { + tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk,tbe.writeMask, false); + } else { + assert(tbe.atomicDataNoReturn); + tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk,tbe.writeMask, true); + } getDirectoryEntry(address).DataBlk := tbe.DataBlk; } else if (tbe.Dirty == true) { APPEND_TRANSITION_COMMENT(" Wrote data back "); @@ -1137,6 +1174,7 @@ machine(MachineType:Directory, "AMD_Base-like protocol") tbe.DataBlk := tmp; } else if (tbe.Dirty) { if(tbe.atomicData == false && tbe.wtData == false) { + assert(tbe.atomicDataReturn == false && tbe.atomicDataNoReturn); DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender); assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data } diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-RegionBuffer.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-RegionBuffer.sm index 5987d7cf76..5d85ad2fc6 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-RegionBuffer.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-RegionBuffer.sm @@ -458,7 +458,9 @@ machine(MachineType:RegionBuffer, "Region Buffer for AMD_Base-like protocol") trigger(Event:CPUWrite, in_msg.addr, cache_entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WriteThrough ) { trigger(Event:CPUWrite, in_msg.addr, cache_entry, tbe); - } else if (in_msg.Type == CoherenceRequestType:Atomic ) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { trigger(Event:CPUWrite, in_msg.addr, cache_entry, tbe); } else { if (in_msg.Type == CoherenceRequestType:VicDirty || @@ -523,9 +525,11 @@ machine(MachineType:RegionBuffer, "Region Buffer for AMD_Base-like protocol") assert(in_msg.Type == CoherenceRequestType:RdBlkM || in_msg.Type == CoherenceRequestType:RdBlkS); } APPEND_TRANSITION_COMMENT(cache_entry.NumOutstandingReqs); - if (in_msg.Type == CoherenceRequestType:RdBlkM || in_msg.Type == CoherenceRequestType:Atomic || - in_msg.Type == CoherenceRequestType:WriteThrough ) - { + if (in_msg.Type == CoherenceRequestType:RdBlkM || + in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn || + in_msg.Type == CoherenceRequestType:WriteThrough) { cache_entry.dirty := true; } if (in_msg.Type == CoherenceRequestType:VicDirty || diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index c3bbfa1950..b9401d680a 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -159,6 +159,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") bool MemData, desc="Got MemData?",default="false"; bool wtData, desc="Got write through data?",default="false"; bool atomicData, desc="Got Atomic op?",default="false"; + // Note, protocol invariant: atomicData = atomicDataReturn || atomicDataNoReturn; + bool atomicDataReturn, desc="Got Atomic op and need return value?",default="false"; + bool atomicDataNoReturn, desc="Got Atomic op and don't need return value?",default="false"; Cycles InitialRequestTime, desc="..."; Cycles ForwardRequestTime, desc="..."; Cycles ProbeRequestStartTime, desc="..."; @@ -399,7 +402,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") trigger(Event:RdBlkM, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WriteThrough) { trigger(Event:WriteThrough, in_msg.addr, entry, tbe); - } else if (in_msg.Type == CoherenceRequestType:Atomic) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { trigger(Event:Atomic, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:VicDirty) { if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) { @@ -743,7 +748,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") // CPU + GPU or GPU only system if ((in_msg.Type != CoherenceRequestType:WriteThrough && - in_msg.Type != CoherenceRequestType:Atomic) || + in_msg.Type != CoherenceRequestType:Atomic && + in_msg.Type != CoherenceRequestType:AtomicReturn && + in_msg.Type != CoherenceRequestType:AtomicNoReturn) || !in_msg.NoWriteConflict) { if (noTCCdir) { probe_dests.add(mapAddressToRange(address, MachineType:TCC, @@ -1013,10 +1020,18 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } - if (in_msg.Type == CoherenceRequestType:Atomic) { + if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { tbe.writeMask.clear(); tbe.writeMask.orMask(in_msg.writeMask); tbe.atomicData := true; + if (in_msg.Type == CoherenceRequestType:AtomicReturn) { + tbe.atomicDataReturn := true; + } else { + assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); + tbe.atomicDataNoReturn := true; + } tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; tbe.isSLCSet := in_msg.isSLCSet; @@ -1043,7 +1058,12 @@ machine(MachineType:Directory, "AMD Baseline protocol") // Only perform atomics in the directory if the SLC bit is set, or // if the L2 is WT if (tbe.atomicData && (tbe.isSLCSet || !L2isWB)) { - tbe.DataBlk.atomicPartial(tbe.DataBlk, tbe.writeMask); + if (tbe.atomicDataReturn) { + tbe.DataBlk.atomicPartial(tbe.DataBlk, tbe.writeMask, false); + } else { + assert(tbe.atomicDataNoReturn); + tbe.DataBlk.atomicPartial(tbe.DataBlk, tbe.writeMask, true); + } } enqueue(memQueue_out, MemoryMsg, to_memory_controller_latency) { out_msg.addr := address; @@ -1083,6 +1103,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.writeMask.fillMask(); } else if (tbe.Dirty) { if(tbe.atomicData == false && tbe.wtData == false) { + assert(tbe.atomicDataReturn == false && tbe.atomicDataNoReturn == false); DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender); assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data } diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm index bb3a013325..984362da39 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm @@ -39,6 +39,8 @@ enumeration(CoherenceRequestType, desc="Coherence Request Types") { VicClean, desc="L2 clean eviction"; VicDirty, desc="L2 dirty eviction"; Atomic, desc="Upper level atomic"; + AtomicReturn, desc="Upper level atomic"; + AtomicNoReturn, desc="Upper level atomic"; AtomicWriteBack, desc="Upper level atomic"; WriteThrough, desc="Ordered WriteThrough w/Data"; WriteThroughFifo, desc="WriteThrough with no data"; diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm index 5e815a7165..4e9e9597aa 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm @@ -170,6 +170,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") bool MemData, desc="Got MemData?",default="false"; bool wtData, desc="Got write through data?",default="false"; bool atomicData, desc="Got Atomic op?",default="false"; + // Note, protocol invariant: atomicData = atomicDataReturn || atomicDataNoReturn; + bool atomicDataReturn, desc="Got Atomic op and need return value?",default="false"; + bool atomicDataNoReturn, desc="Got Atomic op and don't need return value?",default="false"; Cycles InitialRequestTime, desc="..."; Cycles ForwardRequestTime, desc="..."; Cycles ProbeRequestStartTime, desc="..."; @@ -451,7 +454,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") trigger(Event:RdBlkM, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:WriteThrough) { trigger(Event:WriteThrough, in_msg.addr, entry, tbe); - } else if (in_msg.Type == CoherenceRequestType:Atomic) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { trigger(Event:Atomic, in_msg.addr, entry, tbe); } else if (in_msg.Type == CoherenceRequestType:VicDirty) { if (getDirectoryEntry(in_msg.addr).VicDirtyIgnore.isElement(in_msg.Requestor)) { @@ -656,7 +661,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") // add relevant TCC node to list. This replaces all TCPs and SQCs if(isGPUSharer(address)) { if ((in_msg.Type == CoherenceRequestType:WriteThrough || - in_msg.Type == CoherenceRequestType:Atomic) && + in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) && in_msg.NoWriteConflict) { // Don't Include TCCs unless there was write-CAB conflict in the TCC } else if(noTCCdir) { @@ -814,6 +821,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.writeMask.clear(); tbe.wtData := false; tbe.atomicData := false; + tbe.atomicDataReturn := false; + tbe.atomicDataNoReturn := false; tbe.DataBlk := getDirectoryEntry(address).DataBlk; // Data only for WBs tbe.Dirty := false; tbe.NumPendingAcks := 0; @@ -831,10 +840,18 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } - if (in_msg.Type == CoherenceRequestType:Atomic) { + if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { tbe.writeMask.clear(); tbe.writeMask.orMask(in_msg.writeMask); tbe.atomicData := true; + if (in_msg.Type == CoherenceRequestType:AtomicReturn) { + tbe.atomicDataReturn = true; + } else { + assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); + tbe.atomicDataNoReturn = true; + } tbe.WTRequestor := in_msg.WTRequestor; tbe.LastSender := in_msg.Requestor; } @@ -866,8 +883,14 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.DataBlk := tmp; getDirectoryEntry(address).DataBlk := tbe.DataBlk; } else if (tbe.atomicData) { - tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk, - tbe.writeMask); + if (tbe.atomicDataReturn) { + tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk, + tbe.writeMask, false); + } else { + assert(tbe.atomicDataNoReturn); + tbe.DataBlk.atomicPartial(getDirectoryEntry(address).DataBlk, + tbe.writeMask, true); + } getDirectoryEntry(address).DataBlk := tbe.DataBlk; } else if (tbe.Dirty == false) { getDirectoryEntry(address).DataBlk := tbe.DataBlk; @@ -896,6 +919,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.DataBlk := tmp; } else if (tbe.Dirty) { if(tbe.atomicData == false && tbe.wtData == false) { + assert(atomicDataReturn == false && atomicDataNoReturn); DPRINTF(RubySlicc, "Got double data for %s from %s\n", address, in_msg.Sender); assert(tbe.DataBlk == in_msg.DataBlk); // in case of double data } @@ -1050,7 +1074,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") entry.pfState := ProbeFilterState:T; entry.isOnCPU := false; entry.isOnGPU := false; - } else if (in_msg.Type == CoherenceRequestType:Atomic) { + } else if (in_msg.Type == CoherenceRequestType:Atomic || + in_msg.Type == CoherenceRequestType:AtomicReturn || + in_msg.Type == CoherenceRequestType:AtomicNoReturn) { entry.pfState := ProbeFilterState:T; entry.isOnCPU := false; entry.isOnGPU := false; diff --git a/src/mem/ruby/protocol/RubySlicc_Exports.sm b/src/mem/ruby/protocol/RubySlicc_Exports.sm index 9ccafba41f..0d2bc742f9 100644 --- a/src/mem/ruby/protocol/RubySlicc_Exports.sm +++ b/src/mem/ruby/protocol/RubySlicc_Exports.sm @@ -77,6 +77,7 @@ structure(DataBlock, external = "yes", desc="..."){ void copyPartial(DataBlock, int, int); void copyPartial(DataBlock, WriteMask); void atomicPartial(DataBlock, WriteMask); + void atomicPartial(DataBlock, WriteMask, bool); int numAtomicLogEntries(); void clearAtomicLogEntries(); } From 99553fdbee97a866c2c5d3b458f5a3a5ddb246d2 Mon Sep 17 00:00:00 2001 From: Derek Christ <44267643+derchr@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:02:58 +0100 Subject: [PATCH 552/693] systemc: Fix two bugs in gem5-to-tlm bridge (#542) This commit fixes a violation of the TLM2.0 protocol as well as a bug regarding back-pressure: - In the BEGIN_REQ phase, transaction objects are required to set their response status to TLM_INCOMPLETE_RESPONSE. This was not the case in the packet2payload function that converts gem5 packets to TLM2.0 generic payloads. - When the target applies back-pressure to the initiator, an assert condition was triggered as soon as the response is retried. The cause of this was an unintentional nullptr-access into a map. --- src/systemc/tlm_bridge/gem5_to_tlm.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/systemc/tlm_bridge/gem5_to_tlm.cc b/src/systemc/tlm_bridge/gem5_to_tlm.cc index 515975224e..461be11051 100644 --- a/src/systemc/tlm_bridge/gem5_to_tlm.cc +++ b/src/systemc/tlm_bridge/gem5_to_tlm.cc @@ -152,6 +152,7 @@ packet2payload(PacketPtr packet) trans->acquire(); trans->set_address(packet->getAddr()); + trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); /* Check if this transaction was allocated by mm */ sc_assert(trans->has_mm()); @@ -480,7 +481,8 @@ Gem5ToTlmBridge::recvRespRetry() tlm::tlm_generic_payload *trans = blockingResponse; blockingResponse = nullptr; - PacketPtr packet = packetMap[blockingResponse]; + + PacketPtr packet = packetMap[trans]; sc_assert(packet); bool need_retry = !bridgeResponsePort.sendTimingResp(packet); From e95cab429f03d113a9032d3c2fcafaccf297b4b4 Mon Sep 17 00:00:00 2001 From: Derek Christ <44267643+derchr@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:05:11 +0100 Subject: [PATCH 553/693] configs,ext,stdlib: Update DRAMSys integration (#525) Recent breaking changes in the DRAMSys API require user code to be updated. These updates have been applied to the gem5 integration. Furthermore, as DRAMSys started to use CMake dependency management, it is no longer sensible to maintain two separate build systems for DRAMSys. The use of the DRAMSys integration in gem5 will therefore from now on require that CMake is installed on the target machine. Additionally, support for snapshots have been implemented into DRAMSys and coupled with gem5's checkpointing API. --- configs/example/dramsys.py | 5 +- .../gem5_library/dramsys/dramsys-traffic.py | 24 +-- ext/dramsys/CMakeLists.txt | 38 +++++ ext/dramsys/README | 12 +- ext/dramsys/SConscript | 90 +++++------- src/mem/SConscript | 1 + src/mem/dramsys.cc | 138 ++++++++++++++++++ src/mem/dramsys.hh | 34 ++--- src/mem/dramsys_wrapper.cc | 27 +++- src/mem/dramsys_wrapper.hh | 16 +- src/python/gem5/components/memory/dramsys.py | 76 +++++++--- 11 files changed, 330 insertions(+), 131 deletions(-) create mode 100644 ext/dramsys/CMakeLists.txt create mode 100644 src/mem/dramsys.cc diff --git a/configs/example/dramsys.py b/configs/example/dramsys.py index 934ff17b57..0e8bebfb75 100755 --- a/configs/example/dramsys.py +++ b/configs/example/dramsys.py @@ -37,9 +37,8 @@ system.mem_mode = "timing" system.cpu = traffic_gen dramsys = DRAMSys( - configuration="ext/dramsys/DRAMSys/DRAMSys/" - "library/resources/simulations/ddr4-example.json", - resource_directory="ext/dramsys/DRAMSys/DRAMSys/library/resources", + configuration="ext/dramsys/DRAMSys/configs/ddr4-example.json", + resource_directory="ext/dramsys/DRAMSys/configs", ) system.target = dramsys diff --git a/configs/example/gem5_library/dramsys/dramsys-traffic.py b/configs/example/gem5_library/dramsys/dramsys-traffic.py index ee9ad7228d..2f9b768696 100644 --- a/configs/example/gem5_library/dramsys/dramsys-traffic.py +++ b/configs/example/gem5_library/dramsys/dramsys-traffic.py @@ -31,16 +31,14 @@ DRAMSys simulator. DRRAMSys simulator. Please consult 'ext/dramsys/README' on how to compile correctly. If this is not done correctly this script will run with error. """ -import m5 -from gem5.components.memory import DRAMSysMem + +from gem5.components.memory.dramsys import DRAMSysMem from gem5.components.boards.test_board import TestBoard from gem5.components.processors.linear_generator import LinearGenerator -from m5.objects import Root +from gem5.simulate.simulator import Simulator memory = DRAMSysMem( - configuration="ext/dramsys/DRAMSys/DRAMSys/" - "library/resources/simulations/ddr4-example.json", - resource_directory="ext/dramsys/DRAMSys/DRAMSys/library/resources", + configuration="ext/dramsys/DRAMSys/configs/ddr4-example.json", recordable=True, size="4GB", ) @@ -51,12 +49,16 @@ generator = LinearGenerator( num_cores=1, max_addr=memory.get_size(), ) + board = TestBoard( clk_freq="3GHz", generator=generator, memory=memory, cache_hierarchy=None ) -root = Root(full_system=False, system=board) -board._pre_instantiate() -m5.instantiate() -generator.start_traffic() -exit_event = m5.simulate() +simulator = Simulator(board=board) +simulator.run() + +print( + "Exiting @ tick {} because {}.".format( + simulator.get_current_tick(), simulator.get_last_exit_event_cause() + ) +) diff --git a/ext/dramsys/CMakeLists.txt b/ext/dramsys/CMakeLists.txt new file mode 100644 index 0000000000..ada9369124 --- /dev/null +++ b/ext/dramsys/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2023 Fraunhofer IESE +# 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. + +cmake_minimum_required(VERSION 3.22.0) +project(DRAMSys) + +set(BUILD_SHARED_LIBS OFF) + +add_library(systemc INTERFACE) + +target_include_directories(systemc INTERFACE "${SCONS_SOURCE_DIR}/src/systemc/ext/systemc_home/include") + +add_library(SystemC::systemc ALIAS systemc) + +add_subdirectory(DRAMSys) diff --git a/ext/dramsys/README b/ext/dramsys/README index 7abc5a6bfb..1af3903b12 100644 --- a/ext/dramsys/README +++ b/ext/dramsys/README @@ -1,11 +1,13 @@ -Follow these steps to get DRAMSys as part of gem5 +Follow these steps to build DRAMSys as part of gem5 1. Go to ext/dramsys (this directory) -2. Clone DRAMSys: 'git clone https://github.com/tukl-msd/DRAMSys DRAMSys' -3. Change directory to DRAMSys: 'cd DRAMSys' -4. Checkout the correct commit: 'git checkout -b gem5 09f6dcbb91351e6ee7cadfc7bc8b29d97625db8f' -5. Recursively obtain the submodules: 'git submodule update --init --recursive' +2. Clone DRAMSys: 'git clone https://github.com/tukl-msd/DRAMSys --branch v5.0 --depth 1 DRAMSys' + +The latest verified working version is v5.0, but later versions might work too. +gem5 will automatically pick up DRAMSys as an external module when it is rebuilt. If you wish to run a simulation using the gem5 processor cores, make sure to enable the storage mode in DRAMSys. This is done by setting the value of the "StoreMode" key to "Store" in the base configuration file. Those configuration file can be found in 'DRAMSys/library/resources/configs/simulator'. + +Currently, DRAMSys is only supported in conjunction with a cache. Running DRAMSys in Release mode without caches will silently fail! diff --git a/ext/dramsys/SConscript b/ext/dramsys/SConscript index d6ea27e0d1..0cf163aede 100644 --- a/ext/dramsys/SConscript +++ b/ext/dramsys/SConscript @@ -25,72 +25,54 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os +import subprocess -Import('env') +Import("env") -build_root = Dir('../..').abspath -src_root = Dir('DRAMSys/DRAMSys/library').srcnode().abspath +build_root = Dir("../..").abspath +build_current = Dir(".").abspath +src_root = Dir(".").srcnode().abspath +scons_root = Dir("#").abspath # See if we got a cloned DRAMSys repo as a subdirectory and set the # HAVE_DRAMSys flag accordingly -if not os.path.exists(Dir('.').srcnode().abspath + '/DRAMSys'): - env['HAVE_DRAMSYS'] = False +if not os.path.exists(Dir(".").srcnode().abspath + "/DRAMSys"): + env["HAVE_DRAMSYS"] = False Return() -env['HAVE_DRAMSYS'] = True +env["HAVE_DRAMSYS"] = True -dramsys_files = [] -dramsys_configuration_files = [] +subprocess.run( + [ + "cmake", + f"-S{src_root}", + f"-B{build_current}", + "-DCMAKE_BUILD_TYPE=Release", + f"-DSCONS_SOURCE_DIR:STRING={scons_root}", + "-DDRAMSYS_BUILD_CLI=OFF" + ], + check=True +) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/controller")) -for root, dirs, files in os.walk(f"{src_root}/src/controller", topdown=False): - for dir in dirs: - dramsys_files.extend(Glob("%s/*.cpp" % os.path.join(root, dir))) +subprocess.run( + ["cmake", "--build", build_current], + check=True +) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/simulation")) -for root, dirs, files in os.walk(f"{src_root}/src/simulation", topdown=False): - for dir in dirs: - dramsys_files.extend(Glob("%s/*.cpp" % os.path.join(root, dir))) +env.Append(LIBS="DRAMSys_libdramsys") +env.Append(LIBPATH=Dir("./DRAMSys/src/libdramsys").abspath) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/configuration")) -for root, dirs, files in os.walk(f"{src_root}/src/configuration", topdown=False): - for dir in dirs: - dramsys_files.extend(Glob("%s/*.cpp" % os.path.join(root, dir))) +env.Append(LIBS="DRAMSys_Configuration") +env.Append(LIBPATH=Dir("./DRAMSys/src/configuration").abspath) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/error")) -dramsys_files.extend(Glob(f"{src_root}/src/error/ECC/Bit.cpp")) -dramsys_files.extend(Glob(f"{src_root}/src/error/ECC/ECC.cpp")) -dramsys_files.extend(Glob(f"{src_root}/src/error/ECC/Word.cpp")) +env.Append(LIBS="sqlite3") +env.Append(LIBPATH=Dir("./DRAMSys/lib/sqlite3").abspath) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/common")) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/common/configuration")) -dramsys_files.extend(Glob("%s/*.cpp" % f"{src_root}/src/common/configuration/memspec")) -dramsys_files.extend(Glob("%s/*.c" % f"{src_root}/src/common/third_party/sqlite-amalgamation")) +env.Append(CPPPATH=src_root + "/DRAMSys/src/libdramsys") +env.Append(CPPPATH=src_root + "/DRAMSys/src/configuration") +env.Append(CPPPATH=src_root + "/DRAMSys/src/util") +env.Append(CPPPATH=src_root + "/DRAMSys/lib/nlohmann_json/include") -env.Prepend(CPPPATH=[ - src_root + "/src", - src_root + "/src/common/configuration", - src_root + "/src/common/third_party/nlohmann/include", -]) - -env.Prepend(CPPDEFINES=[("DRAMSysResourceDirectory", '\\"' + os.getcwd() + '/resources' + '\\"')]) env.Prepend(CPPDEFINES=[("SYSTEMC_VERSION", 20191203)]) - -dramsys = env.Clone() - -if '-Werror' in dramsys['CCFLAGS']: - dramsys['CCFLAGS'].remove('-Werror') - -dramsys.Prepend(CPPPATH=[ - src_root + "/src/common/third_party/sqlite-amalgamation", - build_root + "/systemc/ext" -]) - -dramsys.Prepend(CPPDEFINES=[("SQLITE_ENABLE_RTREE", "1")]) - -dramsys_configuration = env.Clone() - -dramsys.Library('dramsys', dramsys_files) - -env.Append(LIBS=['dramsys', 'dl']) -env.Append(LIBPATH=[Dir('.')]) +env.Prepend(CPPDEFINES=[("DRAMSYS_RESOURCE_DIR", + '\\"' + os.getcwd() + '/DRAMSys/configs' + '\\"')]) diff --git a/src/mem/SConscript b/src/mem/SConscript index e2a91146d0..70a5c43758 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -127,6 +127,7 @@ if env['HAVE_DRAMSIM3']: if env['HAVE_DRAMSYS']: SimObject('DRAMSys.py', sim_objects=['DRAMSys']) Source('dramsys_wrapper.cc') + Source('dramsys.cc') SimObject('MemChecker.py', sim_objects=['MemChecker', 'MemCheckerMonitor']) Source('mem_checker.cc') diff --git a/src/mem/dramsys.cc b/src/mem/dramsys.cc new file mode 100644 index 0000000000..68fe983d30 --- /dev/null +++ b/src/mem/dramsys.cc @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2023 Fraunhofer IESE + * 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. + */ + +#include "dramsys.hh" + +namespace gem5 +{ + +namespace memory +{ + +DRAMSys::DRAMSys(Params const& params) : + AbstractMemory(params), + tlmWrapper(dramSysWrapper.tSocket, params.name + ".tlm", InvalidPortID), + config(::DRAMSys::Config::from_path(params.configuration, + params.resource_directory)), + dramSysWrapper( + params.name.c_str(), config, params.recordable, params.range) +{ + dramSysWrapper.dramsys->registerIdleCallback( + [this] + { + if (dramSysWrapper.dramsys->idle()) + { + signalDrainDone(); + } + }); +} + +gem5::Port& DRAMSys::getPort(const std::string& if_name, PortID idx) +{ + if (if_name != "tlm") + { + return AbstractMemory::getPort(if_name, idx); + } + + return tlmWrapper; +} + +DrainState DRAMSys::drain() +{ + return dramSysWrapper.dramsys->idle() ? DrainState::Drained + : DrainState::Draining; +} + +void DRAMSys::serialize(CheckpointOut& cp) const +{ + std::filesystem::path checkpointPath = CheckpointIn::dir(); + + auto topLevelObjects = sc_core::sc_get_top_level_objects(); + for (auto const* object : topLevelObjects) + { + std::function serialize; + serialize = + [&serialize, &checkpointPath](sc_core::sc_object const* object) + { + auto const* serializableObject = + dynamic_cast<::DRAMSys::Serialize const*>(object); + + if (serializableObject != nullptr) + { + std::string dumpFileName(object->name()); + dumpFileName += ".pmem"; + std::ofstream stream(checkpointPath / dumpFileName, + std::ios::binary); + serializableObject->serialize(stream); + } + + for (auto const* childObject : object->get_child_objects()) + { + serialize(childObject); + } + }; + + serialize(object); + } +} + +void DRAMSys::unserialize(CheckpointIn& cp) +{ + std::filesystem::path checkpointPath = CheckpointIn::dir(); + + auto topLevelObjects = sc_core::sc_get_top_level_objects(); + for (auto* object : topLevelObjects) + { + std::function deserialize; + deserialize = + [&deserialize, &checkpointPath](sc_core::sc_object* object) + { + auto* deserializableObject = + dynamic_cast<::DRAMSys::Deserialize*>(object); + + if (deserializableObject != nullptr) + { + std::string dumpFileName(object->name()); + dumpFileName += ".pmem"; + std::ifstream stream(checkpointPath / dumpFileName, + std::ios::binary); + deserializableObject->deserialize(stream); + } + + for (auto* childObject : object->get_child_objects()) + { + deserialize(childObject); + } + }; + + deserialize(object); + } +} + +} // namespace memory +} // namespace gem5 diff --git a/src/mem/dramsys.hh b/src/mem/dramsys.hh index d4d9ab8859..8530f2c563 100644 --- a/src/mem/dramsys.hh +++ b/src/mem/dramsys.hh @@ -29,7 +29,7 @@ #ifndef __MEM_DRAMSYS_H__ #define __MEM_DRAMSYS_H__ -#include "DRAMSysConfiguration.h" +#include "DRAMSys/config/DRAMSysConfiguration.h" #include "mem/abstract_mem.hh" #include "mem/dramsys_wrapper.hh" #include "params/DRAMSys.hh" @@ -43,36 +43,20 @@ namespace memory class DRAMSys : public AbstractMemory { PARAMS(DRAMSys); - sc_gem5::TlmTargetWrapper<32> tlmWrapper; + sc_gem5::TlmTargetWrapper<> tlmWrapper; public: - DRAMSys(Params const ¶ms) - : AbstractMemory(params), - tlmWrapper(dramSysWrapper.tSocket, - params.name + ".tlm", - InvalidPortID), - config(DRAMSysConfiguration::from_path( - params.configuration, - params.resource_directory)), - dramSysWrapper(params.name.c_str(), - config, - params.recordable, - params.range) - { - } + DRAMSys(Params const& params); - gem5::Port &getPort(const std::string &if_name, PortID idx) override - { - if (if_name != "tlm") - { - return AbstractMemory::getPort(if_name, idx); - } + gem5::Port& getPort(const std::string& if_name, PortID idx) override; - return tlmWrapper; - } + DrainState drain() override; + + void serialize(CheckpointOut& cp) const override; + void unserialize(CheckpointIn& cp) override; private: - DRAMSysConfiguration::Configuration config; + ::DRAMSys::Config::Configuration config; DRAMSysWrapper dramSysWrapper; }; diff --git a/src/mem/dramsys_wrapper.cc b/src/mem/dramsys_wrapper.cc index afa67f3bf2..2decec42a2 100644 --- a/src/mem/dramsys_wrapper.cc +++ b/src/mem/dramsys_wrapper.cc @@ -36,7 +36,7 @@ namespace memory DRAMSysWrapper::DRAMSysWrapper( sc_core::sc_module_name name, - DRAMSysConfiguration::Configuration const &config, + ::DRAMSys::Config::Configuration const &config, bool recordable, AddrRange range) : sc_core::sc_module(name), @@ -44,28 +44,41 @@ DRAMSysWrapper::DRAMSysWrapper( range(range) { tSocket.register_nb_transport_fw(this, &DRAMSysWrapper::nb_transport_fw); - tSocket.register_transport_dbg(this, &DRAMSysWrapper::transport_dbg); iSocket.register_nb_transport_bw(this, &DRAMSysWrapper::nb_transport_bw); + + tSocket.register_b_transport(this, &DRAMSysWrapper::b_transport); + + tSocket.register_transport_dbg(this, &DRAMSysWrapper::transport_dbg); iSocket.bind(dramsys->tSocket); // Register a callback to compensate for the destructor not // being called. registerExitCallback( - [this]() + []() { // Workaround for BUG GEM5-1233 sc_gem5::Kernel::stop(); }); } -std::shared_ptr<::DRAMSys> +std::shared_ptr<::DRAMSys::DRAMSys> DRAMSysWrapper::instantiateDRAMSys( bool recordable, - DRAMSysConfiguration::Configuration const &config) + ::DRAMSys::Config::Configuration const &config) { return recordable - ? std::make_shared<::DRAMSysRecordable>("DRAMSys", config) - : std::make_shared<::DRAMSys>("DRAMSys", config); + ? std::make_shared<::DRAMSys::DRAMSysRecordable>("DRAMSys", config) + : std::make_shared<::DRAMSys::DRAMSys>("DRAMSys", config); +} + +void DRAMSysWrapper::b_transport( + tlm::tlm_generic_payload &payload, + sc_core::sc_time &delay) +{ + // Subtract base address offset + payload.set_address(payload.get_address() - range.start()); + + iSocket->b_transport(payload, delay); } tlm::tlm_sync_enum DRAMSysWrapper::nb_transport_fw( diff --git a/src/mem/dramsys_wrapper.hh b/src/mem/dramsys_wrapper.hh index f1437cb761..26d552fd2f 100644 --- a/src/mem/dramsys_wrapper.hh +++ b/src/mem/dramsys_wrapper.hh @@ -32,13 +32,14 @@ #include #include -#include "DRAMSysConfiguration.h" +#include "DRAMSys/config/DRAMSysConfiguration.h" +#include "DRAMSys/simulation/DRAMSysRecordable.h" #include "mem/abstract_mem.hh" #include "params/DRAMSys.hh" #include "sim/core.hh" -#include "simulation/DRAMSysRecordable.h" #include "systemc/core/kernel.hh" #include "systemc/ext/core/sc_module_name.hh" + #include "systemc/ext/systemc" #include "systemc/ext/tlm" #include "systemc/ext/tlm_utils/simple_target_socket.h" @@ -57,14 +58,14 @@ class DRAMSysWrapper : public sc_core::sc_module public: SC_HAS_PROCESS(DRAMSysWrapper); DRAMSysWrapper(sc_core::sc_module_name name, - DRAMSysConfiguration::Configuration const &config, + ::DRAMSys::Config::Configuration const &config, bool recordable, AddrRange range); private: - static std::shared_ptr<::DRAMSys> + static std::shared_ptr<::DRAMSys::DRAMSys> instantiateDRAMSys(bool recordable, - DRAMSysConfiguration::Configuration const &config); + ::DRAMSys::Config::Configuration const &config); tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, @@ -74,12 +75,15 @@ class DRAMSysWrapper : public sc_core::sc_module tlm::tlm_phase &phase, sc_core::sc_time &bwDelay); + void b_transport(tlm::tlm_generic_payload &payload, + sc_core::sc_time &delay); + unsigned int transport_dbg(tlm::tlm_generic_payload &trans); tlm_utils::simple_initiator_socket iSocket; tlm_utils::simple_target_socket tSocket; - std::shared_ptr<::DRAMSys> dramsys; + std::shared_ptr<::DRAMSys::DRAMSys> dramsys; AddrRange range; }; diff --git a/src/python/gem5/components/memory/dramsys.py b/src/python/gem5/components/memory/dramsys.py index 28f3bd319f..a09d2fa0fc 100644 --- a/src/python/gem5/components/memory/dramsys.py +++ b/src/python/gem5/components/memory/dramsys.py @@ -24,7 +24,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import m5 +from typing import Tuple, Sequence, List, Optional +from pathlib import Path from m5.objects import ( DRAMSys, @@ -40,27 +41,46 @@ from ...utils.override import overrides from ..boards.abstract_board import AbstractBoard from .abstract_memory_system import AbstractMemorySystem -from typing import Tuple, Sequence, List + +DEFAULT_DRAMSYS_DIRECTORY = Path("ext/dramsys/DRAMSys") class DRAMSysMem(AbstractMemorySystem): + """ + A DRAMSys memory controller. + + This class requires gem5 to be built with DRAMSys (see ext/dramsys). + The specified memory size does not control the simulated memory size but it's sole purpose is + to notify gem5 of DRAMSys's memory size. + Therefore it has to match the DRAMSys configuration. + DRAMSys is configured using JSON files, whose base configuration has to be passed as a + parameter. Sub-configs are specified relative to the optional resource directory parameter. + """ + def __init__( self, configuration: str, size: str, - resource_directory: str, recordable: bool, + resource_directory: Optional[str] = None, ) -> None: """ :param configuration: Path to the base configuration JSON for DRAMSys. :param size: Memory size of DRAMSys. Must match the size specified in JSON configuration. - :param resource_directory: Path to the base resource directory for DRAMSys. :param recordable: Whether the database recording feature of DRAMSys is enabled. + :param resource_directory: Path to the base resource directory for DRAMSys. """ super().__init__() + + resource_directory_path = ( + DEFAULT_DRAMSYS_DIRECTORY / "configs" + if resource_directory is None + else Path(resource_directory) + ) + self.dramsys = DRAMSys( configuration=configuration, - resource_directory=resource_directory, + resource_directory=resource_directory_path.as_posix(), recordable=recordable, ) @@ -97,56 +117,72 @@ class DRAMSysMem(AbstractMemorySystem): class DRAMSysDDR4_1866(DRAMSysMem): + """ + An example DDR4 1866 DRAMSys configuration. + """ + def __init__(self, recordable: bool): """ :param recordable: Whether the database recording feature of DRAMSys is enabled. """ super().__init__( - configuration="ext/dramsys/DRAMSys/DRAMSys/" - "library/resources/simulations/ddr4-example.json", + configuration=( + DEFAULT_DRAMSYS_DIRECTORY / "configs/ddr4-example.json" + ).as_posix(), size="4GB", - resource_directory="ext/dramsys/DRAMSys/DRAMSys/library/resources", recordable=recordable, ) class DRAMSysDDR3_1600(DRAMSysMem): + """ + An example DDR3 1600 DRAMSys configuration. + """ + def __init__(self, recordable: bool): """ :param recordable: Whether the database recording feature of DRAMSys is enabled. """ super().__init__( - configuration="ext/dramsys/DRAMSys/DRAMSys/" - "library/resources/simulations/ddr3-gem5-se.json", - size="4GB", - resource_directory="ext/dramsys/DRAMSys/DRAMSys/library/resources", + configuration=( + DEFAULT_DRAMSYS_DIRECTORY / "configs/ddr3-gem5-se.json" + ).as_posix(), + size="1GB", recordable=recordable, ) class DRAMSysLPDDR4_3200(DRAMSysMem): + """ + An example LPDDR4 3200 DRAMSys configuration. + """ + def __init__(self, recordable: bool): """ :param recordable: Whether the database recording feature of DRAMSys is enabled. """ super().__init__( - configuration="ext/dramsys/DRAMSys/DRAMSys/" - "library/resources/simulations/lpddr4-example.json", - size="4GB", - resource_directory="ext/dramsys/DRAMSys/DRAMSys/library/resources", + configuration=( + DEFAULT_DRAMSYS_DIRECTORY / "configs/lpddr4-example.json" + ).as_posix(), + size="1GB", recordable=recordable, ) class DRAMSysHBM2(DRAMSysMem): + """ + An example HBM2 DRAMSys configuration. + """ + def __init__(self, recordable: bool): """ :param recordable: Whether the database recording feature of DRAMSys is enabled. """ super().__init__( - configuration="ext/dramsys/DRAMSys/DRAMSys/" - "library/resources/simulations/hbm2-example.json", - size="4GB", - resource_directory="ext/dramsys/DRAMSys/DRAMSys/library/resources", + configuration=( + DEFAULT_DRAMSYS_DIRECTORY / "configs/hbm2-example.json" + ).as_posix(), + size="1GB", recordable=recordable, ) From 8859592893fb8cfc835c056227d80407a87b6b38 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 14 Nov 2023 08:43:00 -0800 Subject: [PATCH 554/693] tests,gpu-compute: Fix Lulesh 'Obtain LULESH' step (#563) The `working-directory: ${{ github.workspace }}` line was included by mistake and resulted in this step failing as the command was being executed in the wrong directory. Example failure: https://github.com/gem5/gem5/actions/runs/6832831307/job/18593080567 --- .github/workflows/gpu-tests.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index 836bace7d7..b390e0750f 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -53,7 +53,6 @@ jobs: - run: chmod u+x build/GCN3_X86/gem5.opt - name: Obtain LULESH - working-directory: ${{ github.workspace }}/lulesh # Obtains the latest LULESH compatible with this version of gem5 via # gem5 Resources. run: build/GCN3_X86/gem5.opt util/obtain-resource.py lulesh -p lulesh From 30787b59d4eaccdfaab153a8f031010d5ffa349e Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 14 Nov 2023 11:00:07 -0800 Subject: [PATCH 555/693] tests: Remove multiple suites per job for Weekly tests (#562) I believe the weekly test failures (example: https://github.com/gem5/gem5/actions/runs/6832805510/job/18592876184) are due to a container running out of memory when running the very-long x86 boot tests. I found that the `-t $(nproc)` flag meant, on our runners, 4 x86 full system gem5 simulations were being pawned. Locally I found these gem5 x86 boot sims can reach 4GB in size so I suspect they eventually grew big enough exceed the 16GB memory of the VM. I have removed `-t $(nproc)` meaning each execution to see if this fixes the issue (we may want to use `-t 2` later if the Weeklies take too long running single-threaded). --- .github/workflows/weekly-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 8e00df5e75..72b1454a5e 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -59,7 +59,7 @@ jobs: - run: chmod u+x build/ALL/gem5.opt - name: very-long ${{ matrix.test-type }} working-directory: ${{ github.workspace }}/tests - run: ./main.py run gem5/${{ matrix.test-type }} --length very-long --skip-build -vv -t $(nproc) + run: ./main.py run gem5/${{ matrix.test-type }} --length very-long --skip-build -vv - name: create zip of results if: success() || failure() run: | From 4a5ec70e0822da711ce0c4a1f5e33bf63114885d Mon Sep 17 00:00:00 2001 From: BujSet Date: Wed, 15 Nov 2023 09:20:07 -0600 Subject: [PATCH 556/693] gpu-compute: Minor edits for atomic no returns and stores (#565) Since returned data is not needed for AtomicNoReturn and Store memory requests, the coalescer need not spend time writing in dummy data for packets of these types. Change-Id: Ie669e8c2a3bf44b5b0c290f62c49c5d4876a9a6a --- src/mem/ruby/system/GPUCoalescer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/ruby/system/GPUCoalescer.cc b/src/mem/ruby/system/GPUCoalescer.cc index 9b1b537618..f9d071ba62 100644 --- a/src/mem/ruby/system/GPUCoalescer.cc +++ b/src/mem/ruby/system/GPUCoalescer.cc @@ -600,8 +600,8 @@ GPUCoalescer::hitCallback(CoalescedRequest* crequest, // data response is not needed. case RubyRequestType_ATOMIC_NO_RETURN: assert(pkt->isAtomicOp()); + break; case RubyRequestType_ST: - data.setData(pkt->getPtr(), offset, pkt_size); break; case RubyRequestType_LD: pkt->setData(data.getData(offset, pkt_size)); From a8440f367deab31abcbd44fe3bbee17298b07a6c Mon Sep 17 00:00:00 2001 From: wmin0 Date: Thu, 16 Nov 2023 02:04:01 +0800 Subject: [PATCH 557/693] arch-riscv: Move fault handler addr logic to ISA (#554) mtvec.mode is extended in the new riscv proposal, like fast interrupt. This change moves that part from Fault class to ISA class for extendable. Ref: https://github.com/riscv/riscv-fast-interrupt --- src/arch/riscv/faults.cc | 4 +--- src/arch/riscv/isa.cc | 10 ++++++++++ src/arch/riscv/isa.hh | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 502b748087..7d4e9f90b6 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -158,9 +158,7 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) isa->clearLoadReservation(tc->contextId()); // Set PC to fault handler address - Addr addr = mbits(tc->readMiscReg(tvec), 63, 2); - if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1) - addr += 4 * _code; + Addr addr = isa->getFaultHandlerAddr(tvec, _code, isInterrupt()); pc_state.set(addr); tc->pcState(pc_state); } else { diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 877b795551..0ba6d15b6c 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -837,6 +837,16 @@ ISA::resetThread() Reset().invoke(tc); } +Addr +ISA::getFaultHandlerAddr(RegIndex idx, uint64_t cause, bool intr) const +{ + auto vec = tc->readMiscRegNoEffect(idx); + Addr addr = mbits(vec, 63, 2); + if (intr && bits(vec, 1, 0) == 1) + addr += 4 * cause; + return addr; +} + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 5581c3b677..66cba0f7fa 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -158,10 +158,14 @@ class ISA : public BaseISA Addr& load_reservation_addr = load_reservation_addrs[cid]; load_reservation_addr = INVALID_RESERVATION_ADDR; } + /** Methods for getting VLEN, VLENB and ELEN values */ unsigned getVecLenInBits() { return vlen; } unsigned getVecLenInBytes() { return vlen >> 3; } unsigned getVecElemLenInBits() { return elen; } + + virtual Addr getFaultHandlerAddr( + RegIndex idx, uint64_t cause, bool intr) const; }; } // namespace RiscvISA From 83f1fe3fec2c3d07d2e66a16749e72f62397b74a Mon Sep 17 00:00:00 2001 From: hungweihsuG <145444687+hungweihsuG@users.noreply.github.com> Date: Thu, 16 Nov 2023 02:04:46 +0800 Subject: [PATCH 558/693] dev: add debug flag in register bank. (#386) Print extra logs for the full/partial read/write access to the registers through the register bank. The debug flag is empty by default and would not print anything. Test: run unittest of dev/reg_bank.test.xml to check the behavior would not affect the original functionality. run gem5 with debug flags and use m5term to poke on registers. --- src/dev/SConscript | 2 +- src/dev/reg_bank.hh | 134 ++++++++++++++++++++++---------------------- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/src/dev/SConscript b/src/dev/SConscript index a7714a22d7..89e797acc8 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -54,4 +54,4 @@ Source('pixelpump.cc') DebugFlag('Intel8254Timer') DebugFlag('MC146818') -GTest('reg_bank.test', 'reg_bank.test.cc') +GTest('reg_bank.test', 'reg_bank.test.cc', with_tag('gem5 trace')) diff --git a/src/dev/reg_bank.hh b/src/dev/reg_bank.hh index 3a89a00ab6..c639a2d562 100644 --- a/src/dev/reg_bank.hh +++ b/src/dev/reg_bank.hh @@ -42,7 +42,9 @@ #include #include "base/bitfield.hh" +#include "base/debug.hh" #include "base/logging.hh" +#include "base/trace.hh" #include "base/types.hh" #include "sim/byteswap.hh" #include "sim/serialize_handlers.hh" @@ -861,9 +863,27 @@ class RegisterBank : public RegisterBankBase void reset() override { _resetter(*this); } }; + // Allow gem5 models to set a debug flag to the register bank for logging + // all full/partial read/write access to the registers. The register bank + // would not log if the flag is not set. + // + // The debug flag is the one declared in the SConscript + // + // DebugFlag('HelloExample') + // + // Then the flag can be set in the register bank with: + // + // setDebugFlag(::gem5::debug::HelloExample) + void + setDebugFlag(const ::gem5::debug::SimpleFlag& flag) + { + _debug_flag = &flag; + } + private: std::map> _offsetMap; + const ::gem5::debug::SimpleFlag* _debug_flag = nullptr; Addr _base = 0; Addr _size = 0; const std::string _name; @@ -956,45 +976,34 @@ class RegisterBank : public RegisterBankBase if (it == _offsetMap.end() || it->first > addr) it--; - if (it->first < addr) { - RegisterBase ® = it->second.get(); - // Skip at least the beginning of the first register. + std::ostringstream ss; + while (done != bytes) { + RegisterBase ® = it->second.get(); + const size_t reg_off = addr - it->first; + const size_t reg_size = reg.size() - reg_off; + const size_t reg_bytes = std::min(reg_size, bytes - done); - // Figure out what parts of it we're accessing. - const off_t reg_off = addr - it->first; - const size_t reg_bytes = std::min(reg.size() - reg_off, - bytes - done); + if (reg_bytes != reg.size()) { + if (_debug_flag) { + ccprintf(ss, "Read register %s, byte offset %d, size %d\n", + reg.name(), reg_off, reg_bytes); + } + reg.read(ptr + done, reg_off, reg_bytes); + } else { + if (_debug_flag) { + ccprintf(ss, "Read register %s\n", reg.name()); + } + reg.read(ptr + done); + } - // Actually do the access. - reg.read(ptr, reg_off, reg_bytes); - done += reg_bytes; - it++; - - // Was that everything? - if (done == bytes) - return; + done += reg_bytes; + addr += reg_bytes; + ++it; } - while (true) { - RegisterBase ® = it->second.get(); - - const size_t reg_size = reg.size(); - const size_t remaining = bytes - done; - - if (remaining == reg_size) { - // A complete register read, and then we're done. - reg.read(ptr + done); - return; - } else if (remaining > reg_size) { - // A complete register read, with more to go. - reg.read(ptr + done); - done += reg_size; - it++; - } else { - // Skip the end of the register, and then we're done. - reg.read(ptr + done, 0, remaining); - return; - } + if (_debug_flag) { + ::gem5::trace::getDebugLogger()->dprintf_flag( + curTick(), name(), _debug_flag->name(), "%s", ss.str()); } } @@ -1013,45 +1022,34 @@ class RegisterBank : public RegisterBankBase if (it == _offsetMap.end() || it->first > addr) it--; - if (it->first < addr) { + std::ostringstream ss; + while (done != bytes) { RegisterBase ® = it->second.get(); - // Skip at least the beginning of the first register. + const size_t reg_off = addr - it->first; + const size_t reg_size = reg.size() - reg_off; + const size_t reg_bytes = std::min(reg_size, bytes - done); - // Figure out what parts of it we're accessing. - const off_t reg_off = addr - it->first; - const size_t reg_bytes = std::min(reg.size() - reg_off, - bytes - done); + if (reg_bytes != reg.size()) { + if (_debug_flag) { + ccprintf(ss, "Write register %s, byte offset %d, size %d\n", + reg.name(), reg_off, reg_size); + } + reg.write(ptr + done, reg_off, reg_bytes); + } else { + if (_debug_flag) { + ccprintf(ss, "Write register %s\n", reg.name()); + } + reg.write(ptr + done); + } - // Actually do the access. - reg.write(ptr, reg_off, reg_bytes); done += reg_bytes; - it++; - - // Was that everything? - if (done == bytes) - return; + addr += reg_bytes; + ++it; } - while (true) { - RegisterBase ® = it->second.get(); - - const size_t reg_size = reg.size(); - const size_t remaining = bytes - done; - - if (remaining == reg_size) { - // A complete register write, and then we're done. - reg.write(ptr + done); - return; - } else if (remaining > reg_size) { - // A complete register write, with more to go. - reg.write(ptr + done); - done += reg_size; - it++; - } else { - // Skip the end of the register, and then we're done. - reg.write(ptr + done, 0, remaining); - return; - } + if (_debug_flag) { + ::gem5::trace::getDebugLogger()->dprintf_flag( + curTick(), name(), _debug_flag->name(), "%s", ss.str()); } } From 065ddf759fbde9b5a17bf9b149aa18cd8e5146c3 Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Sun, 5 Nov 2023 02:34:22 -0600 Subject: [PATCH 559/693] mem-ruby, gpu-compute: fix bug with GPU bypassing loads The current GPU TCP (L1D$) Ruby SLICC code had a bug where a GPU load that wants to bypass the L1D$ (e.g., GLC or SLC bit was set) but the line is in Invalid when that request arrives, results in a non-bypassing load being sent to the GPU TCC (L2$) instead of a bypassing load. This issue was not caught by currently nightly or weekly tests, because the tests do not test for correctness in terms of hits and misses in the caches. However, tests for these corner cases expose this issue. To fix, this, this patch removes the check that the entry is valid when deciding what to do with a bypassing GPU load -- since the TCP Ruby code has transitions for bypassing loads in both I and V, we can simply call the LoadBypassEvict event in both cases and the appropriate transition will handle the bypassing load given the cache line's current state in the TCP. Change-Id: Ia224cefdf56b4318b2bcbd0bed995fc8d3b62a14 --- src/mem/ruby/protocol/GPU_VIPER-TCP.sm | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm index ee49d859a8..ae35d4c5f7 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm @@ -292,10 +292,13 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") TBE tbe := TBEs.lookup(in_msg.LineAddress); DPRINTF(RubySlicc, "%s\n", in_msg); if (in_msg.Type == RubyRequestType:LD) { - if ((in_msg.isGLCSet || in_msg.isSLCSet) && is_valid(cache_entry)) { - // Read requests with GLC or SLC bit set should not cache in the L1. - // They need to bypass the L1 and go to the L2. If an entry exists - // in the L1, it needs to be evicted + // Read requests with GLC or SLC bit set should not cache in the L1. + // They need to bypass the L1 and go to the L2. If an entry exists in + // the L1, it needs to be evicted, and if no entry or invalid entry in + // the L1, still need to bypass. The LoadBypassEvict Event handles + // both cases in its transitions below, so call LoadBypassEvict for + // both. + if ((in_msg.isGLCSet || in_msg.isSLCSet)) { trigger(Event:LoadBypassEvict, in_msg.LineAddress, cache_entry, tbe); } else { From c3326c78e6f714894c73f13a0b696a5d4edd7191 Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Sun, 5 Nov 2023 21:54:06 -0600 Subject: [PATCH 560/693] mem-ruby, gpu-compute: fix SQC/TCP requests to same line Currently, the GPU SQC (L1I$) and TCP (L1D$) have a performance bug where they do not behave correctly when multiple requests to the same cache line overlap one another. The intended behavior is that if the first request that arrives at the Ruby code for the SQC/TCP misses, it should send a request to the GPU TCC (L2$). If any requests to the same cache line occur while this first request is pending, they should wait locally at the L1 in the MSHRs (TBEs) until the first request has returned. At that point they can be serviced, and assuming the line has not been evicted, they should hit. For example, in the following test (on 1 GPU thread, in 1 WG): load Arr[0] load Arr[1] load Arr[2] The expected behavior (confirmed via profiling on real GPUs) is that we should get 1 miss (Arr[0]) and 2 hits (Arr[1], Arr[2]) for such a program. However, the current support in the VIPER SQC/TCP code does not model this correctly. Instead it lets all 3 concurrent requests go straight through to the TCC instead of stopping the Arr[1] and Arr[2] requests locally while Arr[0] is serviced. This causes all 3 requests to be classified as misses. To resolve this, this patch adds support into the SQC/TCP code to prevent subsequent, concurrent requests to a pending cache line from being sent in parallel with the original one. To do this, we add an additional transient state (IV) to indicate that a load is pending to this cache line. If a subsequent request of any kind to the same cache line occurs while this load is pending, the requests are put on the local wait buffer and woken up when the first request returns to the SQC/TCP. Likewise, when the first load is returned to the SQC/TCP, it transitions from IV --> V. As part of this support, additional transitions were also added to account for corner cases such as what happens when the line is evicted by another request that maps to the same set index while the first load is pending (the line is immediately given to the new request, and when the load returns it completes, wakes up any pending requests to the same line, but does not attempt to change the state of the line) and how GPU bypassing loads and stores should interact with the pending requests (they are forced to wait if they reach the L1 after the pending, non-bypassing load; but if they reach the L1 before the non-bypassing load then they make sure not to change the state of the line from IV if they return before the non-bypassing load). As part of this change, we also move the MSHR behavior from internally in the GPUCoalescer for loads to the Ruby code (like all other requests). This is important to get correct hits and misses in stats and other prints, since the GPUCoalescer MSHR behavior assumes all requests serviced out of its MSHR also miss if the original request to that line missed. Although the SQC does not support stores, the TCP does. Thus, we could have applied a similar change to the GPU stores at the TCP. However, since the TCP support assumes write-through caches and does not attempt to allocate space in the TCP, we elected not to add this support since it seems to run contrary to the intended behavior (i.e., the intended behavior seems to be that writes just bypass the TCP and thus should not need to wait for another write to the same cache line to complete). Additionally, making these changes introduced issues with deadlocks at the TCC. Specifically, some Pannotia applications have accesses to the same cache line where some of the accesses are GLC (i.e., they bypass the GPU L1 cache) and others are non-GLC (i.e., they want to be cached in the GPU L1 cache). We have support already per CU in the above code. However, the problem here is that these requests are coming from different CUs and happening concurrently (seemingly because different WGs are at different points in the kernel around the same time). This causes a problem because our support at the TCC for the TBEs overwrites the information about the GPU bypassing bits (SLC, GLC) every time. The problem is when the second (non-GLC) load reaches the TCC, it overwrites the SLC/GLC information for the first (GLC) load. Thus, when the the first load returns from the directory/memory, it no longer has the GLC bit set, which causes an assert failure at the TCP. After talking with other developers, it was decided the best way handle this and attempt to model real hardware more closely was to move the point at which requests are put to sleep on the wakeup buffer from the TCC to the directory. Accordingly, this patch includes support for that -- now when multiple loads (bypassing or non-bypassing) from different CUs reach the directory, all but the first one will be forced to wait there until the first one completes, then will be woken up and performed. This required updating the WTRequestor information at the TCC to pass the information about what CU performed the original request for loads as well (otherwise since the TBE can be updated by multiple pending loads, we can't tell where to send the final result to). Thus, I changed the field to be named CURequestor instead of WTRequestor since it is now used for more than stores. Moreover, I also updated the directory to take this new field and the GLC information from incoming TCC requests and then pass that information back to the TCC on the response -- without doing this, because the TBE can be updated by multiple pending, concurrent requests we cannot determine if this memory request was a bypassing or non-bypassing request. Finally, these changes introduced a lot of additional contention and protocol stalls at the directory, so this patch converted all directory uses of z_stall to instead put requests on the wakeup buffer (and wake them up when the current request completes) instead. Without this, protocol stalls cause many applications to deadlock at the directory. However, this exposed another issue at the TCC: other applications (e.g., HACC) have a mix of atomics and non-atomics to the same cache line in the same kernel. Since the TCC transitions to the A state when an atomic arrives. For example, after the first pending load returns to the TCC from the directory, which causes the TCC state to become V, but when there are still other pending loads at the TCC. This causes invalid transition errors at the TCC when those pending loads return, because the A state thinks they are atomics and decrements the pending atomic count (plus the loads are never sent to the TCP as returning loads). This patch fixes this by changing the TCC TBEs to model the number of pending requests, and not allowing atomics to be issued from the TCC until all prior, pending non-atomic requests have returned. Change-Id: I37f8bda9f8277f2355bca5ef3610f6b63ce93563 --- src/mem/ruby/protocol/GPU_VIPER-SQC.sm | 59 ++++- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 269 ++++++++++++++------ src/mem/ruby/protocol/GPU_VIPER-TCP.sm | 111 ++++++-- src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm | 58 ++++- src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm | 10 +- src/mem/ruby/system/GPUCoalescer.cc | 24 +- 6 files changed, 407 insertions(+), 124 deletions(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-SQC.sm b/src/mem/ruby/protocol/GPU_VIPER-SQC.sm index 000cf5b1e6..bdc5d73f20 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-SQC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-SQC.sm @@ -48,6 +48,9 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") { state_declaration(State, desc="SQC Cache States", default="SQC_State_I") { I, AccessPermission:Invalid, desc="Invalid"; + // Note: currently IV in the TCP is only for pending loads to a given cache + // line. Since the SQC is read only, there are no stores. + IV, AccessPermission:Invalid, desc="Going from I to V, waiting on TCC data"; V, AccessPermission:Read_Only, desc="Valid"; } @@ -98,6 +101,7 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") void unset_tbe(); void wakeUpAllBuffers(); void wakeUpBuffers(Addr a); + void wakeUpAllBuffers(Addr a); Cycles curCycle(); // Internal functions @@ -270,6 +274,21 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") } } + action(t_allocateTBE, "t", desc="allocate TBE Entry") { + check_allocate(TBEs); + TBEs.allocate(address); + set_tbe(TBEs.lookup(address)); + } + + action(d_deallocateTBE, "d", desc="Deallocate TBE") { + TBEs.deallocate(address); + unset_tbe(); + } + + action(st_stallAndWaitRequest, "st", desc="Stall and wait on the address") { + stall_and_wait(mandatoryQueue_in, address); + } + action(p_popMandatoryQueue, "pm", desc="Pop Mandatory Queue") { mandatoryQueue_in.dequeue(clockEdge()); } @@ -278,6 +297,10 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") responseToSQC_in.dequeue(clockEdge()); } + action(wada_wakeUpAllDependentsAddr, "wada", desc="Wake up any requests waiting for this address") { + wakeUpAllBuffers(address); + } + action(l_loadDoneHit, "ldh", desc="local load done (hits in SQC)") { assert(is_valid(cache_entry)); sequencer.readCallback(address, cache_entry.DataBlk, true, MachineType:L1Cache); @@ -313,22 +336,52 @@ machine(MachineType:SQC, "GPU SQC (L1 I Cache)") // Transitions + // if another request arrives for the same cache line that has a pending + // load, put it on the wakeup buffer. This reduced resource contention since + // they won't try again every cycle and will instead only try again once woken + // up + transition(IV, {Fetch}) { + st_stallAndWaitRequest; + } + // transitions from base - transition({I, V}, Repl, I) {TagArrayRead, TagArrayWrite} { + transition({I, IV, V}, Repl, I) {TagArrayRead, TagArrayWrite} { // since we're evicting something, don't bother classifying as hit/miss ic_invCache; } - transition(I, Data, V) {TagArrayRead, TagArrayWrite, DataArrayRead} { + // if we got a response for a load where the line is in I, then + // another request must have come in that replaced the line in question in + // the cache. Thus, complete this request without allocating the line, but + // still deallocate TBE and wakeup any dependent addresses. + transition(I, Data) {TagArrayRead, TagArrayWrite, DataArrayRead} { + // don't profile this as a hit/miss since it's a reponse from L2, + // so we already counted it + l_loadDoneMiss; + wada_wakeUpAllDependentsAddr; + d_deallocateTBE; + pr_popResponseQueue; + } + + // if line is currently in IV, then Data is returning the data for a + // pending load, so transition to V, deallocate TBE, and wakeup any dependent + // requests so they will be replayed now that this request has returned. + transition(IV, Data, V) {TagArrayRead, TagArrayWrite, DataArrayRead} { a_allocate; // don't profile this as a hit/miss since it's a reponse from L2, // so we already counted it w_writeCache; l_loadDoneMiss; + wada_wakeUpAllDependentsAddr; + d_deallocateTBE; pr_popResponseQueue; } - transition(I, Fetch) {TagArrayRead, TagArrayWrite} { + // if we have a load that misses, allocate TBE entry and transition to IV + // to prevent subsequent requests to same cache line from also going to TCC + // while this request is pending + transition(I, Fetch, IV) {TagArrayRead, TagArrayWrite} { + t_allocateTBE; nS_issueRdBlkS; uu_profileDataMiss; // since line wasn't in SQC, we missed p_popMandatoryQueue; diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index 7cb3a00e26..14c9c8c1cc 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -61,6 +61,7 @@ machine(MachineType:TCC, "TCC Cache") WrVicBlk, desc="L1 Write Through"; WrVicBlkBack, desc="L1 Write Through(dirty cache)"; WrVicBlkEvict, desc="L1 Write Through(dirty cache) and evict"; + AtomicWait, desc="Atomic Op that must wait for pending loads"; Atomic, desc="Atomic Op"; AtomicPassOn, desc="Atomic Op Passed on to Directory"; AtomicDone, desc="AtomicOps Complete"; @@ -113,6 +114,7 @@ machine(MachineType:TCC, "TCC Cache") bool Shared, desc="Victim hit by shared probe"; MachineID From, desc="Waiting for writeback from..."; NetDest Destination, desc="Data destination"; + int numPending, desc="num pending requests"; int numPendingDirectoryAtomics, desc="number of pending atomics to be performed in directory"; int atomicDoneCnt, desc="number AtomicDones triggered"; bool isGLCSet, desc="Bypass L1 Cache"; @@ -293,11 +295,14 @@ machine(MachineType:TCC, "TCC Cache") peek(responseFromNB_in, ResponseMsg, block_on="addr") { TBE tbe := TBEs.lookup(in_msg.addr); Entry cache_entry := getCacheEntry(in_msg.addr); - bool is_slc_set := false; - - if (!is_invalid(tbe)) { - is_slc_set := tbe.isSLCSet; - } + /* + MOESI_AMD_Base-dir acts as the directory, and it always passes + SLC information back to L2 because of races at L2 with requests + from different CUs sending requests to same cache line in parallel. + If these requests have different GLC/SLC settings, the L2 TBE may + not have the correct GLC/SLC information for a given request. + */ + bool is_slc_set := in_msg.isSLCSet; // Whether the SLC bit is set or not, WB acks should invoke the // WBAck event. For cases where a read response will follow a @@ -372,16 +377,29 @@ machine(MachineType:TCC, "TCC Cache") } else if (in_msg.Type == CoherenceRequestType:Atomic || in_msg.Type == CoherenceRequestType:AtomicReturn || in_msg.Type == CoherenceRequestType:AtomicNoReturn) { - // If the request is system-level, if the address isn't in the cache, - // or if this cache is write-through, then send the request to the - // directory. Since non-SLC atomics won't be performed by the directory, - // TCC will perform the atomic on the return path on Event:Data. - // The action will invalidate the cache line if SLC is set and the address is - // in the cache. - if(in_msg.isSLCSet || !WB) { - trigger(Event:AtomicPassOn, in_msg.addr, cache_entry, tbe); + /* + If there are pending requests for this line already and those + requests are not atomics, because we can't easily differentiate + between different request types on return and because decrementing + the atomic count assumes all returned requests in the A state are + atomics, we will need to put this atomic to sleep and wake it up + when the loads return. + */ + if (is_valid(tbe) && (tbe.numPending > 0) && + (tbe.numPendingDirectoryAtomics == 0)) { + trigger(Event:AtomicWait, in_msg.addr, cache_entry, tbe); } else { - trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); + // If the request is system-level, if the address isn't in the cache, + // or if this cache is write-through, then send the request to the + // directory. Since non-SLC atomics won't be performed by the directory, + // TCC will perform the atomic on the return path on Event:Data. + // The action will invalidate the cache line if SLC is set and the address is + // in the cache. + if(in_msg.isSLCSet || !WB) { + trigger(Event:AtomicPassOn, in_msg.addr, cache_entry, tbe); + } else { + trigger(Event:Atomic, in_msg.addr, cache_entry, tbe); + } } } else if (in_msg.Type == CoherenceRequestType:RdBlk) { if (in_msg.isSLCSet) { @@ -433,24 +451,35 @@ machine(MachineType:TCC, "TCC Cache") out_msg.addr := address; out_msg.Type := CoherenceResponseType:TDSysResp; out_msg.Sender := machineID; - out_msg.Destination := tbe.Destination; - out_msg.DataBlk := cache_entry.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Data; out_msg.Dirty := false; out_msg.State := CoherenceState:Shared; - DPRINTF(RubySlicc, "%s\n", out_msg); peek(responseFromNB_in, ResponseMsg) { - out_msg.isGLCSet := tbe.isGLCSet; - out_msg.isSLCSet := tbe.isSLCSet; + // if line state is Invalid, then we must be doing the transition(I, Data) + // so use the DataBlk from the incoming message + if ((getAccessPermission(address) == AccessPermission:NotPresent) || + (getAccessPermission(address) == AccessPermission:Invalid)) { + out_msg.DataBlk := in_msg.DataBlk; + } else { + out_msg.DataBlk := cache_entry.DataBlk; + } + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; + // reuse CURequestor field to allow multiple concurrent loads and + // track where they should go back to (since TBE can't distinguish + // destinations) + out_msg.Destination.clear(); + out_msg.Destination.add(in_msg.CURequestor); } + DPRINTF(RubySlicc, "%s\n", out_msg); } enqueue(unblockToNB_out, UnblockMsg, 1) { out_msg.addr := address; out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); out_msg.MessageSize := MessageSizeType:Unblock_Control; peek(responseFromNB_in, ResponseMsg) { - out_msg.isGLCSet := tbe.isGLCSet; - out_msg.isSLCSet := tbe.isSLCSet; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } DPRINTF(RubySlicc, "%s\n", out_msg); } @@ -462,13 +491,17 @@ machine(MachineType:TCC, "TCC Cache") out_msg.addr := address; out_msg.Type := CoherenceResponseType:TDSysResp; out_msg.Sender := machineID; - out_msg.Destination := tbe.Destination; + // reuse CURequestor field to allow multiple concurrent loads and + // track where they should go back to (since TBE can't distinguish + // destinations) + out_msg.Destination.clear(); + out_msg.Destination.add(in_msg.CURequestor); out_msg.DataBlk := in_msg.DataBlk; out_msg.MessageSize := MessageSizeType:Response_Data; out_msg.Dirty := false; out_msg.State := CoherenceState:Shared; - out_msg.isGLCSet := tbe.isGLCSet; - out_msg.isSLCSet := tbe.isSLCSet; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; DPRINTF(RubySlicc, "%s\n", out_msg); } enqueue(unblockToNB_out, UnblockMsg, 1) { @@ -481,19 +514,25 @@ machine(MachineType:TCC, "TCC Cache") } action(rd_requestData, "r", desc="Miss in L2, pass on") { - if(tbe.Destination.count()==1){ - peek(coreRequestNetwork_in, CPURequestMsg) { - enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { - out_msg.addr := address; - out_msg.Type := in_msg.Type; - out_msg.Requestor := machineID; - out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); - out_msg.Shared := false; // unneeded for this request - out_msg.MessageSize := in_msg.MessageSize; - out_msg.isGLCSet := tbe.isGLCSet; - out_msg.isSLCSet := tbe.isSLCSet; - DPRINTF(RubySlicc, "%s\n", out_msg); - } + peek(coreRequestNetwork_in, CPURequestMsg) { + DPRINTF(RubySlicc, "in_msg: %s\n", in_msg); + enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { + out_msg.addr := address; + out_msg.Type := in_msg.Type; + out_msg.Requestor := machineID; + /* + To allow multiple concurrent requests from different CUs, we pass + the orgin information along to the directory, which stores it in its + TBE as appropriate before passing it back to the TCC on the return + path. + */ + out_msg.CURequestor := in_msg.Requestor; + out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); + out_msg.Shared := false; // unneeded for this request + out_msg.MessageSize := in_msg.MessageSize; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; + DPRINTF(RubySlicc, "out_msg: %s\n", out_msg); } } } @@ -504,7 +543,7 @@ machine(MachineType:TCC, "TCC Cache") out_msg.addr := address; out_msg.Type := CoherenceResponseType:TDSysWBAck; out_msg.Destination.clear(); - out_msg.Destination.add(in_msg.WTRequestor); + out_msg.Destination.add(in_msg.CURequestor); out_msg.Sender := machineID; out_msg.MessageSize := MessageSizeType:Writeback_Control; out_msg.instSeqNum := in_msg.instSeqNum; @@ -562,7 +601,7 @@ machine(MachineType:TCC, "TCC Cache") enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { out_msg.addr := address; out_msg.Type := CoherenceResponseType:TDSysResp; - out_msg.Destination.add(in_msg.WTRequestor); + out_msg.Destination.add(in_msg.CURequestor); out_msg.Sender := machineID; out_msg.MessageSize := in_msg.MessageSize; out_msg.DataBlk := cache_entry.DataBlk; @@ -578,12 +617,12 @@ machine(MachineType:TCC, "TCC Cache") enqueue(responseToCore_out, ResponseMsg, l2_response_latency) { out_msg.addr := address; out_msg.Type := CoherenceResponseType:TDSysResp; - out_msg.Destination.add(in_msg.WTRequestor); + out_msg.Destination.add(in_msg.CURequestor); out_msg.Sender := machineID; out_msg.MessageSize := in_msg.MessageSize; out_msg.DataBlk := in_msg.DataBlk; - out_msg.isGLCSet := tbe.isGLCSet; - out_msg.isSLCSet := tbe.isSLCSet; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } } } @@ -611,7 +650,10 @@ machine(MachineType:TCC, "TCC Cache") tbe.Destination.clear(); tbe.numPendingDirectoryAtomics := 0; tbe.atomicDoneCnt := 0; + tbe.numPending := 0; } + // each pending requests increments this count by 1 + tbe.numPending := tbe.numPending + 1; if (coreRequestNetwork_in.isReady(clockEdge())) { peek(coreRequestNetwork_in, CPURequestMsg) { if(in_msg.Type == CoherenceRequestType:RdBlk || @@ -620,6 +662,16 @@ machine(MachineType:TCC, "TCC Cache") in_msg.Type == CoherenceRequestType:AtomicNoReturn){ tbe.Destination.add(in_msg.Requestor); } + /* + If there are multiple concurrent requests to the same cache line, each + one will overwrite the previous ones GLC/SLC information here. + If these requests have different GLC/SLC information, this causes + a segfault. Hence, currently the support relies on the directory to + pass back the GLC/SLC information instead of relying on L2 TBE to be + correct. + + This message is left here as an FYI for future developers. + */ tbe.isGLCSet := in_msg.isGLCSet; tbe.isSLCSet := in_msg.isSLCSet; if(in_msg.Type == CoherenceRequestType:Atomic || @@ -633,9 +685,14 @@ machine(MachineType:TCC, "TCC Cache") } action(dt_deallocateTBE, "dt", desc="Deallocate TBE entry") { - tbe.Destination.clear(); - TBEs.deallocate(address); - unset_tbe(); + // since we may have multiple destinations, can't deallocate if we aren't + // last one + tbe.numPending := tbe.numPending - 1; + if (tbe.numPending == 0) { + tbe.Destination.clear(); + TBEs.deallocate(address); + unset_tbe(); + } } action(wcb_writeCacheBlock, "wcb", desc="write data to TCC") { @@ -672,7 +729,7 @@ machine(MachineType:TCC, "TCC Cache") enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { out_msg.addr := address; out_msg.Requestor := machineID; - out_msg.WTRequestor := in_msg.Requestor; + out_msg.CURequestor := in_msg.Requestor; out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); out_msg.MessageSize := MessageSizeType:Data; out_msg.Type := CoherenceRequestType:WriteThrough; @@ -680,6 +737,8 @@ machine(MachineType:TCC, "TCC Cache") out_msg.DataBlk := in_msg.DataBlk; out_msg.writeMask.orMask(in_msg.writeMask); out_msg.instSeqNum := in_msg.instSeqNum; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } } } @@ -688,7 +747,7 @@ machine(MachineType:TCC, "TCC Cache") enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { out_msg.addr := address; out_msg.Requestor := machineID; - out_msg.WTRequestor := machineID; + out_msg.CURequestor := machineID; out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); out_msg.MessageSize := MessageSizeType:Data; out_msg.Type := CoherenceRequestType:WriteThrough; @@ -703,13 +762,15 @@ machine(MachineType:TCC, "TCC Cache") enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { out_msg.addr := address; out_msg.Requestor := machineID; - out_msg.WTRequestor := in_msg.Requestor; + out_msg.CURequestor := in_msg.Requestor; out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); out_msg.MessageSize := MessageSizeType:Data; out_msg.Type := CoherenceRequestType:WriteFlush; out_msg.Dirty := true; out_msg.DataBlk := cache_entry.DataBlk; out_msg.writeMask.orMask(cache_entry.writeMask); + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } } } @@ -719,7 +780,7 @@ machine(MachineType:TCC, "TCC Cache") enqueue(requestToNB_out, CPURequestMsg, l2_request_latency) { out_msg.addr := address; out_msg.Requestor := machineID; - out_msg.WTRequestor := in_msg.Requestor; + out_msg.CURequestor := in_msg.Requestor; out_msg.Destination.add(mapAddressToMachine(address, MachineType:Directory)); out_msg.MessageSize := MessageSizeType:Data; out_msg.Type := in_msg.Type; @@ -768,9 +829,17 @@ machine(MachineType:TCC, "TCC Cache") wakeUpAllBuffers(address); } + /* + Currently z_stall is unused because it can lead to Protocol Stalls that + eventually lead to deadlock. Instead, it is recommended to use + st_stallAndWaitRequest in combination with a wakeupBuffer call (e.g., + wada_wakeUpAllDependentsAddr) to put the pending requests to sleep instead of + them causing head of line blocking -- wada_wakeUpAllDependentsAddr should wake + the request up once the request preventing it from completing is done. action(z_stall, "z", desc="stall") { // built-in } + */ action(inpa_incrementNumPendingDirectoryAtomics, "inpa", desc="inc num atomics") { @@ -792,8 +861,8 @@ machine(MachineType:TCC, "TCC Cache") out_msg.addr := address; out_msg.Type := TriggerType:AtomicDone; peek(responseFromNB_in, ResponseMsg) { - out_msg.isGLCSet := tbe.isGLCSet; - out_msg.isSLCSet := tbe.isSLCSet; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } } } @@ -832,31 +901,53 @@ machine(MachineType:TCC, "TCC Cache") // they can cause a resource stall deadlock! transition(WI, {RdBlk, WrVicBlk, Atomic, AtomicPassOn, WrVicBlkBack}) { //TagArrayRead} { - // by putting the stalled requests in a buffer, we reduce resource contention - // since they won't try again every cycle and will instead only try again once - // woken up + // don't profile as hit or miss since it will be tried again + /* + By putting the stalled requests in a buffer, we reduce resource contention + since they won't try again every cycle and will instead only try again once + woken up. + */ st_stallAndWaitRequest; } transition(WIB, {RdBlk, WrVicBlk, Atomic, WrVicBlkBack}) { //TagArrayRead} { - // by putting the stalled requests in a buffer, we reduce resource contention - // since they won't try again every cycle and will instead only try again once - // woken up + // don't profile as hit or miss since it will be tried again + /* + By putting the stalled requests in a buffer, we reduce resource contention + since they won't try again every cycle and will instead only try again once + woken up. + */ st_stallAndWaitRequest; } transition(A, {RdBlk, WrVicBlk, WrVicBlkBack}) { //TagArrayRead} { - // by putting the stalled requests in a buffer, we reduce resource contention - // since they won't try again every cycle and will instead only try again once - // woken up + // don't profile as hit or miss since it will be tried again + /* + By putting the stalled requests in a buffer, we reduce resource contention + since they won't try again every cycle and will instead only try again once + woken up. + */ st_stallAndWaitRequest; } transition(IV, {WrVicBlk, Atomic, AtomicPassOn, WrVicBlkBack}) { //TagArrayRead} { - // by putting the stalled requests in a buffer, we reduce resource contention - // since they won't try again every cycle and will instead only try again once - // woken up + // don't profile as hit or miss since it will be tried again + /* + By putting the stalled requests in a buffer, we reduce resource contention + since they won't try again every cycle and will instead only try again once + woken up. + */ st_stallAndWaitRequest; } + transition({I, IV, V}, AtomicWait) { + // don't profile as hit or miss since it will be tried again + /* + By putting the stalled requests in a buffer, we reduce resource contention + since they won't try again every cycle and will instead only try again once + woken up. + */ + st_stallAndWaitRequest; + } + transition({M, V}, RdBlk) {TagArrayRead, DataArrayRead} { p_profileHit; sd_sendData; @@ -865,12 +956,15 @@ machine(MachineType:TCC, "TCC Cache") } transition(W, RdBlk, WI) {TagArrayRead, DataArrayRead} { + // don't profile as hit or miss since it will be tried again t_allocateTBE; wb_writeBack; - // need to try this request again after writing back the current entry -- to - // do so, put it with other stalled requests in a buffer to reduce resource - // contention since they won't try again every cycle and will instead only - // try again once woken up + /* + Need to try this request again after writing back the current entry -- to + do so, put it with other stalled requests in a buffer to reduce resource + contention since they won't try again every cycle and will instead only + try again once woken up. + */ st_stallAndWaitRequest; } @@ -933,6 +1027,7 @@ machine(MachineType:TCC, "TCC Cache") // Transition to be called when a read request with SLC flag arrives at entry // in transient state. The request stalls until the pending transition is complete. transition({WI, WIB, IV}, RdBypassEvict) { + // don't profile as hit or miss since it will be tried again st_stallAndWaitRequest; } @@ -945,8 +1040,8 @@ machine(MachineType:TCC, "TCC Cache") p_popRequestQueue; } - transition(A, Atomic) { - p_profileMiss; + transition(A, {Atomic, AtomicWait}) { + // don't profile as hit or miss since it will be tried again // by putting the stalled requests in a buffer, we reduce resource contention // since they won't try again every cycle and will instead only try again once // woken up @@ -993,7 +1088,7 @@ machine(MachineType:TCC, "TCC Cache") } transition(A, AtomicPassOn) { - p_profileMiss; + // don't profile as hit or miss since it will be tried again // by putting the stalled requests in a buffer, we reduce resource contention // since they won't try again every cycle and will instead only try again once // woken up @@ -1136,9 +1231,41 @@ machine(MachineType:TCC, "TCC Cache") ut_updateTag; wcb_writeCacheBlock; sdr_sendDataResponse; - pr_popResponseQueue; wada_wakeUpAllDependentsAddr; dt_deallocateTBE; + pr_popResponseQueue; + } + + /* + Since the L2 now allows multiple loads from different CUs to proceed in + parallel to the directory, we may get Event:Data back when the line is + already in V. In this case, send the response to the appropriate TCP + and update MRU/data in TCC, but don't need to allocate line. + */ + transition(V, Data) {TagArrayRead, TagArrayWrite, DataArrayWrite} { + ut_updateTag; + wcb_writeCacheBlock; + sdr_sendDataResponse; + wada_wakeUpAllDependentsAddr; + // tracks # pending requests, so need to decrement here too + dt_deallocateTBE; + pr_popResponseQueue; + } + + /* + Since the L2 now allows multiple loads from different CUs to proceed in + parallel to the directory, we may get Event:Data back when the line is + now in I because it has been evicted by an intervening request to the same + set index. In this case, send the response to the appropriate TCP without + affecting the TCC (essentially, treat it similar to a bypass request except + we also send the unblock back to the directory). + */ + transition(I, Data) { + sdr_sendDataResponse; + wada_wakeUpAllDependentsAddr; + // tracks # pending requests, so need to decrement here too + dt_deallocateTBE; + pr_popResponseQueue; } transition(A, Data, M) {TagArrayRead, TagArrayWrite, DataArrayWrite, AtomicALUOperation} { diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm index ae35d4c5f7..97997a12b5 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCP.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCP.sm @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2015 Advanced Micro Devices, Inc. + * Copyright (c) 2023 Matthew D. Sinclair * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,10 +54,14 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") { state_declaration(State, desc="TCP Cache States", default="TCP_State_I") { I, AccessPermission:Invalid, desc="Invalid"; + // Note: currently IV in the TCP is only for pending loads to a given cache + // line. Since the TCP is write through, stores should be allowed to pass + // through without requiring them to wait. + IV, AccessPermission:Invalid, desc="Going from I to V, waiting on TCC data"; V, AccessPermission:Read_Only, desc="Valid"; A, AccessPermission:Invalid, desc="Waiting on Atomic"; - F, AccessPermission:Invalid, desc="Flushing; Waiting for Ack"; + F, AccessPermission:Invalid, desc="Flushing; Waiting for Ack"; } enumeration(Event, desc="TCP Events") { @@ -102,6 +107,8 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") bool Dirty, desc="Is the data dirty (different than memory)?"; int NumPendingMsgs,desc="Number of acks/data messages that this processor is waiting for"; bool Shared, desc="Victim hit by shared probe"; + bool isGLCSet, desc="Bypass L1 Cache"; + bool isSLCSet, desc="Bypass L1 and L2 Cache"; } structure(TBETable, external="yes") { @@ -123,6 +130,7 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") void unset_tbe(); void wakeUpAllBuffers(); void wakeUpBuffers(Addr a); + void wakeUpAllBuffers(Addr a); Cycles curCycle(); // Internal functions @@ -472,6 +480,15 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") check_allocate(TBEs); TBEs.allocate(address); set_tbe(TBEs.lookup(address)); + + // pass GLC/SLC information along + if (mandatoryQueue_in.isReady(clockEdge())) { + peek(mandatoryQueue_in, RubyRequest) { + DPRINTF(RubySlicc, "Address: %p\n", address); + tbe.isGLCSet := in_msg.isGLCSet; + tbe.isSLCSet := in_msg.isSLCSet; + } + } } action(d_deallocateTBE, "d", desc="Deallocate TBE") { @@ -510,6 +527,10 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") responseToTCP_in.dequeue(clockEdge()); } + action(st_stallAndWaitRequest, "st", desc="Stall and wait on the address") { + stall_and_wait(mandatoryQueue_in, address); + } + action(l_loadDoneHit, "ldh", desc="local load done (hits in TCP)") { assert(is_valid(cache_entry)); if (use_seq_not_coal) { @@ -528,6 +549,20 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") } } + action(ldmi_loadDoneMissInv, "ldmi", + desc="local load done (misses in TCP and line was evicted)") { + // since line was evicted, can't rely on data from cache entry, so use from + // the response message + peek(responseToTCP_in, ResponseMsg) { + DataBlock tmp:= in_msg.DataBlk; + if (use_seq_not_coal) { + sequencer.readCallback(address, tmp, false, MachineType:L1Cache); + } else { + coalescer.readCallback(address, MachineType:L1Cache, tmp); + } + } + } + action(ad_atomicDone, "ad", desc="atomic done") { assert(is_valid(cache_entry)); coalescer.atomicCallback(address, MachineType:L1Cache, cache_entry.DataBlk); @@ -604,6 +639,10 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") L1cache.setMRU(address); } + action(wada_wakeUpAllDependentsAddr, "wada", desc="Wake up any requests waiting for this address") { + wakeUpAllBuffers(address); + } + // action(zz_recycleMandatoryQueue, "\z", desc="recycle mandatory queue") { // mandatoryQueue_in.recycle(clockEdge(), cyclesToTicks(recycle_latency)); // } @@ -632,11 +671,19 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") // Stalling transitions do NOT check the tag array...and if they do, // they can cause a resource stall deadlock! - transition({A}, {Load, Atomic, StoreThrough}) { //TagArrayRead} { - z_stall; + // if another request arrives for the same cache line that has a pending + // atomic or load, put it on the wakeup buffer instead of z_stall'ing it. By + // doing so we reduce resource contention since they won't try again every cycle + // and will instead only try again once woken up + transition({A, IV}, {Load, LoadBypassEvict, Atomic, Store, StoreThrough, Flush}) { + st_stallAndWaitRequest; } - transition(I, Load) {TagArrayRead} { + // if we have a load that misses, allocate TBE entry and transition to IV + // to prevent subsequent requests to same cache line from also going to TCC + // while this request is pending + transition(I, Load, IV) {TagArrayRead} { + t_allocateTBE; n_issueRdBlk; uu_profileDataMiss; p_popMandatoryQueue; @@ -694,14 +741,38 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") p_popMandatoryQueue; } - transition(I, TCC_Ack, V) {TagArrayRead, TagArrayWrite, DataArrayRead, DataArrayWrite} { - a_allocate; - w_writeCache; - l_loadDoneMiss; + // if we got a response for a load where the line is in I, then + // another request must have come in that replaced the line in question in + // the cache. Thus, complete this request without allocating the line, but + // still deallocate TBE and wakeup any dependent addresses. + // (Note: this assumes TCC_AckWB is what stores use) + transition(I, TCC_Ack) {TagArrayRead, TagArrayWrite} { + wada_wakeUpAllDependentsAddr; + // NOTE: Because we invalidated the cache line, the assert in l_loadDoneMiss + // will fail -- unlike atomics that automatically go to I when the line returns + // loads do not automatically go to I. Resolve this by passing data from + // message. + ldmi_loadDoneMissInv; + d_deallocateTBE; pr_popResponseQueue; } - transition(I, Bypass, I) { + // if line is currently in IV, then TCC_Ack is returning the data for a + // pending load, so transition to V, deallocate TBE, and wakeup any dependent + // requests so they will be replayed now that this request has returned. + transition(IV, TCC_Ack, V) {TagArrayRead, TagArrayWrite, DataArrayRead, DataArrayWrite} { + a_allocate; + w_writeCache; + wada_wakeUpAllDependentsAddr; + l_loadDoneMiss; + d_deallocateTBE; + pr_popResponseQueue; + } + + // if a bypass request arrives back at the TCP, regardless of whether the line + // is in I (from the bypass request) or IV (from a subsequent non-bypassing + // load), retain the current state and complete the bypassing request. + transition({I, IV}, Bypass) { rb_bypassDone; pr_popResponseQueue; } @@ -713,12 +784,13 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") } transition(A, TCC_Ack, I) {TagArrayRead, DataArrayRead, DataArrayWrite} { - d_deallocateTBE; a_allocate; w_writeCache; ad_atomicDone; - pr_popResponseQueue; ic_invCache; + wada_wakeUpAllDependentsAddr; + d_deallocateTBE; + pr_popResponseQueue; } transition(V, TCC_Ack, V) {TagArrayRead, DataArrayRead, DataArrayWrite} { @@ -735,20 +807,22 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") ic_invCache; } + // if a line with a pending load gets evicted, transition the line to I and + // invalidate it. + transition(IV, Repl, I) {TagArrayRead, TagArrayWrite} { + ic_invCache; + } + transition({V,I}, Flush, F) {TagArrayFlash} { a_allocate; sf_setFlush; p_popMandatoryQueue; } - transition(A, Flush) { - z_stall; - } - transition({I, V}, Evict, I) {TagArrayFlash} { inv_invDone; - p_popMandatoryQueue; ic_invCache; + p_popMandatoryQueue; } transition(A, Evict) {TagArrayFlash} { @@ -756,8 +830,11 @@ machine(MachineType:TCP, "GPU TCP (L1 Data Cache)") p_popMandatoryQueue; } + // if a line is in IV and a TCC_AckWB comes back, we must have had a WT + // store followed by a load. Thus, complete the store without affecting + // TBE or line state. // TCC_AckWB only snoops TBE - transition({V, I, A}, TCC_AckWB) { + transition({V, I, IV, A}, TCC_AckWB) { wd_wtDone; pr_popResponseQueue; } diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index b9401d680a..c36fc9ec93 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -154,7 +154,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") bool Dirty, desc="Is the data dirty?"; int NumPendingAcks, desc="num acks expected"; MachineID OriginalRequestor, desc="Original Requestor"; - MachineID WTRequestor, desc="WT Requestor"; + MachineID CURequestor, desc="CU that initiated the request"; bool Cached, desc="data hit in Cache"; bool MemData, desc="Got MemData?",default="false"; bool wtData, desc="Got write through data?",default="false"; @@ -170,7 +170,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") uint64_t probe_id, desc="probe id for lifetime profiling"; WriteMask writeMask, desc="outstanding write through mask"; int Len, desc="Length of memory request for DMA"; - bool isSLCSet, desc="Bypass L1 and L2 Cache"; + // GLC is passed along because it is needed in the return path + bool isGLCSet, desc="Bypass GPU L1 Cache"; + bool isSLCSet, desc="Bypass GPU L1 and L2 Cache"; } structure(TBETable, external="yes") { @@ -470,6 +472,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.ForwardRequestTime := tbe.ForwardRequestTime; out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime; out_msg.OriginalResponder := tbe.LastSender; + out_msg.CURequestor := tbe.CURequestor; out_msg.L3Hit := tbe.L3Hit; DPRINTF(RubySlicc, "%s\n", out_msg); } @@ -498,6 +501,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime; out_msg.OriginalResponder := tbe.LastSender; out_msg.L3Hit := tbe.L3Hit; + out_msg.isGLCSet := tbe.isGLCSet; + out_msg.isSLCSet := tbe.isSLCSet; + out_msg.CURequestor := tbe.CURequestor; DPRINTF(RubySlicc, "%s\n", out_msg); } } @@ -527,9 +533,11 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.ForwardRequestTime := tbe.ForwardRequestTime; out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime; out_msg.OriginalResponder := tbe.LastSender; - if(tbe.atomicData){ - out_msg.WTRequestor := tbe.WTRequestor; - } + out_msg.isGLCSet := tbe.isGLCSet; + out_msg.isSLCSet := tbe.isSLCSet; + if(tbe.atomicData){ + out_msg.CURequestor := tbe.CURequestor; + } out_msg.L3Hit := tbe.L3Hit; DPRINTF(RubySlicc, "%s\n", out_msg); } @@ -555,6 +563,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.InitialRequestTime := tbe.InitialRequestTime; out_msg.ForwardRequestTime := curCycle(); out_msg.ProbeRequestStartTime := tbe.ProbeRequestStartTime; + out_msg.isGLCSet := tbe.isGLCSet; + out_msg.isSLCSet := tbe.isSLCSet; DPRINTF(RubySlicc, "%s\n", out_msg); } } @@ -565,13 +575,15 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.addr := address; out_msg.Type := CoherenceResponseType:NBSysWBAck; out_msg.Destination.add(in_msg.Requestor); - out_msg.WTRequestor := in_msg.WTRequestor; + out_msg.CURequestor := in_msg.CURequestor; out_msg.Sender := machineID; out_msg.MessageSize := MessageSizeType:Writeback_Control; out_msg.InitialRequestTime := in_msg.InitialRequestTime; out_msg.ForwardRequestTime := curCycle(); out_msg.ProbeRequestStartTime := curCycle(); out_msg.instSeqNum := in_msg.instSeqNum; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; } } } @@ -582,7 +594,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.addr := address; out_msg.Type := CoherenceResponseType:NBSysWBAck; out_msg.Destination.add(tbe.OriginalRequestor); - out_msg.WTRequestor := tbe.WTRequestor; + out_msg.CURequestor := tbe.CURequestor; out_msg.Sender := machineID; out_msg.MessageSize := MessageSizeType:Writeback_Control; out_msg.InitialRequestTime := tbe.InitialRequestTime; @@ -773,6 +785,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.MessageSize := MessageSizeType:Control; out_msg.Destination := probe_dests; tbe.NumPendingAcks := out_msg.Destination.count(); + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; DPRINTF(RubySlicc, "%s\n", out_msg); APPEND_TRANSITION_COMMENT(" dc: Acks remaining: "); APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks); @@ -877,6 +891,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.MessageSize := MessageSizeType:Control; out_msg.Destination := probe_dests; tbe.NumPendingAcks := out_msg.Destination.count(); + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; DPRINTF(RubySlicc, "%s\n", (out_msg)); APPEND_TRANSITION_COMMENT(" sc: Acks remaining: "); APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks); @@ -931,6 +947,8 @@ machine(MachineType:Directory, "AMD Baseline protocol") out_msg.ReturnData := false; out_msg.MessageSize := MessageSizeType:Control; out_msg.Destination := probe_dests; + out_msg.isGLCSet := in_msg.isGLCSet; + out_msg.isSLCSet := in_msg.isSLCSet; tbe.NumPendingAcks := out_msg.Destination.count(); APPEND_TRANSITION_COMMENT(" ic: Acks remaining: "); APPEND_TRANSITION_COMMENT(tbe.NumPendingAcks); @@ -1017,7 +1035,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.writeMask.clear(); tbe.writeMask.orMask(in_msg.writeMask); tbe.wtData := true; - tbe.WTRequestor := in_msg.WTRequestor; + tbe.CURequestor := in_msg.CURequestor; tbe.LastSender := in_msg.Requestor; } if (in_msg.Type == CoherenceRequestType:Atomic || @@ -1032,10 +1050,14 @@ machine(MachineType:Directory, "AMD Baseline protocol") assert(in_msg.Type == CoherenceRequestType:AtomicNoReturn); tbe.atomicDataNoReturn := true; } - tbe.WTRequestor := in_msg.WTRequestor; + tbe.CURequestor := in_msg.CURequestor; tbe.LastSender := in_msg.Requestor; tbe.isSLCSet := in_msg.isSLCSet; } + // GPU read requests also need to track where the requestor came from + if (in_msg.Type == CoherenceRequestType:RdBlk) { + tbe.CURequestor := in_msg.CURequestor; + } tbe.Dirty := false; if (in_msg.Type == CoherenceRequestType:WriteThrough) { tbe.DataBlk.copyPartial(in_msg.DataBlk,in_msg.writeMask); @@ -1045,6 +1067,9 @@ machine(MachineType:Directory, "AMD Baseline protocol") tbe.NumPendingAcks := 0; tbe.Cached := in_msg.ForceShared; tbe.InitialRequestTime := in_msg.InitialRequestTime; + tbe.isGLCSet := in_msg.isGLCSet; + tbe.isSLCSet := in_msg.isSLCSet; + DPRINTF(RubySlicc, "t_allocateTBE in_msg: %s, tbe: %s\n", in_msg, tbe.CURequestor); } } @@ -1277,11 +1302,20 @@ machine(MachineType:Directory, "AMD Baseline protocol") } action(wada_wakeUpAllDependentsAddr, "wada", desc="Wake up any requests waiting for this address") { + DPRINTF(RubySlicc, "wada wakeup: 0x%x\n", address); wakeUpAllBuffers(address); } + /* + Currently z_stall is unused because it can lead to Protocol Stalls that + eventually lead to deadlock. Instead, it is recommended to use + st_stallAndWaitRequest in combination with a wakeupBuffer call (e.g., + wada_wakeUpAllDependentsAddr) to put the pending requests to sleep instead of + them causing head of line blocking -- wada_wakeUpAllDependentsAddr should wake + the request up once the request preventing it from completing is done. action(z_stall, "z", desc="...") { } + */ // TRANSITIONS transition({BL, BDR_M, BDW_M, BS_M, BM_M, B_M, BP, BDR_PM, BDW_PM, BS_PM, BM_PM, B_PM, BDR_Pm, BDW_Pm, BS_Pm, BM_Pm, B_Pm, B}, {RdBlkS, RdBlkM, RdBlk, CtoD}) { @@ -1383,19 +1417,19 @@ machine(MachineType:Directory, "AMD Baseline protocol") d_writeDataToMemory; al_allocateL3Block; pr_profileL3HitMiss; //Must come after al_allocateL3Block and before dt_deallocateTBE - wad_wakeUpDependents; + wada_wakeUpAllDependentsAddr; dt_deallocateTBE; pr_popResponseQueue; } transition(BL, StaleWB, U) {L3TagArrayWrite} { dt_deallocateTBE; - wa_wakeUpAllDependents; + wada_wakeUpAllDependentsAddr; pr_popResponseQueue; } transition({B, BDR_M, BDW_M, BS_M, BM_M, B_M, BP, BDR_PM, BDW_PM, BS_PM, BM_PM, B_PM, BDR_Pm, BDW_Pm, BS_Pm, BM_Pm, B_Pm}, {VicDirty, VicClean}) { - z_stall; + st_stallAndWaitRequest; } transition({U, BL, BDR_M, BDW_M, BS_M, BM_M, B_M, BP, BDR_PM, BDW_PM, BS_PM, BM_PM, B_PM, BDR_Pm, BDW_Pm, BS_Pm, BM_Pm, B_Pm, B}, WBAck) { diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm index 984362da39..b860ff1681 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-msg.sm @@ -134,14 +134,14 @@ structure(CPURequestMsg, desc="...", interface="Message") { int Acks, default="0", desc="Acks that the dir (mem ctrl) should expect to receive"; CoherenceRequestType OriginalType, default="CoherenceRequestType_NA", desc="Type of request from core fwded through region buffer"; WriteMask writeMask, desc="Write Through Data"; - MachineID WTRequestor, desc="Node who initiated the write through"; + MachineID CURequestor, desc="Node who initiated the request"; int wfid, default="0", desc="wavefront id"; uint64_t instSeqNum, desc="instruction sequence number"; bool NoWriteConflict, default="true", desc="write collided with CAB entry"; int ProgramCounter, desc="PC that accesses to this block"; - bool isGLCSet, default="false", desc="GLC flag value in the request"; - bool isSLCSet, default="false", desc="SLC flag value in the request"; + bool isGLCSet, default="false", desc="GLC flag value in the request"; + bool isSLCSet, default="false", desc="SLC flag value in the request"; bool functionalRead(Packet *pkt) { // Only PUTX messages contains the data block @@ -170,6 +170,8 @@ structure(NBProbeRequestMsg, desc="...", interface="Message") { MachineID Requestor, desc="Requestor id for 3-hop requests"; bool NoAckNeeded, default="false", desc="For short circuting acks"; int ProgramCounter, desc="PC that accesses to this block"; + bool isGLCSet, default="false", desc="GLC flag value in the request"; + bool isSLCSet, default="false", desc="SLC flag value in the request"; bool functionalRead(Packet *pkt) { return false; @@ -240,7 +242,7 @@ structure(ResponseMsg, desc="...", interface="Message") { bool L3Hit, default="false", desc="Did memory or L3 supply the data?"; MachineID OriginalResponder, desc="Mach which wrote the data to the L3"; - MachineID WTRequestor, desc="Node who started the writethrough"; + MachineID CURequestor, desc="Node who started the access"; bool NotCached, default="false", desc="True when the Region buffer has already evicted the line"; diff --git a/src/mem/ruby/system/GPUCoalescer.cc b/src/mem/ruby/system/GPUCoalescer.cc index f9d071ba62..90d6031c6e 100644 --- a/src/mem/ruby/system/GPUCoalescer.cc +++ b/src/mem/ruby/system/GPUCoalescer.cc @@ -526,26 +526,16 @@ GPUCoalescer::readCallback(Addr address, fatal_if(crequest->getRubyType() != RubyRequestType_LD, "readCallback received non-read type response\n"); - // Iterate over the coalesced requests to respond to as many loads as - // possible until another request type is seen. Models MSHR for TCP. - while (crequest->getRubyType() == RubyRequestType_LD) { - hitCallback(crequest, mach, data, true, crequest->getIssueTime(), - forwardRequestTime, firstResponseTime, isRegion); - - delete crequest; - coalescedTable.at(address).pop_front(); - if (coalescedTable.at(address).empty()) { - break; - } - - crequest = coalescedTable.at(address).front(); - } + hitCallback(crequest, mach, data, true, crequest->getIssueTime(), + forwardRequestTime, firstResponseTime, isRegion); + delete crequest; + coalescedTable.at(address).pop_front(); if (coalescedTable.at(address).empty()) { - coalescedTable.erase(address); + coalescedTable.erase(address); } else { - auto nextRequest = coalescedTable.at(address).front(); - issueRequest(nextRequest); + auto nextRequest = coalescedTable.at(address).front(); + issueRequest(nextRequest); } } From ceabe86b311e3bdd7603b4e4631d2ed18365a5bd Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Thu, 16 Nov 2023 10:36:15 +0800 Subject: [PATCH 561/693] arch-riscv: Add overrides to RISC-V Interrupts class (#568) --- src/arch/riscv/interrupts.hh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/arch/riscv/interrupts.hh b/src/arch/riscv/interrupts.hh index a1ee396cd4..d6fa374a14 100644 --- a/src/arch/riscv/interrupts.hh +++ b/src/arch/riscv/interrupts.hh @@ -112,13 +112,13 @@ class Interrupts : public BaseInterrupts } bool checkInterrupt(int num) const { return ip[num] && ie[num]; } - bool checkInterrupts() const + bool checkInterrupts() const override { return checkNonMaskableInterrupt() || (ip & ie & globalMask()).any(); } Fault - getInterrupt() + getInterrupt() override { assert(checkInterrupts()); if (checkNonMaskableInterrupt()) @@ -135,10 +135,10 @@ class Interrupts : public BaseInterrupts return NoFault; } - void updateIntrInfo() {} + void updateIntrInfo() override {} void - post(int int_num, int index) + post(int int_num, int index) override { DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); if (int_num != INT_NMI) { @@ -149,7 +149,7 @@ class Interrupts : public BaseInterrupts } void - clear(int int_num, int index) + clear(int int_num, int index) override { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); if (int_num != INT_NMI) { @@ -163,7 +163,7 @@ class Interrupts : public BaseInterrupts void clearNMI() { tc->setMiscReg(MISCREG_NMIP, 0); } void - clearAll() + clearAll() override { DPRINTF(Interrupt, "All interrupts cleared\n"); ip = 0; @@ -176,7 +176,7 @@ class Interrupts : public BaseInterrupts void setIE(const uint64_t& val) { ie = val; } void - serialize(CheckpointOut &cp) const + serialize(CheckpointOut &cp) const override { unsigned long ip_ulong = ip.to_ulong(); unsigned long ie_ulong = ie.to_ulong(); @@ -185,7 +185,7 @@ class Interrupts : public BaseInterrupts } void - unserialize(CheckpointIn &cp) + unserialize(CheckpointIn &cp) override { unsigned long ip_ulong; unsigned long ie_ulong; From 2abd65c2707695dad735c4e383b1ce7c61158314 Mon Sep 17 00:00:00 2001 From: Nikolaos Kyparissas Date: Tue, 30 Aug 2022 17:04:21 +0100 Subject: [PATCH 562/693] mem: added distance parameter to stride prefetcher The Stride Prefetcher will skip this number of strides ahead of the first identified prefetch, then generate `degree` prefetches at `stride` intervals. A value of zero indicates no skip (i.e. start prefetching from the next identified prefetch address). This parameter can be used to increase the timeliness of prefetches by starting to prefetch far enough ahead of the demand stream to cover the memory system latency. [Richard Cooper : - Added detail to commit comment and `distance` Param documentation. - Changed `distance` Param from `Param.Int` to `Param.Unsigned`. ] Change-Id: I6c4e744079b53a7b804d8eab93b0f07b566f0c08 Reviewed-by: Giacomo Travaglini Signed-off-by: Richard Cooper --- src/mem/cache/prefetch/Prefetcher.py | 9 ++++++++- src/mem/cache/prefetch/stride.cc | 6 ++++-- src/mem/cache/prefetch/stride.hh | 4 +++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index ecc67f4857..c15ef6539c 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012, 2014, 2019 ARM Limited +# Copyright (c) 2012, 2014, 2019, 2022 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -192,6 +192,13 @@ class StridePrefetcher(QueuedPrefetcher): use_requestor_id = Param.Bool(True, "Use requestor id based history") degree = Param.Int(4, "Number of prefetches to generate") + distance = Param.Unsigned( + 0, + "How far ahead of the demand stream to start prefetching. " + "Skip this number of strides ahead of the first identified prefetch, " + "then generate `degree` prefetches at `stride` intervals. " + "A value of zero indicates no skip.", + ) table_assoc = Param.Int(4, "Associativity of the PC table") table_entries = Param.MemorySize("64", "Number of entries of the PC table") diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index 0a77b28a1c..d21fcd160c 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015 ARM Limited + * Copyright (c) 2012-2013, 2015, 2022 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -84,6 +84,7 @@ Stride::Stride(const StridePrefetcherParams &p) threshConf(p.confidence_threshold/100.0), useRequestorId(p.use_requestor_id), degree(p.degree), + distance(p.distance), pcTableInfo(p.table_assoc, p.table_entries, p.table_indexing_policy, p.table_replacement_policy) { @@ -175,7 +176,8 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi, prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; } - Addr new_addr = pf_addr + d * prefetch_stride; + Addr new_addr = pf_addr + distance * prefetch_stride + + d * prefetch_stride; addresses.push_back(AddrPriority(new_addr, 0)); } } else { diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index 7e55abea21..35ba4eed4e 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015 ARM Limited + * Copyright (c) 2012-2013, 2015, 2022 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -105,6 +105,8 @@ class Stride : public Queued const int degree; + const int distance; + /** * Information used to create a new PC table. All of them behave equally. */ From 047a494c2be9ef2b1a6d493d60a152e53ce92171 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 9 Nov 2023 16:57:01 +0000 Subject: [PATCH 563/693] mem-cache: Optimize strided prefetcher address generation This commit optimizes the address generation logic in the strided prefetcher by introducing the following changes (d is the degree of the prefetcher) * Evaluate the fixed prefetch_stride only once (and not d-times) * Replace 2d multiplications (d * prefetch_stride and distance * prefetch_stride) with additions by updating the new base prefetch address while looping Change-Id: I49c52333fc4c7071ac3d73443f2ae07bfcd5b8e4 Signed-off-by: Giacomo Travaglini Reviewed-by: Richard Cooper Reviewed-by: Tiberiu Bucur --- src/mem/cache/prefetch/stride.cc | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index d21fcd160c..4b709400c5 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015, 2022 Arm Limited + * Copyright (c) 2012-2013, 2015, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -168,17 +168,16 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi, return; } + // Round strides up to atleast 1 cacheline + int prefetch_stride = new_stride; + if (abs(new_stride) < blkSize) { + prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; + } + + Addr new_addr = pf_addr + distance * prefetch_stride; // Generate up to degree prefetches for (int d = 1; d <= degree; d++) { - // Round strides up to atleast 1 cacheline - int prefetch_stride = new_stride; - if (abs(new_stride) < blkSize) { - prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; - } - - Addr new_addr = pf_addr + distance * prefetch_stride - + d * prefetch_stride; - addresses.push_back(AddrPriority(new_addr, 0)); + addresses.push_back(AddrPriority(new_addr += prefetch_stride, 0)); } } else { // Miss in table From 94879c241084dde3a76ce9fcd8088a72375eab9a Mon Sep 17 00:00:00 2001 From: David Schall Date: Fri, 20 Oct 2023 07:49:19 +0000 Subject: [PATCH 564/693] cpu: Require BTB hit to detect branches. In a high performance CPU there is no other way than a BTB hit to know about a branch instruction and its type. For low-end CPU's pre-decoding might sit in from of the BPU to provide this information. Currently, the BPU models only low-end behavior and updates the RAS and the indirect branch prediction even without a BTB hit. This patch adds two things to model the correct behavior for high-end CPUs. 1. A check before the RAS and indirect predictor wheather there was a BTB hit or not. Only for BTB hits the BPU will consolidate RAS, and indirect predictor. 2. Since, this check requires a BTB hit for indirect branches they must also be installed into the BTB. For returns this was already done. Change-Id: Ibef9aa890f180efe547c82f41fc71f457c988a89 Signed-off-by: David Schall --- src/cpu/pred/BranchPredictor.py | 9 ++++++ src/cpu/pred/bpred_unit.cc | 54 +++++++++++++++++++++------------ src/cpu/pred/bpred_unit.hh | 8 +++++ 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index 8589fe5d51..d9289fa835 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -137,6 +137,15 @@ class BranchPredictor(SimObject): numThreads = Param.Unsigned(Parent.numThreads, "Number of threads") instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") + requiresBTBHit = Param.Bool( + False, + "Requires the BTB to hit for returns and indirect branches. For an" + "advanced front-end there is no other way than a BTB hit to know " + "that the branch exists in the first place. Furthermore, the BPU " + "needs to know the branch type to make the correct RAS operations. " + "This info is only available from the BTB. " + "Low-end CPUs predecoding might be used to identify branches. ", + ) btb = Param.BranchTargetBuffer(SimpleBTB(), "Branch target buffer (BTB)") ras = Param.ReturnAddrStack( diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index f705b93b71..c59a592980 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -58,6 +58,7 @@ namespace branch_prediction BPredUnit::BPredUnit(const Params ¶ms) : SimObject(params), numThreads(params.numThreads), + requiresBTBHit(params.requiresBTBHit), instShiftAmt(params.instShiftAmt), predHist(numThreads), btb(params.btb), @@ -169,7 +170,11 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, /* ----------------------------------------------- * Branch Target Buffer (BTB) * ----------------------------------------------- - * The BTB will be checked for all branches. + * First check for a BTB hit. This will be done + * regardless of whether the RAS or the indirect + * predictor provide the final target. That is + * necessary as modern front-end does not have a + * chance to detect a branch without a BTB hit. */ stats.BTBLookups++; const PCStateBase * btb_target = btb->lookup(tid, pc.instAddr(), brType); @@ -187,6 +192,13 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, tid, seqNum, hist->pc, (hist->btbHit) ? "hit" : "miss"); + // In a high performance CPU there is no other way than a BTB hit + // to know about a branch instruction. In that case consolidate + // indirect and RAS predictor only if there was a BTB it. + // For low end CPUs predecoding might be used to identify branches. + const bool branch_detected = (hist->btbHit || !requiresBTBHit); + + /* ----------------------------------------------- * Return Address Stack (RAS) * ----------------------------------------------- @@ -196,7 +208,7 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, * Return: pop the the return address from the * top of the RAS. */ - if (ras) { + if (ras && branch_detected) { if (inst->isCall()) { // In case of a call build the return address and // push it to the RAS. @@ -239,7 +251,7 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, * using the target from the BTB is the optimal * to save space in the indirect predictor itself. */ - if (iPred && hist->predTaken && + if (iPred && hist->predTaken && branch_detected && inst->isIndirectCtrl() && !inst->isReturn()) { ++stats.indirectLookups; @@ -362,7 +374,7 @@ BPredUnit::commitBranch(ThreadID tid, PredictorHistory* &hist) hist->inst, hist->target->instAddr()); - // Commite also Indirect predictor and RAS + // Commit also Indirect predictor and RAS if (iPred) { iPred->commit(tid, hist->seqNum, hist->indirectHistory); @@ -561,27 +573,29 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, } // Correct BTB --------------------------------------------------- - // Check if the misprediction happened was because of a BTB miss - // or incorrect indirect predictor - if (actually_taken) { - if (hist->inst->isIndirectCtrl() && !hist->inst->isReturn()) { - ++stats.indirectMispredicted; - } else { - - ++stats.BTBUpdates; - btb->update(tid, hist->pc, corr_target, - getBranchType(hist->inst)); + // Update the BTB for all mispredicted taken branches. + // Always if `requiresBTBHit` is true otherwise only if the + // branch was direct or no indirect predictor is available. + if (actually_taken && + (requiresBTBHit || hist->inst->isDirectCtrl() || + (!iPred && !hist->inst->isReturn()))) { + if (!hist->btbHit) { ++stats.BTBMispredicted; if (hist->condPred) ++stats.predTakenBTBMiss; - - btb->incorrectTarget(hist->pc, hist->type); - - DPRINTF(Branch,"[tid:%i] [squash sn:%llu] " - "BTB miss PC %#x %s \n", tid, squashed_sn, - hist->pc, toString(hist->type)); } + + DPRINTF(Branch,"[tid:%i] BTB Update called for [sn:%llu] " + "PC %#x -> T: %#x\n", tid, + hist->seqNum, hist->pc, hist->target->instAddr()); + + stats.BTBUpdates++; + btb->update(tid, hist->pc, + *hist->target, + hist->type, + hist->inst); + btb->incorrectTarget(hist->pc, hist->type); } } else { diff --git a/src/cpu/pred/bpred_unit.hh b/src/cpu/pred/bpred_unit.hh index 6aaec616c6..5a4faf1a1e 100644 --- a/src/cpu/pred/bpred_unit.hh +++ b/src/cpu/pred/bpred_unit.hh @@ -368,6 +368,14 @@ class BPredUnit : public SimObject /** Number of the threads for which the branch history is maintained. */ const unsigned numThreads; + /** Requires the BTB to hit for returns and indirect branches. For an + * advanced front-end there is no other way than a BTB hit to know + * that the branch exists in the first place. Furthermore, the BPU needs + * to know the branch type to make the correct RAS operations. + * This info is only available from the BTB. + * Low-end CPUs predecoding might be used to identify branches. */ + const bool requiresBTBHit; + /** Number of bits to shift instructions by for predictor addresses. */ const unsigned instShiftAmt; From 4ca2efac1668f9ccbdc852ef29d0f0049b63c626 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 16 Nov 2023 23:20:51 +0000 Subject: [PATCH 565/693] mem-ruby: AtomicNoReturn should check comp_anr instead of comp_wu (#545) The comp_anr parameter is currently unused. Both parameters (comp_wu and comp_anr) are set to false by default Change-Id: If09567504540dbee082191d46fcd53f1363d819f Signed-off-by: Giacomo Travaglini --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index ffa57cb03b..3dc70ceb26 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -1039,7 +1039,7 @@ action(Initiate_AtomicNoReturn_LocalWrite, desc="") { // no one will send us data unless we explicitly ask tbe.actions.push(Event:SendSnpUniqueRetToSrc); } - if (comp_wu) { + if (comp_anr) { tbe.actions.push(Event:SendDBIDResp_ANR); tbe.actions.pushNB(Event:WriteFEPipe); tbe.actions.pushNB(Event:SendComp_ANR); @@ -1072,7 +1072,7 @@ action(Initiate_AtomicNoReturn_Forward, desc="") { (tbe.dir_sharers.isElement(tbe.requestor))){ tbe.dir_sharers.remove(tbe.requestor); } - if (comp_wu) { + if (comp_anr) { tbe.actions.push(Event:SendAtomicNoReturn); tbe.actions.push(Event:SendDBIDResp_ANR); tbe.actions.pushNB(Event:SendComp_ANR); @@ -1103,7 +1103,7 @@ action(Initiate_AtomicReturn_Miss, desc="") { action(Initiate_AtomicNoReturn_Miss, desc="") { assert(is_HN); tbe.actions.push(Event:SendReadNoSnp); - if (comp_wu) { + if (comp_anr) { tbe.actions.push(Event:SendDBIDResp_ANR); tbe.actions.pushNB(Event:WriteFEPipe); tbe.actions.pushNB(Event:SendComp_ANR); From d19d6fc31ed2255d83fba42cbceb679c49fa5ac4 Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Thu, 16 Nov 2023 17:12:01 -0600 Subject: [PATCH 566/693] dev-amdgpu: Add PM4 queue ID to GPU used VMID map When restoring checkpoints for certain applications, gem5 tries to create new doorbells with a pre-existing queue ID and simulation crashes shortly after. This commit adds existing IDs to the GPU device's used VMID map so that new doorbells are aware of existing queue IDs and use a new ID. This ensures that queue IDs are unique after checkpoint restoration Change-Id: I9bf89a2769db26ceab4441634ff2da936eea6d6f --- src/dev/amdgpu/pm4_packet_processor.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dev/amdgpu/pm4_packet_processor.cc b/src/dev/amdgpu/pm4_packet_processor.cc index 352af400b0..1e889799ef 100644 --- a/src/dev/amdgpu/pm4_packet_processor.cc +++ b/src/dev/amdgpu/pm4_packet_processor.cc @@ -1197,6 +1197,8 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) PM4MapQueues* pkt = new PM4MapQueues; memset(pkt, 0, sizeof(PM4MapQueues)); newQueue(mqd, offset[i], pkt, id[i]); + PM4Queue *new_q = queuesMap[offset[i]]; + gpuDevice->insertQId(gpuDevice->lastVMID(), new_q->id()); if (ib[i]) { queues[id[i]]->wptr(ib_wptr[i]); From 3896673ddc943cdf2157651d090920da466bc6a7 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sat, 18 Nov 2023 18:13:06 -0800 Subject: [PATCH 567/693] util: Bump GPUFS build docker to 5.4.2 (#571) This dockerfile is used to *build* applications (e.g., from gem5-resources) which can be run using full system mode in a GPU build. The next releases disk image will use ROCm 5.4.2, therefore bump the version from 4.2 to that version. Again this is used to *build* input applications only and is not needed to run or compile gem5 with GPUFS. For example: $ docker build -t rocm54-build . /some/gem5-resources/src/gpu/lulesh$ docker run --rm -u $UID:$GID -v \ ${PWD}:${PWD} -w ${PWD} rocm54-build make Change-Id: If169c8d433afb3044f9b88e883ff3bb2f4bc70d2 --- util/dockerfiles/gpu-fs/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/dockerfiles/gpu-fs/Dockerfile b/util/dockerfiles/gpu-fs/Dockerfile index fb2465e50c..55f4de4aff 100644 --- a/util/dockerfiles/gpu-fs/Dockerfile +++ b/util/dockerfiles/gpu-fs/Dockerfile @@ -44,12 +44,12 @@ RUN apt -y install wget gnupg2 rpm # Get the radeon gpg key for apt repository RUN wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | apt-key add - -# Modify apt sources to pull from ROCm 4.2 repository only -RUN echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/4.2/ ubuntu main' | tee /etc/apt/sources.list.d/rocm.list +# Modify apt sources to pull from ROCm 5.4.2 repository only +RUN echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/5.4.2/ ubuntu main' | tee /etc/apt/sources.list.d/rocm.list RUN apt-get update RUN apt -y install libnuma-dev # Install the ROCm-dkms source RUN apt -y install initramfs-tools -RUN apt -y install rocm-dkms +RUN apt -y install rocm-dev From 08c0d1f27ae3a207bb209d93df7f34562cbfdda9 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 20 Nov 2023 16:04:13 -0800 Subject: [PATCH 568/693] dev: Fix `std::min` type mismatch in reg_bank.hh https://github.com/gem5/gem5/pull/386 included two cases in "src/dev/reg_bank.hh" where `std:: min` was used to compare a an integer of type `size_t` and another of type `Addr`. This cause an error on my Apple Silicon Mac as this is a comparison between an "unsigned long" and an "unsigned long long" which (at least on my setup) was not permitted. To fix this issue the `reg_size` was changed from `size_t` to `Addr`, as well as it the types of the values it was derived from and the variable used to hold the return from the `std::min` calls. Change-Id: I31e9c04a8e0327d4f6f5390bc5a743c629db4746 --- src/dev/reg_bank.hh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dev/reg_bank.hh b/src/dev/reg_bank.hh index c639a2d562..9f53c44e38 100644 --- a/src/dev/reg_bank.hh +++ b/src/dev/reg_bank.hh @@ -979,9 +979,9 @@ class RegisterBank : public RegisterBankBase std::ostringstream ss; while (done != bytes) { RegisterBase ® = it->second.get(); - const size_t reg_off = addr - it->first; - const size_t reg_size = reg.size() - reg_off; - const size_t reg_bytes = std::min(reg_size, bytes - done); + const Addr reg_off = addr - it->first; + const Addr reg_size = reg.size() - reg_off; + const Addr reg_bytes = std::min(reg_size, bytes - done); if (reg_bytes != reg.size()) { if (_debug_flag) { @@ -1025,9 +1025,9 @@ class RegisterBank : public RegisterBankBase std::ostringstream ss; while (done != bytes) { RegisterBase ® = it->second.get(); - const size_t reg_off = addr - it->first; - const size_t reg_size = reg.size() - reg_off; - const size_t reg_bytes = std::min(reg_size, bytes - done); + const Addr reg_off = addr - it->first; + const Addr reg_size = reg.size() - reg_off; + const Addr reg_bytes = std::min(reg_size, bytes - done); if (reg_bytes != reg.size()) { if (_debug_flag) { From 06161ded8c5d30f79bdd9d9a1ec33e445b3ae65b Mon Sep 17 00:00:00 2001 From: Vishnu Ramadas Date: Thu, 16 Nov 2023 17:12:01 -0600 Subject: [PATCH 569/693] dev-amdgpu: Add VMID map to checkpoint When restoring checkpoints for certain applications, gem5 tries to create new doorbells with a pre-existing queue ID and simulation crashes shortly after. This commit checkpoints the existing VMID map so that any new doorbells after restoration use a unique queue ID Change-Id: I9bf89a2769db26ceab4441634ff2da936eea6d6f --- src/dev/amdgpu/amdgpu_device.cc | 61 ++++++++++++++++++++++++++ src/dev/amdgpu/pm4_packet_processor.cc | 2 - 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/dev/amdgpu/amdgpu_device.cc b/src/dev/amdgpu/amdgpu_device.cc index b25ffbf79f..48f450c2b2 100644 --- a/src/dev/amdgpu/amdgpu_device.cc +++ b/src/dev/amdgpu/amdgpu_device.cc @@ -678,10 +678,13 @@ AMDGPUDevice::serialize(CheckpointOut &cp) const uint64_t regs_size = regs.size(); uint64_t doorbells_size = doorbells.size(); uint64_t sdma_engs_size = sdmaEngs.size(); + uint64_t used_vmid_map_size = usedVMIDs.size(); SERIALIZE_SCALAR(regs_size); SERIALIZE_SCALAR(doorbells_size); SERIALIZE_SCALAR(sdma_engs_size); + // Save the number of vmids used + SERIALIZE_SCALAR(used_vmid_map_size); // Make a c-style array of the regs to serialize uint32_t reg_addrs[regs_size]; @@ -690,6 +693,9 @@ AMDGPUDevice::serialize(CheckpointOut &cp) const QueueType doorbells_queues[doorbells_size]; uint32_t sdma_engs_offset[sdma_engs_size]; int sdma_engs[sdma_engs_size]; + int used_vmids[used_vmid_map_size]; + int used_queue_id_sizes[used_vmid_map_size]; + std::vector used_vmid_sets; int idx = 0; for (auto & it : regs) { @@ -712,6 +718,20 @@ AMDGPUDevice::serialize(CheckpointOut &cp) const ++idx; } + idx = 0; + for (auto & it : usedVMIDs) { + used_vmids[idx] = it.first; + used_queue_id_sizes[idx] = it.second.size(); + std::vector set_vector(it.second.begin(), it.second.end()); + used_vmid_sets.insert(used_vmid_sets.end(), + set_vector.begin(), set_vector.end()); + ++idx; + } + + int num_queue_id = used_vmid_sets.size(); + int* vmid_array = new int[num_queue_id]; + std::copy(used_vmid_sets.begin(), used_vmid_sets.end(), vmid_array); + SERIALIZE_ARRAY(reg_addrs, sizeof(reg_addrs)/sizeof(reg_addrs[0])); SERIALIZE_ARRAY(reg_values, sizeof(reg_values)/sizeof(reg_values[0])); SERIALIZE_ARRAY(doorbells_offset, sizeof(doorbells_offset)/ @@ -721,10 +741,21 @@ AMDGPUDevice::serialize(CheckpointOut &cp) const SERIALIZE_ARRAY(sdma_engs_offset, sizeof(sdma_engs_offset)/ sizeof(sdma_engs_offset[0])); SERIALIZE_ARRAY(sdma_engs, sizeof(sdma_engs)/sizeof(sdma_engs[0])); + // Save the vmids used in an array + SERIALIZE_ARRAY(used_vmids, sizeof(used_vmids)/sizeof(used_vmids[0])); + // Save the size of the set of queue ids mapped to each vmid + SERIALIZE_ARRAY(used_queue_id_sizes, + sizeof(used_queue_id_sizes)/sizeof(used_queue_id_sizes[0])); + // Save all the queue ids used for all the vmids + SERIALIZE_ARRAY(vmid_array, num_queue_id); + // Save the total number of queue idsused + SERIALIZE_SCALAR(num_queue_id); // Serialize the device memory deviceMem.serializeSection(cp, "deviceMem"); gpuvm.serializeSection(cp, "GPUVM"); + + delete[] vmid_array; } void @@ -736,10 +767,13 @@ AMDGPUDevice::unserialize(CheckpointIn &cp) uint64_t regs_size = 0; uint64_t doorbells_size = 0; uint64_t sdma_engs_size = 0; + uint64_t used_vmid_map_size = 0; UNSERIALIZE_SCALAR(regs_size); UNSERIALIZE_SCALAR(doorbells_size); UNSERIALIZE_SCALAR(sdma_engs_size); + UNSERIALIZE_SCALAR(used_vmid_map_size); + if (regs_size > 0) { uint32_t reg_addrs[regs_size]; @@ -786,6 +820,33 @@ AMDGPUDevice::unserialize(CheckpointIn &cp) } } + if (used_vmid_map_size > 0) { + int used_vmids[used_vmid_map_size]; + int used_queue_id_sizes[used_vmid_map_size]; + int num_queue_id = 0; + std::vector used_vmid_sets; + // Extract the total number of queue ids used + UNSERIALIZE_SCALAR(num_queue_id); + int* vmid_array = new int[num_queue_id]; + // Extract the number of vmids used + UNSERIALIZE_ARRAY(used_vmids, used_vmid_map_size); + // Extract the size of the queue id set for each vmid + UNSERIALIZE_ARRAY(used_queue_id_sizes, used_vmid_map_size); + // Extract all the queue ids used + UNSERIALIZE_ARRAY(vmid_array, num_queue_id); + // Populate the usedVMIDs map with the queue ids per vm + int idx = 0; + for (int it = 0; it < used_vmid_map_size; it++) { + int vmid = used_vmids[it]; + int vmid_set_size = used_queue_id_sizes[it]; + for (int j = 0; j < vmid_set_size; j++) { + usedVMIDs[vmid].insert(vmid_array[idx + j]); + } + idx += vmid_set_size; + } + delete[] vmid_array; + } + // Unserialize the device memory deviceMem.unserializeSection(cp, "deviceMem"); gpuvm.unserializeSection(cp, "GPUVM"); diff --git a/src/dev/amdgpu/pm4_packet_processor.cc b/src/dev/amdgpu/pm4_packet_processor.cc index 1e889799ef..352af400b0 100644 --- a/src/dev/amdgpu/pm4_packet_processor.cc +++ b/src/dev/amdgpu/pm4_packet_processor.cc @@ -1197,8 +1197,6 @@ PM4PacketProcessor::unserialize(CheckpointIn &cp) PM4MapQueues* pkt = new PM4MapQueues; memset(pkt, 0, sizeof(PM4MapQueues)); newQueue(mqd, offset[i], pkt, id[i]); - PM4Queue *new_q = queuesMap[offset[i]]; - gpuDevice->insertQId(gpuDevice->lastVMID(), new_q->id()); if (ib[i]) { queues[id[i]]->wptr(ib_wptr[i]); From f26867a0758d1ec80d1916459e3f9bfeea44754f Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 20 Nov 2023 15:36:03 -0800 Subject: [PATCH 570/693] mem-cache: Revert "Prefetchers Improvements" Reverts PR https://github.com/gem5/gem5/pull/564 Reverts commits: * 047a494c2be9ef2b1a6d493d60a152e53ce92171 * 2abd65c2707695dad735c4e383b1ce7c61158314 * 38045d7a252c46f5f57692e5eff5b18dd4fd2547 * 6416304e07a6bcbcf338d20f8852923f050afa70 * 8598764a0345ec4326061d94f917597b65e25c8f Change-Id: Id523acc1778c3f827637302a6465f5a9e539d6b5 --- src/mem/cache/Cache.py | 4 ++-- src/mem/cache/prefetch/Prefetcher.py | 9 +-------- src/mem/cache/prefetch/base.cc | 3 +-- src/mem/cache/prefetch/queued.cc | 4 ++-- src/mem/cache/prefetch/stride.cc | 19 +++++++++---------- src/mem/cache/prefetch/stride.hh | 4 +--- 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py index 501bb92682..d853a08cd9 100644 --- a/src/mem/cache/Cache.py +++ b/src/mem/cache/Cache.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2013, 2015, 2018, 2022 Arm Limited +# Copyright (c) 2012-2013, 2015, 2018 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -112,7 +112,7 @@ class BaseCache(ClockedObject): "Notify the hardware prefetcher on every access (not just misses)", ) prefetch_on_pf_hit = Param.Bool( - True, "Notify the hardware prefetcher on hit on prefetched lines" + False, "Notify the hardware prefetcher on hit on prefetched lines" ) tags = Param.BaseTags(BaseSetAssoc(), "Tag store") diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index c15ef6539c..ecc67f4857 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012, 2014, 2019, 2022 Arm Limited +# Copyright (c) 2012, 2014, 2019 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -192,13 +192,6 @@ class StridePrefetcher(QueuedPrefetcher): use_requestor_id = Param.Bool(True, "Use requestor id based history") degree = Param.Int(4, "Number of prefetches to generate") - distance = Param.Unsigned( - 0, - "How far ahead of the demand stream to start prefetching. " - "Skip this number of strides ahead of the first identified prefetch, " - "then generate `degree` prefetches at `stride` intervals. " - "A value of zero indicates no skip.", - ) table_assoc = Param.Int(4, "Associativity of the PC table") table_entries = Param.MemorySize("64", "Number of entries of the PC table") diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index 25c37df323..e3e4b24cf2 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2022 Arm Limited + * Copyright (c) 2013-2014 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -245,7 +245,6 @@ Base::probeNotify(const PacketPtr &pkt, bool miss) // operations or for writes that we are coaslescing. if (pkt->cmd.isSWPrefetch()) return; if (pkt->req->isCacheMaintenance()) return; - if (pkt->isCleanEviction()) return; if (pkt->isWrite() && cache != nullptr && cache->coalesce()) return; if (!pkt->req->hasPaddr()) { panic("Request must have a physical address"); diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index c67c315dad..1ab34d2e9b 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, 2022 Arm Limited + * Copyright (c) 2014-2015 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -178,7 +178,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi) if (queueSquash) { auto itr = pfq.begin(); while (itr != pfq.end()) { - if (blockAddress(itr->pfInfo.getAddr()) == blk_addr && + if (itr->pfInfo.getAddr() == blk_addr && itr->pfInfo.isSecure() == is_secure) { DPRINTF(HWPrefetch, "Removing pf candidate addr: %#x " "(cl: %#x), demand request going to the same addr\n", diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index 4b709400c5..0a77b28a1c 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015, 2022-2023 Arm Limited + * Copyright (c) 2012-2013, 2015 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -84,7 +84,6 @@ Stride::Stride(const StridePrefetcherParams &p) threshConf(p.confidence_threshold/100.0), useRequestorId(p.use_requestor_id), degree(p.degree), - distance(p.distance), pcTableInfo(p.table_assoc, p.table_entries, p.table_indexing_policy, p.table_replacement_policy) { @@ -168,16 +167,16 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi, return; } - // Round strides up to atleast 1 cacheline - int prefetch_stride = new_stride; - if (abs(new_stride) < blkSize) { - prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; - } - - Addr new_addr = pf_addr + distance * prefetch_stride; // Generate up to degree prefetches for (int d = 1; d <= degree; d++) { - addresses.push_back(AddrPriority(new_addr += prefetch_stride, 0)); + // Round strides up to atleast 1 cacheline + int prefetch_stride = new_stride; + if (abs(new_stride) < blkSize) { + prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; + } + + Addr new_addr = pf_addr + d * prefetch_stride; + addresses.push_back(AddrPriority(new_addr, 0)); } } else { // Miss in table diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index 35ba4eed4e..7e55abea21 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015, 2022 Arm Limited + * Copyright (c) 2012-2013, 2015 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -105,8 +105,6 @@ class Stride : public Queued const int degree; - const int distance; - /** * Information used to create a new PC table. All of them behave equally. */ From 3009e0fb5713a28a6b3a50983edc348dcdd03167 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Mon, 20 Nov 2023 21:38:13 -0800 Subject: [PATCH 571/693] mem-ruby: Fix typo in CHI's Send_CompI (#579) The destination for the response is set twice. --- src/mem/ruby/protocol/chi/CHI-cache-actions.sm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 3dc70ceb26..ca7b3e203a 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -2949,7 +2949,6 @@ action(Send_CompI, desc="") { out_msg.type := CHIResponseType:Comp_I; out_msg.responder := machineID; out_msg.Destination.add(tbe.requestor); - out_msg.Destination.add(tbe.requestor); out_msg.txnId := tbe.txnId; out_msg.dbid := tbe.txnId; } From 90b711e879f2031502102a3ed87beebaefa25731 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 13 Oct 2023 12:19:07 +0100 Subject: [PATCH 572/693] arch-arm: Define an ISR type register Change-Id: I358050a507fb76654e87165720dfb3b2ea6ca838 Signed-off-by: Giacomo Travaglini --- src/arch/arm/interrupts.hh | 2 +- src/arch/arm/regs/misc_types.hh | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index c2a2d13a8d..25799a66ee 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -203,7 +203,7 @@ class Interrupts : public BaseInterrupts getISR(HCR hcr, CPSR cpsr, SCR scr) { bool useHcrMux; - CPSR isr = 0; // ARM ARM states ISR reg uses same bit possitions as CPSR + ISR isr = 0; useHcrMux = (cpsr.mode != MODE_HYP) && !isSecure(tc); isr.i = (useHcrMux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi) diff --git a/src/arch/arm/regs/misc_types.hh b/src/arch/arm/regs/misc_types.hh index 0e6bdc8fe3..3bc06ac97c 100644 --- a/src/arch/arm/regs/misc_types.hh +++ b/src/arch/arm/regs/misc_types.hh @@ -75,6 +75,12 @@ namespace ArmISA Bitfield<0> sp; // AArch64 EndBitUnion(CPSR) + BitUnion32(ISR) + Bitfield<8> a; + Bitfield<7> i; + Bitfield<6> f; + EndBitUnion(ISR) + BitUnion32(ISAR5) Bitfield<31, 28> vcma; Bitfield<27, 24> rdm; From 3d4133936665df7465936225165e07df7d7c83c0 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 16 Oct 2023 17:16:40 +0100 Subject: [PATCH 573/693] arch-arm: Fix ISR_EL1 register read in secure mode Vitual interrupts are enabled in secure mode as well after the introduction of FEAT_SEL2. Replacing the secure mode check with the EL2Enabled one Change-Id: Id685a05d5adfa87b2a366f6be42bf344168927d4 Signed-off-by: Giacomo Travaglini --- src/arch/arm/interrupts.hh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index 25799a66ee..436b064eb7 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013, 2016 ARM Limited + * Copyright (c) 2010, 2012-2013, 2016, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -202,15 +202,14 @@ class Interrupts : public BaseInterrupts uint32_t getISR(HCR hcr, CPSR cpsr, SCR scr) { - bool useHcrMux; + bool use_hcr_mux = currEL(cpsr) < EL2 && EL2Enabled(tc); ISR isr = 0; - useHcrMux = (cpsr.mode != MODE_HYP) && !isSecure(tc); - isr.i = (useHcrMux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi) - : interrupts[INT_IRQ]; - isr.f = (useHcrMux & hcr.fmo) ? (interrupts[INT_VIRT_FIQ] || hcr.vf) - : interrupts[INT_FIQ]; - isr.a = (useHcrMux & hcr.amo) ? hcr.va : interrupts[INT_ABT]; + isr.i = (use_hcr_mux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi) + : interrupts[INT_IRQ]; + isr.f = (use_hcr_mux & hcr.fmo) ? (interrupts[INT_VIRT_FIQ] || hcr.vf) + : interrupts[INT_FIQ]; + isr.a = (use_hcr_mux & hcr.amo) ? hcr.va : interrupts[INT_ABT]; return isr; } From bb323923f259323321545fc5716a00be5e9b6480 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 17 Oct 2023 10:52:21 +0100 Subject: [PATCH 574/693] arch-arm: Simplify get/checkInterrupts with takeVirtualInt With this patch we align virtual interrupts with respect to the physical ones by introducing a matching takeVirtualInt method. Change-Id: Ib7835a21b85e4330ba9f051bc8fed691d6e1382e Signed-off-by: Giacomo Travaglini --- src/arch/arm/interrupts.cc | 43 +++++++++++++++++++++++ src/arch/arm/interrupts.hh | 72 ++++++++++---------------------------- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/arch/arm/interrupts.cc b/src/arch/arm/interrupts.cc index c2f1009147..1d1dc327fd 100644 --- a/src/arch/arm/interrupts.cc +++ b/src/arch/arm/interrupts.cc @@ -285,4 +285,47 @@ ArmISA::Interrupts::takeInt(InterruptTypes int_type) const } +bool +ArmISA::Interrupts::takeVirtualInt(InterruptTypes int_type) const +{ + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + + bool no_vhe = !HaveExt(tc, ArmExtension::FEAT_VHE); + bool amo, fmo, imo; + bool cpsr_mask_bit, hcr_mask_override_bit; + + if (hcr.tge == 1){ + amo = (no_vhe || hcr.e2h == 0); + fmo = (no_vhe || hcr.e2h == 0); + imo = (no_vhe || hcr.e2h == 0); + } else { + amo = hcr.amo; + fmo = hcr.fmo; + imo = hcr.imo; + } + + bool is_hyp_mode = currEL(tc) == EL2; + bool is_secure = ArmISA::isSecure(tc); + + switch(int_type) { + case INT_VIRT_FIQ: + cpsr_mask_bit = cpsr.f; + hcr_mask_override_bit = fmo; + break; + case INT_VIRT_IRQ: + cpsr_mask_bit = cpsr.i; + hcr_mask_override_bit = imo; + break; + case INT_VIRT_ABT: + cpsr_mask_bit = cpsr.a; + hcr_mask_override_bit = amo; + break; + default: + panic("Unhandled interrupt type!"); + } + return !cpsr_mask_bit && hcr_mask_override_bit && + !is_secure && !is_hyp_mode; +} + } // namespace gem5 diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index 436b064eb7..71325bee63 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -65,7 +65,11 @@ enum InterruptTypes INT_SEV, // Special interrupt for recieving SEV's INT_VIRT_IRQ, INT_VIRT_FIQ, - NumInterruptTypes + NumInterruptTypes, + // Cannot be raised by an external signal + // (for now) from the IC so we don't instantiate a + // interrupt entry in the state array + INT_VIRT_ABT }; class Interrupts : public BaseInterrupts @@ -132,6 +136,8 @@ class Interrupts : public BaseInterrupts bool takeInt32(InterruptTypes int_type) const; bool takeInt64(InterruptTypes int_type) const; + bool takeVirtualInt(InterruptTypes int_type) const; + bool checkInterrupts() const override { @@ -140,40 +146,19 @@ class Interrupts : public BaseInterrupts if (!(intStatus || hcr.va || hcr.vi || hcr.vf)) return false; - CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); - - bool no_vhe = !HaveExt(tc, ArmExtension::FEAT_VHE); - bool amo, fmo, imo; - if (hcr.tge == 1){ - amo = (no_vhe || hcr.e2h == 0); - fmo = (no_vhe || hcr.e2h == 0); - imo = (no_vhe || hcr.e2h == 0); - } else { - amo = hcr.amo; - fmo = hcr.fmo; - imo = hcr.imo; - } - - bool isHypMode = currEL(tc) == EL2; - bool isSecure = ArmISA::isSecure(tc); - bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode; - bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode; - bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode; - - if ( !(intStatus || (hcr.vi && allowVIrq) || (hcr.vf && allowVFiq) || - (hcr.va && allowVAbort)) ) - return false; - bool take_irq = takeInt(INT_IRQ); bool take_fiq = takeInt(INT_FIQ); bool take_ea = takeInt(INT_ABT); + bool take_virq = takeVirtualInt(INT_VIRT_IRQ); + bool take_vfiq = takeVirtualInt(INT_VIRT_FIQ); + bool take_vabt = takeVirtualInt(INT_VIRT_ABT); return ((interrupts[INT_IRQ] && take_irq) || (interrupts[INT_FIQ] && take_fiq) || (interrupts[INT_ABT] && take_ea) || - ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq) || - ((interrupts[INT_VIRT_FIQ] || hcr.vf) && allowVFiq) || - (hcr.va && allowVAbort) || + ((interrupts[INT_VIRT_IRQ] || hcr.vi) && take_virq) || + ((interrupts[INT_VIRT_FIQ] || hcr.vf) && take_vfiq) || + (hcr.va && take_vabt) || (interrupts[INT_RST]) || (interrupts[INT_SEV]) ); @@ -238,44 +223,25 @@ class Interrupts : public BaseInterrupts assert(checkInterrupts()); HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); - CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); - - bool no_vhe = !HaveExt(tc, ArmExtension::FEAT_VHE); - bool amo, fmo, imo; - if (hcr.tge == 1){ - amo = (no_vhe || hcr.e2h == 0); - fmo = (no_vhe || hcr.e2h == 0); - imo = (no_vhe || hcr.e2h == 0); - } else { - amo = hcr.amo; - fmo = hcr.fmo; - imo = hcr.imo; - } - - // Calculate a few temp vars so we can work out if there's a pending - // virtual interrupt, and if its allowed to happen - // ARM ARM Issue C section B1.9.9, B1.9.11, and B1.9.13 - bool isHypMode = currEL(tc) == EL2; - bool isSecure = ArmISA::isSecure(tc); - bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode; - bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode; - bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode; bool take_irq = takeInt(INT_IRQ); bool take_fiq = takeInt(INT_FIQ); bool take_ea = takeInt(INT_ABT); + bool take_virq = takeVirtualInt(INT_VIRT_IRQ); + bool take_vfiq = takeVirtualInt(INT_VIRT_FIQ); + bool take_vabt = takeVirtualInt(INT_VIRT_ABT); if (interrupts[INT_IRQ] && take_irq) return std::make_shared(); - if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq) + if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && take_virq) return std::make_shared(); if (interrupts[INT_FIQ] && take_fiq) return std::make_shared(); - if ((interrupts[INT_VIRT_FIQ] || hcr.vf) && allowVFiq) + if ((interrupts[INT_VIRT_FIQ] || hcr.vf) && take_vfiq) return std::make_shared(); if (interrupts[INT_ABT] && take_ea) return std::make_shared(); - if (hcr.va && allowVAbort) + if (hcr.va && take_vabt) return std::make_shared( 0, TlbEntry::DomainType::NoAccess, false, ArmFault::AsynchronousExternalAbort); From 49d07578de18e26ac7a49da05189ce54026caafe Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 17 Oct 2023 10:59:54 +0100 Subject: [PATCH 575/693] arch-arm: Call take(Virtual)Int only when needed There is no need to call the methods for every kind of interrupt. A pending one should short-circuit the remaining checks Change-Id: I2c9eb680a7baa4644745b8cbe48183ff6f8e3102 Signed-off-by: Giacomo Travaglini --- src/arch/arm/interrupts.hh | 44 +++++++++++++++----------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index 71325bee63..df6ffaa30c 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -146,20 +146,15 @@ class Interrupts : public BaseInterrupts if (!(intStatus || hcr.va || hcr.vi || hcr.vf)) return false; - bool take_irq = takeInt(INT_IRQ); - bool take_fiq = takeInt(INT_FIQ); - bool take_ea = takeInt(INT_ABT); - bool take_virq = takeVirtualInt(INT_VIRT_IRQ); - bool take_vfiq = takeVirtualInt(INT_VIRT_FIQ); - bool take_vabt = takeVirtualInt(INT_VIRT_ABT); - - return ((interrupts[INT_IRQ] && take_irq) || - (interrupts[INT_FIQ] && take_fiq) || - (interrupts[INT_ABT] && take_ea) || - ((interrupts[INT_VIRT_IRQ] || hcr.vi) && take_virq) || - ((interrupts[INT_VIRT_FIQ] || hcr.vf) && take_vfiq) || - (hcr.va && take_vabt) || - (interrupts[INT_RST]) || + return ((interrupts[INT_IRQ] && takeInt(INT_IRQ)) || + (interrupts[INT_FIQ] && takeInt(INT_FIQ)) || + (interrupts[INT_ABT] && takeInt(INT_ABT)) || + ((interrupts[INT_VIRT_IRQ] || hcr.vi) && + takeVirtualInt(INT_VIRT_IRQ)) || + ((interrupts[INT_VIRT_FIQ] || hcr.vf) && + takeVirtualInt(INT_VIRT_FIQ)) || + (hcr.va && takeVirtualInt(INT_VIRT_ABT)) || + (interrupts[INT_RST]) || (interrupts[INT_SEV]) ); } @@ -224,24 +219,19 @@ class Interrupts : public BaseInterrupts HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); - bool take_irq = takeInt(INT_IRQ); - bool take_fiq = takeInt(INT_FIQ); - bool take_ea = takeInt(INT_ABT); - bool take_virq = takeVirtualInt(INT_VIRT_IRQ); - bool take_vfiq = takeVirtualInt(INT_VIRT_FIQ); - bool take_vabt = takeVirtualInt(INT_VIRT_ABT); - - if (interrupts[INT_IRQ] && take_irq) + if (interrupts[INT_IRQ] && takeInt(INT_IRQ)) return std::make_shared(); - if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && take_virq) + if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && + takeVirtualInt(INT_VIRT_IRQ)) return std::make_shared(); - if (interrupts[INT_FIQ] && take_fiq) + if (interrupts[INT_FIQ] && takeInt(INT_FIQ)) return std::make_shared(); - if ((interrupts[INT_VIRT_FIQ] || hcr.vf) && take_vfiq) + if ((interrupts[INT_VIRT_FIQ] || hcr.vf) && + takeVirtualInt(INT_VIRT_FIQ)) return std::make_shared(); - if (interrupts[INT_ABT] && take_ea) + if (interrupts[INT_ABT] && takeInt(INT_ABT)) return std::make_shared(); - if (hcr.va && take_vabt) + if (hcr.va && takeVirtualInt(INT_VIRT_ABT)) return std::make_shared( 0, TlbEntry::DomainType::NoAccess, false, ArmFault::AsynchronousExternalAbort); From b8fabc15d99d5058171554eaf4283edc491f79c0 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 17 Oct 2023 11:29:57 +0100 Subject: [PATCH 576/693] arch-arm: Revamp takeVirtualInt to take FEAT_SEL2 into account Similarly to the physical version [1], we rewrite the masking logic to account for FEAT_SEL2. The interrupt table is taken from the Arm architecture reference manual (version DDI 0487H.a, section D1.3.6, table R_BKHXL) [1]: https://github.com/gem5/gem5/pull/430 Change-Id: Icb6eb1944d8241293b3ef3c349b20f3981bcc558 Signed-off-by: Giacomo Travaglini --- src/arch/arm/interrupts.cc | 81 ++++++++++++++++++++++++++++++++++++++ src/arch/arm/interrupts.hh | 2 + 2 files changed, 83 insertions(+) diff --git a/src/arch/arm/interrupts.cc b/src/arch/arm/interrupts.cc index 1d1dc327fd..8e8ee39da4 100644 --- a/src/arch/arm/interrupts.cc +++ b/src/arch/arm/interrupts.cc @@ -287,6 +287,14 @@ ArmISA::Interrupts::takeInt(InterruptTypes int_type) const bool ArmISA::Interrupts::takeVirtualInt(InterruptTypes int_type) const +{ + return ArmSystem::highestELIs64(tc) ? takeVirtualInt64(int_type) : + takeVirtualInt32(int_type); + +} + +bool +ArmISA::Interrupts::takeVirtualInt32(InterruptTypes int_type) const { CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); @@ -328,4 +336,77 @@ ArmISA::Interrupts::takeVirtualInt(InterruptTypes int_type) const !is_secure && !is_hyp_mode; } +bool +ArmISA::Interrupts::takeVirtualInt64(InterruptTypes int_type) const +{ + InterruptMask mask; + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + SCR scr = tc->readMiscReg(MISCREG_SCR_EL3); + + ExceptionLevel el = currEL(tc); + bool cpsr_mask_bit, hcr_mask_override_bit; + bool is_secure = ArmISA::isSecureBelowEL3(tc); + + switch(int_type) { + case INT_VIRT_FIQ: + cpsr_mask_bit = cpsr.f; + hcr_mask_override_bit = hcr.fmo; + break; + case INT_VIRT_IRQ: + cpsr_mask_bit = cpsr.i; + hcr_mask_override_bit = hcr.imo; + break; + case INT_VIRT_ABT: + cpsr_mask_bit = cpsr.a; + hcr_mask_override_bit = hcr.amo; + break; + default: + panic("Unhandled interrupt type!"); + } + + if (is_secure) { + if (!scr.eel2) { + // NS=0,EEL2=0 + mask = INT_MASK_P; + } else { + if (!hcr.tge) { + if (!hcr_mask_override_bit) { + // NS=0,EEL2=1,TGE=0,AMO/IMO/FMO=0 + mask = INT_MASK_P; + } else { + // NS=0,EEL2=1,TGE=0,AMO/IMO/FMO=1 + if (el == EL2 || el == EL3) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } + } else { + // NS=0,EEL2=1,TGE=1 + mask = INT_MASK_P; + } + } + } else { + if (!hcr.tge) { + if (!hcr_mask_override_bit) { + // NS=1,TGE=0,AMO/IMO/FMO=0 + mask = INT_MASK_P; + } else { + // NS=1,TGE=0,AMO/IMO/FMO=1 + if (el == EL2 || el == EL3) + mask = INT_MASK_P; + else + mask = INT_MASK_M; + } + } else { + // NS=1,TGE=1 + mask = INT_MASK_P; + } + } + + return ((mask == INT_MASK_T) || + ((mask == INT_MASK_M) && !cpsr_mask_bit)) && + (mask != INT_MASK_P); +} + } // namespace gem5 diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index df6ffaa30c..da2a17206c 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -137,6 +137,8 @@ class Interrupts : public BaseInterrupts bool takeInt64(InterruptTypes int_type) const; bool takeVirtualInt(InterruptTypes int_type) const; + bool takeVirtualInt32(InterruptTypes int_type) const; + bool takeVirtualInt64(InterruptTypes int_type) const; bool checkInterrupts() const override From 098feb40427f3f3755b504fa4740219ba4743cc3 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 17 Oct 2023 15:54:49 +0100 Subject: [PATCH 577/693] arch-arm: Fix WFI sleeping in secure mode The CPU should not sleep with a pending virtual interrupt if secure mode EL2 is supported (FEAT_SEL2) Change-Id: Ib71c4a09d76a790331cf6750da45f83694946aee Signed-off-by: Giacomo Travaglini --- src/arch/arm/interrupts.hh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/arch/arm/interrupts.hh b/src/arch/arm/interrupts.hh index da2a17206c..bddb932323 100644 --- a/src/arch/arm/interrupts.hh +++ b/src/arch/arm/interrupts.hh @@ -169,16 +169,16 @@ class Interrupts : public BaseInterrupts bool checkWfiWake(HCR hcr, CPSR cpsr, SCR scr) const { - uint64_t maskedIntStatus; - bool virtWake; + uint64_t masked_int_status; + bool virt_wake; - maskedIntStatus = intStatus & ~((1 << INT_VIRT_IRQ) | - (1 << INT_VIRT_FIQ)); - virtWake = (hcr.vi || interrupts[INT_VIRT_IRQ]) && hcr.imo; - virtWake |= (hcr.vf || interrupts[INT_VIRT_FIQ]) && hcr.fmo; - virtWake |= hcr.va && hcr.amo; - virtWake &= (cpsr.mode != MODE_HYP) && !isSecure(tc); - return maskedIntStatus || virtWake; + masked_int_status = intStatus & ~((1 << INT_VIRT_IRQ) | + (1 << INT_VIRT_FIQ)); + virt_wake = (hcr.vi || interrupts[INT_VIRT_IRQ]) && hcr.imo; + virt_wake |= (hcr.vf || interrupts[INT_VIRT_FIQ]) && hcr.fmo; + virt_wake |= hcr.va && hcr.amo; + virt_wake &= currEL(cpsr) < EL2 && EL2Enabled(tc); + return masked_int_status || virt_wake; } uint32_t From 368fcdde75252db5c79c6bc97a0360f4b150dc82 Mon Sep 17 00:00:00 2001 From: Aditya K Kamath Date: Wed, 22 Nov 2023 20:09:45 +0000 Subject: [PATCH 578/693] arch-x86: Fixes page fault for CLFLUSH on write-protected pages Converts CLFLUSHOPT/WB/FLUSH operations from Write to Read operations during address translation so that they don't trigger a page fault when done on write-protected pages. --- src/arch/x86/tlb.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 5ccd3e832d..c7d144bd8a 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -509,6 +509,9 @@ TLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) { bool delayedResponse; + // CLFLUSHOPT/WB/FLUSH should be treated as read for protection checks + if (req->isCacheClean()) + mode = BaseMMU::Read; return TLB::translate(req, tc, NULL, mode, delayedResponse, false); } @@ -516,6 +519,9 @@ Fault TLB::translateFunctional(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) { + // CLFLUSHOPT/WB/FLUSH should be treated as read for protection checks + if (req->isCacheClean()) + mode = BaseMMU::Read; unsigned logBytes; const Addr vaddr = req->getVaddr(); Addr addr = vaddr; @@ -553,6 +559,9 @@ TLB::translateTiming(const RequestPtr &req, ThreadContext *tc, { bool delayedResponse; assert(translation); + // CLFLUSHOPT/WB/FLUSH should be treated as read for protection checks + if (req->isCacheClean()) + mode = BaseMMU::Read; Fault fault = TLB::translate(req, tc, translation, mode, delayedResponse, true); if (!delayedResponse) From 6e433ed8851ba40ae29071bef1aeece5615f5322 Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Wed, 22 Nov 2023 14:05:43 -0800 Subject: [PATCH 579/693] mem-ruby: Fixes for new AtomicWait event in VIPER TCC (#585) The AtomicWait event was not being woken up properly due to the numPending count in the TBE not being decremented. This patch decrements the count when Data is returned. Since that moves to a base state, the TBE should no longer be needed. Additionally added a transition which stalls and wait when an AtomicWait occurs while in WI state so that it retries. Change-Id: Ic8bfc700f9df3f95bea0799121898926a23d8163 --- src/mem/ruby/protocol/GPU_VIPER-TCC.sm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm index 14c9c8c1cc..e599d2f937 100644 --- a/src/mem/ruby/protocol/GPU_VIPER-TCC.sm +++ b/src/mem/ruby/protocol/GPU_VIPER-TCC.sm @@ -938,7 +938,7 @@ machine(MachineType:TCC, "TCC Cache") st_stallAndWaitRequest; } - transition({I, IV, V}, AtomicWait) { + transition({I, IV, V, WI}, AtomicWait) { // don't profile as hit or miss since it will be tried again /* By putting the stalled requests in a buffer, we reduce resource contention @@ -1273,6 +1273,7 @@ machine(MachineType:TCC, "TCC Cache") wardb_writeAtomicResponseDirtyBytes; pa_performAtomic; baplr_sendBypassedAtomicPerformedLocallyResponse; + dt_deallocateTBE; pr_popResponseQueue; } From 5f73a9bbf08751ca04b6486ecae0ccf138d97c78 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 8 Feb 2022 18:39:27 -0800 Subject: [PATCH 580/693] scons: Use either the "build" or "gem5.build" as build anchor. If gem5.build already exists within a directory, then that build directory can be used without having to worry about variants. If it doesn't exist and we find a build/${VARIANT} style path, then we use that as the anchor. In either case, the variant name is the final component of the build path. The parse_build_path function had been separating that out, but it was just put back onto the path again anyway by the only caller, and then split out again when that path was consumed. We save a step by not splitting it out in parse_build_path. Change-Id: I8705b3dbb7664748f5525869cb188df70319d403 --- SConstruct | 26 ++++--------------------- site_scons/gem5_scons/__init__.py | 32 +++++++++++++++++-------------- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/SConstruct b/SConstruct index e7fa4b53b7..69c941a078 100755 --- a/SConstruct +++ b/SConstruct @@ -240,27 +240,9 @@ def makePathListAbsolute(path_list, root=GetLaunchDir()): # doesn't work (obviously!). BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS) -# Generate a list of the unique build roots and configs that the -# collected targets reference. -variant_paths = set() -build_root = None -for t in BUILD_TARGETS: - this_build_root, variant = parse_build_path(t) - - # Make sure all targets use the same build root. - if not build_root: - build_root = this_build_root - elif this_build_root != build_root: - error("build targets not under same build root\n %s\n %s" % - (build_root, this_build_root)) - - # Collect all the variants into a set. - variant_paths.add(os.path.join('/', build_root, variant)) - -# Make sure build_root exists (might not if this is the first build there) -if not isdir(build_root): - mkdir(build_root) -main['BUILDROOT'] = build_root +# Generate a list of the unique build directories that the collected targets +# reference. +variant_paths = set(map(parse_build_path, BUILD_TARGETS)) ######################################################################## @@ -395,7 +377,7 @@ for variant_path in variant_paths: env = main.Clone() env['BUILDDIR'] = variant_path - gem5_build = os.path.join(build_root, variant_path, 'gem5.build') + gem5_build = os.path.join(variant_path, 'gem5.build') env['GEM5BUILD'] = gem5_build Execute(Mkdir(gem5_build)) diff --git a/site_scons/gem5_scons/__init__.py b/site_scons/gem5_scons/__init__.py index c93a5e29e0..3638d9c561 100644 --- a/site_scons/gem5_scons/__init__.py +++ b/site_scons/gem5_scons/__init__.py @@ -39,6 +39,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os +import os.path import pickle import sys import tempfile @@ -56,7 +57,7 @@ termcap = get_termcap() def strip_build_path(path, env): path = str(path) build_base = "build/" - variant_base = env["BUILDROOT"] + os.path.sep + variant_base = os.path.dirname(env["BUILDDIR"]) + os.path.sep if path.startswith(variant_base): path = path[len(variant_base) :] elif path.startswith(build_base): @@ -117,7 +118,7 @@ class Transform: source = source[0 : self.max_sources] def strip(f): - return strip_build_path(str(f), env) + return strip_build_path(f, env) if len(source) > 0: srcs = list(map(strip, source)) @@ -255,18 +256,21 @@ def error(*args, **kwargs): def parse_build_path(target): path_dirs = target.split("/") - # Pop off the target file. - path_dirs.pop() - - # Search backwards for the "build" directory. Whatever was just before it - # was the name of the variant. - variant_dir = path_dirs.pop() - while path_dirs and path_dirs[-1] != "build": - variant_dir = path_dirs.pop() - if not path_dirs: - error("No non-leaf 'build' dir found on target path.", target) - - return os.path.join("/", *path_dirs), variant_dir + # Search backwards for a directory with a gem5.build sub-directory, or a + # directory who's parent is called "build". gem5.build identifies an + # existing gem5 build directory. A directory called "build" is an anchor + # for a legacy "build/${VARIANT}/${TARGET}" style build path, where the + # variant selects a default config to use. + while path_dirs: + dot_gem5 = os.path.join("/", *path_dirs, "gem5.build") + if ( + os.path.isdir(dot_gem5) + or len(path_dirs) > 1 + and path_dirs[-2] == "build" + ): + return os.path.join("/", *path_dirs) + path_dirs.pop() + error(f"No existing build directory and no variant for {target}") # The MakeAction wrapper, and a SCons tool to set up the *COMSTR variables. From db3a6e8e84cede09d305fc2d1fc54470bb19ed21 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 16 Feb 2022 04:54:22 -0800 Subject: [PATCH 581/693] scons: Use Kconfig to configure gem5. These are not yet consumed by anything, but convert all the settings from SCons variables to Kconfig variables. If you have existing SConsopts files which need to be converted, you should take a look at KCONFIG.md to learn about how kconfig is used in gem5. You should decide if any variables need to be available to C++ or kconfig itself, and whether those are options which should be detected automatically, or should be up to the user. Options which should be measured automatically should still be in SConsopts files, while user facing options should be added to new or existing Kconfig files. Generally, make sure you're storing c++/kconfig visible options in env['CONF'][...]. Also remove references to sticky_vars since persistent options should now be handled with kconfig, and export_vars since everything in env['CONF'] is now exported automatically. Switch SCons/gem5 to use Kconfig for configuration, except EXTRAS which is still a sticky SCons variable. This is necessary because EXTRAS also controls what config options exist. If it came from Kconfig itself, then there would be a circular dependency. This dependency could theoretically be handled by reparsing the Kconfig when EXTRAS directories were added or removed, but that would be complicated, and isn't supported by kconfiglib. It wouldn't be worth the significant effort it would take to add it, just to use Kconfig more purely. Change-Id: I29ab1940b2d7b0e6635a490452d05befe5b4a2c9 --- SConsopts | 53 -------- SConstruct | 105 +++++----------- build_opts/ALL | 15 +-- build_opts/ARM | 5 +- build_opts/ARM_MESI_Three_Level | 8 +- build_opts/ARM_MESI_Three_Level_HTM | 8 +- build_opts/ARM_MOESI_hammer | 8 +- build_opts/GCN3_X86 | 9 +- build_opts/Garnet_standalone | 5 +- build_opts/MIPS | 5 +- build_opts/NULL | 5 +- build_opts/NULL_MESI_Two_Level | 5 +- build_opts/NULL_MOESI_CMP_directory | 5 +- build_opts/NULL_MOESI_CMP_token | 5 +- build_opts/NULL_MOESI_hammer | 5 +- build_opts/POWER | 5 +- build_opts/RISCV | 5 +- build_opts/SPARC | 5 +- build_opts/VEGA_X86 | 9 +- build_opts/X86 | 7 +- build_opts/X86_MESI_Two_Level | 7 +- build_opts/X86_MI_example | 5 +- build_opts/X86_MOESI_AMD_Base | 5 +- site_scons/gem5_scons/kconfig.py | 116 ++++++++++++++++++ src/Kconfig | 53 ++++++++ src/arch/Kconfig | 37 ++++++ src/arch/{power/SConsopts => amdgpu/Kconfig} | 13 +- src/arch/amdgpu/gcn3/Kconfig | 33 +++++ src/arch/amdgpu/vega/Kconfig | 33 +++++ src/arch/{x86/SConsopts => arm/Kconfig} | 8 +- src/arch/arm/SConscript | 4 +- src/arch/arm/fastmodel/Kconfig | 60 +++++++++ src/arch/arm/fastmodel/SConscript | 4 + src/arch/arm/fastmodel/SConsopts | 27 ++-- src/arch/{arm/SConsopts => mips/Kconfig} | 6 +- src/arch/mips/SConscript | 2 +- src/arch/null/{SConsopts => Kconfig} | 6 +- src/arch/{mips/SConsopts => power/Kconfig} | 6 +- src/arch/power/SConscript | 2 +- src/arch/riscv/Kconfig | 27 ++++ src/arch/riscv/SConscript | 2 +- src/arch/riscv/SConsopts | 28 ----- src/arch/sparc/Kconfig | 27 ++++ src/arch/sparc/SConscript | 2 +- src/arch/sparc/SConsopts | 28 ----- src/arch/x86/Kconfig | 27 ++++ src/arch/x86/SConscript | 2 +- src/{arch/SConsopts => base/Kconfig} | 28 +++-- src/base/SConsopts | 3 - src/base/stats/Kconfig | 27 ++++ src/cpu/kvm/Kconfig | 34 +++++ src/cpu/kvm/SConsopts | 12 +- src/cpu/testers/directedtest/SConscript | 2 +- .../garnet_synthetic_traffic/SConscript | 2 +- src/cpu/testers/gpu_ruby_test/SConscript | 2 +- src/cpu/testers/rubytest/SConscript | 2 +- src/dev/net/Kconfig | 27 ++++ src/gpu-compute/Kconfig | 28 +++++ .../SConsopts => learning_gem5/part3/Kconfig} | 11 +- src/learning_gem5/part3/SConsopts | 3 - src/mem/ruby/Kconfig | 50 ++++++++ src/mem/ruby/SConscript | 4 +- src/mem/ruby/SConsopts | 10 +- src/mem/ruby/common/SConscript | 2 +- src/mem/ruby/network/SConscript | 2 +- src/mem/ruby/network/fault_model/SConscript | 2 +- src/mem/ruby/network/garnet/SConscript | 2 +- src/mem/ruby/network/simple/SConscript | 2 +- src/mem/ruby/profiler/SConscript | 2 +- src/mem/ruby/protocol/Kconfig | 62 ++++++++++ src/mem/ruby/protocol/SConscript | 2 +- src/mem/ruby/protocol/SConsopts | 17 --- src/mem/ruby/protocol/chi/Kconfig | 35 ++++++ src/mem/ruby/protocol/chi/SConsopts | 7 -- src/mem/ruby/slicc_interface/SConscript | 2 +- src/mem/ruby/structures/SConscript | 4 +- src/mem/ruby/system/SConscript | 4 +- src/proto/Kconfig | 27 ++++ src/systemc/Kconfig | 28 +++++ src/systemc/SConsopts | 3 - 80 files changed, 925 insertions(+), 370 deletions(-) delete mode 100644 SConsopts create mode 100644 site_scons/gem5_scons/kconfig.py create mode 100644 src/Kconfig create mode 100644 src/arch/Kconfig rename src/arch/{power/SConsopts => amdgpu/Kconfig} (90%) create mode 100644 src/arch/amdgpu/gcn3/Kconfig create mode 100644 src/arch/amdgpu/vega/Kconfig rename src/arch/{x86/SConsopts => arm/Kconfig} (92%) create mode 100644 src/arch/arm/fastmodel/Kconfig rename src/arch/{arm/SConsopts => mips/Kconfig} (92%) rename src/arch/null/{SConsopts => Kconfig} (92%) rename src/arch/{mips/SConsopts => power/Kconfig} (92%) create mode 100644 src/arch/riscv/Kconfig delete mode 100644 src/arch/riscv/SConsopts create mode 100644 src/arch/sparc/Kconfig delete mode 100644 src/arch/sparc/SConsopts create mode 100644 src/arch/x86/Kconfig rename src/{arch/SConsopts => base/Kconfig} (78%) create mode 100644 src/base/stats/Kconfig create mode 100644 src/cpu/kvm/Kconfig create mode 100644 src/dev/net/Kconfig create mode 100644 src/gpu-compute/Kconfig rename src/{gpu-compute/SConsopts => learning_gem5/part3/Kconfig} (89%) create mode 100644 src/mem/ruby/Kconfig create mode 100644 src/mem/ruby/protocol/Kconfig create mode 100644 src/mem/ruby/protocol/chi/Kconfig create mode 100644 src/proto/Kconfig create mode 100644 src/systemc/Kconfig diff --git a/SConsopts b/SConsopts deleted file mode 100644 index bb2de864b5..0000000000 --- a/SConsopts +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2013, 2015-2020 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) 2011 Advanced Micro Devices, Inc. -# Copyright (c) 2009 The Hewlett-Packard Development Company -# Copyright (c) 2004-2005 The Regents of The University of Michigan -# 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. - -import os -import os.path - -from gem5_scons import warning - -Import('*') - -sticky_vars.AddVariables( - ('BATCH', 'Use batch pool for build and tests', False), - ('BATCH_CMD', 'Batch pool submission command name', 'qdo'), - ('M5_BUILD_CACHE', 'Cache built objects in this directory', False), - ('USE_EFENCE', 'Link with Electric Fence malloc debugger', False), - ) diff --git a/SConstruct b/SConstruct index 69c941a078..405adbc080 100755 --- a/SConstruct +++ b/SConstruct @@ -77,6 +77,7 @@ # Global Python imports import atexit +import itertools import os import sys @@ -115,8 +116,6 @@ AddOption('--no-colors', dest='use_colors', action='store_false', help="Don't add color to abbreviated scons output") AddOption('--with-cxx-config', action='store_true', help="Build with support for C++-based configuration") -AddOption('--default', - help='Override which build_opts file to use for defaults') AddOption('--ignore-style', action='store_true', help='Disable style checking hooks') AddOption('--linker', action='store', default=None, choices=linker_options, @@ -162,6 +161,7 @@ sys.path[1:1] = [ Dir('#build_tools').abspath ] # declared above. from gem5_scons import error, warning, summarize_warnings, parse_build_path from gem5_scons import TempFileSpawn, EnvDefaults, MakeAction, MakeActionTool +from gem5_scons import kconfig import gem5_scons from gem5_scons.builders import ConfigFile, AddLocalRPATH, SwitchingHeaders from gem5_scons.builders import Blob @@ -215,13 +215,6 @@ Default(environ.get('M5_DEFAULT_BINARY', 'build/ARM/gem5.debug')) # ######################################################################## -# helper function: find last occurrence of element in list -def rfind(l, elt, offs = -1): - for i in range(len(l)+offs, 0, -1): - if l[i] == elt: - return i - raise ValueError("element not found") - # Take a list of paths (or SCons Nodes) and return a list with all # paths made absolute and ~-expanded. Paths will be interpreted # relative to the launch directory unless a different root is provided @@ -381,6 +374,10 @@ for variant_path in variant_paths: env['GEM5BUILD'] = gem5_build Execute(Mkdir(gem5_build)) + config_file = Dir(gem5_build).File('config') + kconfig_file = Dir(gem5_build).File('Kconfig') + gem5_kconfig_file = Dir('#src').File('Kconfig') + env.SConsignFile(os.path.join(gem5_build, 'sconsign')) # Set up default C++ compiler flags @@ -662,59 +659,13 @@ for variant_path in variant_paths: after_sconsopts_callbacks.append(cb) Export('AfterSConsopts') - # Sticky variables get saved in the variables file so they persist from - # one invocation to the next (unless overridden, in which case the new - # value becomes sticky). - sticky_vars = Variables(args=ARGUMENTS) - Export('sticky_vars') + extras_file = os.path.join(gem5_build, 'extras') + extras_var = Variables(extras_file, args=ARGUMENTS) - # EXTRAS is special since it affects what SConsopts need to be read. - sticky_vars.Add(('EXTRAS', 'Add extra directories to the compilation', '')) - - # Set env variables according to the build directory config. - sticky_vars.files = [] - # Variables for $BUILD_ROOT/$VARIANT_DIR are stored in - # $BUILD_ROOT/$VARIANT_DIR/gem5.build/variables - - gem5_build_vars = os.path.join(gem5_build, 'variables') - build_root_vars = os.path.join(build_root, 'variables', variant_dir) - current_vars_files = [gem5_build_vars, build_root_vars] - existing_vars_files = list(filter(isfile, current_vars_files)) - if existing_vars_files: - sticky_vars.files.extend(existing_vars_files) - if not GetOption('silent'): - print('Using saved variables file(s) %s' % - ', '.join(existing_vars_files)) - else: - # Variant specific variables file doesn't exist. - - # Get default build variables from source tree. Variables are - # normally determined by name of $VARIANT_DIR, but can be - # overridden by '--default=' arg on command line. - default = GetOption('default') - opts_dir = Dir('#build_opts').abspath - if default: - default_vars_files = [ - gem5_build_vars, - build_root_vars, - os.path.join(opts_dir, default) - ] - else: - default_vars_files = [os.path.join(opts_dir, variant_dir)] - existing_default_files = list(filter(isfile, default_vars_files)) - if existing_default_files: - default_vars_file = existing_default_files[0] - sticky_vars.files.append(default_vars_file) - print("Variables file(s) %s not found,\n using defaults in %s" % - (' or '.join(current_vars_files), default_vars_file)) - else: - error("Cannot find variables file(s) %s or default file(s) %s" % - (' or '.join(current_vars_files), - ' or '.join(default_vars_files))) - Exit(1) + extras_var.Add(('EXTRAS', 'Add extra directories to the compilation', '')) # Apply current settings for EXTRAS to env. - sticky_vars.Update(env) + extras_var.Update(env) # Parse EXTRAS variable to build list of all directories where we're # look for sources etc. This list is exported as extras_dir_list. @@ -725,6 +676,17 @@ for variant_path in variant_paths: Export('extras_dir_list') + # Generate a Kconfig that will source the main gem5 one, and any in any + # EXTRAS directories. + kconfig_base_py = Dir('#build_tools').File('kconfig_base.py') + kconfig_base_cmd_parts = [f'"{kconfig_base_py}" "{kconfig_file.abspath}"', + f'"{gem5_kconfig_file.abspath}"'] + for ed in extras_dir_list: + kconfig_base_cmd_parts.append(f'"{ed}"') + kconfig_base_cmd = ' '.join(kconfig_base_cmd_parts) + if env.Execute(kconfig_base_cmd) != 0: + error("Failed to build base Kconfig file") + # Variables which were determined with Configure. env['CONF'] = {} @@ -752,24 +714,15 @@ for variant_path in variant_paths: for cb in after_sconsopts_callbacks: cb() - # Update env for new variables added by the SConsopts. - sticky_vars.Update(env) + # If no config exists yet, see if we know how to make one? + if not isfile(config_file.abspath): + buildopts_file = Dir('#build_opts').File(variant_dir) + if not isfile(buildopts_file.abspath): + error('No config found, and no implicit config recognized') + kconfig.defconfig(env, kconfig_file.abspath, buildopts_file.abspath, + config_file.abspath) - Help(''' -Build variables for {dir}: -{help} -'''.format(dir=variant_dir, help=sticky_vars.GenerateHelpText(env)), - append=True) - - # If the old vars file exists, delete it to avoid confusion/stale values. - if isfile(build_root_vars): - warning(f'Deleting old variant variables file "{build_root_vars}"') - remove(build_root_vars) - # Save sticky variables back to the gem5.build variant variables file. - sticky_vars.Save(gem5_build_vars, env) - - # Pull all the sticky variables into the CONF dict. - env['CONF'].update({key: env[key] for key in sticky_vars.keys()}) + kconfig.update_env(env, kconfig_file.abspath, config_file.abspath) # Do this after we save setting back, or else we'll tack on an # extra 'qdo' every time we run scons. diff --git a/build_opts/ALL b/build_opts/ALL index 6e5ede2d50..7597531c3a 100644 --- a/build_opts/ALL +++ b/build_opts/ALL @@ -1,7 +1,8 @@ -USE_ARM_ISA = True -USE_MIPS_ISA = True -USE_POWER_ISA = True -USE_RISCV_ISA = True -USE_SPARC_ISA = True -USE_X86_ISA = True -PROTOCOL = 'MESI_Two_Level' +RUBY=y +RUBY_PROTOCOL_MESI_TWO_LEVEL=y +USE_ARM_ISA=y +USE_MIPS_ISA=y +USE_POWER_ISA=y +USE_RISCV_ISA=y +USE_SPARC_ISA=y +USE_X86_ISA=y diff --git a/build_opts/ARM b/build_opts/ARM index 8c30c21e5a..998b2cf008 100644 --- a/build_opts/ARM +++ b/build_opts/ARM @@ -1,2 +1,3 @@ -USE_ARM_ISA = True -PROTOCOL = 'CHI' +USE_ARM_ISA=y +RUBY=y +RUBY_PROTOCOL_CHI=y diff --git a/build_opts/ARM_MESI_Three_Level b/build_opts/ARM_MESI_Three_Level index 3057bec0c4..3782efb706 100644 --- a/build_opts/ARM_MESI_Three_Level +++ b/build_opts/ARM_MESI_Three_Level @@ -1,5 +1,3 @@ -# Copyright (c) 2019 ARM Limited -# All rights reserved. - -USE_ARM_ISA = True -PROTOCOL = 'MESI_Three_Level' +USE_ARM_ISA=y +RUBY=y +RUBY_PROTOCOL_MESI_THREE_LEVEL=y diff --git a/build_opts/ARM_MESI_Three_Level_HTM b/build_opts/ARM_MESI_Three_Level_HTM index 7f80c4eee2..04e2a5ebe1 100644 --- a/build_opts/ARM_MESI_Three_Level_HTM +++ b/build_opts/ARM_MESI_Three_Level_HTM @@ -1,5 +1,3 @@ -# Copyright (c) 2019 ARM Limited -# All rights reserved. - -USE_ARM_ISA = True -PROTOCOL = 'MESI_Three_Level_HTM' +USE_ARM_ISA=y +RUBY=y +RUBY_PROTOCOL_MESI_THREE_LEVEL_HTM=y diff --git a/build_opts/ARM_MOESI_hammer b/build_opts/ARM_MOESI_hammer index 5322fd96f2..ce8509280f 100644 --- a/build_opts/ARM_MOESI_hammer +++ b/build_opts/ARM_MOESI_hammer @@ -1,5 +1,3 @@ -# Copyright (c) 2019 ARM Limited -# All rights reserved. - -USE_ARM_ISA = True -PROTOCOL = 'MOESI_hammer' +USE_ARM_ISA=y +RUBY=y +RUBY_PROTOCOL_MOESI_HAMMER=y diff --git a/build_opts/GCN3_X86 b/build_opts/GCN3_X86 index aca2f62878..6e5534caf8 100644 --- a/build_opts/GCN3_X86 +++ b/build_opts/GCN3_X86 @@ -1,4 +1,5 @@ -PROTOCOL = 'GPU_VIPER' -USE_X86_ISA = True -TARGET_GPU_ISA = 'gcn3' -BUILD_GPU = True +RUBY=y +RUBY_PROTOCOL_GPU_VIPER=y +USE_X86_ISA=y +GCN3_GPU_ISA=y +BUILD_GPU=y diff --git a/build_opts/Garnet_standalone b/build_opts/Garnet_standalone index 2351c5221d..7460c9d73a 100644 --- a/build_opts/Garnet_standalone +++ b/build_opts/Garnet_standalone @@ -1,2 +1,3 @@ -USE_NULL_ISA = True -PROTOCOL = 'Garnet_standalone' +RUBY=y +RUBY_PROTOCOL_GARNET_STANDALONE=y +USE_NULL_ISA=y diff --git a/build_opts/MIPS b/build_opts/MIPS index 382e10163a..40955cf999 100644 --- a/build_opts/MIPS +++ b/build_opts/MIPS @@ -1,2 +1,3 @@ -USE_MIPS_ISA = True -PROTOCOL = 'MI_example' +RUBY=y +RUBY_PROTOCOL_MI_EXAMPLE=y +USE_MIPS_ISA=y diff --git a/build_opts/NULL b/build_opts/NULL index 51e287a080..d514ef168f 100644 --- a/build_opts/NULL +++ b/build_opts/NULL @@ -1,2 +1,3 @@ -USE_NULL_ISA = True -PROTOCOL='MI_example' +RUBY=y +RUBY_PROTOCOL_MI_EXAMPLE=y +USE_NULL_ISA=y diff --git a/build_opts/NULL_MESI_Two_Level b/build_opts/NULL_MESI_Two_Level index bafb199592..a6279e6b49 100644 --- a/build_opts/NULL_MESI_Two_Level +++ b/build_opts/NULL_MESI_Two_Level @@ -1,2 +1,3 @@ -USE_NULL_ISA = True -PROTOCOL = 'MESI_Two_Level' +RUBY=y +RUBY_PROTOCOL_MESI_TWO_LEVEL=y +USE_NULL_ISA=y diff --git a/build_opts/NULL_MOESI_CMP_directory b/build_opts/NULL_MOESI_CMP_directory index 3346964a6b..88b1de8dbc 100644 --- a/build_opts/NULL_MOESI_CMP_directory +++ b/build_opts/NULL_MOESI_CMP_directory @@ -1,2 +1,3 @@ -USE_NULL_ISA = True -PROTOCOL='MOESI_CMP_directory' +RUBY=y +RUBY_PROTOCOL_MOESI_CMP_DIRECTORY=y +USE_NULL_ISA=y diff --git a/build_opts/NULL_MOESI_CMP_token b/build_opts/NULL_MOESI_CMP_token index 4ea9e70536..5c3308125e 100644 --- a/build_opts/NULL_MOESI_CMP_token +++ b/build_opts/NULL_MOESI_CMP_token @@ -1,2 +1,3 @@ -USE_NULL_ISA = True -PROTOCOL='MOESI_CMP_token' +RUBY=y +RUBY_PROTOCOL_MOESI_CMP_TOKEN=y +USE_NULL_ISA=y diff --git a/build_opts/NULL_MOESI_hammer b/build_opts/NULL_MOESI_hammer index e91b78dddb..79cc7de4f9 100644 --- a/build_opts/NULL_MOESI_hammer +++ b/build_opts/NULL_MOESI_hammer @@ -1,2 +1,3 @@ -USE_NULL_ISA = True -PROTOCOL='MOESI_hammer' +RUBY=y +RUBY_PROTOCOL_MOESI_HAMMER=y +USE_NULL_ISA=y diff --git a/build_opts/POWER b/build_opts/POWER index 207356c0be..69f5e395cf 100644 --- a/build_opts/POWER +++ b/build_opts/POWER @@ -1,2 +1,3 @@ -USE_POWER_ISA = True -PROTOCOL = 'MI_example' +RUBY=y +RUBY_PROTOCOL_MI_EXAMPLE=y +USE_POWER_ISA=y diff --git a/build_opts/RISCV b/build_opts/RISCV index 22097b0b3e..756c39ec02 100644 --- a/build_opts/RISCV +++ b/build_opts/RISCV @@ -1,2 +1,3 @@ -USE_RISCV_ISA = True -PROTOCOL = 'MI_example' +RUBY=y +RUBY_PROTOCOL_MI_EXAMPLE=y +USE_RISCV_ISA=y diff --git a/build_opts/SPARC b/build_opts/SPARC index 22dec5f867..f2766d5ce4 100644 --- a/build_opts/SPARC +++ b/build_opts/SPARC @@ -1,2 +1,3 @@ -USE_SPARC_ISA = True -PROTOCOL = 'MI_example' +RUBY=y +RUBY_PROTOCOL_MI_EXAMPLE=y +USE_SPARC_ISA=y diff --git a/build_opts/VEGA_X86 b/build_opts/VEGA_X86 index 437b048ce7..58187a355d 100644 --- a/build_opts/VEGA_X86 +++ b/build_opts/VEGA_X86 @@ -1,4 +1,5 @@ -PROTOCOL = 'GPU_VIPER' -USE_X86_ISA = True -TARGET_GPU_ISA = 'vega' -BUILD_GPU = True +RUBY=y +RUBY_PROTOCOL_GPU_VIPER=y +USE_X86_ISA=y +VEGA_GPU_ISA=y +BUILD_GPU=y diff --git a/build_opts/X86 b/build_opts/X86 index 259325b92e..5167bf8c06 100644 --- a/build_opts/X86 +++ b/build_opts/X86 @@ -1,3 +1,4 @@ -USE_X86_ISA = True -PROTOCOL = 'MESI_Two_Level' -NUMBER_BITS_PER_SET = '128' +RUBY=y +NUMBER_BITS_PER_SET=128 +RUBY_PROTOCOL_MESI_TWO_LEVEL=y +USE_X86_ISA=y diff --git a/build_opts/X86_MESI_Two_Level b/build_opts/X86_MESI_Two_Level index 259325b92e..5167bf8c06 100644 --- a/build_opts/X86_MESI_Two_Level +++ b/build_opts/X86_MESI_Two_Level @@ -1,3 +1,4 @@ -USE_X86_ISA = True -PROTOCOL = 'MESI_Two_Level' -NUMBER_BITS_PER_SET = '128' +RUBY=y +NUMBER_BITS_PER_SET=128 +RUBY_PROTOCOL_MESI_TWO_LEVEL=y +USE_X86_ISA=y diff --git a/build_opts/X86_MI_example b/build_opts/X86_MI_example index 71bc9a5f3a..1388769868 100644 --- a/build_opts/X86_MI_example +++ b/build_opts/X86_MI_example @@ -1,2 +1,3 @@ -USE_X86_ISA = True -PROTOCOL = 'MI_example' +RUBY=y +RUBY_PROTOCOL_MI_EXAMPLE=y +USE_X86_ISA=y diff --git a/build_opts/X86_MOESI_AMD_Base b/build_opts/X86_MOESI_AMD_Base index f8f2ce7c8d..09b50b6558 100644 --- a/build_opts/X86_MOESI_AMD_Base +++ b/build_opts/X86_MOESI_AMD_Base @@ -1,2 +1,3 @@ -PROTOCOL = 'MOESI_AMD_Base' -USE_X86_ISA = True +RUBY=y +RUBY_PROTOCOL_MOESI_AMD_BASE=y +USE_X86_ISA=y diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py new file mode 100644 index 0000000000..6c2ec81fa3 --- /dev/null +++ b/site_scons/gem5_scons/kconfig.py @@ -0,0 +1,116 @@ +# Copyright 2022 Google LLC +# +# 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. + +import os + +from . import error +import kconfiglib + + +def _prep_env(env, base_kconfig, config_path=None): + """ + Prepare the required env vars for Kconfiglib + return the Scons env with Kconfiglib env + + :param env: Scons env + :param base_kconfig: path to the Top-level Kconfig file + :param config_path: path to the configuration file + """ + kconfig_env = env.Clone() + for key, val in kconfig_env["CONF"].items(): + if isinstance(val, bool): + val = "y" if val else "n" + kconfig_env["ENV"][key] = val + kconfig_env["ENV"]["CONFIG_"] = "" + if config_path: + kconfig_env["ENV"]["KCONFIG_CONFIG"] = config_path + + ext = env.Dir("#ext") + kconfiglib_dir = ext.Dir("Kconfiglib") + defconfig_py = kconfiglib_dir.File("defconfig.py") + menuconfig_py = kconfiglib_dir.File("menuconfig.py") + + kconfig_env["DEFCONFIG_PY"] = defconfig_py + kconfig_env["MENUCONFIG_PY"] = menuconfig_py + kconfig_env["BASE_KCONFIG"] = base_kconfig + return kconfig_env + + +def defconfig(env, base_kconfig, config_in, config_out): + """ + Interface of handling defconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_out) + kconfig_env["CONFIG_IN"] = config_in + if ( + kconfig_env.Execute( + '"${DEFCONFIG_PY}" --kconfig "${BASE_KCONFIG}" ' '"${CONFIG_IN}"' + ) + != 0 + ): + error("Failed to run defconfig") + + +def update_env(env, base_kconfig, config_path): + """ + Update the Scons' env["CONF"] options from kconfig env + + :param env: Scons env + :param base_kconfig: path to the Top-level Kconfig file + :param config_path: path to the configuration file + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + + saved_env = os.environ + os.environ.update( + {key: str(val) for key, val in kconfig_env["ENV"].items()} + ) + kconfig = kconfiglib.Kconfig(filename=base_kconfig) + os.environ = saved_env + + kconfig.load_config(config_path) + for sym in kconfig.unique_defined_syms: + val = sym.str_value + if sym.type == kconfiglib.BOOL: + env["CONF"][sym.name] = True if val == "y" else False + elif sym.type == kconfiglib.TRISTATE: + warning("No way to configure modules for now") + env["CONF"][sym.name] = True if val == "y" else False + elif sym.type == kconfiglib.INT: + if not val: + val = "0" + env["CONF"][sym.name] = int(val, 0) + elif sym.type == kconfiglib.HEX: + if not val: + val = "0" + env["CONF"][sym.name] = int(val, 16) + elif sym.type == kconfiglib.STRING: + env["CONF"][sym.name] = val + elif sym.type == kconfiglib.UNKNOWN: + warning(f'Config symbol "{sym.name}" has unknown type') + env["CONF"][sym.name] = val + else: + type_name = kconfiglib.TYPE_TO_STR[sym.type] + error(f"Unrecognized symbol type {type_name}") diff --git a/src/Kconfig b/src/Kconfig new file mode 100644 index 0000000000..02bf90ab86 --- /dev/null +++ b/src/Kconfig @@ -0,0 +1,53 @@ +# Copyright 2022 Google LLC +# +# 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. + +mainmenu "$(MAIN_MENU_TEXT)" + +config BATCH + bool "Use batch pool for build and test" + default n + +config BATCH_CMD + string "Batch pool submission command name" + default "qdo" + depends on BATCH + +config M5_BUILD_CACHE + string "Cache built objects in this directory" + default "" + +config USE_EFENCE + bool "Link with Electric Fence malloc debugger" + default n + +rsource "base/Kconfig" +rsource "mem/ruby/Kconfig" +rsource "learning_gem5/part3/Kconfig" +rsource "proto/Kconfig" +rsource "dev/net/Kconfig" +rsource "arch/Kconfig" +rsource "cpu/kvm/Kconfig" +rsource "systemc/Kconfig" +rsource "gpu-compute/Kconfig" diff --git a/src/arch/Kconfig b/src/arch/Kconfig new file mode 100644 index 0000000000..05d637913e --- /dev/null +++ b/src/arch/Kconfig @@ -0,0 +1,37 @@ +# Copyright 2022 Google LLC +# +# 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. + +config TARGET_GPU_ISA + string + +rsource "amdgpu/Kconfig" + +rsource "arm/Kconfig" +rsource "mips/Kconfig" +rsource "null/Kconfig" +rsource "power/Kconfig" +rsource "riscv/Kconfig" +rsource "sparc/Kconfig" +rsource "x86/Kconfig" diff --git a/src/arch/power/SConsopts b/src/arch/amdgpu/Kconfig similarity index 90% rename from src/arch/power/SConsopts rename to src/arch/amdgpu/Kconfig index 099f37553a..5140f2b103 100644 --- a/src/arch/power/SConsopts +++ b/src/arch/amdgpu/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2021 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,6 +23,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') -sticky_vars.Add(BoolVariable('USE_POWER_ISA', 'Enable POWER ISA support', - False)) +if BUILD_GPU +choice "TARGET_GPU_ISA" +prompt "GPU ISA" +endchoice +endif + +rsource "gcn3/Kconfig" +rsource "vega/Kconfig" diff --git a/src/arch/amdgpu/gcn3/Kconfig b/src/arch/amdgpu/gcn3/Kconfig new file mode 100644 index 0000000000..2ba21a6521 --- /dev/null +++ b/src/arch/amdgpu/gcn3/Kconfig @@ -0,0 +1,33 @@ +# Copyright 2022 Google LLC +# +# 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. + +config TARGET_GPU_ISA + default "gcn3" if GCN3_GPU_ISA + +cont_choice "TARGET_GPU_ISA" + config GCN3_GPU_ISA + depends on BUILD_GPU + bool "GCN3" +endchoice diff --git a/src/arch/amdgpu/vega/Kconfig b/src/arch/amdgpu/vega/Kconfig new file mode 100644 index 0000000000..81f8be3551 --- /dev/null +++ b/src/arch/amdgpu/vega/Kconfig @@ -0,0 +1,33 @@ +# Copyright 2022 Google LLC +# +# 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. + +config TARGET_GPU_ISA + default 'vega' if VEGA_GPU_ISA + +cont_choice "TARGET_GPU_ISA" + config VEGA_GPU_ISA + depends on BUILD_GPU + bool "VEGA" +endchoice diff --git a/src/arch/x86/SConsopts b/src/arch/arm/Kconfig similarity index 92% rename from src/arch/x86/SConsopts rename to src/arch/arm/Kconfig index 425c92145f..d75a21a267 100644 --- a/src/arch/x86/SConsopts +++ b/src/arch/arm/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2021 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,5 +23,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') -sticky_vars.Add(BoolVariable('USE_X86_ISA', 'Enable X86 ISA support', False)) +config USE_ARM_ISA + bool "ARM ISA support" + +rsource "fastmodel/Kconfig" diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index ee5efebf13..0aa4e66659 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -40,7 +40,7 @@ Import('*') -if env['USE_ARM_ISA']: +if env['CONF']['USE_ARM_ISA']: env.TagImplies('arm isa', 'gem5 lib') # The GTest function does not have a 'tags' parameter. We therefore apply this @@ -48,7 +48,7 @@ if env['USE_ARM_ISA']: # # Note: This will need reconfigured for multi-isa. E.g., if this is # incorporated: https://gem5-review.googlesource.com/c/public/gem5/+/52491 -if env['USE_ARM_ISA']: +if env['CONF']['USE_ARM_ISA']: GTest('aapcs64.test', 'aapcs64.test.cc', '../../base/debug.cc', '../../cpu/reg_class.cc', diff --git a/src/arch/arm/fastmodel/Kconfig b/src/arch/arm/fastmodel/Kconfig new file mode 100644 index 0000000000..f4eec968f9 --- /dev/null +++ b/src/arch/arm/fastmodel/Kconfig @@ -0,0 +1,60 @@ +# Copyright 2022 Google LLC +# +# 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. + +menu "Fast Model" + + config USE_ARM_FASTMODEL + bool "Fast Model integration" + default n + depends on USE_ARM_ISA + depends on USE_SYSTEMC + + if USE_ARM_FASTMODEL + config PVLIB_HOME + string "Fast Model portfolio directory" + default "$(PVLIB_HOME)" + + config PVLIB_FLAVOR + string "What build flavor of the Fast Model pvlib to use" + default "Linux64_GCC-7.3" + + config MAXCORE_HOME + string "Fast Model tools directory" + default "$(MAXCORE_HOME)" + + config ARMLMD_LICENSE_FILE + string "ARM license file location" + default "$(ARMLMD_LICENSE_FILE)" + + config ARMLMD_LICENSE_COUNT + int "The maximum number of ARM licenses to use concurrently" + default 1 + + config SIMGEN + string "simgen executable (leave unset for MAXCORE_HOME/bin/simgen" + default "" + endif + +endmenu diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript index 7c6019e2a8..f8cfd5991c 100644 --- a/src/arch/arm/fastmodel/SConscript +++ b/src/arch/arm/fastmodel/SConscript @@ -302,6 +302,10 @@ for header in common_headers: header_src = examples_common_dir.Dir('include').File(header) Command(header_target, header_src, Copy('${TARGET}', '${SOURCE}')) +if not env['CONF']['SIMGEN']: + env['CONF']['SIMGEN'] = os.path.join( + env['CONF']['MAXCORE_HOME'], 'bin', 'simgen') + class ArmFastModelComponent(object): def __init__(self, project_file, *extra_deps, tags=None): if not tags: diff --git a/src/arch/arm/fastmodel/SConsopts b/src/arch/arm/fastmodel/SConsopts index d3f898004d..e592bdbf55 100644 --- a/src/arch/arm/fastmodel/SConsopts +++ b/src/arch/arm/fastmodel/SConsopts @@ -1,5 +1,4 @@ -# Copyright 2019 Google, Inc. -# All rights reserved. +# Copyright 2019,2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -28,20 +27,12 @@ Import('*') import os -default_simgen = os.path.join('${MAXCORE_HOME}', 'bin', 'simgen') +def extract_var(name): + val = os.environ.get(name, None) + if val is not None: + main['CONF'][name] = val -sticky_vars.AddVariables( - BoolVariable('USE_ARM_FASTMODEL', - 'Build support for integrating ARM Fast Models', False), - ('PVLIB_HOME', 'Fast Model portfolio directory', - os.environ.get('PVLIB_HOME', '')), - ('PVLIB_FLAVOR', 'What build flavor of the Fast Model pvlib to use', - 'Linux64_GCC-7.3'), - ('MAXCORE_HOME', 'Fast Model tools directory', - os.environ.get('MAXCORE_HOME', '')), - ('ARMLMD_LICENSE_FILE', 'ARM license file location', - os.environ.get('ARMLMD_LICENSE_FILE', '')), - ('ARMLMD_LICENSE_COUNT', - 'The maximum number of ARM licenses to use concurrently', 1), - ('SIMGEN', 'simgen executable', os.environ.get('SIMGEN', default_simgen)), -) +# Make these environment variables in the host environment available when +# running kconfig tools by putting them in env['CONF']. +for var in 'PVLIB_HOME', 'MAXCORE_HOME', 'ARMLMD_LICENSE_FILE': + extract_var(var) diff --git a/src/arch/arm/SConsopts b/src/arch/mips/Kconfig similarity index 92% rename from src/arch/arm/SConsopts rename to src/arch/mips/Kconfig index f760404957..20d70ded8c 100644 --- a/src/arch/arm/SConsopts +++ b/src/arch/mips/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2021 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,5 +23,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') -sticky_vars.Add(BoolVariable('USE_ARM_ISA', 'Enable ARM ISA support', False)) +config USE_MIPS_ISA + bool "MIPS ISA support" diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 3ef9deceee..05573ae74b 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -29,7 +29,7 @@ Import('*') -if env['USE_MIPS_ISA']: +if env['CONF']['USE_MIPS_ISA']: env.TagImplies('mips isa', 'gem5 lib') Source('decoder.cc', tags='mips isa') diff --git a/src/arch/null/SConsopts b/src/arch/null/Kconfig similarity index 92% rename from src/arch/null/SConsopts rename to src/arch/null/Kconfig index 2d552a1dc8..64151ecf73 100644 --- a/src/arch/null/SConsopts +++ b/src/arch/null/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2021 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,5 +23,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') -sticky_vars.Add(BoolVariable('USE_NULL_ISA', 'Enable NULL ISA support', False)) +config USE_NULL_ISA + bool "Null ISA support" diff --git a/src/arch/mips/SConsopts b/src/arch/power/Kconfig similarity index 92% rename from src/arch/mips/SConsopts rename to src/arch/power/Kconfig index 6c5061fd5d..f585a1e023 100644 --- a/src/arch/mips/SConsopts +++ b/src/arch/power/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2021 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,5 +23,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') -sticky_vars.Add(BoolVariable('USE_MIPS_ISA', 'Enable MIPS ISA support', False)) +config USE_POWER_ISA + bool "POWER ISA support" diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript index 8ddb96694a..ede15cfd22 100644 --- a/src/arch/power/SConscript +++ b/src/arch/power/SConscript @@ -30,7 +30,7 @@ Import('*') -if env['USE_POWER_ISA']: +if env['CONF']['USE_POWER_ISA']: env.TagImplies('power isa', 'gem5 lib') Source('decoder.cc', tags='power isa') diff --git a/src/arch/riscv/Kconfig b/src/arch/riscv/Kconfig new file mode 100644 index 0000000000..7f09731e5e --- /dev/null +++ b/src/arch/riscv/Kconfig @@ -0,0 +1,27 @@ +# Copyright 2022 Google LLC +# +# 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. + +config USE_RISCV_ISA + bool "RISC-V ISA support" diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript index bf40b6eccd..d3dd1d5970 100644 --- a/src/arch/riscv/SConscript +++ b/src/arch/riscv/SConscript @@ -43,7 +43,7 @@ Import('*') -if env['USE_RISCV_ISA']: +if env['CONF']['USE_RISCV_ISA']: env.TagImplies('riscv isa', 'gem5 lib') Source('decoder.cc', tags='riscv isa') diff --git a/src/arch/riscv/SConsopts b/src/arch/riscv/SConsopts deleted file mode 100644 index 751311de5c..0000000000 --- a/src/arch/riscv/SConsopts +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2021 Google, Inc. -# -# 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. - -Import('*') -sticky_vars.Add(BoolVariable('USE_RISCV_ISA', 'Enable RISC-V ISA support', - False)) diff --git a/src/arch/sparc/Kconfig b/src/arch/sparc/Kconfig new file mode 100644 index 0000000000..ec2aef7326 --- /dev/null +++ b/src/arch/sparc/Kconfig @@ -0,0 +1,27 @@ +# Copyright 2022 Google LLC +# +# 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. + +config USE_SPARC_ISA + bool "SPARC ISA support" diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index a721c4ae56..9291c8a741 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['USE_SPARC_ISA']: +if env['CONF']['USE_SPARC_ISA']: env.TagImplies('sparc isa', 'gem5 lib') Source('asi.cc', tags='sparc isa') diff --git a/src/arch/sparc/SConsopts b/src/arch/sparc/SConsopts deleted file mode 100644 index 917485af9c..0000000000 --- a/src/arch/sparc/SConsopts +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2021 Google, Inc. -# -# 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. - -Import('*') -sticky_vars.Add(BoolVariable('USE_SPARC_ISA', 'Enable SPARC ISA support', - False)) diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig new file mode 100644 index 0000000000..ba10fad55b --- /dev/null +++ b/src/arch/x86/Kconfig @@ -0,0 +1,27 @@ +# Copyright 2022 Google LLC +# +# 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. + +config USE_X86_ISA + bool "X86 ISA support" diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 97c34f51c3..cbf5356761 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -40,7 +40,7 @@ Import('*') -if env['USE_X86_ISA']: +if env['CONF']['USE_X86_ISA']: env.TagImplies('x86 isa', 'gem5 lib') Source('cpuid.cc', tags='x86 isa') diff --git a/src/arch/SConsopts b/src/base/Kconfig similarity index 78% rename from src/arch/SConsopts rename to src/base/Kconfig index f05bdef14b..19d58c865a 100644 --- a/src/arch/SConsopts +++ b/src/base/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2020 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,11 +23,23 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') +config HAVE_FENV + def_bool $(HAVE_FENV) -def add_isa_lists(): - sticky_vars.AddVariables( - EnumVariable('TARGET_GPU_ISA', 'Target GPU ISA', 'gcn3', - sorted(set(main.Split('${ALL_GPU_ISAS}')))), - ) -AfterSConsopts(add_isa_lists) +config HAVE_PNG + def_bool $(HAVE_PNG) + +config HAVE_VALGRIND + def_bool $(HAVE_VALGRIND) + +config HAVE_DEPRECATED_NAMESPACE + def_bool $(HAVE_DEPRECATED_NAMESPACE) + +config HAVE_POSIX_CLOCK + def_bool $(HAVE_POSIX_CLOCK) + +config USE_POSIX_CLOCK + depends on HAVE_POSIX_CLOCK + bool "Use POSIX clocks" + +rsource "stats/Kconfig" diff --git a/src/base/SConsopts b/src/base/SConsopts index 68e40587b9..6c438768b2 100644 --- a/src/base/SConsopts +++ b/src/base/SConsopts @@ -81,6 +81,3 @@ with gem5_scons.Configure(werror_env) as conf: warning("Deprecated namespaces are not supported by this compiler.\n" "Please make sure to check the mailing list for deprecation " "announcements.") - -sticky_vars.Add(BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', - '${CONF["HAVE_POSIX_CLOCK"]}')) diff --git a/src/base/stats/Kconfig b/src/base/stats/Kconfig new file mode 100644 index 0000000000..2b7bb9610d --- /dev/null +++ b/src/base/stats/Kconfig @@ -0,0 +1,27 @@ +# Copyright 2022 Google LLC +# +# 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. + +config HAVE_HDF5 + def_bool $(HAVE_HDF5) diff --git a/src/cpu/kvm/Kconfig b/src/cpu/kvm/Kconfig new file mode 100644 index 0000000000..824a2e3c41 --- /dev/null +++ b/src/cpu/kvm/Kconfig @@ -0,0 +1,34 @@ +# Copyright 2022 Google LLC +# +# 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. + +config KVM_ISA + string + default "$(KVM_ISA)" + +config USE_KVM + depends on KVM_ISA != "" + bool "Enable hardware virtualized (KVM) CPU models" + default y if KVM_ISA != "" + default n diff --git a/src/cpu/kvm/SConsopts b/src/cpu/kvm/SConsopts index 275eedaa54..1363d60951 100644 --- a/src/cpu/kvm/SConsopts +++ b/src/cpu/kvm/SConsopts @@ -61,13 +61,5 @@ with gem5_scons.Configure(main) as conf: warning("perf_event headers lack support for the exclude_host " "attribute. KVM instruction counts will be inaccurate.") - -def create_use_kvm_var(): - if main['CONF']['HAVE_KVM'] and main['CONF']['KVM_ISA']: - sticky_vars.Add(BoolVariable('USE_KVM', - 'Enable hardware virtualized (KVM) CPU models', True)) - else: - main['CONF']['USE_KVM'] = False - warning("Cannot enable KVM, host seems to lack KVM support") - -AfterSConsopts(create_use_kvm_var) +if not main['CONF']['KVM_ISA']: + warning("Can not enable KVM, host seems to lack KVM support") diff --git a/src/cpu/testers/directedtest/SConscript b/src/cpu/testers/directedtest/SConscript index 6787648608..e4e9f10c2b 100644 --- a/src/cpu/testers/directedtest/SConscript +++ b/src/cpu/testers/directedtest/SConscript @@ -35,7 +35,7 @@ Import('*') # When this dependency is removed, the ruby tester should be compiled # independently from Ruby # -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('RubyDirectedTester.py', sim_objects=[ diff --git a/src/cpu/testers/garnet_synthetic_traffic/SConscript b/src/cpu/testers/garnet_synthetic_traffic/SConscript index 14f4abdc67..e2eb4cffd6 100644 --- a/src/cpu/testers/garnet_synthetic_traffic/SConscript +++ b/src/cpu/testers/garnet_synthetic_traffic/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('GarnetSyntheticTraffic.py', sim_objects=['GarnetSyntheticTraffic']) diff --git a/src/cpu/testers/gpu_ruby_test/SConscript b/src/cpu/testers/gpu_ruby_test/SConscript index 0231649043..b56be9448f 100644 --- a/src/cpu/testers/gpu_ruby_test/SConscript +++ b/src/cpu/testers/gpu_ruby_test/SConscript @@ -34,7 +34,7 @@ Import('*') if not env['CONF']['BUILD_GPU']: Return() -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('ProtocolTester.py', sim_objects=['ProtocolTester']) diff --git a/src/cpu/testers/rubytest/SConscript b/src/cpu/testers/rubytest/SConscript index cc76d2bdfd..a4eac87499 100644 --- a/src/cpu/testers/rubytest/SConscript +++ b/src/cpu/testers/rubytest/SConscript @@ -35,7 +35,7 @@ Import('*') # When this dependency is removed, the ruby tester should be compiled # independently from Ruby # -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('RubyTester.py', sim_objects=['RubyTester']) diff --git a/src/dev/net/Kconfig b/src/dev/net/Kconfig new file mode 100644 index 0000000000..0e2c3eb551 --- /dev/null +++ b/src/dev/net/Kconfig @@ -0,0 +1,27 @@ +# Copyright 2022 Google LLC +# +# 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. + +config HAVE_TUNTAP + def_bool $(HAVE_TUNTAP) diff --git a/src/gpu-compute/Kconfig b/src/gpu-compute/Kconfig new file mode 100644 index 0000000000..574f670833 --- /dev/null +++ b/src/gpu-compute/Kconfig @@ -0,0 +1,28 @@ +# Copyright 2022 Google LLC +# +# 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. + +menuconfig BUILD_GPU + bool "Build the compute-GPU model" + default n diff --git a/src/gpu-compute/SConsopts b/src/learning_gem5/part3/Kconfig similarity index 89% rename from src/gpu-compute/SConsopts rename to src/learning_gem5/part3/Kconfig index 251ac5d8cf..9d06122d2e 100644 --- a/src/gpu-compute/SConsopts +++ b/src/learning_gem5/part3/Kconfig @@ -1,4 +1,4 @@ -# Copyright 2020 Google, Inc. +# Copyright 2022 Google LLC # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -23,7 +23,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Import('*') +config PROTOCOL + default "MSI" if RUBY_PROTOCOL_MSI -sticky_vars.Add(BoolVariable('BUILD_GPU', 'Build the compute-GPU model', - False)) +cont_choice "Ruby protocol" + config RUBY_PROTOCOL_MSI + bool "MSI" +endchoice diff --git a/src/learning_gem5/part3/SConsopts b/src/learning_gem5/part3/SConsopts index dabfd1e146..39968d7fdc 100644 --- a/src/learning_gem5/part3/SConsopts +++ b/src/learning_gem5/part3/SConsopts @@ -2,8 +2,5 @@ Import('*') # NOTE: All SLICC setup code found in src/mem/ruby/protocol/SConscript -# Register this protocol with gem5/SCons -main.Append(ALL_PROTOCOLS=['MSI']) - # Add this directory to the search path for SLICC main.Append(PROTOCOL_DIRS=[Dir('.')]) diff --git a/src/mem/ruby/Kconfig b/src/mem/ruby/Kconfig new file mode 100644 index 0000000000..362174d5b7 --- /dev/null +++ b/src/mem/ruby/Kconfig @@ -0,0 +1,50 @@ +# Copyright 2022 Google LLC +# +# 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. + +menu "Ruby" + menuconfig RUBY + bool "Enable" + + if RUBY + config PROTOCOL + string + + config NEED_PARTIAL_FUNC_READS + bool + + choice "Ruby protocol" + prompt "Ruby protocol" + endchoice + + config SLICC_HTML + bool 'Create HTML files' + + config NUMBER_BITS_PER_SET + int 'Max elements in set' + default 64 + endif +endmenu + +rsource "protocol/Kconfig" diff --git a/src/mem/ruby/SConscript b/src/mem/ruby/SConscript index 1e386f922d..2eb46b0f4d 100644 --- a/src/mem/ruby/SConscript +++ b/src/mem/ruby/SConscript @@ -49,7 +49,7 @@ from gem5_scons import Transform Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() DebugFlag('ProtocolTrace') @@ -112,7 +112,7 @@ MakeInclude('structures/PerfectCacheMemory.hh') MakeInclude('structures/PersistentTable.hh') MakeInclude('structures/RubyPrefetcher.hh') MakeInclude('structures/TBEStorage.hh') -if env['PROTOCOL'] == 'CHI': +if env['CONF']['PROTOCOL'] == 'CHI': MakeInclude('structures/MN_TBEStorage.hh') MakeInclude('structures/MN_TBETable.hh') MakeInclude('structures/TBETable.hh') diff --git a/src/mem/ruby/SConsopts b/src/mem/ruby/SConsopts index f26b6d05f8..7c4a1a9ea9 100644 --- a/src/mem/ruby/SConsopts +++ b/src/mem/ruby/SConsopts @@ -25,12 +25,4 @@ Import('*') -main.SetDefault(ALL_PROTOCOLS=[], PROTOCOL_DIRS=[], SLICC_INCLUDES=[]) - -def add_protocols_var(): - sticky_vars.Add(EnumVariable('PROTOCOL', 'Coherence protocol for Ruby', - 'None', main['ALL_PROTOCOLS'])) -AfterSConsopts(add_protocols_var) - -sticky_vars.Add(('NUMBER_BITS_PER_SET', 'Max elements in set (default 64)', - 64)) +main.SetDefault(PROTOCOL_DIRS=[], SLICC_INCLUDES=[]) diff --git a/src/mem/ruby/common/SConscript b/src/mem/ruby/common/SConscript index 9f683cbaf1..9c1fc795a6 100644 --- a/src/mem/ruby/common/SConscript +++ b/src/mem/ruby/common/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() env.Append(CPPDEFINES={'NUMBER_BITS_PER_SET': diff --git a/src/mem/ruby/network/SConscript b/src/mem/ruby/network/SConscript index b5a4e7950f..e9a79746d7 100644 --- a/src/mem/ruby/network/SConscript +++ b/src/mem/ruby/network/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('BasicLink.py', sim_objects=[ diff --git a/src/mem/ruby/network/fault_model/SConscript b/src/mem/ruby/network/fault_model/SConscript index bd55947795..e6ff61aed8 100644 --- a/src/mem/ruby/network/fault_model/SConscript +++ b/src/mem/ruby/network/fault_model/SConscript @@ -33,7 +33,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('FaultModel.py', sim_objects=['FaultModel']) diff --git a/src/mem/ruby/network/garnet/SConscript b/src/mem/ruby/network/garnet/SConscript index 9e6e19e9b6..b0dcfe690c 100644 --- a/src/mem/ruby/network/garnet/SConscript +++ b/src/mem/ruby/network/garnet/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('GarnetLink.py', enums=['CDCType'], sim_objects=[ diff --git a/src/mem/ruby/network/simple/SConscript b/src/mem/ruby/network/simple/SConscript index 97055f5080..011552afae 100644 --- a/src/mem/ruby/network/simple/SConscript +++ b/src/mem/ruby/network/simple/SConscript @@ -40,7 +40,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('SimpleLink.py', sim_objects=['SimpleExtLink', 'SimpleIntLink']) diff --git a/src/mem/ruby/profiler/SConscript b/src/mem/ruby/profiler/SConscript index 0c493e9be3..ff9cc099f2 100644 --- a/src/mem/ruby/profiler/SConscript +++ b/src/mem/ruby/profiler/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() Source('AccessTraceForAddress.cc') diff --git a/src/mem/ruby/protocol/Kconfig b/src/mem/ruby/protocol/Kconfig new file mode 100644 index 0000000000..bed47a1108 --- /dev/null +++ b/src/mem/ruby/protocol/Kconfig @@ -0,0 +1,62 @@ +# Copyright 2022 Google LLC +# +# 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. + +config PROTOCOL + default "GPU_VIPER" if RUBY_PROTOCOL_GPU_VIPER + default "MOESI_AMD_Base" if RUBY_PROTOCOL_MOESI_AMD_BASE + default "MESI_Two_Level" if RUBY_PROTOCOL_MESI_TWO_LEVEL + default "MESI_Three_Level" if RUBY_PROTOCOL_MESI_THREE_LEVEL + default "MESI_Three_Level_HTM" if RUBY_PROTOCOL_MESI_THREE_LEVEL_HTM + default "MI_example" if RUBY_PROTOCOL_MI_EXAMPLE + default "MOESI_CMP_directory" if RUBY_PROTOCOL_MOESI_CMP_DIRECTORY + default "MOESI_CMP_token" if RUBY_PROTOCOL_MOESI_CMP_TOKEN + default "MOESI_hammer" if RUBY_PROTOCOL_MOESI_HAMMER + default "Garnet_standalone" if RUBY_PROTOCOL_GARNET_STANDALONE + +cont_choice "Ruby protocol" + config RUBY_PROTOCOL_GPU_VIPER + bool "GPU VIPER" + depends on BUILD_GPU + config RUBY_PROTOCOL_MOESI_AMD_BASE + bool "MOESI AMD base" + config RUBY_PROTOCOL_MESI_TWO_LEVEL + bool "MESI two level" + config RUBY_PROTOCOL_MESI_THREE_LEVEL + bool "MESI three level" + config RUBY_PROTOCOL_MESI_THREE_LEVEL_HTM + bool "MESI three level HTM" + config RUBY_PROTOCOL_MI_EXAMPLE + bool "MI example" + config RUBY_PROTOCOL_MOESI_CMP_DIRECTORY + bool "MOESI CMP directory" + config RUBY_PROTOCOL_MOESI_CMP_TOKEN + bool "MOESI CMP token" + config RUBY_PROTOCOL_MOESI_HAMMER + bool "MOESI hammer" + config RUBY_PROTOCOL_GARNET_STANDALONE + bool "Garnet standalone" +endchoice + +rsource "chi/Kconfig" diff --git a/src/mem/ruby/protocol/SConscript b/src/mem/ruby/protocol/SConscript index 07545c3ae0..7369c0c193 100644 --- a/src/mem/ruby/protocol/SConscript +++ b/src/mem/ruby/protocol/SConscript @@ -36,7 +36,7 @@ from gem5_scons import Transform Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() output_dir = Dir('.') diff --git a/src/mem/ruby/protocol/SConsopts b/src/mem/ruby/protocol/SConsopts index 2fcc57a5f5..bcbc83ba9b 100644 --- a/src/mem/ruby/protocol/SConsopts +++ b/src/mem/ruby/protocol/SConsopts @@ -30,23 +30,6 @@ import os Import('*') -main.Append(ALL_PROTOCOLS=[ - 'GPU_VIPER', - 'MOESI_AMD_Base', - 'MESI_Two_Level', - 'MESI_Three_Level', - 'MESI_Three_Level_HTM', - 'MI_example', - 'MOESI_CMP_directory', - 'MOESI_CMP_token', - 'MOESI_hammer', - 'Garnet_standalone', - 'None' - ]) - -opt = BoolVariable('SLICC_HTML', 'Create HTML files', False) -sticky_vars.Add(opt) - main.Append(PROTOCOL_DIRS=[Dir('.')]) protocol_base = Dir('.') diff --git a/src/mem/ruby/protocol/chi/Kconfig b/src/mem/ruby/protocol/chi/Kconfig new file mode 100644 index 0000000000..708f162fd7 --- /dev/null +++ b/src/mem/ruby/protocol/chi/Kconfig @@ -0,0 +1,35 @@ +# Copyright 2022 Google LLC +# +# 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. + +config PROTOCOL + default "CHI" if RUBY_PROTOCOL_CHI + +config NEED_PARTIAL_FUNC_READS + default y if RUBY_PROTOCOL_CHI + +cont_choice "Ruby protocol" + config RUBY_PROTOCOL_CHI + bool "CHI" +endchoice diff --git a/src/mem/ruby/protocol/chi/SConsopts b/src/mem/ruby/protocol/chi/SConsopts index 6f686878ef..8551d7325f 100644 --- a/src/mem/ruby/protocol/chi/SConsopts +++ b/src/mem/ruby/protocol/chi/SConsopts @@ -37,11 +37,4 @@ Import('*') -# Register this protocol with gem5/SCons - -main.Append(ALL_PROTOCOLS=['CHI']) - -# CHI requires Ruby's inerface to support partial functional reads -main.Append(NEED_PARTIAL_FUNC_READS=['CHI']) - main.Append(PROTOCOL_DIRS=[Dir('.')]) diff --git a/src/mem/ruby/slicc_interface/SConscript b/src/mem/ruby/slicc_interface/SConscript index 47dd49d42e..7fb84b348c 100644 --- a/src/mem/ruby/slicc_interface/SConscript +++ b/src/mem/ruby/slicc_interface/SConscript @@ -28,7 +28,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('Controller.py', sim_objects=['RubyController']) diff --git a/src/mem/ruby/structures/SConscript b/src/mem/ruby/structures/SConscript index 7baab6a4c4..242a72e919 100644 --- a/src/mem/ruby/structures/SConscript +++ b/src/mem/ruby/structures/SConscript @@ -40,7 +40,7 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() SimObject('RubyCache.py', sim_objects=['RubyCache']) @@ -57,5 +57,5 @@ Source('TimerTable.cc') Source('BankedArray.cc') Source('ALUFreeListArray.cc') Source('TBEStorage.cc') -if env['PROTOCOL'] == 'CHI': +if env['CONF']['PROTOCOL'] == 'CHI': Source('MN_TBETable.cc') diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript index c0b85bb350..77bce7f851 100644 --- a/src/mem/ruby/system/SConscript +++ b/src/mem/ruby/system/SConscript @@ -40,12 +40,12 @@ Import('*') -if env['CONF']['PROTOCOL'] == 'None': +if not env['CONF']['RUBY']: Return() env.Append(CPPDEFINES=['PROTOCOL_' + env['CONF']['PROTOCOL']]) -if env['CONF']['PROTOCOL'] in env['NEED_PARTIAL_FUNC_READS']: +if env['CONF']['NEED_PARTIAL_FUNC_READS']: env.Append(CPPDEFINES=['PARTIAL_FUNC_READS']) if env['CONF']['BUILD_GPU']: diff --git a/src/proto/Kconfig b/src/proto/Kconfig new file mode 100644 index 0000000000..a497d6e2de --- /dev/null +++ b/src/proto/Kconfig @@ -0,0 +1,27 @@ +# Copyright 2022 Google LLC +# +# 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. + +config HAVE_PROTOBUF + def_bool $(HAVE_PROTOBUF) diff --git a/src/systemc/Kconfig b/src/systemc/Kconfig new file mode 100644 index 0000000000..3f3df93f53 --- /dev/null +++ b/src/systemc/Kconfig @@ -0,0 +1,28 @@ +# Copyright 2022 Google LLC +# +# 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. + +config USE_SYSTEMC + bool "Enable SystemC API support" + default $(USE_SYSTEMC) diff --git a/src/systemc/SConsopts b/src/systemc/SConsopts index e8702882e5..20436ec81b 100644 --- a/src/systemc/SConsopts +++ b/src/systemc/SConsopts @@ -45,6 +45,3 @@ def use_systemc_check(env, warn=False): main.AddMethod(use_systemc_check, 'UseSystemcCheck') main['CONF']['USE_SYSTEMC'] = main.UseSystemcCheck() - -sticky_vars.Add(BoolVariable('USE_SYSTEMC', 'Enable SystemC API support', - main.UseSystemcCheck())) From 1cdccd7ac016ef51b72f220d148fd4061bffb499 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 17 Feb 2022 00:36:03 -0800 Subject: [PATCH 582/693] scons: Add a build script for generating a root Kconfig file. This root Kconfig file "source"s (includes) the base gem5 src/Kconfig file, and also any optional Kconfig files found in the base of EXTRAS directories. These will be called out in the menuconfig interface and config files with the name of the EXTRAS directory they came from, and a blank section will be present either if the Kconfig didn't exist, or it did exist but had no options in it. Change-Id: I54060d613f0e0ab9372bed37a2fe5849bf5bbcdb --- build_tools/kconfig_base.py | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 build_tools/kconfig_base.py diff --git a/build_tools/kconfig_base.py b/build_tools/kconfig_base.py new file mode 100755 index 0000000000..13cdb7377a --- /dev/null +++ b/build_tools/kconfig_base.py @@ -0,0 +1,55 @@ +#! /usr/bin/env python3 +# +# Copyright 2022 Google LLC +# +# 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. + +import argparse + +from code_formatter import code_formatter + +parser = argparse.ArgumentParser() +parser.add_argument("output", help="path of generated base Kconfig file") +parser.add_argument("main", help="relative path to the main gem5 Kconfig file") +parser.add_argument("extras_dirs", nargs="*", help="EXTRAS paths") + +args = parser.parse_args() + +code = code_formatter() + +code( + f"""# Automatically generated base Kconfig file, DO NOT EDIT! + +source "{args.main}" +""" +) + +for extras_dir in args.extras_dirs: + code( + f""" +osource "{extras_dir}/Kconfig" +""" + ) + +code.write(args.output) From f4c578f458768b72e628d9267217a78fd603b406 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 24 Mar 2022 16:20:58 -0700 Subject: [PATCH 583/693] scons: Flesh out the help text for "magic" targets. These targets are not necessarily obvious, and tell SCons to do useful things, like build a particular version of the gem5 binary with a particular configuration, or run the unit tests. Add descriptions of these targets to the help so that they are much more discoverable. Change-Id: If84399be1a7155ff5f66f511efe1f1c241089c84 --- SConstruct | 64 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/SConstruct b/SConstruct index 405adbc080..3a26e35843 100755 --- a/SConstruct +++ b/SConstruct @@ -44,15 +44,6 @@ # # SCons top-level build description (SConstruct) file. # -# While in this directory ('gem5'), just type 'scons' to build the default -# configuration (see below), or type 'scons build//' -# to build some other configuration (e.g., 'build/X86/gem5.opt' for -# the optimized X86 version). -# -# You can build gem5 in a different directory as long as there is a -# 'build/' somewhere along the target path. The build system -# expects that all configs under the same build directory are being -# built for the same host system. # # Examples: # @@ -81,7 +72,7 @@ import itertools import os import sys -from os import mkdir, remove, environ +from os import mkdir, remove, environ, listdir from os.path import abspath, dirname, expanduser from os.path import isdir, isfile from os.path import join, split @@ -207,6 +198,59 @@ if not ('CC' in main and 'CXX' in main): # Find default configuration & binary. Default(environ.get('M5_DEFAULT_BINARY', 'build/ARM/gem5.debug')) +buildopts_dir = Dir('#build_opts') +buildopts = list([f for f in os.listdir(buildopts_dir.abspath) if + isfile(os.path.join(buildopts_dir.abspath, f))]) +buildopts.sort() + +buildopt_list = '\n'.join(' ' * 10 + buildopt for buildopt in buildopts) + +Help(f""" +Targets: + To build gem5 using a predefined configuration, use a target with + a directory called "build" in the path, followed by a directory named + after a predefined configuration, and then the actual target, likely + a gem5 binary. For example: + + scons build/X86/gem5.opt + + The "build" component tells SCons that the next part names an initial + configuration, and the part after that is the actual target. + The predefined targets currently available are: + +{buildopt_list} + + The extension on the gem5 binary specifies what type of binary to + build. Options are: + + debug: A debug binary with optimizations turned off and debug info + turned on. + opt: An optimized binary with debugging still turned on. + fast: An optimized binary with debugging, asserts, and tracing + disabled. + + gem5 can also be built as a static or dynamic library. In that case, + the extension is fixed by the operating system, so the binary type + is part of the target file name. For example: + + scons build/ARM/libgem5_opt.so + + To build unit tests, you can use a target like this: + + scons build/RISCV/unittests.debug + + The unittests.debug part of the target is actual a directory which + holds the results for all the unit tests built with the "debug" + settings. When that's used as the target, SCons will build all the + files under that directory, which will run all the tests. + + To build and run an individual test, you can built it's binary + specifically and then run it manually: + + scons build/SPARC/base/bitunion.test.opt + build/SPARC/base/bitunion.test.opt +""", append=True) + ######################################################################## # From 1e84d9f941d4b5397fc2322bc180d1ec31e00260 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 17 Feb 2022 00:48:54 -0800 Subject: [PATCH 584/693] scons: Add a mechanism to run menuconfig to set up a build dir. If you call scons with the fist argument set to menuconfig, that means to run menuconfig on the path following it. Or in other words, if you ran this command: scons menuconfig build/foo/bar That would tell SCons to set up a build directory at the path build/foo/bar, and then invoke menuconfig so you can set up its configuration. In addition to using this mechanism to set up a new build directory, you can also use it to reconfigure an existing directory. This supplements and does not replace the existing mechanism of using "build/${VARIANT}" to select a config with defconfig. Change-Id: Ief8e8c2ee6477799455c2004bef06c64be5cc1db --- SConstruct | 70 +++++++++++++++++++++++++------- site_scons/gem5_scons/kconfig.py | 13 ++++++ 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/SConstruct b/SConstruct index 3a26e35843..fa51d794a5 100755 --- a/SConstruct +++ b/SConstruct @@ -259,27 +259,60 @@ Targets: # ######################################################################## +kconfig_actions = ('menuconfig',) + +Help(""" +Kconfig: + In addition to the default configs, you can also create your own + configs, or edit one that already exists. To edit or create a config + for a particular directory, give SCons a target which is the directory + to configure, and then "menuconfig". For example: + + scons menuconfig build/foo/bar + + will set up a build directory in build/foo/bar if one doesn't already + exist, and open the menuconfig editor to view/set configuration + values. +""", append=True) + # Take a list of paths (or SCons Nodes) and return a list with all # paths made absolute and ~-expanded. Paths will be interpreted # relative to the launch directory unless a different root is provided + +def makePathAbsolute(path, root=GetLaunchDir()): + return abspath(os.path.join(root, expanduser(str(path)))) def makePathListAbsolute(path_list, root=GetLaunchDir()): - return [abspath(os.path.join(root, expanduser(str(p)))) - for p in path_list] + return [makePathAbsolute(p, root) for p in path_list] -# Each target must have 'build' in the interior of the path; the -# directory below this will determine the build parameters. For -# example, for target 'foo/bar/build/X86/arch/x86/blah.do' we -# recognize that X86 specifies the configuration because it -# follow 'build' in the build path. +if BUILD_TARGETS and BUILD_TARGETS[0] in kconfig_actions: + # The build targets are really arguments for the kconfig action. + kconfig_args = BUILD_TARGETS[:] + BUILD_TARGETS[:] = [] -# The funky assignment to "[:]" is needed to replace the list contents -# in place rather than reassign the symbol to a new list, which -# doesn't work (obviously!). -BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS) + kconfig_action = kconfig_args[0] + if len(kconfig_args) < 2: + error(f'Missing arguments for kconfig action {kconfig_action}') + dir_to_configure = makePathAbsolute(kconfig_args[1]) -# Generate a list of the unique build directories that the collected targets -# reference. -variant_paths = set(map(parse_build_path, BUILD_TARGETS)) + kconfig_args = kconfig_args[2:] + + variant_paths = {dir_to_configure} +else: + # Each target must have 'build' in the interior of the path; the + # directory below this will determine the build parameters. For + # example, for target 'foo/bar/build/X86/arch/x86/blah.do' we + # recognize that X86 specifies the configuration because it + # follow 'build' in the build path. + + # The funky assignment to "[:]" is needed to replace the list contents + # in place rather than reassign the symbol to a new list, which + # doesn't work (obviously!). + BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS) + + # Generate a list of the unique build directories that the collected + # targets reference. + variant_paths = set(map(parse_build_path, BUILD_TARGETS)) + kconfig_action = None ######################################################################## @@ -758,6 +791,15 @@ for variant_path in variant_paths: for cb in after_sconsopts_callbacks: cb() + # Handle any requested kconfig action, then exit. + if kconfig_action: + if kconfig_action == 'menuconfig': + kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, + variant_path) + else: + error(f'Unrecognized kconfig action {kconfig_action}') + Exit(0) + # If no config exists yet, see if we know how to make one? if not isfile(config_file.abspath): buildopts_file = Dir('#build_opts').File(variant_dir) diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index 6c2ec81fa3..d609e24875 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -73,6 +73,19 @@ def defconfig(env, base_kconfig, config_in, config_out): error("Failed to run defconfig") +def menuconfig( + env, base_kconfig, config_path, main_menu_text, style="aquatic" +): + """ + Interface of handling menuconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + kconfig_env["ENV"]["MENUCONFIG_STYLE"] = style + kconfig_env["ENV"]["MAIN_MENU_TEXT"] = main_menu_text + if kconfig_env.Execute('"${MENUCONFIG_PY}" "${BASE_KCONFIG}"') != 0: + error("Failed to run menuconfig") + + def update_env(env, base_kconfig, config_path): """ Update the Scons' env["CONF"] options from kconfig env From 1ae2dfcc56e42e83af20494c9635c33499454058 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:11:07 -0800 Subject: [PATCH 585/693] scons: Add a mechanism to manually defconfig a build dir. This will let you specify *any* defconfig file, instead of implicitly selecting one from the defconfig directory based on the variant name. Change-Id: I74c981b206849f08e60c2df702c06534c670cc7c --- SConstruct | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index fa51d794a5..e27a97eb40 100755 --- a/SConstruct +++ b/SConstruct @@ -259,20 +259,44 @@ Targets: # ######################################################################## -kconfig_actions = ('menuconfig',) +kconfig_actions = ( + 'menuconfig', + 'defconfig', +) Help(""" Kconfig: In addition to the default configs, you can also create your own - configs, or edit one that already exists. To edit or create a config - for a particular directory, give SCons a target which is the directory - to configure, and then "menuconfig". For example: + configs, or edit one that already exists. To use one of the kconfig + tools with a particular directory, use a target which is the directory + to configure, and then the name of the tool. For example, to run + menuconfig on directory build/foo/bar, run: scons menuconfig build/foo/bar will set up a build directory in build/foo/bar if one doesn't already exist, and open the menuconfig editor to view/set configuration values. + + The tools available for working with kconfig are generally very + similar to ones used with the linux kernel, so information about the + kernel versions will typically (but not always) apply here as well. + +Kconfig tools: + menuconfig: + Opens the menuconfig editor which will let you view and edit config + values, and view help text. menuconfig runs in text mode. + + scons menuconfig build/foo/bar + + + defconfig: + Set up a config using values specified in a defconfig file, or if no + value is given, use the default. The second argument specifies the + defconfig file. A defconfig file in the defconfig directory can be + implicitly specified in the build path via `build//` + + scons defconfig build/foo/bar build_opts/MIPS """, append=True) # Take a list of paths (or SCons Nodes) and return a list with all @@ -796,6 +820,12 @@ for variant_path in variant_paths: if kconfig_action == 'menuconfig': kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, variant_path) + elif kconfig_action == 'defconfig': + if len(kconfig_args) != 1: + error('Usage: scons defconfig ') + defconfig_path = makePathAbsolute(kconfig_args[0]) + kconfig.defconfig(env, kconfig_file.abspath, + defconfig_path, config_file.abspath) else: error(f'Unrecognized kconfig action {kconfig_action}') Exit(0) From 083bca1e239c3d4b5b1d690dfcf13227eaea2a0a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:39:44 -0800 Subject: [PATCH 586/693] scons: Hook in the kconfig setconfig utility. This little utility lets you set particular values in an existing config without having to open up the whole menuconfig interface. Also reorganize things in kconfig.py a little to help share code between wrappers. Change-Id: I7cba0c0ef8d318d6c39e49c779ebb2bbdc3d94c8 --- SConstruct | 33 +++++++++++------ site_scons/gem5_scons/kconfig.py | 62 +++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/SConstruct b/SConstruct index e27a97eb40..5ae1080cff 100755 --- a/SConstruct +++ b/SConstruct @@ -260,8 +260,9 @@ Targets: ######################################################################## kconfig_actions = ( - 'menuconfig', 'defconfig', + 'menuconfig', + 'setconfig', ) Help(""" @@ -283,6 +284,15 @@ Kconfig: kernel versions will typically (but not always) apply here as well. Kconfig tools: + defconfig: + Set up a config using values specified in a defconfig file, or if no + value is given, use the default. The second argument specifies the + defconfig file. A defconfig file in the build_opts directory can be + implicitly specified in the build path via `build//` + + scons defconfig build/foo/bar build_opts/MIPS + + menuconfig: Opens the menuconfig editor which will let you view and edit config values, and view help text. menuconfig runs in text mode. @@ -290,13 +300,11 @@ Kconfig tools: scons menuconfig build/foo/bar - defconfig: - Set up a config using values specified in a defconfig file, or if no - value is given, use the default. The second argument specifies the - defconfig file. A defconfig file in the defconfig directory can be - implicitly specified in the build path via `build//` + setconfig: + Set values in an existing config directory as specified on the command + line. For example, to enable gem5's built in systemc kernel: - scons defconfig build/foo/bar build_opts/MIPS + scons setconfig build/foo/bar USE_SYSTEMC=y """, append=True) # Take a list of paths (or SCons Nodes) and return a list with all @@ -817,15 +825,18 @@ for variant_path in variant_paths: # Handle any requested kconfig action, then exit. if kconfig_action: - if kconfig_action == 'menuconfig': - kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, - variant_path) - elif kconfig_action == 'defconfig': + if kconfig_action == 'defconfig': if len(kconfig_args) != 1: error('Usage: scons defconfig ') defconfig_path = makePathAbsolute(kconfig_args[0]) kconfig.defconfig(env, kconfig_file.abspath, defconfig_path, config_file.abspath) + elif kconfig_action == 'menuconfig': + kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, + variant_path) + elif kconfig_action == 'setconfig': + kconfig.setconfig(env, kconfig_file.abspath, config_file.abspath, + ARGUMENTS) else: error(f'Unrecognized kconfig action {kconfig_action}') Exit(0) diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index d609e24875..0251fdd8ea 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -28,6 +28,12 @@ import os from . import error import kconfiglib +_kconfig_helpers = { + "DEFCONFIG_PY": "defconfig.py", + "MENUCONFIG_PY": "menuconfig.py", + "SETCONFIG_PY": "setconfig.py", +} + def _prep_env(env, base_kconfig, config_path=None): """ @@ -47,17 +53,31 @@ def _prep_env(env, base_kconfig, config_path=None): if config_path: kconfig_env["ENV"]["KCONFIG_CONFIG"] = config_path + kconfig_env["BASE_KCONFIG"] = base_kconfig + ext = env.Dir("#ext") kconfiglib_dir = ext.Dir("Kconfiglib") - defconfig_py = kconfiglib_dir.File("defconfig.py") - menuconfig_py = kconfiglib_dir.File("menuconfig.py") - - kconfig_env["DEFCONFIG_PY"] = defconfig_py - kconfig_env["MENUCONFIG_PY"] = menuconfig_py - kconfig_env["BASE_KCONFIG"] = base_kconfig + for key, name in _kconfig_helpers.items(): + kconfig_env[key] = kconfiglib_dir.File(name) return kconfig_env +def _process_kconfig(env, base_kconfig): + """ + Create the kconfig instance by given Scons env vars + + :param env: Scons env + :param base_kconfig: path to the Top-level Kconfig file + """ + saved_env = os.environ + try: + os.environ.update({key: str(val) for key, val in env["ENV"].items()}) + kconfig = kconfiglib.Kconfig(filename=base_kconfig) + finally: + os.environ = saved_env + return kconfig + + def defconfig(env, base_kconfig, config_in, config_out): """ Interface of handling defconfig.py of Kconfiglib @@ -86,6 +106,29 @@ def menuconfig( error("Failed to run menuconfig") +def setconfig(env, base_kconfig, config_path, assignments): + """ + Interface of handling setconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + + kconfig = _process_kconfig(kconfig_env, base_kconfig) + sym_names = list(sym.name for sym in kconfig.unique_defined_syms) + + filtered = dict( + {key: val for key, val in assignments.items() if key in sym_names} + ) + + setconfig_cmd_parts = ['"${SETCONFIG_PY}" --kconfig "${BASE_KCONFIG}"'] + for key, val in filtered.items(): + if isinstance(val, bool): + val = "y" if val else "n" + setconfig_cmd_parts.append(f"{key}={val}") + setconfig_cmd = " ".join(setconfig_cmd_parts) + if kconfig_env.Execute(setconfig_cmd) != 0: + error("Failed to run setconfig") + + def update_env(env, base_kconfig, config_path): """ Update the Scons' env["CONF"] options from kconfig env @@ -96,12 +139,7 @@ def update_env(env, base_kconfig, config_path): """ kconfig_env = _prep_env(env, base_kconfig, config_path) - saved_env = os.environ - os.environ.update( - {key: str(val) for key, val in kconfig_env["ENV"].items()} - ) - kconfig = kconfiglib.Kconfig(filename=base_kconfig) - os.environ = saved_env + kconfig = _process_kconfig(kconfig_env, base_kconfig) kconfig.load_config(config_path) for sym in kconfig.unique_defined_syms: From 91b3da016bd6c7e09f5cca644359deba585b3a9a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:45:56 -0800 Subject: [PATCH 587/693] scons: Hook in the listnewconfig kconfig helper. This helper lists config options which are new in the Kconfig and which are not currently set in the config file. Change-Id: I0c426d85c0cf0d2bdbac599845669165285a82a0 --- SConstruct | 11 +++++++++++ site_scons/gem5_scons/kconfig.py | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/SConstruct b/SConstruct index 5ae1080cff..99b277caae 100755 --- a/SConstruct +++ b/SConstruct @@ -261,6 +261,7 @@ Targets: kconfig_actions = ( 'defconfig', + 'listnewconfig', 'menuconfig', 'setconfig', ) @@ -293,6 +294,13 @@ Kconfig tools: scons defconfig build/foo/bar build_opts/MIPS + listnewconfig: + Lists config options which are new in the Kconfig and which are not + currently set in the existing config file. + + scons listnewconfig build/foo/bar + + menuconfig: Opens the menuconfig editor which will let you view and edit config values, and view help text. menuconfig runs in text mode. @@ -831,6 +839,9 @@ for variant_path in variant_paths: defconfig_path = makePathAbsolute(kconfig_args[0]) kconfig.defconfig(env, kconfig_file.abspath, defconfig_path, config_file.abspath) + elif kconfig_action == 'listnewconfig': + kconfig.listnewconfig(env, kconfig_file.abspath, + config_file.abspath) elif kconfig_action == 'menuconfig': kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, variant_path) diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index 0251fdd8ea..a5fa471b07 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -30,6 +30,7 @@ import kconfiglib _kconfig_helpers = { "DEFCONFIG_PY": "defconfig.py", + "LISTNEWCONFIG_PY": "listnewconfig.py", "MENUCONFIG_PY": "menuconfig.py", "SETCONFIG_PY": "setconfig.py", } @@ -93,6 +94,18 @@ def defconfig(env, base_kconfig, config_in, config_out): error("Failed to run defconfig") +def listnewconfig(env, base_kconfig, config_path): + """ + Interface of handling listnewconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + # Provide a little visual separation between SCons output and + # listnewconfig output. + print() + if kconfig_env.Execute('"${LISTNEWCONFIG_PY}" "${BASE_KCONFIG}"') != 0: + error("Failed to run listnewconfig") + + def menuconfig( env, base_kconfig, config_path, main_menu_text, style="aquatic" ): From 51b8cfcede57badaa4ee21699ce8c0a923098bb3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:52:43 -0800 Subject: [PATCH 588/693] scons: Hook up the kconfig guiconfig program. Change-Id: I0563a2fb2d79cea5974aeaf65a400be5ee51dc63 --- SConstruct | 11 +++++++++++ site_scons/gem5_scons/kconfig.py | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/SConstruct b/SConstruct index 99b277caae..fa321b2873 100755 --- a/SConstruct +++ b/SConstruct @@ -261,6 +261,7 @@ Targets: kconfig_actions = ( 'defconfig', + 'guiconfig', 'listnewconfig', 'menuconfig', 'setconfig', @@ -294,6 +295,13 @@ Kconfig tools: scons defconfig build/foo/bar build_opts/MIPS + guiconfig: + Opens the guiconfig editor which will let you view and edit config + values, and view help text. guiconfig runs as a graphical application. + + scons guiconfig build/foo/bar + + listnewconfig: Lists config options which are new in the Kconfig and which are not currently set in the existing config file. @@ -839,6 +847,9 @@ for variant_path in variant_paths: defconfig_path = makePathAbsolute(kconfig_args[0]) kconfig.defconfig(env, kconfig_file.abspath, defconfig_path, config_file.abspath) + elif kconfig_action == 'guiconfig': + kconfig.guiconfig(env, kconfig_file.abspath, config_file.abspath, + variant_path) elif kconfig_action == 'listnewconfig': kconfig.listnewconfig(env, kconfig_file.abspath, config_file.abspath) diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index a5fa471b07..5638aa7643 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -30,6 +30,7 @@ import kconfiglib _kconfig_helpers = { "DEFCONFIG_PY": "defconfig.py", + "GUICONFIG_PY": "guiconfig.py", "LISTNEWCONFIG_PY": "listnewconfig.py", "MENUCONFIG_PY": "menuconfig.py", "SETCONFIG_PY": "setconfig.py", @@ -94,6 +95,16 @@ def defconfig(env, base_kconfig, config_in, config_out): error("Failed to run defconfig") +def guiconfig(env, base_kconfig, config_path, main_menu_text): + """ + Interface of handling guiconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + kconfig_env["ENV"]["MAIN_MENU_TEXT"] = main_menu_text + if kconfig_env.Execute('"${GUICONFIG_PY}" "${BASE_KCONFIG}"') != 0: + error("Failed to run guiconfig") + + def listnewconfig(env, base_kconfig, config_path): """ Interface of handling listnewconfig.py of Kconfiglib From ec76214f680c824997461638d35654a3d540714b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:59:58 -0800 Subject: [PATCH 589/693] scons: Hook up the savedefconfig kconfig helper. This helper utility lets you save the defconfig which would give rise to a given config. For instance, you could use menuconfig to set up a config how you want it with the options you cared about configured, and then use savedefconfig to save a defconfig of that somewhere to the side, in the gem5 defconfig directory, etc. Then later, you could use that defconfig to set up a new build directory with that same config, even if the kconfig options have changed a little bit since then. A saved defconfig like that can also be a good way to visually see what options have been set to something interesting, and an easier way to pass a config to someone else to use, to put in bug reports, etc. Change-Id: Ifd344278638c59b48c261b36058832034c009c78 --- SConstruct | 18 ++++++++++++++++++ site_scons/gem5_scons/kconfig.py | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/SConstruct b/SConstruct index fa321b2873..57134b6863 100755 --- a/SConstruct +++ b/SConstruct @@ -264,6 +264,7 @@ kconfig_actions = ( 'guiconfig', 'listnewconfig', 'menuconfig', + 'savedefconfig', 'setconfig', ) @@ -316,6 +317,17 @@ Kconfig tools: scons menuconfig build/foo/bar + savedefconfig: + Save a defconfig file which would give rise to the current config. + For instance, you could use menuconfig to set up a config how you want + it with the options you cared about, and then use savedefconfig to save + a minimal config file. These files would be suitable to use in the + defconfig directory. The second argument specifies the filename for + the new defconfig file. + + scons savedefconfig build/foo/bar new_def_config + + setconfig: Set values in an existing config directory as specified on the command line. For example, to enable gem5's built in systemc kernel: @@ -856,6 +868,12 @@ for variant_path in variant_paths: elif kconfig_action == 'menuconfig': kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, variant_path) + elif kconfig_action == 'savedefconfig': + if len(kconfig_args) != 1: + error('Usage: scons defconfig ') + defconfig_path = makePathAbsolute(kconfig_args[0]) + kconfig.savedefconfig(env, kconfig_file.abspath, + config_file.abspath, defconfig_path) elif kconfig_action == 'setconfig': kconfig.setconfig(env, kconfig_file.abspath, config_file.abspath, ARGUMENTS) diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index 5638aa7643..347e11277d 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -33,6 +33,7 @@ _kconfig_helpers = { "GUICONFIG_PY": "guiconfig.py", "LISTNEWCONFIG_PY": "listnewconfig.py", "MENUCONFIG_PY": "menuconfig.py", + "SAVEDEFCONFIG_PY": "savedefconfig.py", "SETCONFIG_PY": "setconfig.py", } @@ -130,6 +131,22 @@ def menuconfig( error("Failed to run menuconfig") +def savedefconfig(env, base_kconfig, config_in, config_out): + """ + Interface of handling savedefconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_in) + kconfig_env["CONFIG_OUT"] = config_out + if ( + kconfig_env.Execute( + '"${SAVEDEFCONFIG_PY}" ' + '--kconfig "${BASE_KCONFIG}" --out "${CONFIG_OUT}"' + ) + != 0 + ): + error("Failed to run savedefconfig") + + def setconfig(env, base_kconfig, config_path, assignments): """ Interface of handling setconfig.py of Kconfiglib From 63919f6a682bc4ee3e9d74491ed0d3540b719670 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 01:11:33 -0800 Subject: [PATCH 590/693] scons: Hook up oldconfig and olddefconfig. These two utilities help update an old config to add settings for new config options. The difference between them is that oldconfig asks what new settings you want to use, while olddefconfig automatically picks the defaults. Change-Id: Icd3e57f834684e620705beb884faa5b6e2cc7baa --- SConstruct | 23 +++++++++++++++++++++++ site_scons/gem5_scons/kconfig.py | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/SConstruct b/SConstruct index 57134b6863..c4782691ff 100755 --- a/SConstruct +++ b/SConstruct @@ -264,6 +264,8 @@ kconfig_actions = ( 'guiconfig', 'listnewconfig', 'menuconfig', + 'oldconfig', + 'olddefconfig', 'savedefconfig', 'setconfig', ) @@ -317,6 +319,22 @@ Kconfig tools: scons menuconfig build/foo/bar + oldconfig: + Update an existing config by adding settings for new options. This is + the same as the olddefconfig tool, except it asks what values you want + for the new settings. + + scons oldconfig build/foo/bar + + + olddefconfig: + Update an existing config by adding settings for new options. This is + the same as the oldconfig tool, except it uses the default for any new + setting. + + scons olddefconfig build/foo/bar + + savedefconfig: Save a defconfig file which would give rise to the current config. For instance, you could use menuconfig to set up a config how you want @@ -868,6 +886,11 @@ for variant_path in variant_paths: elif kconfig_action == 'menuconfig': kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, variant_path) + elif kconfig_action == 'oldconfig': + kconfig.oldconfig(env, kconfig_file.abspath, config_file.abspath) + elif kconfig_action == 'olddefconfig': + kconfig.olddefconfig(env, kconfig_file.abspath, + config_file.abspath) elif kconfig_action == 'savedefconfig': if len(kconfig_args) != 1: error('Usage: scons defconfig ') diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index 347e11277d..42b2eec482 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -33,6 +33,8 @@ _kconfig_helpers = { "GUICONFIG_PY": "guiconfig.py", "LISTNEWCONFIG_PY": "listnewconfig.py", "MENUCONFIG_PY": "menuconfig.py", + "OLDCONFIG_PY": "oldconfig.py", + "OLDDEFCONFIG_PY": "olddefconfig.py", "SAVEDEFCONFIG_PY": "savedefconfig.py", "SETCONFIG_PY": "setconfig.py", } @@ -118,6 +120,24 @@ def listnewconfig(env, base_kconfig, config_path): error("Failed to run listnewconfig") +def oldconfig(env, base_kconfig, config_path): + """ + Interface of handling oldconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + if kconfig_env.Execute('"${OLDCONFIG_PY}" "${BASE_KCONFIG}"') != 0: + error("Failed to run oldconfig") + + +def olddefconfig(env, base_kconfig, config_path): + """ + Interface of handling olddefconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + if kconfig_env.Execute('"${OLDDEFCONFIG_PY}" "${BASE_KCONFIG}"') != 0: + error("Failed to run oldconfig") + + def menuconfig( env, base_kconfig, config_path, main_menu_text, style="aquatic" ): From d37673be9f7c3c0daab596f8957572260cfb2be4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 24 Mar 2022 17:28:26 -0700 Subject: [PATCH 591/693] scons: Remove the default-default build target. In gem5, there are many equally valid and equally useful top level targets which the user might want. It no longer makes sense to arbitrarily pick one to be the default target. It makes sense to force the user to actually specify what they want, instead of assuming it must be the ARM debug binary. There is currently an M5_DEFAULT_BINARY environment variable which will change what the default binary is, if set. This change leaves that in place, but removes the default-default, or in other words the default that is used if M5_DEFAULT_BINARY is not set. This way if the user knows what default they want, they can specify it locally in their environment and avoid having to type it over and over again, but we're not making an arbitrary choice at a more global level without the context to know what actually makes sense. Change-Id: I886adb1289b9879d53387250f950909a4809ed8b --- SConstruct | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index c4782691ff..44b3e8f795 100755 --- a/SConstruct +++ b/SConstruct @@ -196,7 +196,14 @@ if not ('CC' in main and 'CXX' in main): error("No C++ compiler installed (package g++ on Ubuntu and RedHat)") # Find default configuration & binary. -Default(environ.get('M5_DEFAULT_BINARY', 'build/ARM/gem5.debug')) +default_target = environ.get('M5_DEFAULT_BINARY', None) +if default_target: + Default(default_target) + +# If no target is set, even a default, print help instead. +if not BUILD_TARGETS: + warning("No target specified, and no default.") + SetOption('help', True) buildopts_dir = Dir('#build_opts') buildopts = list([f for f in os.listdir(buildopts_dir.abspath) if From d758df4b5ca57dcd1f1b5cd30b272711a60406f5 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 14 Sep 2023 11:41:40 +0800 Subject: [PATCH 592/693] scons: Update the Kconfig build options The CL updates the Kconfig: 1. Replace the USE_NULL_ISA with BUILD_ISA 2. The USE_XXX_ISAs are depends on BUILD_ISA 3. If the BUILD_ISA is set, at least one of USE_XXX_ISAs must be set 4. Refactor the USE_KVM option Change-Id: I2a600dea9fb671263b0191c46c5790ebbe91a7b8 --- build_opts/ALL | 1 + build_opts/ARM | 1 + build_opts/ARM_MESI_Three_Level | 1 + build_opts/ARM_MESI_Three_Level_HTM | 1 + build_opts/ARM_MOESI_hammer | 1 + build_opts/GCN3_X86 | 1 + build_opts/Garnet_standalone | 1 - build_opts/MIPS | 1 + build_opts/NULL | 1 - build_opts/NULL_MESI_Two_Level | 1 - build_opts/NULL_MOESI_CMP_directory | 1 - build_opts/NULL_MOESI_CMP_token | 1 - build_opts/NULL_MOESI_hammer | 1 - build_opts/POWER | 1 + build_opts/RISCV | 1 + build_opts/SPARC | 1 + build_opts/VEGA_X86 | 1 + build_opts/X86 | 1 + build_opts/X86_MESI_Two_Level | 1 + build_opts/X86_MI_example | 1 + build_opts/X86_MOESI_AMD_Base | 1 + src/arch/Kconfig | 13 ++++++++++++- src/arch/SConscript | 25 +++++++++++-------------- src/arch/null/Kconfig | 27 --------------------------- src/cpu/kvm/Kconfig | 3 +-- src/cpu/minor/SConscript | 2 +- src/cpu/o3/SConscript | 2 +- src/cpu/o3/probe/SConscript | 2 +- src/cpu/simple/SConscript | 2 +- src/cpu/simple/probes/SConscript | 2 +- src/python/gem5/runtime.py | 3 +++ 31 files changed, 47 insertions(+), 55 deletions(-) delete mode 100644 src/arch/null/Kconfig diff --git a/build_opts/ALL b/build_opts/ALL index 7597531c3a..b44c7a09f7 100644 --- a/build_opts/ALL +++ b/build_opts/ALL @@ -1,5 +1,6 @@ RUBY=y RUBY_PROTOCOL_MESI_TWO_LEVEL=y +BUILD_ISA=y USE_ARM_ISA=y USE_MIPS_ISA=y USE_POWER_ISA=y diff --git a/build_opts/ARM b/build_opts/ARM index 998b2cf008..b50f366703 100644 --- a/build_opts/ARM +++ b/build_opts/ARM @@ -1,3 +1,4 @@ +BUILD_ISA=y USE_ARM_ISA=y RUBY=y RUBY_PROTOCOL_CHI=y diff --git a/build_opts/ARM_MESI_Three_Level b/build_opts/ARM_MESI_Three_Level index 3782efb706..4cda128fb1 100644 --- a/build_opts/ARM_MESI_Three_Level +++ b/build_opts/ARM_MESI_Three_Level @@ -1,3 +1,4 @@ +BUILD_ISA=y USE_ARM_ISA=y RUBY=y RUBY_PROTOCOL_MESI_THREE_LEVEL=y diff --git a/build_opts/ARM_MESI_Three_Level_HTM b/build_opts/ARM_MESI_Three_Level_HTM index 04e2a5ebe1..ade6a0dfb6 100644 --- a/build_opts/ARM_MESI_Three_Level_HTM +++ b/build_opts/ARM_MESI_Three_Level_HTM @@ -1,3 +1,4 @@ +BUILD_ISA=y USE_ARM_ISA=y RUBY=y RUBY_PROTOCOL_MESI_THREE_LEVEL_HTM=y diff --git a/build_opts/ARM_MOESI_hammer b/build_opts/ARM_MOESI_hammer index ce8509280f..44038ff493 100644 --- a/build_opts/ARM_MOESI_hammer +++ b/build_opts/ARM_MOESI_hammer @@ -1,3 +1,4 @@ +BUILD_ISA=y USE_ARM_ISA=y RUBY=y RUBY_PROTOCOL_MOESI_HAMMER=y diff --git a/build_opts/GCN3_X86 b/build_opts/GCN3_X86 index 6e5534caf8..fd471871b6 100644 --- a/build_opts/GCN3_X86 +++ b/build_opts/GCN3_X86 @@ -1,5 +1,6 @@ RUBY=y RUBY_PROTOCOL_GPU_VIPER=y +BUILD_ISA=y USE_X86_ISA=y GCN3_GPU_ISA=y BUILD_GPU=y diff --git a/build_opts/Garnet_standalone b/build_opts/Garnet_standalone index 7460c9d73a..5df3d6c74f 100644 --- a/build_opts/Garnet_standalone +++ b/build_opts/Garnet_standalone @@ -1,3 +1,2 @@ RUBY=y RUBY_PROTOCOL_GARNET_STANDALONE=y -USE_NULL_ISA=y diff --git a/build_opts/MIPS b/build_opts/MIPS index 40955cf999..e60d44ebc4 100644 --- a/build_opts/MIPS +++ b/build_opts/MIPS @@ -1,3 +1,4 @@ RUBY=y RUBY_PROTOCOL_MI_EXAMPLE=y +BUILD_ISA=y USE_MIPS_ISA=y diff --git a/build_opts/NULL b/build_opts/NULL index d514ef168f..16f4686a5a 100644 --- a/build_opts/NULL +++ b/build_opts/NULL @@ -1,3 +1,2 @@ RUBY=y RUBY_PROTOCOL_MI_EXAMPLE=y -USE_NULL_ISA=y diff --git a/build_opts/NULL_MESI_Two_Level b/build_opts/NULL_MESI_Two_Level index a6279e6b49..57542472df 100644 --- a/build_opts/NULL_MESI_Two_Level +++ b/build_opts/NULL_MESI_Two_Level @@ -1,3 +1,2 @@ RUBY=y RUBY_PROTOCOL_MESI_TWO_LEVEL=y -USE_NULL_ISA=y diff --git a/build_opts/NULL_MOESI_CMP_directory b/build_opts/NULL_MOESI_CMP_directory index 88b1de8dbc..3c5308f525 100644 --- a/build_opts/NULL_MOESI_CMP_directory +++ b/build_opts/NULL_MOESI_CMP_directory @@ -1,3 +1,2 @@ RUBY=y RUBY_PROTOCOL_MOESI_CMP_DIRECTORY=y -USE_NULL_ISA=y diff --git a/build_opts/NULL_MOESI_CMP_token b/build_opts/NULL_MOESI_CMP_token index 5c3308125e..2297bdd722 100644 --- a/build_opts/NULL_MOESI_CMP_token +++ b/build_opts/NULL_MOESI_CMP_token @@ -1,3 +1,2 @@ RUBY=y RUBY_PROTOCOL_MOESI_CMP_TOKEN=y -USE_NULL_ISA=y diff --git a/build_opts/NULL_MOESI_hammer b/build_opts/NULL_MOESI_hammer index 79cc7de4f9..fe63b9c54c 100644 --- a/build_opts/NULL_MOESI_hammer +++ b/build_opts/NULL_MOESI_hammer @@ -1,3 +1,2 @@ RUBY=y RUBY_PROTOCOL_MOESI_HAMMER=y -USE_NULL_ISA=y diff --git a/build_opts/POWER b/build_opts/POWER index 69f5e395cf..02f7e161d2 100644 --- a/build_opts/POWER +++ b/build_opts/POWER @@ -1,3 +1,4 @@ RUBY=y RUBY_PROTOCOL_MI_EXAMPLE=y +BUILD_ISA=y USE_POWER_ISA=y diff --git a/build_opts/RISCV b/build_opts/RISCV index 756c39ec02..c0de30e4b5 100644 --- a/build_opts/RISCV +++ b/build_opts/RISCV @@ -1,3 +1,4 @@ RUBY=y RUBY_PROTOCOL_MI_EXAMPLE=y +BUILD_ISA=y USE_RISCV_ISA=y diff --git a/build_opts/SPARC b/build_opts/SPARC index f2766d5ce4..7f3b544d4a 100644 --- a/build_opts/SPARC +++ b/build_opts/SPARC @@ -1,3 +1,4 @@ RUBY=y RUBY_PROTOCOL_MI_EXAMPLE=y +BUILD_ISA=y USE_SPARC_ISA=y diff --git a/build_opts/VEGA_X86 b/build_opts/VEGA_X86 index 58187a355d..0e070529ad 100644 --- a/build_opts/VEGA_X86 +++ b/build_opts/VEGA_X86 @@ -1,5 +1,6 @@ RUBY=y RUBY_PROTOCOL_GPU_VIPER=y +BUILD_ISA=y USE_X86_ISA=y VEGA_GPU_ISA=y BUILD_GPU=y diff --git a/build_opts/X86 b/build_opts/X86 index 5167bf8c06..6d6f4d523a 100644 --- a/build_opts/X86 +++ b/build_opts/X86 @@ -1,4 +1,5 @@ RUBY=y NUMBER_BITS_PER_SET=128 RUBY_PROTOCOL_MESI_TWO_LEVEL=y +BUILD_ISA=y USE_X86_ISA=y diff --git a/build_opts/X86_MESI_Two_Level b/build_opts/X86_MESI_Two_Level index 5167bf8c06..6d6f4d523a 100644 --- a/build_opts/X86_MESI_Two_Level +++ b/build_opts/X86_MESI_Two_Level @@ -1,4 +1,5 @@ RUBY=y NUMBER_BITS_PER_SET=128 RUBY_PROTOCOL_MESI_TWO_LEVEL=y +BUILD_ISA=y USE_X86_ISA=y diff --git a/build_opts/X86_MI_example b/build_opts/X86_MI_example index 1388769868..4236851d4d 100644 --- a/build_opts/X86_MI_example +++ b/build_opts/X86_MI_example @@ -1,3 +1,4 @@ RUBY=y RUBY_PROTOCOL_MI_EXAMPLE=y +BUILD_ISA=y USE_X86_ISA=y diff --git a/build_opts/X86_MOESI_AMD_Base b/build_opts/X86_MOESI_AMD_Base index 09b50b6558..ffb7fb73c0 100644 --- a/build_opts/X86_MOESI_AMD_Base +++ b/build_opts/X86_MOESI_AMD_Base @@ -1,3 +1,4 @@ RUBY=y RUBY_PROTOCOL_MOESI_AMD_BASE=y +BUILD_ISA=y USE_X86_ISA=y diff --git a/src/arch/Kconfig b/src/arch/Kconfig index 05d637913e..729265c317 100644 --- a/src/arch/Kconfig +++ b/src/arch/Kconfig @@ -28,10 +28,21 @@ config TARGET_GPU_ISA rsource "amdgpu/Kconfig" +config BUILD_ISA + bool "Build the arch ISA" + default n + +menu "ISA" + +if BUILD_ISA + rsource "arm/Kconfig" rsource "mips/Kconfig" -rsource "null/Kconfig" rsource "power/Kconfig" rsource "riscv/Kconfig" rsource "sparc/Kconfig" rsource "x86/Kconfig" + +endif + +endmenu diff --git a/src/arch/SConscript b/src/arch/SConscript index 7285c0ec59..2426401d73 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -56,20 +56,17 @@ Import('*') # ################################################################# -if env['CONF']['USE_ARM_ISA']: - isa = 'arm' -elif env['CONF']['USE_MIPS_ISA']: - isa = 'mips' -elif env['CONF']['USE_POWER_ISA']: - isa = 'power' -elif env['CONF']['USE_RISCV_ISA']: - isa = 'riscv' -elif env['CONF']['USE_SPARC_ISA']: - isa = 'sparc' -elif env['CONF']['USE_X86_ISA']: - isa = 'x86' -elif env['CONF']['USE_NULL_ISA']: - isa = 'null' +if env['CONF']['BUILD_ISA']: + if ( + not env['CONF']['USE_ARM_ISA'] and + not env['CONF']['USE_MIPS_ISA'] and + not env['CONF']['USE_POWER_ISA'] and + not env['CONF']['USE_RISCV_ISA'] and + not env['CONF']['USE_SPARC_ISA'] and + not env['CONF']['USE_X86_ISA'] + ): + error("At least one ISA need to be set") + amdgpu_isa = ['gcn3', 'vega'] diff --git a/src/arch/null/Kconfig b/src/arch/null/Kconfig deleted file mode 100644 index 64151ecf73..0000000000 --- a/src/arch/null/Kconfig +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2022 Google LLC -# -# 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. - -config USE_NULL_ISA - bool "Null ISA support" diff --git a/src/cpu/kvm/Kconfig b/src/cpu/kvm/Kconfig index 824a2e3c41..2b76e94360 100644 --- a/src/cpu/kvm/Kconfig +++ b/src/cpu/kvm/Kconfig @@ -30,5 +30,4 @@ config KVM_ISA config USE_KVM depends on KVM_ISA != "" bool "Enable hardware virtualized (KVM) CPU models" - default y if KVM_ISA != "" - default n + default y diff --git a/src/cpu/minor/SConscript b/src/cpu/minor/SConscript index 9603b4114c..0b98037d6d 100644 --- a/src/cpu/minor/SConscript +++ b/src/cpu/minor/SConscript @@ -40,7 +40,7 @@ Import('*') -if not env['CONF']['USE_NULL_ISA']: +if env['CONF']['BUILD_ISA']: SimObject('BaseMinorCPU.py', sim_objects=[ 'MinorOpClass', 'MinorOpClassSet', 'MinorFUTiming', 'MinorFU', 'MinorFUPool', 'BaseMinorCPU'], diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript index 2ac703b041..c49db9373d 100755 --- a/src/cpu/o3/SConscript +++ b/src/cpu/o3/SConscript @@ -30,7 +30,7 @@ import sys Import('*') -if not env['CONF']['USE_NULL_ISA']: +if env['CONF']['BUILD_ISA']: SimObject('FUPool.py', sim_objects=['FUPool']) SimObject('FuncUnitConfig.py', sim_objects=[]) SimObject('BaseO3CPU.py', sim_objects=['BaseO3CPU'], enums=[ diff --git a/src/cpu/o3/probe/SConscript b/src/cpu/o3/probe/SConscript index 6039ef2eb9..3065e50a8c 100644 --- a/src/cpu/o3/probe/SConscript +++ b/src/cpu/o3/probe/SConscript @@ -37,7 +37,7 @@ Import('*') -if not env['CONF']['USE_NULL_ISA']: +if env['CONF']['BUILD_ISA']: SimObject('SimpleTrace.py', sim_objects=['SimpleTrace']) Source('simple_trace.cc') DebugFlag('SimpleTrace') diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript index ffa6467e9b..f2552012bf 100644 --- a/src/cpu/simple/SConscript +++ b/src/cpu/simple/SConscript @@ -28,7 +28,7 @@ Import('*') -if not env['CONF']['USE_NULL_ISA']: +if env['CONF']['BUILD_ISA']: SimObject('BaseAtomicSimpleCPU.py', sim_objects=['BaseAtomicSimpleCPU']) Source('atomic.cc') diff --git a/src/cpu/simple/probes/SConscript b/src/cpu/simple/probes/SConscript index e9fbbb306c..3af318f76f 100644 --- a/src/cpu/simple/probes/SConscript +++ b/src/cpu/simple/probes/SConscript @@ -28,6 +28,6 @@ Import('*') -if not env['CONF']['USE_NULL_ISA']: +if env['CONF']['BUILD_ISA']: SimObject('SimPoint.py', sim_objects=['SimPoint']) Source('simpoint.cc') diff --git a/src/python/gem5/runtime.py b/src/python/gem5/runtime.py index 6eed62a9da..9118237f37 100644 --- a/src/python/gem5/runtime.py +++ b/src/python/gem5/runtime.py @@ -42,6 +42,9 @@ def get_supported_isas() -> Set[ISA]: """ supported_isas = set() + if not buildEnv["BUILD_ISA"]: + return {ISA.NULL} + if "TARGET_ISA" in buildEnv.keys(): supported_isas.add(get_isa_from_str(buildEnv["TARGET_ISA"])) From 3b06925408369cfe75236adc4de3027cd2c63d02 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 14 Sep 2023 11:45:55 +0800 Subject: [PATCH 593/693] scons: Update Kconfig description Change-Id: I69206fb9881bc0d53660bbd1cf8fc225ead9fea3 --- SConstruct | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/SConstruct b/SConstruct index 44b3e8f795..77bbd3a866 100755 --- a/SConstruct +++ b/SConstruct @@ -216,10 +216,10 @@ Help(f""" Targets: To build gem5 using a predefined configuration, use a target with a directory called "build" in the path, followed by a directory named - after a predefined configuration, and then the actual target, likely - a gem5 binary. For example: + after a predefined configuration in "build_opts" directory, and then + the actual target, likely a gem5 binary. For example: - scons build/X86/gem5.opt + scons build/ALL/gem5.opt The "build" component tells SCons that the next part names an initial configuration, and the part after that is the actual target. @@ -237,11 +237,15 @@ Targets: disabled. gem5 can also be built as a static or dynamic library. In that case, - the extension is fixed by the operating system, so the binary type + the extension is determined by the operating system, so the binary type is part of the target file name. For example: scons build/ARM/libgem5_opt.so + In MacOS, the extension should change to "dylib" like this: + + scons build/ARM/libgem5_opt.dylib + To build unit tests, you can use a target like this: scons build/RISCV/unittests.debug @@ -283,18 +287,14 @@ Kconfig: configs, or edit one that already exists. To use one of the kconfig tools with a particular directory, use a target which is the directory to configure, and then the name of the tool. For example, to run - menuconfig on directory build/foo/bar, run: + menuconfig on directory build_foo/bar, run: - scons menuconfig build/foo/bar + scons menuconfig build_foo/bar - will set up a build directory in build/foo/bar if one doesn't already + will set up a build directory in build_foo/bar if one doesn't already exist, and open the menuconfig editor to view/set configuration values. - The tools available for working with kconfig are generally very - similar to ones used with the linux kernel, so information about the - kernel versions will typically (but not always) apply here as well. - Kconfig tools: defconfig: Set up a config using values specified in a defconfig file, or if no @@ -302,28 +302,28 @@ Kconfig tools: defconfig file. A defconfig file in the build_opts directory can be implicitly specified in the build path via `build//` - scons defconfig build/foo/bar build_opts/MIPS + scons defconfig build_foo/bar build_opts/MIPS guiconfig: Opens the guiconfig editor which will let you view and edit config values, and view help text. guiconfig runs as a graphical application. - scons guiconfig build/foo/bar + scons guiconfig build_foo/bar listnewconfig: Lists config options which are new in the Kconfig and which are not currently set in the existing config file. - scons listnewconfig build/foo/bar + scons listnewconfig build_foo/bar menuconfig: Opens the menuconfig editor which will let you view and edit config values, and view help text. menuconfig runs in text mode. - scons menuconfig build/foo/bar + scons menuconfig build_foo/bar oldconfig: @@ -331,7 +331,7 @@ Kconfig tools: the same as the olddefconfig tool, except it asks what values you want for the new settings. - scons oldconfig build/foo/bar + scons oldconfig build_foo/bar olddefconfig: @@ -339,7 +339,7 @@ Kconfig tools: the same as the oldconfig tool, except it uses the default for any new setting. - scons olddefconfig build/foo/bar + scons olddefconfig build_foo/bar savedefconfig: @@ -350,14 +350,14 @@ Kconfig tools: defconfig directory. The second argument specifies the filename for the new defconfig file. - scons savedefconfig build/foo/bar new_def_config + scons savedefconfig build_foo/bar new_def_config setconfig: Set values in an existing config directory as specified on the command line. For example, to enable gem5's built in systemc kernel: - scons setconfig build/foo/bar USE_SYSTEMC=y + scons setconfig build_foo/bar USE_SYSTEMC=y """, append=True) # Take a list of paths (or SCons Nodes) and return a list with all @@ -907,8 +907,6 @@ for variant_path in variant_paths: elif kconfig_action == 'setconfig': kconfig.setconfig(env, kconfig_file.abspath, config_file.abspath, ARGUMENTS) - else: - error(f'Unrecognized kconfig action {kconfig_action}') Exit(0) # If no config exists yet, see if we know how to make one? From 7b35765217c9caa9713789a35c06f4482f281fb8 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Wed, 18 Oct 2023 11:33:39 +0800 Subject: [PATCH 594/693] scons: Refactor the USE_SYSTEMC option Change-Id: I2f51081e0db932b83eea9dd395551afe13d54a34 --- src/systemc/Kconfig | 6 +++++- src/systemc/SConsopts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/systemc/Kconfig b/src/systemc/Kconfig index 3f3df93f53..3dde45d8da 100644 --- a/src/systemc/Kconfig +++ b/src/systemc/Kconfig @@ -23,6 +23,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +config HAVE_SYSTEMC + def_bool "$(HAVE_SYSTEMC)" + config USE_SYSTEMC + depends on HAVE_SYSTEMC bool "Enable SystemC API support" - default $(USE_SYSTEMC) + default y diff --git a/src/systemc/SConsopts b/src/systemc/SConsopts index 20436ec81b..e7d9c04fd1 100644 --- a/src/systemc/SConsopts +++ b/src/systemc/SConsopts @@ -44,4 +44,4 @@ def use_systemc_check(env, warn=False): main.AddMethod(use_systemc_check, 'UseSystemcCheck') -main['CONF']['USE_SYSTEMC'] = main.UseSystemcCheck() +main['CONF']['HAVE_SYSTEMC'] = main.UseSystemcCheck() From 758f9d2ea1625c659258b4da98cd3efea30774b2 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 19 Oct 2023 08:43:35 +0800 Subject: [PATCH 595/693] util: Add python3-tk package to dockerfile The guiconfig required the python3-tk package to run. Change-Id: I1d126021c2c57448b1ceefb9fff256e2a6bbbf33 --- util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile | 2 +- util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile index 8f092adc7a..80580edf41 100644 --- a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile @@ -32,7 +32,7 @@ RUN apt -y update && apt -y upgrade && \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev python-is-python3 doxygen libboost-all-dev \ libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config pip \ - python3-venv black gcc-10 g++-10 + python3-venv black gcc-10 g++-10 python3-tk RUN pip install mypy pre-commit diff --git a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile index 9e2580e642..21626ed994 100644 --- a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile @@ -31,6 +31,6 @@ RUN apt -y update && apt -y upgrade && \ apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev doxygen libboost-all-dev libhdf5-serial-dev python3-pydot \ - libpng-dev libelf-dev pkg-config pip python3-venv black + libpng-dev libelf-dev pkg-config pip python3-venv black python3-tk RUN pip install mypy pre-commit From 5b212334913d6f9f23cd835979c938db9d9bc070 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 19 Oct 2023 13:11:05 +0800 Subject: [PATCH 596/693] tests: Update Gem5Fixture to compatible of Kconfig system Used after the build system changed to Kconfig Change-Id: I699b36f09691dc821da8ee80fe5b60f30fe2179c --- tests/gem5/fixture.py | 68 ++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index da2cf11be2..94596f4f5c 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -151,9 +151,44 @@ class SConsFixture(UniqueFixture): if config.skip_build: return - def _setup(self, testitem): - if config.skip_build: - return + if not self.targets: + log.test_log.error("No SCons targets specified.") + else: + log.test_log.message( + "Building the following targets. This may take a while." + ) + log.test_log.message(f"{', '.join(self.targets)}") + log.test_log.message( + "You may want to use --skip-build, or use 'rerun'." + ) + + if self.protocol: + defconfig_command = [ + "scons", + "-C", + self.directory, + "--ignore-style", + "--no-compress-debug", + "defconfig", + self.target_dir, + joinpath(self.directory, "build_opts", self.isa.upper()), + ] + setconfig_command = [ + "scons", + "-C", + self.directory, + "--ignore-style", + "--no-compress-debug", + "setconfig", + self.target_dir, + f"RUBY_PROTOCOL_{self.protocol.upper()}=y", + ] + log_call( + log.test_log, defconfig_command, time=None, stderr=sys.stderr + ) + log_call( + log.test_log, setconfig_command, time=None, stderr=sys.stderr + ) command = [ "scons", @@ -164,26 +199,7 @@ class SConsFixture(UniqueFixture): "--ignore-style", "--no-compress-debug", ] - - if not self.targets: - log.test_log.warn( - "No SCons targets specified, this will" - " build the default all target.\n" - "This is likely unintended, and you" - " may wish to kill testlib and reconfigure." - ) - else: - log.test_log.message( - "Building the following targets. This may take a while." - ) - log.test_log.message(f"{', '.join(self.targets)}") - log.test_log.message( - "You may want to use --skip-build, or use 'rerun'." - ) - command.extend(self.targets) - if self.options: - command.extend(self.options) log_call(log.test_log, command, time=None, stderr=sys.stderr) @@ -194,6 +210,7 @@ class Gem5Fixture(SConsFixture): target_dir += "_" + protocol target = joinpath(target_dir, f"gem5.{variant}") obj = super().__new__(cls, target) + obj.target_dir = target_dir return obj def _init(self, isa, variant, protocol=None): @@ -203,15 +220,12 @@ class Gem5Fixture(SConsFixture): self.path = self.target self.directory = config.base_dir - self.options = [] - if protocol: - self.options = ["--default=" + isa.upper(), "PROTOCOL=" + protocol] + self.isa = isa + self.protocol = protocol self.set_global() def get_get_build_info(self) -> Optional[str]: build_target = self.target - if self.options: - build_target += " ".join(self.options) return build_target From 5828b1eb32b439d3695df2568c807045553182ae Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 19 Oct 2023 13:22:35 +0800 Subject: [PATCH 597/693] misc: Update daily-test.yaml to match Kconfig build system configuration Change-Id: I20b04d006c67374e3226a91c03550f2731ed7fe7 --- .github/workflows/daily-tests.yaml | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/daily-tests.yaml b/.github/workflows/daily-tests.yaml index 89a72fd852..987f5c1ad2 100644 --- a/.github/workflows/daily-tests.yaml +++ b/.github/workflows/daily-tests.yaml @@ -28,15 +28,20 @@ jobs: # the default is to add -j $(nproc), but some images # require more specifications when built include: - - command-line: -j $(nproc) + - setconfig-option: '' + - isa-option: '' - image: ALL_CHI - command-line: --default=ALL PROTOCOL=CHI -j $(nproc) + setconfig-option: RUBY_PROTOCOL_CHI=y + isa-option: ALL - image: ALL_MSI - command-line: --default=ALL PROTOCOL=MSI -j $(nproc) + setconfig-option: RUBY_PROTOCOL_MSI=y + isa-option: ALL - image: ALL_MESI_Two_Level - command-line: --default=ALL PROTOCOL=MESI_Two_Level -j $(nproc) + setconfig-option: RUBY_PROTOCOL_MESI_TWO_LEVEL=y + isa-option: ALL - image: NULL_MI_example - command-line: --default=NULL PROTOCOL=MI_example -j $(nproc) + setconfig-option: RUBY_PROTOCOL_MI_EXAMPLE=y + isa-option: 'NULL' runs-on: [self-hosted, linux, x64] needs: name-artifacts container: ghcr.io/gem5/ubuntu-22.04_all-dependencies:latest @@ -46,8 +51,14 @@ jobs: # Scheduled workflows run on the default branch by default. We # therefore need to explicitly checkout the develop branch. ref: develop + - name: defconfig gem5 + if: ${{ matrix.setconfig-option != '' }} + run: scons defconfig build/${{ matrix.image }} build_opts/${{ matrix.isa-option }} + - name: setconfig gem5 + if: ${{ matrix.setconfig-option != '' }} + run: scons setconfig build/${{ matrix.image }} ${{ matrix.setconfig-option }} - name: Build gem5 - run: scons build/${{ matrix.image }}/gem5.opt ${{ matrix.command-line }} + run: scons build/${{ matrix.image }}/gem5.opt -j $(nproc) - uses: actions/upload-artifact@v3 with: name: ${{ needs.name-artifacts.outputs.build-name }}${{ matrix.image }} @@ -245,8 +256,10 @@ jobs: ref: develop - name: Build ARM/gem5.opt run: scons build/ARM/gem5.opt --ignore-style --duplicate-sources -j$(nproc) + - name: disable systemc + run: scons setconfig build/ARM --ignore-style USE_SYSTEMC=n - name: Build ARM/libgem5_opt.so - run: scons build/ARM/libgem5_opt.so --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 -j$(nproc) --duplicate-sources + run: scons build/ARM/libgem5_opt.so --with-cxx-config --without-python --without-tcmalloc -j$(nproc) --duplicate-sources - name: Compile gem5 withing SystemC working-directory: ${{ github.workspace }}/util/systemc/gem5_within_systemc run: make From 4d632cb73fbac542fcc625dd0a70ab2ba97721d4 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 24 Oct 2023 10:34:31 +0800 Subject: [PATCH 598/693] scons: Add new config option HAVE_CAPSTONE to Kconfig The config option HAVE_CAPSTONE is added in the previous [1] and the Kconfig options should be sync with it. [1] https://github.com/gem5/gem5/pull/494 Change-Id: Id83718bc825f53d87d37d6ac930b96371209bdb3 --- src/Kconfig | 2 +- src/cpu/Kconfig | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/cpu/Kconfig diff --git a/src/Kconfig b/src/Kconfig index 02bf90ab86..2d24aad1ad 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -48,6 +48,6 @@ rsource "learning_gem5/part3/Kconfig" rsource "proto/Kconfig" rsource "dev/net/Kconfig" rsource "arch/Kconfig" -rsource "cpu/kvm/Kconfig" +rsource "cpu/Kconfig" rsource "systemc/Kconfig" rsource "gpu-compute/Kconfig" diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig new file mode 100644 index 0000000000..33a00e9c45 --- /dev/null +++ b/src/cpu/Kconfig @@ -0,0 +1,29 @@ +# Copyright 2023 Google LLC +# +# 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. + +config HAVE_CAPSTONE + def_bool $(HAVE_CAPSTONE) + +rsource "kvm/Kconfig" From 23e4525e29cc3580ed32506f587a5a6739b755ea Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 23 Nov 2023 08:41:37 +0800 Subject: [PATCH 599/693] util: Update the tlm README Change-Id: I4006257bf55d7065136347788783796fd39ab725 --- util/tlm/README | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/util/tlm/README b/util/tlm/README index 3ae43c5909..1dbfe41ae7 100644 --- a/util/tlm/README +++ b/util/tlm/README @@ -93,13 +93,14 @@ without python. > cd ../.. > scons build/ARM/gem5.opt -> scons --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 \ -> build/ARM/libgem5_opt.so +> scons setconfig build/ARM USE_SYSTEMC=n +> scons --with-cxx-config --without-python --without-tcmalloc \ +> --duplicate-sources build/ARM/libgem5_opt.so > cd util/tlm Note: For MAC / OSX this command should be used: -> scons --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 \ -> build/ARM/libgem5_opt.dylib +> scons --with-cxx-config --without-python --without-tcmalloc \ +> --duplicate-sources build/ARM/libgem5_opt.dylib To build all sources of the SystemC binding and the examples simply run scons: From 412cf3e644e32f0caa217bd759fe465fdd01881f Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 23 Nov 2023 08:46:27 +0800 Subject: [PATCH 600/693] util: Update the gem5_within_systemc README Change-Id: Ife34fe5ccd00fa2c6a83f34af49333d49017dfed --- util/systemc/gem5_within_systemc/README | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/util/systemc/gem5_within_systemc/README b/util/systemc/gem5_within_systemc/README index bcaaceeb77..8d396c15ad 100644 --- a/util/systemc/gem5_within_systemc/README +++ b/util/systemc/gem5_within_systemc/README @@ -36,12 +36,13 @@ present in the "build" directory. > cd ../../.. > scons build/ARM/gem5.opt -> scons --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 \ +> scons setconfig build/ARM USE_SYSTEMC=n +> scons --with-cxx-config --without-python --without-tcmalloc \ > --duplicate-source build/ARM/libgem5_opt.so > cd util/systemc Note: For MAC / OSX this command should be used: -> scons --with-cxx-config --without-python --without-tcmalloc USE_SYSTEMC=0 \ +> scons --with-cxx-config --without-python --without-tcmalloc \ > --duplicate-sources build/ARM/libgem5_opt.dylib Set a proper LD_LIBRARY_PATH e.g. for bash: @@ -67,7 +68,7 @@ Then run make: Make a config file for the C++-configured gem5 using normal gem5 -> ../../../build/ARM/gem5.opt ../../../configs/example/se.py -c \ +> ../../../build/ARM/gem5.opt ../../../configs/deprecated/example/se.py -c \ > ../../../tests/test-progs/hello/bin/arm/linux/hello The binary 'gem5.opt.cxx' can now be used to load in the generated config From 92670e974561f6f0dfcacf81ba9b43a0826d623e Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Thu, 23 Nov 2023 14:15:28 +0800 Subject: [PATCH 601/693] fastmodel: Simply the logic of USE_ARM_FASTMODEL setting Change-Id: Ib00cf83ca881727987050a987a2adb1e9f9d31ef --- src/arch/arm/fastmodel/SConscript | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript index f8cfd5991c..8b1ab6af05 100644 --- a/src/arch/arm/fastmodel/SConscript +++ b/src/arch/arm/fastmodel/SConscript @@ -48,11 +48,7 @@ from gem5_scons import Transform, warning, error import os.path if env['CONF']['USE_ARM_FASTMODEL']: - if env['CONF']['USE_SYSTEMC']: - env.TagImplies('arm fastmodel', 'arm isa') - else: - warning('ARM Fast Models require systemc support') - env['CONF']['USE_ARM_FASTMODEL'] = False + env.TagImplies('arm fastmodel', 'arm isa') systemc_home = Dir('#/src/systemc/ext/systemc_home') From cea169f5e7d382f520ebdab07c0779d66e795c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20G=C3=B3mez=20Hern=C3=A1ndez?= Date: Thu, 23 Nov 2023 09:52:41 +0100 Subject: [PATCH 602/693] arch-x86: Fix segment registers in instructions 8C and 8E MOV instructions 8C and 8E can be prefixed with a REX prefix to extend the source/destination register. However, the R bit in REX will be applied to the segment register. The decoder file checks for valid segment registers, checking the MODRM_REG only, however, later this will be extended with the REX_R when adding the register to the sources/destinations of the instruction. This will trigger an assert. This patch checks that the REX_R is not set, otherwise, UD2 will be generated. Change-Id: I78a93c35116232fe37e5ec50025e721b8c633c5f --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index ef596dfd71..13b05e62ff 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -287,25 +287,31 @@ 0x1: MOV(Ev,Gv); 0x2: MOV(Gb,Eb); 0x3: MOV(Gv,Ev); - 0x4: decode MODRM_REG { - 0x0, 0x1, 0x2, - 0x3, 0x4, 0x5: MOV(Ev,Sv); + 0x4: decode REX_R { + 0x0: decode MODRM_REG { + 0x0, 0x1, 0x2, + 0x3, 0x4, 0x5: MOV(Ev,Sv); + } + default: UD2(); } 0x5: LEA(Gv,M); - 0x6: decode MODE_SUBMODE { - 0x3, 0x4: decode MODRM_REG { - // Moving to the CS selector (0x1) is illegal, and 0x6 and - // 0x7 are reserved. - 0x1, 0x6, 0x7: UD2(); - default: MOV_REAL(Sv,Ev); - } - default: decode MODRM_REG { - // Moving to the CS selector (0x1) is illegal, and 0x6 and - // 0x7 are reserved. - 0x1, 0x6, 0x7: UD2(); - 0x2: MOVSS(Sv,Ev); - default: MOV(Sv,Ev); + 0x6: decode REX_R { + 0x0: decode MODE_SUBMODE { + 0x3, 0x4: decode MODRM_REG { + // Moving to the CS selector (0x1) is illegal, and 0x6 and + // 0x7 are reserved. + 0x1, 0x6, 0x7: UD2(); + default: MOV_REAL(Sv,Ev); + } + default: decode MODRM_REG { + // Moving to the CS selector (0x1) is illegal, and 0x6 and + // 0x7 are reserved. + 0x1, 0x6, 0x7: UD2(); + 0x2: MOVSS(Sv,Ev); + default: MOV(Sv,Ev); + } } + default: UD2(); } //0x7: group10_Ev(); 0x7: decode MODRM_REG { From 670bf6a488a12a61840655644d4c0baf4377ecf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20G=C3=B3mez=20Hern=C3=A1ndez?= Date: Fri, 24 Nov 2023 13:33:38 +0100 Subject: [PATCH 603/693] arch-x86: Check REX_R for MOV misc registers Change-Id: I08ea37ffe695df500ea84cbddd94be246f916caf --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index dac5706a06..48c3a2d20d 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -287,24 +287,27 @@ 0x6: HINT_NOP(); 0x7: HINT_NOP(); } - 0x04: decode LEGACY_DECODEVAL { - // no prefix - 0x0: decode OPCODE_OP_BOTTOM3 { - 0x0: Cpl0CondInst::MOV( - {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Rd,Cd); - 0x1: Cpl0CondInst::MOV({{MODRM_REG < 8}},Rd,Dd); - 0x2: Cpl0CondInst::MOV( - {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Cd,Rd); - 0x3: Cpl0CondInst::MOV({{MODRM_REG < 8}},Dd,Rd); + 0x04: decode REX_R { + 0x0: decode LEGACY_DECODEVAL { + // no prefix + 0x0: decode OPCODE_OP_BOTTOM3 { + 0x6: Cpl0CondInst::MOV( + {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Rd,Cd); + 0x1: Cpl0CondInst::MOV({{MODRM_REG < 8}},Rd,Dd); + 0x2: Cpl0CondInst::MOV( + {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Cd,Rd); + 0x3: Cpl0CondInst::MOV({{MODRM_REG < 8}},Dd,Rd); + default: UD2(); + } + // operand size (0x66) + 0x1: decode OPCODE_OP_BOTTOM3 { + 0x0: Cpl0CondInst::MOV( + {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Rd,Cd); + 0x2: Cpl0CondInst::MOV( + {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Cd,Rd); + } default: UD2(); } - // operand size (0x66) - 0x1: decode OPCODE_OP_BOTTOM3 { - 0x0: Cpl0CondInst::MOV( - {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Rd,Cd); - 0x2: Cpl0CondInst::MOV( - {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Cd,Rd); - } default: UD2(); } 0x05: decode LEGACY_DECODEVAL { From cb61d01ededc4ef6d7297f6064b71ac0b198e020 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 20 Nov 2023 13:24:32 -0800 Subject: [PATCH 604/693] ext: Add 'cmake' dep check to DRAMSys install CMake is not required to build gem5. It is only required to build and link the optional DRAMSysm library. Therefore, if the DRAMSys repo has been cloned but CMake is not present this patch ensures no attempt at building or linking DRAMSysm is made. A warning is thrown inform the user of the missing CMake. Change-Id: I4d22e3a16655fd90f6b109b4e75859628f7d532d --- ext/dramsys/SConscript | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ext/dramsys/SConscript b/ext/dramsys/SConscript index 0cf163aede..bfe4ee5ec1 100644 --- a/ext/dramsys/SConscript +++ b/ext/dramsys/SConscript @@ -27,6 +27,10 @@ import os import subprocess +from shutil import which + +from gem5_scons import warning + Import("env") build_root = Dir("../..").abspath @@ -40,6 +44,16 @@ if not os.path.exists(Dir(".").srcnode().abspath + "/DRAMSys"): env["HAVE_DRAMSYS"] = False Return() +# DRAMSys requires CMake to build but this is is not a dependency for +# gem5 outside of this DRAMSys integration. Therefore, we do not fail the +# entire gem5 build if CMake is not found. Instead we just skip the building of +# DRAMSys and print a warning. +if which("cmake") is None: + warning("The DRAMSys repo is present but CMake cannot be found. " + "DRAMSys will not be built.") + env["HAVE_DRAMSYS"] = False + Return() + env["HAVE_DRAMSYS"] = True subprocess.run( From 575114b63b39e1b102eb58fcdc72ed2277466784 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 20 Nov 2023 13:31:42 -0800 Subject: [PATCH 605/693] ext: Add .gitignore to ext/dramsys Change-Id: Ifc1a3c77b56cbe5777d041a88b2c0d5cb77eaf89 --- ext/dramsys/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 ext/dramsys/.gitignore diff --git a/ext/dramsys/.gitignore b/ext/dramsys/.gitignore new file mode 100644 index 0000000000..0193b6e8f3 --- /dev/null +++ b/ext/dramsys/.gitignore @@ -0,0 +1 @@ +DRAMSys From 8f9a3286529a81903ed4434e85d791e1aac69775 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 20 Nov 2023 13:32:10 -0800 Subject: [PATCH 606/693] util-docker: Add 'cmake' to all-deps 'cmake' is required to build DRAMSysm. This is an optional dependency for compiling DRAMSys. It is therefore not required. It is included in the "all-dependencies" Docker images as they may be needed if DRAMSys is desired. Change-Id: I1a3e1a6fa2da4d0116d423e9267d4d3095000d4e --- util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile | 2 +- util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile index 8f092adc7a..ba3d554c3b 100644 --- a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile @@ -32,7 +32,7 @@ RUN apt -y update && apt -y upgrade && \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev python-is-python3 doxygen libboost-all-dev \ libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config pip \ - python3-venv black gcc-10 g++-10 + python3-venv black gcc-10 g++-10 cmake RUN pip install mypy pre-commit diff --git a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile index 9e2580e642..679248a081 100644 --- a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile @@ -31,6 +31,6 @@ RUN apt -y update && apt -y upgrade && \ apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev doxygen libboost-all-dev libhdf5-serial-dev python3-pydot \ - libpng-dev libelf-dev pkg-config pip python3-venv black + libpng-dev libelf-dev pkg-config pip python3-venv black cmake RUN pip install mypy pre-commit From 36e83943b594c829e2f3d97e709fab30516a6bd4 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 20 Nov 2023 13:35:19 -0800 Subject: [PATCH 607/693] tests,misc: Update DRAMSys test clone command This clone is updated to reflect the new advice given in ext/dramasys/README that was introduced in PR https://github.com/gem5/gem5/pull/525 to upgrade DRAMSysm to v5.0. Change-Id: I868619ecc1a44298dd3885e5719979bdaa24e9c2 --- .github/workflows/weekly-tests.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/weekly-tests.yaml b/.github/workflows/weekly-tests.yaml index 72b1454a5e..6c211435c2 100644 --- a/.github/workflows/weekly-tests.yaml +++ b/.github/workflows/weekly-tests.yaml @@ -89,11 +89,7 @@ jobs: - name: Checkout DRAMSys working-directory: ${{ github.workspace }}/ext/dramsys - run: | - git clone https://github.com/tukl-msd/DRAMSys DRAMSys - cd DRAMSys - git checkout -b gem5 09f6dcbb91351e6ee7cadfc7bc8b29d97625db8f - git submodule update --init --recursive + run: git clone https://github.com/tukl-msd/DRAMSys --branch v5.0 --depth 1 DRAMSys # gem5 is built separately because it depends on the DRAMSys library - name: Build gem5 From cc9f81b08a0493d82a10145f15d36f9453e3625b Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Sun, 26 Nov 2023 23:22:01 -0800 Subject: [PATCH 608/693] arch-vega,arch-gcn3: Bugfix V_PERM_B32 and V_OR3_B32 (#599) The V_PERM_B32 instruction is selecting the correct byte, but is shifting into place moving by bits instead of bytes. The V_OR3_B32 instruction is calling the wrong instruction implementation in the decoder. This patch fixes both issues plus a bonus fix for GCN3's V_PERM_B32. (GCN3 does not have V_OR3_B32). Change-Id: Ied66c43981bc4236f680db42a9868f760becc284 --- src/arch/amdgpu/gcn3/insts/instructions.cc | 2 +- src/arch/amdgpu/vega/decoder.cc | 2 +- src/arch/amdgpu/vega/insts/instructions.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arch/amdgpu/gcn3/insts/instructions.cc b/src/arch/amdgpu/gcn3/insts/instructions.cc index 478b1d38d0..b9d29a2204 100644 --- a/src/arch/amdgpu/gcn3/insts/instructions.cc +++ b/src/arch/amdgpu/gcn3/insts/instructions.cc @@ -29692,7 +29692,7 @@ namespace Gcn3ISA for (int i = 0; i < 4 ; ++i) { VecElemU32 permuted_val = permute(selector, 0xFF & ((VecElemU32)src2[lane] >> (8 * i))); - vdst[lane] |= (permuted_val << i); + vdst[lane] |= (permuted_val << (8 * i)); } DPRINTF(GCN3, "v_perm result: 0x%08x\n", vdst[lane]); diff --git a/src/arch/amdgpu/vega/decoder.cc b/src/arch/amdgpu/vega/decoder.cc index a86dd668ec..065f8c8493 100644 --- a/src/arch/amdgpu/vega/decoder.cc +++ b/src/arch/amdgpu/vega/decoder.cc @@ -7020,7 +7020,7 @@ namespace VegaISA GPUStaticInst* Decoder::decode_OPU_VOP3__V_OR3_B32(MachInst iFmt) { - return new Inst_VOP3__V_OR_B32(&iFmt->iFmt_VOP3A); + return new Inst_VOP3__V_OR3_B32(&iFmt->iFmt_VOP3A); } GPUStaticInst* diff --git a/src/arch/amdgpu/vega/insts/instructions.cc b/src/arch/amdgpu/vega/insts/instructions.cc index 74b6abee62..cd4ad74e6e 100644 --- a/src/arch/amdgpu/vega/insts/instructions.cc +++ b/src/arch/amdgpu/vega/insts/instructions.cc @@ -32671,7 +32671,7 @@ namespace VegaISA for (int i = 0; i < 4 ; ++i) { VecElemU32 permuted_val = permute(selector, 0xFF & ((VecElemU32)src2[lane] >> (8 * i))); - vdst[lane] |= (permuted_val << i); + vdst[lane] |= (permuted_val << (8 * i)); } DPRINTF(VEGA, "v_perm result: 0x%08x\n", vdst[lane]); From 1de992bc757e59c592df13e94c9299d3544330ff Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Mon, 27 Nov 2023 07:42:59 -0800 Subject: [PATCH 609/693] tests: fix lulesh (#600) - fixed the broken command that was causing lulesh to fail the run Change-Id: I4e8a310f153d86deb8829f41b5ddd0c317df23cb --- .github/workflows/gpu-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index b390e0750f..7edcab5ba5 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -61,7 +61,7 @@ jobs: working-directory: ${{ github.workspace }} run: | build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --mem-size=8GB --reg-alloc-policy=dynamic --benchmark-root="lulesh" -c \ - lulesh 0.01 2 + lulesh --options="0.01 2" HACC-tests: runs-on: [self-hosted, linux, x64] From 9e6a87e67a907ee04b06eeaa1d34e5549dbed7ce Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Mon, 27 Nov 2023 11:02:11 -0800 Subject: [PATCH 610/693] dev-amdgpu: Writeback PM4 queue rptr when empty (#597) The GPU device keeps a local copy of each ring buffers read pointer (rptr) to avoid constant DMAs to/from host memory. This means it needs to be periodically updated on the host side as the driver uses this to determine how much space is left in the queue and may hang if it believe the queue is full. For user-mode queues, this already happens when queues are unmapped. For kernel mode queues (e.g., HIQ, KIQ) the rptr is never updated leading to a hang. In this patch the rptr for *all* queues is reported back to the kernel whenever the queue reaches an empty state (rptr == wptr). Additionally to handle PM4 queue wrap-around, the queue processing function checks if the queue is not empty instead of rptr < wptr. This is state because the driver fills PM4 queues with NOP packets on initialization and when wrap around occurs. Change-Id: Ie13a4354f82999208a75bb1eaec70513039ff30f --- src/dev/amdgpu/pm4_packet_processor.cc | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/dev/amdgpu/pm4_packet_processor.cc b/src/dev/amdgpu/pm4_packet_processor.cc index 352af400b0..5f270a0c70 100644 --- a/src/dev/amdgpu/pm4_packet_processor.cc +++ b/src/dev/amdgpu/pm4_packet_processor.cc @@ -168,7 +168,7 @@ PM4PacketProcessor::decodeNext(PM4Queue *q) DPRINTF(PM4PacketProcessor, "PM4 decode queue %d rptr %p, wptr %p\n", q->id(), q->rptr(), q->wptr()); - if (q->rptr() < q->wptr()) { + if (q->rptr() != q->wptr()) { /* Additional braces here are needed due to a clang compilation bug falsely throwing a "suggest braces around initialization of subject" error. More info on this bug is available here: @@ -181,11 +181,28 @@ PM4PacketProcessor::decodeNext(PM4Queue *q) dmaReadVirt(getGARTAddr(q->rptr()), sizeof(uint32_t), cb, &cb->dmaBuffer); } else { + // Reached the end of processable data in the queue. Switch out of IB + // if this is an indirect buffer. + assert(q->rptr() == q->wptr()); q->processing(false); if (q->ib()) { q->ib(false); decodeNext(q); } + + // Write back rptr when the queue is empty. For static queues which + // are not unmapped, this is how the driver knows there is enough + // space in the queue to continue writing packets to the ring buffer. + if (q->getMQD()->aqlRptr) { + Addr addr = getGARTAddr(q->getMQD()->aqlRptr); + uint32_t *data = new uint32_t; + // gem5 stores rptr as a bytes offset while the driver expects + // a dword offset. Convert the offset to dword count. + *data = q->getRptr() >> 2; + auto cb = new DmaVirtCallback( + [data](const uint32_t &) { delete data; }); + dmaWriteVirt(addr, sizeof(uint32_t), cb, data); + } } } From 9a0566e295d54d9748bd91d0ba2a5a618726eafc Mon Sep 17 00:00:00 2001 From: Aditya K Kamath Date: Wed, 22 Nov 2023 20:09:45 +0000 Subject: [PATCH 611/693] arch-x86: Fixes page fault for CLFLUSH on write-protected pages Converts CLFLUSHOPT/WB/FLUSH operations from Write to Read operations during address translation so that they don't trigger a page fault when done on write-protected pages. Change-Id: I20e89cc0cb2b288b36ba1f0ba39a2e1bf0f728af --- src/arch/x86/tlb.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 5ccd3e832d..c7d144bd8a 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -509,6 +509,9 @@ TLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) { bool delayedResponse; + // CLFLUSHOPT/WB/FLUSH should be treated as read for protection checks + if (req->isCacheClean()) + mode = BaseMMU::Read; return TLB::translate(req, tc, NULL, mode, delayedResponse, false); } @@ -516,6 +519,9 @@ Fault TLB::translateFunctional(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) { + // CLFLUSHOPT/WB/FLUSH should be treated as read for protection checks + if (req->isCacheClean()) + mode = BaseMMU::Read; unsigned logBytes; const Addr vaddr = req->getVaddr(); Addr addr = vaddr; @@ -553,6 +559,9 @@ TLB::translateTiming(const RequestPtr &req, ThreadContext *tc, { bool delayedResponse; assert(translation); + // CLFLUSHOPT/WB/FLUSH should be treated as read for protection checks + if (req->isCacheClean()) + mode = BaseMMU::Read; Fault fault = TLB::translate(req, tc, translation, mode, delayedResponse, true); if (!delayedResponse) From f745e8cf89e31abe7957109cc8ae02eb634b025e Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 30 Oct 2023 10:37:56 +0800 Subject: [PATCH 612/693] arch-riscv: Initial the privilege modes configuration 1. Declare the new enum type PrivilegeModes 2. Disallow setting the MISA register RVU and RVS. Change-Id: I932d714bc70c9720a706353c557a5be76c950f81 --- src/arch/riscv/RiscvISA.py | 15 +++++++++++++++ src/arch/riscv/SConscript | 2 +- src/arch/riscv/isa.cc | 29 +++++++++++++++++++++++++---- src/arch/riscv/isa.hh | 7 +++++++ src/arch/riscv/pcstate.hh | 3 +++ 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index bce7f2497f..5d53c882aa 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -74,6 +74,16 @@ class RiscvType(Enum): vals = ["RV32", "RV64"] +class PrivilegeModeSet(Enum): + vals = [ + "M", # Machine privilege mode only + "MU", # Machine and user privlege modes implemented + "MNU", # MU privilege modes with user-mode trap + "MSU", # Machine, supervisor and user modes implemented + "MNSU", # MSU privilege modes with user-mode trap + ] + + class RiscvISA(BaseISA): type = "RiscvISA" cxx_class = "gem5::RiscvISA::ISA" @@ -95,6 +105,11 @@ class RiscvISA(BaseISA): "Length of each vector element in bits. \ ELEN in Ch. 2 of RISC-V vector spec", ) + privilege_mode_set = Param.PrivilegeModeSet( + "MSU", + "The combination of privilege modes \ + in Privilege Levels section of RISC-V privileged spec", + ) enable_Zicbom_fs = Param.Bool(True, "Enable Zicbom extension in FS mode") enable_Zicboz_fs = Param.Bool(True, "Enable Zicboz extension in FS mode") diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript index d3dd1d5970..41da97bcc1 100644 --- a/src/arch/riscv/SConscript +++ b/src/arch/riscv/SConscript @@ -73,7 +73,7 @@ SimObject('RiscvFsWorkload.py', SimObject('RiscvInterrupts.py', sim_objects=['RiscvInterrupts'], tags='riscv isa') SimObject('RiscvISA.py', sim_objects=['RiscvISA'], - enums=['RiscvType'], tags='riscv isa') + enums=['RiscvType', 'PrivilegeModeSet'], tags='riscv isa') SimObject('RiscvMMU.py', sim_objects=['RiscvMMU'], tags='riscv isa') SimObject('RiscvSeWorkload.py', sim_objects=[ 'RiscvSEWorkload', 'RiscvEmuLinux'], tags='riscv isa') diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 0ba6d15b6c..81fb7f3061 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -254,9 +254,10 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs); } // anonymous namespace -ISA::ISA(const Params &p) :BaseISA(p), +ISA::ISA(const Params &p) : BaseISA(p), _rvType(p.riscv_type), checkAlignment(p.check_alignment), - enableRvv(p.enable_rvv),vlen(p.vlen),elen(p.elen) + enableRvv(p.enable_rvv), vlen(p.vlen), elen(p.elen), + _privilegeModeSet(p.privilege_mode_set) { _regClasses.push_back(&intRegClass); _regClasses.push_back(&floatRegClass); @@ -324,8 +325,25 @@ void ISA::clear() // default config arch isa string is rv64(32)imafdc misa.rvi = misa.rvm = misa.rva = misa.rvf = misa.rvd = misa.rvc = 1; - // default privlege modes if MSU - misa.rvs = misa.rvu = 1; + + switch (getPrivilegeModeSet()) { + case enums::M: + break; + case enums::MU: + misa.rvu = 1; + break; + case enums::MNU: + misa.rvu = misa.rvn = 1; + break; + case enums::MSU: + misa.rvs = misa.rvu = 1; + break; + case enums::MNSU: + misa.rvs = misa.rvu = misa.rvn = 1; + break; + default: + panic("Privilege mode set config should not reach here"); + } // mark FS is initial status.fs = INITIAL; @@ -697,6 +715,9 @@ ISA::setMiscReg(RegIndex idx, RegVal val) if (!getEnableRvv()) { new_misa.rvv = 0; } + new_misa.rvn = cur_misa.rvn; + new_misa.rvs = cur_misa.rvs; + new_misa.rvu = cur_misa.rvu; setMiscRegNoEffect(idx, new_misa); } break; diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 66cba0f7fa..6a3547ab2c 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -94,6 +94,11 @@ class ISA : public BaseISA */ unsigned elen; + /** The combination of privilege modes + * in Privilege Levels section of RISC-V privileged spec + */ + PrivilegeModeSet _privilegeModeSet; + public: using Params = RiscvISAParams; @@ -164,6 +169,8 @@ class ISA : public BaseISA unsigned getVecLenInBytes() { return vlen >> 3; } unsigned getVecElemLenInBits() { return elen; } + PrivilegeModeSet getPrivilegeModeSet() { return _privilegeModeSet; } + virtual Addr getFaultHandlerAddr( RegIndex idx, uint64_t cause, bool intr) const; }; diff --git a/src/arch/riscv/pcstate.hh b/src/arch/riscv/pcstate.hh index 91fb507034..62ecd9f960 100644 --- a/src/arch/riscv/pcstate.hh +++ b/src/arch/riscv/pcstate.hh @@ -44,6 +44,7 @@ #include "arch/generic/pcstate.hh" #include "arch/riscv/regs/vector.hh" +#include "enums/PrivilegeModeSet.hh" #include "enums/RiscvType.hh" namespace gem5 @@ -55,6 +56,8 @@ using RiscvType = enums::RiscvType; constexpr enums::RiscvType RV32 = enums::RV32; constexpr enums::RiscvType RV64 = enums::RV64; +using PrivilegeModeSet = enums::PrivilegeModeSet; + class PCState : public GenericISA::UPCState<4> { protected: From 0e4f82a1194a926498b791bc9dd55686dbad5bab Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 30 Oct 2023 15:59:32 +0800 Subject: [PATCH 613/693] arch-riscv: define the CSR masks for each privilege modes Change-Id: I9936d9bc816921a827b94550847d4898b3aa3292 --- src/arch/riscv/isa.hh | 2 +- src/arch/riscv/regs/misc.hh | 383 +++++++++++++++++++++++++++++------ src/arch/riscv/remote_gdb.cc | 81 +++++--- 3 files changed, 366 insertions(+), 100 deletions(-) diff --git a/src/arch/riscv/isa.hh b/src/arch/riscv/isa.hh index 6a3547ab2c..9a24a76745 100644 --- a/src/arch/riscv/isa.hh +++ b/src/arch/riscv/isa.hh @@ -129,7 +129,7 @@ class ISA : public BaseISA virtual const std::unordered_map& getCSRMaskMap() const { - return CSRMasks[_rvType]; + return CSRMasks[_rvType][_privilegeModeSet]; } bool alignmentCheckEnabled() const { return checkAlignment; } diff --git a/src/arch/riscv/regs/misc.hh b/src/arch/riscv/regs/misc.hh index d36776d7ef..7f7621f8ea 100644 --- a/src/arch/riscv/regs/misc.hh +++ b/src/arch/riscv/regs/misc.hh @@ -1118,41 +1118,137 @@ const RegVal STATUS_UPIE_MASK = 1ULL << 4; const RegVal STATUS_MIE_MASK = 1ULL << 3; const RegVal STATUS_SIE_MASK = 1ULL << 1; const RegVal STATUS_UIE_MASK = 1ULL << 0; -const RegVal MSTATUS_MASKS[enums::Num_RiscvType] = { - [RV32] = STATUS_SD_MASKS[RV32] | STATUS_TSR_MASK | STATUS_TW_MASK | - STATUS_TVM_MASK | STATUS_MXR_MASK | STATUS_SUM_MASK | - STATUS_MPRV_MASK | STATUS_XS_MASK | STATUS_FS_MASK | - STATUS_VS_MASK | STATUS_MPP_MASK | STATUS_SPP_MASK | - STATUS_MPIE_MASK | STATUS_SPIE_MASK | STATUS_UPIE_MASK | - STATUS_MIE_MASK | STATUS_SIE_MASK | STATUS_UIE_MASK, - [RV64] = STATUS_SD_MASKS[RV64] | STATUS_MBE_MASK[RV64] | - STATUS_SBE_MASK[RV64] | STATUS_SXL_MASK | STATUS_UXL_MASK | - STATUS_TSR_MASK | STATUS_TW_MASK | STATUS_TVM_MASK | - STATUS_MXR_MASK | STATUS_SUM_MASK | STATUS_MPRV_MASK | - STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK| - STATUS_MPP_MASK | STATUS_SPP_MASK | STATUS_MPIE_MASK | - STATUS_SPIE_MASK | STATUS_UPIE_MASK | STATUS_MIE_MASK | - STATUS_SIE_MASK | STATUS_UIE_MASK, +const RegVal +MSTATUS_MASKS[enums::Num_RiscvType][enums::Num_PrivilegeModeSet] = { + [RV32] = { + [enums::M] = STATUS_SD_MASKS[RV32] | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPIE_MASK | STATUS_MIE_MASK, + [enums::MU] = STATUS_SD_MASKS[RV32] | STATUS_TW_MASK | + STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | STATUS_MPIE_MASK | STATUS_MIE_MASK, + [enums::MNU] = STATUS_SD_MASKS[RV32] | STATUS_TW_MASK | + STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | + STATUS_MPIE_MASK | STATUS_UPIE_MASK | + STATUS_MIE_MASK | STATUS_UIE_MASK, + [enums::MSU] = STATUS_SD_MASKS[RV32] | STATUS_TSR_MASK | + STATUS_TW_MASK | STATUS_TVM_MASK | STATUS_MXR_MASK | + STATUS_SUM_MASK | STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | STATUS_SPP_MASK | + STATUS_MPIE_MASK | STATUS_SPIE_MASK | + STATUS_MIE_MASK | STATUS_SIE_MASK, + [enums::MNSU] = STATUS_SD_MASKS[RV32] | STATUS_TSR_MASK | + STATUS_TW_MASK | STATUS_TVM_MASK | STATUS_MXR_MASK | + STATUS_SUM_MASK | STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | STATUS_SPP_MASK | + STATUS_MPIE_MASK | STATUS_SPIE_MASK | + STATUS_UPIE_MASK | STATUS_MIE_MASK | STATUS_SIE_MASK | + STATUS_UIE_MASK, + }, + [RV64] = { + [enums::M] = STATUS_SD_MASKS[RV64] | STATUS_MBE_MASK[RV64] | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPIE_MASK | STATUS_MIE_MASK, + [enums::MU] = STATUS_SD_MASKS[RV64] | STATUS_MBE_MASK[RV64] | + STATUS_UXL_MASK | STATUS_TW_MASK | STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | STATUS_MPIE_MASK | STATUS_MIE_MASK, + [enums::MNU] = STATUS_SD_MASKS[RV64] | STATUS_MBE_MASK[RV64] | + STATUS_UXL_MASK | STATUS_TW_MASK | STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | + STATUS_MPIE_MASK | STATUS_UPIE_MASK | + STATUS_MIE_MASK | STATUS_UIE_MASK, + [enums::MSU] = STATUS_SD_MASKS[RV64] | + STATUS_MBE_MASK[RV64] | STATUS_SBE_MASK[RV64] | + STATUS_SXL_MASK | STATUS_UXL_MASK | + STATUS_TSR_MASK | STATUS_TW_MASK | STATUS_TVM_MASK | + STATUS_MXR_MASK | STATUS_SUM_MASK | STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | STATUS_SPP_MASK | + STATUS_MPIE_MASK | STATUS_SPIE_MASK | + STATUS_MIE_MASK | STATUS_SIE_MASK, + [enums::MNSU] = STATUS_SD_MASKS[RV64] | + STATUS_MBE_MASK[RV64] | STATUS_SBE_MASK[RV64] | + STATUS_SXL_MASK | STATUS_UXL_MASK | + STATUS_TSR_MASK | STATUS_TW_MASK | STATUS_TVM_MASK | + STATUS_MXR_MASK | STATUS_SUM_MASK | STATUS_MPRV_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_MPP_MASK | STATUS_SPP_MASK | + STATUS_MPIE_MASK | STATUS_SPIE_MASK | STATUS_UPIE_MASK | + STATUS_MIE_MASK | STATUS_SIE_MASK | STATUS_UIE_MASK, + }, }; // rv32 only -const RegVal MSTATUSH_MASKS = STATUS_MBE_MASK[RV32] | STATUS_SBE_MASK[RV32]; -const RegVal SSTATUS_MASKS[enums::Num_RiscvType] = { - [RV32] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | STATUS_SUM_MASK | - STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | - STATUS_SPP_MASK | STATUS_SPIE_MASK | STATUS_UPIE_MASK | - STATUS_SIE_MASK | STATUS_UIE_MASK, - [RV64] = STATUS_SD_MASKS[RV64] | STATUS_UXL_MASK | STATUS_MXR_MASK | - STATUS_SUM_MASK | STATUS_XS_MASK | STATUS_FS_MASK | - STATUS_VS_MASK | STATUS_SPP_MASK | STATUS_SPIE_MASK | - STATUS_UPIE_MASK | STATUS_SIE_MASK | STATUS_UIE_MASK, +const RegVal MSTATUSH_MASKS[enums::Num_PrivilegeModeSet] = { + [enums::M] = STATUS_MBE_MASK[RV32], + [enums::MU] = STATUS_MBE_MASK[RV32], + [enums::MNU] = STATUS_MBE_MASK[RV32], + [enums::MSU] = STATUS_MBE_MASK[RV32] | STATUS_SBE_MASK[RV32], + [enums::MNSU] = STATUS_MBE_MASK[RV32] | STATUS_SBE_MASK[RV32], }; -const RegVal USTATUS_MASKS[enums::Num_RiscvType] = { - [RV32] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | STATUS_SUM_MASK | - STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | - STATUS_UPIE_MASK | STATUS_UIE_MASK, - [RV64] = STATUS_SD_MASKS[RV64] | STATUS_MXR_MASK | STATUS_SUM_MASK | - STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | - STATUS_UPIE_MASK | STATUS_UIE_MASK, +const RegVal +SSTATUS_MASKS[enums::Num_RiscvType][enums::Num_PrivilegeModeSet] = { + [RV32] = { + [enums::M] = 0ULL, + [enums::MU] = 0ULL, + [enums::MNU] = 0ULL, + [enums::MSU] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | + STATUS_SUM_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_SPP_MASK | STATUS_SPIE_MASK | STATUS_SIE_MASK, + [enums::MNSU] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | + STATUS_SUM_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_SPP_MASK | STATUS_SPIE_MASK | STATUS_UPIE_MASK | + STATUS_SIE_MASK | STATUS_UIE_MASK, + }, + [RV64] = { + [enums::M] = 0ULL, + [enums::MU] = 0ULL, + [enums::MNU] = 0ULL, + [enums::MSU] = STATUS_SD_MASKS[RV64] | STATUS_UXL_MASK | + STATUS_MXR_MASK | STATUS_SUM_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_SPP_MASK | STATUS_SPIE_MASK | STATUS_SIE_MASK, + [enums::MNSU] = STATUS_SD_MASKS[RV64] | STATUS_UXL_MASK | + STATUS_MXR_MASK | STATUS_SUM_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_SPP_MASK | STATUS_SPIE_MASK | + STATUS_UPIE_MASK | STATUS_SIE_MASK | STATUS_UIE_MASK, + }, +}; +const RegVal +USTATUS_MASKS[enums::Num_RiscvType][enums::Num_PrivilegeModeSet] = { + [RV32] = { + [enums::M] = 0ULL, + [enums::MU] = 0ULL, + [enums::MNU] = STATUS_SD_MASKS[RV32] | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_UPIE_MASK | STATUS_UIE_MASK, + [enums::MSU] = 0ULL, + [enums::MNSU] = STATUS_SD_MASKS[RV32] | STATUS_MXR_MASK | + STATUS_SUM_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_UPIE_MASK | STATUS_UIE_MASK, + }, + [RV64] = { + [enums::M] = 0ULL, + [enums::MU] = 0ULL, + [enums::MNU] = STATUS_SD_MASKS[RV64] | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_UPIE_MASK | STATUS_UIE_MASK, + [enums::MSU] = 0ULL, + [enums::MNSU] = STATUS_SD_MASKS[RV64] | STATUS_MXR_MASK | + STATUS_SUM_MASK | + STATUS_XS_MASK | STATUS_FS_MASK | STATUS_VS_MASK | + STATUS_UPIE_MASK | STATUS_UIE_MASK, + }, }; const RegVal MEI_MASK = 1ULL << 11; @@ -1164,13 +1260,33 @@ const RegVal UTI_MASK = 1ULL << 4; const RegVal MSI_MASK = 1ULL << 3; const RegVal SSI_MASK = 1ULL << 1; const RegVal USI_MASK = 1ULL << 0; -const RegVal MI_MASK = MEI_MASK | SEI_MASK | UEI_MASK | - MTI_MASK | STI_MASK | UTI_MASK | - MSI_MASK | SSI_MASK | USI_MASK; -const RegVal SI_MASK = SEI_MASK | UEI_MASK | - STI_MASK | UTI_MASK | - SSI_MASK | USI_MASK; -const RegVal UI_MASK = UEI_MASK | UTI_MASK | USI_MASK; +const RegVal MI_MASK[enums::Num_PrivilegeModeSet] = { + [enums::M] = MEI_MASK| MTI_MASK | MSI_MASK, + [enums::MU] = MEI_MASK| MTI_MASK | MSI_MASK, + [enums::MNU] = MEI_MASK | UEI_MASK | MTI_MASK | UTI_MASK | + MSI_MASK | USI_MASK, + [enums::MSU] = MEI_MASK | SEI_MASK | MTI_MASK | STI_MASK | + MSI_MASK | SSI_MASK, + [enums::MNSU] = MEI_MASK | SEI_MASK | UEI_MASK | + MTI_MASK | STI_MASK | UTI_MASK | + MSI_MASK | SSI_MASK | USI_MASK, +}; +const RegVal SI_MASK[enums::Num_PrivilegeModeSet] = { + [enums::M] = 0ULL, + [enums::MU] = 0ULL, + [enums::MNU] = UEI_MASK | UTI_MASK | USI_MASK, + [enums::MSU] = SEI_MASK | STI_MASK | SSI_MASK, + [enums::MNSU] = SEI_MASK | UEI_MASK | + STI_MASK | UTI_MASK | + SSI_MASK | USI_MASK, +}; +const RegVal UI_MASK[enums::Num_PrivilegeModeSet] = { + [enums::M] = 0ULL, + [enums::MU] = 0ULL, + [enums::MNU] = UEI_MASK | UTI_MASK | USI_MASK, + [enums::MSU] = 0ULL, + [enums::MNSU] = UEI_MASK | UTI_MASK | USI_MASK, +}; const RegVal FFLAGS_MASK = (1 << FRM_OFFSET) - 1; const RegVal FRM_MASK = 0x7; @@ -1179,34 +1295,167 @@ const RegVal CAUSE_INTERRUPT_MASKS[enums::Num_RiscvType] = { [RV64] = (1ULL << 63), }; -const std::unordered_map CSRMasks[enums::Num_RiscvType] = { - [RV32] = {{CSR_USTATUS, USTATUS_MASKS[RV32]}, - {CSR_UIE, UI_MASK}, - {CSR_UIP, UI_MASK}, - {CSR_FFLAGS, FFLAGS_MASK}, - {CSR_FRM, FRM_MASK}, - {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, - {CSR_SSTATUS, SSTATUS_MASKS[RV32]}, - {CSR_SIE, SI_MASK}, - {CSR_SIP, SI_MASK}, - {CSR_MSTATUS, MSTATUS_MASKS[RV32]}, - {CSR_MISA, MISA_MASKS[RV32]}, - {CSR_MIE, MI_MASK}, - {CSR_MSTATUSH, MSTATUSH_MASKS}, - {CSR_MIP, MI_MASK}}, - [RV64] = {{CSR_USTATUS, USTATUS_MASKS[RV64]}, - {CSR_UIE, UI_MASK}, - {CSR_UIP, UI_MASK}, - {CSR_FFLAGS, FFLAGS_MASK}, - {CSR_FRM, FRM_MASK}, - {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, - {CSR_SSTATUS, SSTATUS_MASKS[RV64]}, - {CSR_SIE, SI_MASK}, - {CSR_SIP, SI_MASK}, - {CSR_MSTATUS, MSTATUS_MASKS[RV64]}, - {CSR_MISA, MISA_MASKS[RV64]}, - {CSR_MIE, MI_MASK}, - {CSR_MIP, MI_MASK}}, +const std::unordered_map +CSRMasks[enums::Num_RiscvType][enums::Num_PrivilegeModeSet] = { + [RV32] = { + [enums::M] = { + {CSR_USTATUS, USTATUS_MASKS[RV32][enums::M]}, + {CSR_UIE, UI_MASK[enums::M]}, + {CSR_UIP, UI_MASK[enums::M]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV32][enums::M]}, + {CSR_SIE, SI_MASK[enums::M]}, + {CSR_SIP, SI_MASK[enums::M]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV32][enums::M]}, + {CSR_MISA, MISA_MASKS[RV32]}, + {CSR_MIE, MI_MASK[enums::M]}, + {CSR_MSTATUSH, MSTATUSH_MASKS[enums::M]}, + {CSR_MIP, MI_MASK[enums::M]}, + }, + [enums::MU] = { + {CSR_USTATUS, USTATUS_MASKS[RV32][enums::MU]}, + {CSR_UIE, UI_MASK[enums::MU]}, + {CSR_UIP, UI_MASK[enums::MU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV32][enums::MU]}, + {CSR_SIE, SI_MASK[enums::MU]}, + {CSR_SIP, SI_MASK[enums::MU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV32][enums::MU]}, + {CSR_MISA, MISA_MASKS[RV32]}, + {CSR_MIE, MI_MASK[enums::MU]}, + {CSR_MSTATUSH, MSTATUSH_MASKS[enums::MU]}, + {CSR_MIP, MI_MASK[enums::MU]}, + }, + [enums::MNU] = { + {CSR_USTATUS, USTATUS_MASKS[RV32][enums::MNU]}, + {CSR_UIE, UI_MASK[enums::MNU]}, + {CSR_UIP, UI_MASK[enums::MNU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV32][enums::MNU]}, + {CSR_SIE, SI_MASK[enums::MNU]}, + {CSR_SIP, SI_MASK[enums::MNU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV32][enums::MNU]}, + {CSR_MISA, MISA_MASKS[RV32]}, + {CSR_MIE, MI_MASK[enums::MNU]}, + {CSR_MSTATUSH, MSTATUSH_MASKS[enums::MNU]}, + {CSR_MIP, MI_MASK[enums::MNU]}, + }, + [enums::MSU] = { + {CSR_USTATUS, USTATUS_MASKS[RV32][enums::MSU]}, + {CSR_UIE, UI_MASK[enums::MSU]}, + {CSR_UIP, UI_MASK[enums::MSU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV32][enums::MSU]}, + {CSR_SIE, SI_MASK[enums::MSU]}, + {CSR_SIP, SI_MASK[enums::MSU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV32][enums::MSU]}, + {CSR_MISA, MISA_MASKS[RV32]}, + {CSR_MIE, MI_MASK[enums::MSU]}, + {CSR_MSTATUSH, MSTATUSH_MASKS[enums::MSU]}, + {CSR_MIP, MI_MASK[enums::MSU]}, + }, + [enums::MNSU] = { + {CSR_USTATUS, USTATUS_MASKS[RV32][enums::MNSU]}, + {CSR_UIE, UI_MASK[enums::MNSU]}, + {CSR_UIP, UI_MASK[enums::MNSU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV32][enums::MNSU]}, + {CSR_SIE, SI_MASK[enums::MNSU]}, + {CSR_SIP, SI_MASK[enums::MNSU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV32][enums::MNSU]}, + {CSR_MISA, MISA_MASKS[RV32]}, + {CSR_MIE, MI_MASK[enums::MNSU]}, + {CSR_MSTATUSH, MSTATUSH_MASKS[enums::MNSU]}, + {CSR_MIP, MI_MASK[enums::MNSU]}, + }, + }, + [RV64] = { + [enums::M] = { + {CSR_USTATUS, USTATUS_MASKS[RV64][enums::M]}, + {CSR_UIE, UI_MASK[enums::M]}, + {CSR_UIP, UI_MASK[enums::M]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV64][enums::M]}, + {CSR_SIE, SI_MASK[enums::M]}, + {CSR_SIP, SI_MASK[enums::M]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV64][enums::M]}, + {CSR_MISA, MISA_MASKS[RV64]}, + {CSR_MIE, MI_MASK[enums::M]}, + {CSR_MIP, MI_MASK[enums::M]}, + }, + [enums::MU] = { + {CSR_USTATUS, USTATUS_MASKS[RV64][enums::MU]}, + {CSR_UIE, UI_MASK[enums::MU]}, + {CSR_UIP, UI_MASK[enums::MU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV64][enums::MU]}, + {CSR_SIE, SI_MASK[enums::MU]}, + {CSR_SIP, SI_MASK[enums::MU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV64][enums::MU]}, + {CSR_MISA, MISA_MASKS[RV64]}, + {CSR_MIE, MI_MASK[enums::MU]}, + {CSR_MIP, MI_MASK[enums::MU]}, + }, + [enums::MNU] = { + {CSR_USTATUS, USTATUS_MASKS[RV64][enums::MNU]}, + {CSR_UIE, UI_MASK[enums::MNU]}, + {CSR_UIP, UI_MASK[enums::MNU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV64][enums::MNU]}, + {CSR_SIE, SI_MASK[enums::MNU]}, + {CSR_SIP, SI_MASK[enums::MNU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV64][enums::MNU]}, + {CSR_MISA, MISA_MASKS[RV64]}, + {CSR_MIE, MI_MASK[enums::MNU]}, + {CSR_MIP, MI_MASK[enums::MNU]}, + }, + [enums::MSU] = { + {CSR_USTATUS, USTATUS_MASKS[RV64][enums::MSU]}, + {CSR_UIE, UI_MASK[enums::MSU]}, + {CSR_UIP, UI_MASK[enums::MSU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV64][enums::MSU]}, + {CSR_SIE, SI_MASK[enums::MSU]}, + {CSR_SIP, SI_MASK[enums::MSU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV64][enums::MSU]}, + {CSR_MISA, MISA_MASKS[RV64]}, + {CSR_MIE, MI_MASK[enums::MSU]}, + {CSR_MIP, MI_MASK[enums::MSU]}, + }, + [enums::MNSU] = { + {CSR_USTATUS, USTATUS_MASKS[RV64][enums::MNSU]}, + {CSR_UIE, UI_MASK[enums::MNSU]}, + {CSR_UIP, UI_MASK[enums::MNSU]}, + {CSR_FFLAGS, FFLAGS_MASK}, + {CSR_FRM, FRM_MASK}, + {CSR_FCSR, FFLAGS_MASK | (FRM_MASK << FRM_OFFSET)}, + {CSR_SSTATUS, SSTATUS_MASKS[RV64][enums::MNSU]}, + {CSR_SIE, SI_MASK[enums::MNSU]}, + {CSR_SIP, SI_MASK[enums::MNSU]}, + {CSR_MSTATUS, MSTATUS_MASKS[RV64][enums::MNSU]}, + {CSR_MISA, MISA_MASKS[RV64]}, + {CSR_MIE, MI_MASK[enums::MNSU]}, + {CSR_MIP, MI_MASK[enums::MNSU]}, + }, + }, }; } // namespace RiscvISA diff --git a/src/arch/riscv/remote_gdb.cc b/src/arch/riscv/remote_gdb.cc index 48ce1d5d3b..df660d40d2 100644 --- a/src/arch/riscv/remote_gdb.cc +++ b/src/arch/riscv/remote_gdb.cc @@ -167,13 +167,22 @@ getRvType(ThreadContext* tc) return isa->rvType(); } +static PrivilegeModeSet +getPrivilegeModeSet(ThreadContext* tc) +{ + auto isa = dynamic_cast(tc->getIsaPtr()); + panic_if(!isa, "Cannot derive rv_type from non-riscv isa"); + return isa->getPrivilegeModeSet(); +} + template static void setRegNoEffectWithMask( - ThreadContext *context, RiscvType type, CSRIndex idx, xint val) + ThreadContext *context, RiscvType type, PrivilegeModeSet pms, + CSRIndex idx, xint val) { RegVal oldVal, newVal; - RegVal mask = CSRMasks[type].at(idx); + RegVal mask = CSRMasks[type][pms].at(idx); oldVal = context->readMiscRegNoEffect(CSRData.at(idx).physIndex); newVal = (oldVal & ~mask) | (val & mask); context->setMiscRegNoEffect(CSRData.at(idx).physIndex, newVal); @@ -181,10 +190,12 @@ setRegNoEffectWithMask( template static void -setRegWithMask(ThreadContext *context, RiscvType type, CSRIndex idx, xint val) +setRegWithMask( + ThreadContext *context, RiscvType type, PrivilegeModeSet pms, + CSRIndex idx, xint val) { RegVal oldVal, newVal; - RegVal mask = CSRMasks[type].at(idx); + RegVal mask = CSRMasks[type][pms].at(idx); oldVal = context->readMiscReg(CSRData.at(idx).physIndex); newVal = (oldVal & ~mask) | (val & mask); context->setMiscReg(CSRData.at(idx).physIndex, newVal); @@ -225,7 +236,8 @@ void RemoteGDB::Riscv32GdbRegCache::getRegs(ThreadContext *context) { DPRINTF(GDBAcc, "getregs in remotegdb, size %lu\n", size()); - auto& RVxCSRMasks = CSRMasks[RV32]; + PrivilegeModeSet pms = getPrivilegeModeSet(context); + auto& RVxCSRMasks = CSRMasks[RV32][pms]; // General registers for (int i = 0; i < int_reg::NumArchRegs; i++) { @@ -339,6 +351,7 @@ void RemoteGDB::Riscv32GdbRegCache::setRegs(ThreadContext *context) const { DPRINTF(GDBAcc, "setregs in remotegdb \n"); + PrivilegeModeSet pms = getPrivilegeModeSet(context); for (int i = 0; i < int_reg::NumArchRegs; i++) context->setReg(intRegClass[i], r.gpr[i]); context->pcState(r.pc); @@ -347,16 +360,16 @@ RemoteGDB::Riscv32GdbRegCache::setRegs(ThreadContext *context) const for (int i = 0; i < float_reg::NumRegs; i++) context->setReg(floatRegClass[i], r.fpu[i]); - setRegNoEffectWithMask(context, RV32, CSR_FFLAGS, r.fflags); - setRegNoEffectWithMask(context, RV32, CSR_FRM, r.frm); - setRegNoEffectWithMask(context, RV32, CSR_FCSR, r.fcsr); + setRegNoEffectWithMask(context, RV32, pms, CSR_FFLAGS, r.fflags); + setRegNoEffectWithMask(context, RV32, pms, CSR_FRM, r.frm); + setRegNoEffectWithMask(context, RV32, pms, CSR_FCSR, r.fcsr); // TODO: implement CSR counter registers for mcycle(h), minstret(h) // U mode CSR - setRegNoEffectWithMask(context, RV32, CSR_USTATUS, r.ustatus); - setRegWithMask(context, RV32, CSR_UIE, r.uie); - setRegWithMask(context, RV32, CSR_UIP, r.uip); + setRegNoEffectWithMask(context, RV32, pms, CSR_USTATUS, r.ustatus); + setRegWithMask(context, RV32, pms, CSR_UIE, r.uie); + setRegWithMask(context, RV32, pms, CSR_UIP, r.uip); context->setMiscRegNoEffect( CSRData.at(CSR_UTVEC).physIndex, r.utvec); context->setMiscRegNoEffect( @@ -369,9 +382,9 @@ RemoteGDB::Riscv32GdbRegCache::setRegs(ThreadContext *context) const CSRData.at(CSR_UTVAL).physIndex, r.utval); // S mode CSR - setRegNoEffectWithMask(context, RV32, CSR_SSTATUS, r.sstatus); - setRegWithMask(context, RV32, CSR_SIE, r.sie); - setRegWithMask(context, RV32, CSR_SIP, r.sip); + setRegNoEffectWithMask(context, RV32, pms, CSR_SSTATUS, r.sstatus); + setRegWithMask(context, RV32, pms, CSR_SIE, r.sie); + setRegWithMask(context, RV32, pms, CSR_SIP, r.sip); context->setMiscRegNoEffect( CSRData.at(CSR_SEDELEG).physIndex, r.sedeleg); context->setMiscRegNoEffect( @@ -392,10 +405,10 @@ RemoteGDB::Riscv32GdbRegCache::setRegs(ThreadContext *context) const CSRData.at(CSR_SATP).physIndex, r.satp); // M mode CSR - setRegNoEffectWithMask(context, RV32, CSR_MSTATUS, r.mstatus); - setRegNoEffectWithMask(context, RV32, CSR_MISA, r.misa); - setRegWithMask(context, RV32, CSR_MIE, r.mie); - setRegWithMask(context, RV32, CSR_MIP, r.mip); + setRegNoEffectWithMask(context, RV32, pms, CSR_MSTATUS, r.mstatus); + setRegNoEffectWithMask(context, RV32, pms, CSR_MISA, r.misa); + setRegWithMask(context, RV32, pms, CSR_MIE, r.mie); + setRegWithMask(context, RV32, pms, CSR_MIP, r.mip); context->setMiscRegNoEffect( CSRData.at(CSR_MEDELEG).physIndex, r.medeleg); context->setMiscRegNoEffect( @@ -420,7 +433,8 @@ void RemoteGDB::Riscv64GdbRegCache::getRegs(ThreadContext *context) { DPRINTF(GDBAcc, "getregs in remotegdb, size %lu\n", size()); - auto& RVxCSRMasks = CSRMasks[RV64]; + PrivilegeModeSet pms = getPrivilegeModeSet(context); + auto& RVxCSRMasks = CSRMasks[RV64][pms]; // General registers for (int i = 0; i < int_reg::NumArchRegs; i++) { @@ -528,6 +542,7 @@ void RemoteGDB::Riscv64GdbRegCache::setRegs(ThreadContext *context) const { DPRINTF(GDBAcc, "setregs in remotegdb \n"); + PrivilegeModeSet pms = getPrivilegeModeSet(context); for (int i = 0; i < int_reg::NumArchRegs; i++) context->setReg(intRegClass[i], r.gpr[i]); context->pcState(r.pc); @@ -536,16 +551,16 @@ RemoteGDB::Riscv64GdbRegCache::setRegs(ThreadContext *context) const for (int i = 0; i < float_reg::NumRegs; i++) context->setReg(floatRegClass[i], r.fpu[i]); - setRegNoEffectWithMask(context, RV64, CSR_FFLAGS, r.fflags); - setRegNoEffectWithMask(context, RV64, CSR_FRM, r.frm); - setRegNoEffectWithMask(context, RV64, CSR_FCSR, r.fcsr); + setRegNoEffectWithMask(context, RV64, pms, CSR_FFLAGS, r.fflags); + setRegNoEffectWithMask(context, RV64, pms, CSR_FRM, r.frm); + setRegNoEffectWithMask(context, RV64, pms, CSR_FCSR, r.fcsr); // TODO: implement CSR counter registers for mcycle, minstret // U mode CSR - setRegNoEffectWithMask(context, RV64, CSR_USTATUS, r.ustatus); - setRegWithMask(context, RV64, CSR_UIE, r.uie); - setRegWithMask(context, RV64, CSR_UIP, r.uip); + setRegNoEffectWithMask(context, RV64, pms, CSR_USTATUS, r.ustatus); + setRegWithMask(context, RV64, pms, CSR_UIE, r.uie); + setRegWithMask(context, RV64, pms, CSR_UIP, r.uip); context->setMiscRegNoEffect( CSRData.at(CSR_UTVEC).physIndex, r.utvec); context->setMiscRegNoEffect( @@ -558,9 +573,10 @@ RemoteGDB::Riscv64GdbRegCache::setRegs(ThreadContext *context) const CSRData.at(CSR_UTVAL).physIndex, r.utval); // S mode CSR - setRegNoEffectWithMask(context, RV64, CSR_SSTATUS, r.sstatus); - setRegWithMask(context, RV64, CSR_SIE, r.sie); - setRegWithMask(context, RV64, CSR_SIP, r.sip); + setRegNoEffectWithMask( + context, RV64, pms, CSR_SSTATUS, r.sstatus); + setRegWithMask(context, RV64, pms, CSR_SIE, r.sie); + setRegWithMask(context, RV64, pms, CSR_SIP, r.sip); context->setMiscRegNoEffect( CSRData.at(CSR_SEDELEG).physIndex, r.sedeleg); context->setMiscRegNoEffect( @@ -581,10 +597,11 @@ RemoteGDB::Riscv64GdbRegCache::setRegs(ThreadContext *context) const CSRData.at(CSR_SATP).physIndex, r.satp); // M mode CSR - setRegNoEffectWithMask(context, RV64, CSR_MSTATUS, r.mstatus); - setRegNoEffectWithMask(context, RV64, CSR_MISA, r.misa); - setRegWithMask(context, RV64, CSR_MIE, r.mie); - setRegWithMask(context, RV64, CSR_MIP, r.mip); + setRegNoEffectWithMask( + context, RV64, pms, CSR_MSTATUS, r.mstatus); + setRegNoEffectWithMask(context, RV64, pms, CSR_MISA, r.misa); + setRegWithMask(context, RV64, pms, CSR_MIE, r.mie); + setRegWithMask(context, RV64, pms, CSR_MIP, r.mip); context->setMiscRegNoEffect( CSRData.at(CSR_MEDELEG).physIndex, r.medeleg); context->setMiscRegNoEffect( From 9e738a65eaa07286c354e18772583c192d388b54 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Mon, 30 Oct 2023 17:28:16 +0800 Subject: [PATCH 614/693] arch-riscv: Add isaExts field for CSR registers Change-Id: Idd94af57f3a721d455ea7fb9d335fab7b16a0f7e --- src/arch/riscv/isa/formats/standard.isa | 9 + src/arch/riscv/regs/misc.hh | 645 +++++++++++++++--------- 2 files changed, 425 insertions(+), 229 deletions(-) diff --git a/src/arch/riscv/isa/formats/standard.isa b/src/arch/riscv/isa/formats/standard.isa index 98b0af1e2d..051c526377 100644 --- a/src/arch/riscv/isa/formats/standard.isa +++ b/src/arch/riscv/isa/formats/standard.isa @@ -334,6 +334,7 @@ def template CSRExecute {{ auto isa = static_cast(xc->tcBase()->getIsaPtr()); auto& csr_data = isa->getCSRDataMap(); auto& csr_masks = isa->getCSRMaskMap(); + MISA misa = isa->readMiscRegNoEffect(MISCREG_ISA); auto csr_data_it = csr_data.find(csr); if (csr_data_it == csr_data.end()) { @@ -351,6 +352,14 @@ def template CSRExecute {{ machInst); } + MISA csr_exts = csr_data_it->second.isaExts; + if ((csr_exts & misa) != csr_exts) { + return std::make_shared( + csprintf("%s is not support in the isa spec %d\n", + csrName), + machInst); + } + auto mask_it = csr_masks.find(csr); RegVal maskVal = (mask_it == csr_masks.end()) ? mask(64) : mask_it->second; diff --git a/src/arch/riscv/regs/misc.hh b/src/arch/riscv/regs/misc.hh index 7f7621f8ea..96e88c7438 100644 --- a/src/arch/riscv/regs/misc.hh +++ b/src/arch/riscv/regs/misc.hh @@ -500,6 +500,7 @@ struct CSRMetadata const std::string name; const int physIndex; const uint64_t rvTypes; + const uint64_t isaExts; }; template @@ -507,474 +508,660 @@ constexpr uint64_t rvTypeFlags(T... args) { return ((1 << args) | ...); } +template +constexpr uint64_t isaExtsFlags(T... isa_exts) { + return ((1ULL << (isa_exts - 'a')) | ...); +} + +constexpr uint64_t isaExtsFlags() { + return 0ULL; +} + const std::unordered_map CSRData = { {CSR_USTATUS, - {"ustatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, + {"ustatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32), + isaExtsFlags('n')}}, {CSR_UIE, - {"uie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, + {"uie", MISCREG_IE, rvTypeFlags(RV64, RV32), isaExtsFlags('n')}}, {CSR_UTVEC, - {"utvec", MISCREG_UTVEC, rvTypeFlags(RV64, RV32)}}, + {"utvec", MISCREG_UTVEC, rvTypeFlags(RV64, RV32), isaExtsFlags('n')}}, {CSR_USCRATCH, - {"uscratch", MISCREG_USCRATCH, rvTypeFlags(RV64, RV32)}}, + {"uscratch", MISCREG_USCRATCH, rvTypeFlags(RV64, RV32), + isaExtsFlags('n')}}, {CSR_UEPC, - {"uepc", MISCREG_UEPC, rvTypeFlags(RV64, RV32)}}, + {"uepc", MISCREG_UEPC, rvTypeFlags(RV64, RV32), isaExtsFlags('n')}}, {CSR_UCAUSE, - {"ucause", MISCREG_UCAUSE, rvTypeFlags(RV64, RV32)}}, + {"ucause", MISCREG_UCAUSE, rvTypeFlags(RV64, RV32), + isaExtsFlags('n')}}, {CSR_UTVAL, - {"utval", MISCREG_UTVAL, rvTypeFlags(RV64, RV32)}}, + {"utval", MISCREG_UTVAL, rvTypeFlags(RV64, RV32), isaExtsFlags('n')}}, {CSR_UIP, - {"uip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, + {"uip", MISCREG_IP, rvTypeFlags(RV64, RV32), isaExtsFlags('n')}}, {CSR_FFLAGS, - {"fflags", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32)}}, + {"fflags", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32), + isaExtsFlags('f')}}, {CSR_FRM, - {"frm", MISCREG_FRM, rvTypeFlags(RV64, RV32)}}, + {"frm", MISCREG_FRM, rvTypeFlags(RV64, RV32), isaExtsFlags('f')}}, // Actually FRM << 5 | FFLAGS {CSR_FCSR, - {"fcsr", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32)}}, + {"fcsr", MISCREG_FFLAGS, rvTypeFlags(RV64, RV32), isaExtsFlags('f')}}, {CSR_CYCLE, - {"cycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32)}}, + {"cycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_TIME, - {"time", MISCREG_TIME, rvTypeFlags(RV64, RV32)}}, + {"time", MISCREG_TIME, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_INSTRET, - {"instret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32)}}, + {"instret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_HPMCOUNTER03, - {"hpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER04, - {"hpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER05, - {"hpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER06, - {"hpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER07, - {"hpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER08, - {"hpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER09, - {"hpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER10, - {"hpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER11, - {"hpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER12, - {"hpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER13, - {"hpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER14, - {"hpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER15, - {"hpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER16, - {"hpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER17, - {"hpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER18, - {"hpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER19, - {"hpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER20, - {"hpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER21, - {"hpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER22, - {"hpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER23, - {"hpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER24, - {"hpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER25, - {"hpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER26, - {"hpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER27, - {"hpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER28, - {"hpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER29, - {"hpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER30, - {"hpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER31, - {"hpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32)}}, + {"hpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_CYCLEH, - {"cycleh", MISCREG_CYCLEH, rvTypeFlags(RV32)}}, + {"cycleh", MISCREG_CYCLEH, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_TIMEH, - {"timeh", MISCREG_TIMEH, rvTypeFlags(RV32)}}, + {"timeh", MISCREG_TIMEH, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_INSTRETH, - {"instreth", MISCREG_INSTRETH, rvTypeFlags(RV32)}}, + {"instreth", MISCREG_INSTRETH, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_HPMCOUNTER03H, - {"hpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32)}}, + {"hpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER04H, - {"hpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32)}}, + {"hpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER05H, - {"hpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32)}}, + {"hpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER06H, - {"hpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32)}}, + {"hpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER07H, - {"hpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32)}}, + {"hpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER08H, - {"hpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32)}}, + {"hpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER09H, - {"hpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32)}}, + {"hpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER10H, - {"hpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32)}}, + {"hpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER11H, - {"hpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32)}}, + {"hpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER12H, - {"hpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32)}}, + {"hpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER13H, - {"hpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32)}}, + {"hpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER14H, - {"hpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32)}}, + {"hpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER15H, - {"hpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32)}}, + {"hpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER16H, - {"hpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32)}}, + {"hpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER17H, - {"hpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32)}}, + {"hpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER18H, - {"hpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32)}}, + {"hpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER19H, - {"hpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32)}}, + {"hpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER20H, - {"hpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32)}}, + {"hpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER21H, - {"hpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32)}}, + {"hpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER22H, - {"hpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32)}}, + {"hpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER23H, - {"hpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32)}}, + {"hpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER24H, - {"hpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32)}}, + {"hpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER25H, - {"hpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32)}}, + {"hpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER26H, - {"hpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32)}}, + {"hpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER27H, - {"hpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32)}}, + {"hpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER28H, - {"hpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32)}}, + {"hpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER29H, - {"hpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32)}}, + {"hpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER30H, - {"hpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32)}}, + {"hpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_HPMCOUNTER31H, - {"hpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32)}}, + {"hpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_SSTATUS, - {"sstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, + {"sstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32), + isaExtsFlags('s')}}, {CSR_SEDELEG, - {"sedeleg", MISCREG_SEDELEG, rvTypeFlags(RV64, RV32)}}, + {"sedeleg", MISCREG_SEDELEG, rvTypeFlags(RV64, RV32), + isaExtsFlags('s')}}, {CSR_SIDELEG, - {"sideleg", MISCREG_SIDELEG, rvTypeFlags(RV64, RV32)}}, + {"sideleg", MISCREG_SIDELEG, rvTypeFlags(RV64, RV32), + isaExtsFlags('s')}}, {CSR_SIE, - {"sie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, + {"sie", MISCREG_IE, rvTypeFlags(RV64, RV32), isaExtsFlags('s')}}, {CSR_STVEC, - {"stvec", MISCREG_STVEC, rvTypeFlags(RV64, RV32)}}, + {"stvec", MISCREG_STVEC, rvTypeFlags(RV64, RV32), isaExtsFlags('s')}}, {CSR_SCOUNTEREN, - {"scounteren", MISCREG_SCOUNTEREN, rvTypeFlags(RV64, RV32)}}, + {"scounteren", MISCREG_SCOUNTEREN, rvTypeFlags(RV64, RV32), + isaExtsFlags('s')}}, {CSR_SSCRATCH, - {"sscratch", MISCREG_SSCRATCH, rvTypeFlags(RV64, RV32)}}, + {"sscratch", MISCREG_SSCRATCH, rvTypeFlags(RV64, RV32), + isaExtsFlags('s')}}, {CSR_SEPC, - {"sepc", MISCREG_SEPC, rvTypeFlags(RV64, RV32)}}, + {"sepc", MISCREG_SEPC, rvTypeFlags(RV64, RV32), isaExtsFlags('s')}}, {CSR_SCAUSE, - {"scause", MISCREG_SCAUSE, rvTypeFlags(RV64, RV32)}}, + {"scause", MISCREG_SCAUSE, rvTypeFlags(RV64, RV32), + isaExtsFlags('s')}}, {CSR_STVAL, - {"stval", MISCREG_STVAL, rvTypeFlags(RV64, RV32)}}, + {"stval", MISCREG_STVAL, rvTypeFlags(RV64, RV32), isaExtsFlags('s')}}, {CSR_SIP, - {"sip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, + {"sip", MISCREG_IP, rvTypeFlags(RV64, RV32), isaExtsFlags('s')}}, {CSR_SATP, - {"satp", MISCREG_SATP, rvTypeFlags(RV64, RV32)}}, + {"satp", MISCREG_SATP, rvTypeFlags(RV64, RV32), isaExtsFlags('s')}}, {CSR_MVENDORID, - {"mvendorid", MISCREG_VENDORID, rvTypeFlags(RV64, RV32)}}, + {"mvendorid", MISCREG_VENDORID, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MARCHID, - {"marchid", MISCREG_ARCHID, rvTypeFlags(RV64, RV32)}}, + {"marchid", MISCREG_ARCHID, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MIMPID, - {"mimpid", MISCREG_IMPID, rvTypeFlags(RV64, RV32)}}, + {"mimpid", MISCREG_IMPID, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MHARTID, - {"mhartid", MISCREG_HARTID, rvTypeFlags(RV64, RV32)}}, + {"mhartid", MISCREG_HARTID, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MSTATUS, - {"mstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32)}}, + {"mstatus", MISCREG_STATUS, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MISA, - {"misa", MISCREG_ISA, rvTypeFlags(RV64, RV32)}}, + {"misa", MISCREG_ISA, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MEDELEG, - {"medeleg", MISCREG_MEDELEG, rvTypeFlags(RV64, RV32)}}, + {"medeleg", MISCREG_MEDELEG, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MIDELEG, - {"mideleg", MISCREG_MIDELEG, rvTypeFlags(RV64, RV32)}}, + {"mideleg", MISCREG_MIDELEG, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MIE, - {"mie", MISCREG_IE, rvTypeFlags(RV64, RV32)}}, + {"mie", MISCREG_IE, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MTVEC, - {"mtvec", MISCREG_MTVEC, rvTypeFlags(RV64, RV32)}}, + {"mtvec", MISCREG_MTVEC, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MCOUNTEREN, - {"mcounteren", MISCREG_MCOUNTEREN, rvTypeFlags(RV64, RV32)}}, + {"mcounteren", MISCREG_MCOUNTEREN, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MSTATUSH, - {"mstatush", MISCREG_MSTATUSH, rvTypeFlags(RV32)}}, + {"mstatush", MISCREG_MSTATUSH, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_MSCRATCH, - {"mscratch", MISCREG_MSCRATCH, rvTypeFlags(RV64, RV32)}}, + {"mscratch", MISCREG_MSCRATCH, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MEPC, - {"mepc", MISCREG_MEPC, rvTypeFlags(RV64, RV32)}}, + {"mepc", MISCREG_MEPC, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MCAUSE, - {"mcause", MISCREG_MCAUSE, rvTypeFlags(RV64, RV32)}}, + {"mcause", MISCREG_MCAUSE, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MTVAL, - {"mtval", MISCREG_MTVAL, rvTypeFlags(RV64, RV32)}}, + {"mtval", MISCREG_MTVAL, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MIP, - {"mip", MISCREG_IP, rvTypeFlags(RV64, RV32)}}, + {"mip", MISCREG_IP, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_PMPCFG0, - {"pmpcfg0", MISCREG_PMPCFG0, rvTypeFlags(RV64, RV32)}}, + {"pmpcfg0", MISCREG_PMPCFG0, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, // pmpcfg1 rv32 only {CSR_PMPCFG1, - {"pmpcfg1", MISCREG_PMPCFG1, rvTypeFlags(RV32)}}, + {"pmpcfg1", MISCREG_PMPCFG1, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_PMPCFG2, - {"pmpcfg2", MISCREG_PMPCFG2, rvTypeFlags(RV64, RV32)}}, + {"pmpcfg2", MISCREG_PMPCFG2, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, // pmpcfg3 rv32 only {CSR_PMPCFG3, - {"pmpcfg3", MISCREG_PMPCFG3, rvTypeFlags(RV32)}}, + {"pmpcfg3", MISCREG_PMPCFG3, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_PMPADDR00, - {"pmpaddr0", MISCREG_PMPADDR00, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr0", MISCREG_PMPADDR00, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR01, - {"pmpaddr1", MISCREG_PMPADDR01, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr1", MISCREG_PMPADDR01, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR02, - {"pmpaddr2", MISCREG_PMPADDR02, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr2", MISCREG_PMPADDR02, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR03, - {"pmpaddr3", MISCREG_PMPADDR03, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr3", MISCREG_PMPADDR03, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR04, - {"pmpaddr4", MISCREG_PMPADDR04, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr4", MISCREG_PMPADDR04, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR05, - {"pmpaddr5", MISCREG_PMPADDR05, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr5", MISCREG_PMPADDR05, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR06, - {"pmpaddr6", MISCREG_PMPADDR06, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr6", MISCREG_PMPADDR06, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR07, - {"pmpaddr7", MISCREG_PMPADDR07, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr7", MISCREG_PMPADDR07, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR08, - {"pmpaddr8", MISCREG_PMPADDR08, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr8", MISCREG_PMPADDR08, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR09, - {"pmpaddr9", MISCREG_PMPADDR09, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr9", MISCREG_PMPADDR09, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR10, - {"pmpaddr10", MISCREG_PMPADDR10, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr10", MISCREG_PMPADDR10, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR11, - {"pmpaddr11", MISCREG_PMPADDR11, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr11", MISCREG_PMPADDR11, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR12, - {"pmpaddr12", MISCREG_PMPADDR12, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr12", MISCREG_PMPADDR12, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR13, - {"pmpaddr13", MISCREG_PMPADDR13, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr13", MISCREG_PMPADDR13, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR14, - {"pmpaddr14", MISCREG_PMPADDR14, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr14", MISCREG_PMPADDR14, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_PMPADDR15, - {"pmpaddr15", MISCREG_PMPADDR15, rvTypeFlags(RV64, RV32)}}, + {"pmpaddr15", MISCREG_PMPADDR15, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MCYCLE, - {"mcycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32)}}, + {"mcycle", MISCREG_CYCLE, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_MINSTRET, - {"minstret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32)}}, + {"minstret", MISCREG_INSTRET, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER03, - {"mhpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter03", MISCREG_HPMCOUNTER03, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER04, - {"mhpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter04", MISCREG_HPMCOUNTER04, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER05, - {"mhpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter05", MISCREG_HPMCOUNTER05, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER06, - {"mhpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter06", MISCREG_HPMCOUNTER06, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER07, - {"mhpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter07", MISCREG_HPMCOUNTER07, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER08, - {"mhpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter08", MISCREG_HPMCOUNTER08, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER09, - {"mhpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter09", MISCREG_HPMCOUNTER09, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER10, - {"mhpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter10", MISCREG_HPMCOUNTER10, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER11, - {"mhpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter11", MISCREG_HPMCOUNTER11, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER12, - {"mhpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter12", MISCREG_HPMCOUNTER12, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER13, - {"mhpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter13", MISCREG_HPMCOUNTER13, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER14, - {"mhpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter14", MISCREG_HPMCOUNTER14, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER15, - {"mhpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter15", MISCREG_HPMCOUNTER15, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER16, - {"mhpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter16", MISCREG_HPMCOUNTER16, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER17, - {"mhpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter17", MISCREG_HPMCOUNTER17, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER18, - {"mhpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter18", MISCREG_HPMCOUNTER18, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER19, - {"mhpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter19", MISCREG_HPMCOUNTER19, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER20, - {"mhpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter20", MISCREG_HPMCOUNTER20, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER21, - {"mhpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter21", MISCREG_HPMCOUNTER21, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER22, - {"mhpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter22", MISCREG_HPMCOUNTER22, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER23, - {"mhpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter23", MISCREG_HPMCOUNTER23, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER24, - {"mhpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter24", MISCREG_HPMCOUNTER24, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER25, - {"mhpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter25", MISCREG_HPMCOUNTER25, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER26, - {"mhpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter26", MISCREG_HPMCOUNTER26, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER27, - {"mhpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter27", MISCREG_HPMCOUNTER27, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER28, - {"mhpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter28", MISCREG_HPMCOUNTER28, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER29, - {"mhpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter29", MISCREG_HPMCOUNTER29, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER30, - {"mhpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter30", MISCREG_HPMCOUNTER30, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER31, - {"mhpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32)}}, + {"mhpmcounter31", MISCREG_HPMCOUNTER31, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MCYCLEH, - {"mcycleh", MISCREG_CYCLEH, rvTypeFlags(RV32)}}, + {"mcycleh", MISCREG_CYCLEH, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_MINSTRETH, - {"minstreth", MISCREG_INSTRETH, rvTypeFlags(RV32)}}, + {"minstreth", MISCREG_INSTRETH, rvTypeFlags(RV32), isaExtsFlags()}}, {CSR_MHPMCOUNTER03H, - {"mhpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32)}}, + {"mhpmcounter03h", MISCREG_HPMCOUNTER03H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER04H, - {"mhpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32)}}, + {"mhpmcounter04h", MISCREG_HPMCOUNTER04H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER05H, - {"mhpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32)}}, + {"mhpmcounter05h", MISCREG_HPMCOUNTER05H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER06H, - {"mhpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32)}}, + {"mhpmcounter06h", MISCREG_HPMCOUNTER06H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER07H, - {"mhpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32)}}, + {"mhpmcounter07h", MISCREG_HPMCOUNTER07H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER08H, - {"mhpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32)}}, + {"mhpmcounter08h", MISCREG_HPMCOUNTER08H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER09H, - {"mhpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32)}}, + {"mhpmcounter09h", MISCREG_HPMCOUNTER09H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER10H, - {"mhpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32)}}, + {"mhpmcounter10h", MISCREG_HPMCOUNTER10H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER11H, - {"mhpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32)}}, + {"mhpmcounter11h", MISCREG_HPMCOUNTER11H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER12H, - {"mhpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32)}}, + {"mhpmcounter12h", MISCREG_HPMCOUNTER12H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER13H, - {"mhpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32)}}, + {"mhpmcounter13h", MISCREG_HPMCOUNTER13H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER14H, - {"mhpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32)}}, + {"mhpmcounter14h", MISCREG_HPMCOUNTER14H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER15H, - {"mhpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32)}}, + {"mhpmcounter15h", MISCREG_HPMCOUNTER15H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER16H, - {"mhpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32)}}, + {"mhpmcounter16h", MISCREG_HPMCOUNTER16H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER17H, - {"mhpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32)}}, + {"mhpmcounter17h", MISCREG_HPMCOUNTER17H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER18H, - {"mhpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32)}}, + {"mhpmcounter18h", MISCREG_HPMCOUNTER18H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER19H, - {"mhpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32)}}, + {"mhpmcounter19h", MISCREG_HPMCOUNTER19H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER20H, - {"mhpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32)}}, + {"mhpmcounter20h", MISCREG_HPMCOUNTER20H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER21H, - {"mhpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32)}}, + {"mhpmcounter21h", MISCREG_HPMCOUNTER21H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER22H, - {"mhpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32)}}, + {"mhpmcounter22h", MISCREG_HPMCOUNTER22H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER23H, - {"mhpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32)}}, + {"mhpmcounter23h", MISCREG_HPMCOUNTER23H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER24H, - {"mhpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32)}}, + {"mhpmcounter24h", MISCREG_HPMCOUNTER24H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER25H, - {"mhpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32)}}, + {"mhpmcounter25h", MISCREG_HPMCOUNTER25H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER26H, - {"mhpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32)}}, + {"mhpmcounter26h", MISCREG_HPMCOUNTER26H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER27H, - {"mhpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32)}}, + {"mhpmcounter27h", MISCREG_HPMCOUNTER27H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER28H, - {"mhpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32)}}, + {"mhpmcounter28h", MISCREG_HPMCOUNTER28H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER29H, - {"mhpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32)}}, + {"mhpmcounter29h", MISCREG_HPMCOUNTER29H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER30H, - {"mhpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32)}}, + {"mhpmcounter30h", MISCREG_HPMCOUNTER30H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMCOUNTER31H, - {"mhpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32)}}, + {"mhpmcounter31h", MISCREG_HPMCOUNTER31H, rvTypeFlags(RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT03, - {"mhpmevent03", MISCREG_HPMEVENT03, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent03", MISCREG_HPMEVENT03, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT04, - {"mhpmevent04", MISCREG_HPMEVENT04, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent04", MISCREG_HPMEVENT04, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT05, - {"mhpmevent05", MISCREG_HPMEVENT05, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent05", MISCREG_HPMEVENT05, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT06, - {"mhpmevent06", MISCREG_HPMEVENT06, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent06", MISCREG_HPMEVENT06, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT07, - {"mhpmevent07", MISCREG_HPMEVENT07, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent07", MISCREG_HPMEVENT07, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT08, - {"mhpmevent08", MISCREG_HPMEVENT08, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent08", MISCREG_HPMEVENT08, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT09, - {"mhpmevent09", MISCREG_HPMEVENT09, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent09", MISCREG_HPMEVENT09, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT10, - {"mhpmevent10", MISCREG_HPMEVENT10, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent10", MISCREG_HPMEVENT10, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT11, - {"mhpmevent11", MISCREG_HPMEVENT11, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent11", MISCREG_HPMEVENT11, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT12, - {"mhpmevent12", MISCREG_HPMEVENT12, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent12", MISCREG_HPMEVENT12, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT13, - {"mhpmevent13", MISCREG_HPMEVENT13, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent13", MISCREG_HPMEVENT13, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT14, - {"mhpmevent14", MISCREG_HPMEVENT14, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent14", MISCREG_HPMEVENT14, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT15, - {"mhpmevent15", MISCREG_HPMEVENT15, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent15", MISCREG_HPMEVENT15, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT16, - {"mhpmevent16", MISCREG_HPMEVENT16, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent16", MISCREG_HPMEVENT16, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT17, - {"mhpmevent17", MISCREG_HPMEVENT17, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent17", MISCREG_HPMEVENT17, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT18, - {"mhpmevent18", MISCREG_HPMEVENT18, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent18", MISCREG_HPMEVENT18, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT19, - {"mhpmevent19", MISCREG_HPMEVENT19, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent19", MISCREG_HPMEVENT19, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT20, - {"mhpmevent20", MISCREG_HPMEVENT20, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent20", MISCREG_HPMEVENT20, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT21, - {"mhpmevent21", MISCREG_HPMEVENT21, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent21", MISCREG_HPMEVENT21, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT22, - {"mhpmevent22", MISCREG_HPMEVENT22, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent22", MISCREG_HPMEVENT22, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT23, - {"mhpmevent23", MISCREG_HPMEVENT23, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent23", MISCREG_HPMEVENT23, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT24, - {"mhpmevent24", MISCREG_HPMEVENT24, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent24", MISCREG_HPMEVENT24, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT25, - {"mhpmevent25", MISCREG_HPMEVENT25, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent25", MISCREG_HPMEVENT25, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT26, - {"mhpmevent26", MISCREG_HPMEVENT26, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent26", MISCREG_HPMEVENT26, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT27, - {"mhpmevent27", MISCREG_HPMEVENT27, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent27", MISCREG_HPMEVENT27, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT28, - {"mhpmevent28", MISCREG_HPMEVENT28, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent28", MISCREG_HPMEVENT28, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT29, - {"mhpmevent29", MISCREG_HPMEVENT29, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent29", MISCREG_HPMEVENT29, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT30, - {"mhpmevent30", MISCREG_HPMEVENT30, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent30", MISCREG_HPMEVENT30, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_MHPMEVENT31, - {"mhpmevent31", MISCREG_HPMEVENT31, rvTypeFlags(RV64, RV32)}}, + {"mhpmevent31", MISCREG_HPMEVENT31, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_TSELECT, - {"tselect", MISCREG_TSELECT, rvTypeFlags(RV64, RV32)}}, + {"tselect", MISCREG_TSELECT, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_TDATA1, - {"tdata1", MISCREG_TDATA1, rvTypeFlags(RV64, RV32)}}, + {"tdata1", MISCREG_TDATA1, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_TDATA2, - {"tdata2", MISCREG_TDATA2, rvTypeFlags(RV64, RV32)}}, + {"tdata2", MISCREG_TDATA2, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_TDATA3, - {"tdata3", MISCREG_TDATA3, rvTypeFlags(RV64, RV32)}}, + {"tdata3", MISCREG_TDATA3, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_DCSR, - {"dcsr", MISCREG_DCSR, rvTypeFlags(RV64, RV32)}}, + {"dcsr", MISCREG_DCSR, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_DPC, - {"dpc", MISCREG_DPC, rvTypeFlags(RV64, RV32)}}, + {"dpc", MISCREG_DPC, rvTypeFlags(RV64, RV32), isaExtsFlags()}}, {CSR_DSCRATCH, - {"dscratch", MISCREG_DSCRATCH, rvTypeFlags(RV64, RV32)}}, + {"dscratch", MISCREG_DSCRATCH, rvTypeFlags(RV64, RV32), + isaExtsFlags()}}, {CSR_VSTART, - {"vstart", MISCREG_VSTART, rvTypeFlags(RV64, RV32)}}, + {"vstart", MISCREG_VSTART, rvTypeFlags(RV64, RV32), + isaExtsFlags('v')}}, {CSR_VXSAT, - {"vxsat", MISCREG_VXSAT, rvTypeFlags(RV64, RV32)}}, + {"vxsat", MISCREG_VXSAT, rvTypeFlags(RV64, RV32), isaExtsFlags('v')}}, {CSR_VXRM, - {"vxrm", MISCREG_VXRM, rvTypeFlags(RV64, RV32)}}, + {"vxrm", MISCREG_VXRM, rvTypeFlags(RV64, RV32), isaExtsFlags('v')}}, {CSR_VCSR, - {"vcsr", MISCREG_VCSR, rvTypeFlags(RV64, RV32)}}, + {"vcsr", MISCREG_VCSR, rvTypeFlags(RV64, RV32), isaExtsFlags('v')}}, {CSR_VL, - {"vl", MISCREG_VL, rvTypeFlags(RV64, RV32)}}, + {"vl", MISCREG_VL, rvTypeFlags(RV64, RV32), isaExtsFlags('v')}}, {CSR_VTYPE, - {"vtype", MISCREG_VTYPE, rvTypeFlags(RV64, RV32)}}, + {"vtype", MISCREG_VTYPE, rvTypeFlags(RV64, RV32), isaExtsFlags('v')}}, {CSR_VLENB, - {"VLENB", MISCREG_VLENB, rvTypeFlags(RV64, RV32)}} + {"VLENB", MISCREG_VLENB, rvTypeFlags(RV64, RV32), isaExtsFlags('v')}} }; /** From 6fd4feb79774e7c4a1d13d8af8c37c211e262951 Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 31 Oct 2023 14:34:28 +0800 Subject: [PATCH 615/693] arch-riscv: fatal_if the process run without SU modes Change-Id: Ifce7eec6cea10881964c29d206a92f3d10271de6 --- src/arch/riscv/process.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc index cd00f5d63a..a9ad7b1d32 100644 --- a/src/arch/riscv/process.cc +++ b/src/arch/riscv/process.cc @@ -106,6 +106,10 @@ RiscvProcess64::initState() tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U); auto *isa = dynamic_cast(tc->getIsaPtr()); fatal_if(isa->rvType() != RV64, "RISC V CPU should run in 64 bits mode"); + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); + fatal_if(!(misa.rvu && misa.rvs), + "RISC V SE mode can't run without supervisor and user " + "privilege modes."); } } @@ -120,6 +124,10 @@ RiscvProcess32::initState() tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U); auto *isa = dynamic_cast(tc->getIsaPtr()); fatal_if(isa->rvType() != RV32, "RISC V CPU should run in 32 bits mode"); + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); + fatal_if(!(misa.rvu && misa.rvs), + "RISC V SE mode can't run without supervisor and user " + "privilege modes."); } } From d56801c2407e7f4c438bddde37725706e7461a2e Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 31 Oct 2023 15:26:37 +0800 Subject: [PATCH 616/693] arch-riscv: Add misa rvs check for memory translation The memory translation require supervisor mode implement. If the supervisor mode is not implemented, the satp CSR is not exists and should not do address translation Change-Id: Ie6c8a1a130d0aab0647b35e0f731f6b930834176 --- src/arch/riscv/remote_gdb.cc | 3 ++- src/arch/riscv/tlb.cc | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/arch/riscv/remote_gdb.cc b/src/arch/riscv/remote_gdb.cc index df660d40d2..661fe2e2ca 100644 --- a/src/arch/riscv/remote_gdb.cc +++ b/src/arch/riscv/remote_gdb.cc @@ -218,7 +218,8 @@ RemoteGDB::acc(Addr va, size_t len) PrivilegeMode pmode = mmu->getMemPriv(context(), BaseMMU::Read); SATP satp = context()->readMiscReg(MISCREG_SATP); - if (pmode != PrivilegeMode::PRV_M && + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); + if (misa.rvs && pmode != PrivilegeMode::PRV_M && satp.mode != AddrXlateMode::BARE) { Walker *walker = mmu->getDataWalker(); Fault fault = walker->startFunctional( diff --git a/src/arch/riscv/tlb.cc b/src/arch/riscv/tlb.cc index ac8c8ae029..a8b6e75aed 100644 --- a/src/arch/riscv/tlb.cc +++ b/src/arch/riscv/tlb.cc @@ -341,9 +341,12 @@ TLB::translate(const RequestPtr &req, ThreadContext *tc, if (FullSystem) { PrivilegeMode pmode = getMemPriv(tc, mode); + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); SATP satp = tc->readMiscReg(MISCREG_SATP); - if (pmode == PrivilegeMode::PRV_M || satp.mode == AddrXlateMode::BARE) + if (!misa.rvs || pmode == PrivilegeMode::PRV_M || + satp.mode == AddrXlateMode::BARE) { req->setFlags(Request::PHYSICAL); + } Fault fault; if (req->getFlags() & Request::PHYSICAL) { @@ -434,8 +437,9 @@ TLB::translateFunctional(const RequestPtr &req, ThreadContext *tc, MMU *mmu = static_cast(tc->getMMUPtr()); PrivilegeMode pmode = mmu->getMemPriv(tc, mode); + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); SATP satp = tc->readMiscReg(MISCREG_SATP); - if (pmode != PrivilegeMode::PRV_M && + if (misa.rvs && pmode != PrivilegeMode::PRV_M && satp.mode != AddrXlateMode::BARE) { Walker *walker = mmu->getDataWalker(); unsigned logBytes; From 9a0c671cced7c7d3e096b41957f6db4722137e3d Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 31 Oct 2023 16:33:34 +0800 Subject: [PATCH 617/693] arch-riscv: Handle the exception following the privilege mode set Change-Id: I4867941ec286fe485e01db848b8c7357488f6cf4 --- src/arch/riscv/faults.cc | 9 +++++---- src/arch/riscv/interrupts.hh | 36 ++++++++++++++++++++++++++-------- src/arch/riscv/isa.cc | 18 +++++++++++++++++ src/arch/riscv/isa/decoder.isa | 23 ++++++++++++++++++++-- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/arch/riscv/faults.cc b/src/arch/riscv/faults.cc index 7d4e9f90b6..2e583e3680 100644 --- a/src/arch/riscv/faults.cc +++ b/src/arch/riscv/faults.cc @@ -67,6 +67,7 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) if (FullSystem) { PrivilegeMode pp = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV); PrivilegeMode prv = PRV_M; + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); STATUS status = tc->readMiscReg(MISCREG_STATUS); // According to riscv-privileged-v1.11, if a NMI occurs at the middle @@ -82,18 +83,18 @@ RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) } else if (isInterrupt()) { if (pp != PRV_M && bits(tc->readMiscReg(MISCREG_MIDELEG), _code) != 0) { - prv = PRV_S; + prv = (misa.rvs) ? PRV_S : ((misa.rvn) ? PRV_U : PRV_M); } - if (pp == PRV_U && + if (pp == PRV_U && misa.rvs && misa.rvn && bits(tc->readMiscReg(MISCREG_SIDELEG), _code) != 0) { prv = PRV_U; } } else { if (pp != PRV_M && bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) { - prv = PRV_S; + prv = (misa.rvs) ? PRV_S : ((misa.rvn) ? PRV_U : PRV_M); } - if (pp == PRV_U && + if (pp == PRV_U && misa.rvs && misa.rvn && bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) { prv = PRV_U; } diff --git a/src/arch/riscv/interrupts.hh b/src/arch/riscv/interrupts.hh index d6fa374a14..b003b59426 100644 --- a/src/arch/riscv/interrupts.hh +++ b/src/arch/riscv/interrupts.hh @@ -69,21 +69,41 @@ class Interrupts : public BaseInterrupts { INTERRUPT mask = 0; STATUS status = tc->readMiscReg(MISCREG_STATUS); - INTERRUPT mideleg = tc->readMiscReg(MISCREG_MIDELEG); - INTERRUPT sideleg = tc->readMiscReg(MISCREG_SIDELEG); + MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA); + INTERRUPT mideleg = 0; + if (misa.rvs || misa.rvn) { + mideleg = tc->readMiscReg(MISCREG_MIDELEG); + } + INTERRUPT sideleg = 0; + if (misa.rvs && misa.rvn) { + sideleg = tc->readMiscReg(MISCREG_SIDELEG); + } PrivilegeMode prv = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV); switch (prv) { case PRV_U: - mask.mei = (!sideleg.mei) | (sideleg.mei & status.uie); - mask.mti = (!sideleg.mti) | (sideleg.mti & status.uie); - mask.msi = (!sideleg.msi) | (sideleg.msi & status.uie); - mask.sei = (!sideleg.sei) | (sideleg.sei & status.uie); - mask.sti = (!sideleg.sti) | (sideleg.sti & status.uie); - mask.ssi = (!sideleg.ssi) | (sideleg.ssi & status.uie); + // status.uie is always 0 if misa.rvn is disabled + if (misa.rvs) { + mask.mei = (!sideleg.mei) | (sideleg.mei & status.uie); + mask.mti = (!sideleg.mti) | (sideleg.mti & status.uie); + mask.msi = (!sideleg.msi) | (sideleg.msi & status.uie); + mask.sei = (!sideleg.sei) | (sideleg.sei & status.uie); + mask.sti = (!sideleg.sti) | (sideleg.sti & status.uie); + mask.ssi = (!sideleg.ssi) | (sideleg.ssi & status.uie); + } else { + // According to the RISC-V privilege spec v1.10, if the + // S privilege mode is not implemented and user-trap + // support, setting mideleg/medeleg bits will delegate the + // trap to U-mode trap handler + mask.mei = (!mideleg.mei) | (mideleg.mei & status.uie); + mask.mti = (!mideleg.mti) | (mideleg.mti & status.uie); + mask.msi = (!mideleg.msi) | (mideleg.msi & status.uie); + mask.sei = mask.sti = mask.ssi = 0; + } if (status.uie) mask.uei = mask.uti = mask.usi = 1; break; case PRV_S: + // status.sie is always 0 if misa.rvn is disabled mask.mei = (!mideleg.mei) | (mideleg.mei & status.sie); mask.mti = (!mideleg.mti) | (mideleg.mti & status.sie); mask.msi = (!mideleg.msi) | (mideleg.msi & status.sie); diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 81fb7f3061..18e9b5fce2 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -528,6 +528,24 @@ ISA::readMiscReg(RegIndex idx) default: panic("%s: Unknown _rvType: %d", name(), (int)_rvType); } + // Check status.mpp + MISA misa = readMiscRegNoEffect(MISCREG_ISA); + switch(status.mpp) { + case PRV_U: + status.mpp = (misa.rvu) ? PRV_U : PRV_M; + break; + case PRV_S: + if (misa.rvs) + status.mpp = PRV_S; + else + status.mpp = (misa.rvu) ? PRV_U : PRV_M; + break; + case PRV_M: + break; + default: + status.mpp = (misa.rvu) ? PRV_U : PRV_M; + } + setMiscRegNoEffect(idx, status); return readMiscRegNoEffect(idx); diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 3d1d396165..cf2d3491e3 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -4595,6 +4595,12 @@ decode QUADRANT default Unknown::unknown() { xc->pcState()); }}, IsSerializeAfter, IsNonSpeculative, No_OpClass); 0x2: uret({{ + MISA misa = xc->readMiscReg(MISCREG_ISA); + if (!misa.rvn) { + return std::make_shared( + "sret can't execute without N systems", + machInst); + } STATUS status = xc->readMiscReg(MISCREG_STATUS); status.uie = status.upie; status.upie = 1; @@ -4604,6 +4610,12 @@ decode QUADRANT default Unknown::unknown() { } 0x8: decode RS2 { 0x2: sret({{ + MISA misa = xc->readMiscReg(MISCREG_ISA); + if (!misa.rvs) { + return std::make_shared( + "sret can't execute without RVS", + machInst); + } STATUS status = xc->readMiscReg(MISCREG_STATUS); auto pm = (PrivilegeMode)xc->readMiscReg( MISCREG_PRV); @@ -4623,11 +4635,12 @@ decode QUADRANT default Unknown::unknown() { } }}, IsSerializeAfter, IsNonSpeculative, IsReturn); 0x5: wfi({{ + MISA misa = xc->readMiscReg(MISCREG_ISA); STATUS status = xc->readMiscReg(MISCREG_STATUS); auto pm = (PrivilegeMode)xc->readMiscReg( MISCREG_PRV); - if (pm == PRV_U || - (pm == PRV_S && status.tw == 1)) { + if (misa.rvs && (pm == PRV_U || + (pm == PRV_S && status.tw == 1))) { return std::make_shared( "wfi in user mode or TW enabled", machInst); @@ -4647,6 +4660,12 @@ decode QUADRANT default Unknown::unknown() { IsSerializeAfter, No_OpClass); } 0x9: sfence_vma({{ + MISA misa = xc->readMiscReg(MISCREG_ISA); + if (!misa.rvs) { + return std::make_shared( + "sfence_vma can't execute without RVS", + machInst); + } STATUS status = xc->readMiscReg(MISCREG_STATUS); auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV); if (pm == PRV_U || (pm == PRV_S && status.tvm == 1)) { From af2ee0db306cda5f6cea27f631fc67d87e5fa1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Fri, 20 Oct 2023 18:03:56 -0500 Subject: [PATCH 618/693] mem-cache: decoupled prefetchers from cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patches decouples the prefetchers from the cache implementation as the first step to allow using the classic prefetchers with ruby caches. The prefetchers that need do cache lookups can do so using the accessor object provided when the probes are notified. This may also facilitate connecting the same prefetcher to multiple caches. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Change-Id: I4fee1a3613ae009fabf45d7b747e4582cad315ef Signed-off-by: Tiago Mück --- src/mem/cache/base.cc | 32 +++-- src/mem/cache/base.hh | 53 ++++---- src/mem/cache/cache_probe_arg.hh | 115 ++++++++++++++++++ src/mem/cache/compressors/frequent_values.hh | 3 +- .../prefetch/access_map_pattern_matching.cc | 8 +- .../prefetch/access_map_pattern_matching.hh | 6 +- src/mem/cache/prefetch/base.cc | 77 +++++------- src/mem/cache/prefetch/base.hh | 41 +++---- src/mem/cache/prefetch/bop.cc | 7 +- src/mem/cache/prefetch/bop.hh | 5 +- .../delta_correlating_prediction_tables.cc | 8 +- .../delta_correlating_prediction_tables.hh | 7 +- src/mem/cache/prefetch/indirect_memory.cc | 3 +- src/mem/cache/prefetch/indirect_memory.hh | 3 +- .../cache/prefetch/irregular_stream_buffer.cc | 3 +- .../cache/prefetch/irregular_stream_buffer.hh | 3 +- src/mem/cache/prefetch/multi.cc | 6 +- src/mem/cache/prefetch/multi.hh | 12 +- src/mem/cache/prefetch/pif.cc | 3 +- src/mem/cache/prefetch/pif.hh | 3 +- src/mem/cache/prefetch/queued.cc | 32 ++--- src/mem/cache/prefetch/queued.hh | 21 ++-- src/mem/cache/prefetch/sbooe.cc | 7 +- src/mem/cache/prefetch/sbooe.hh | 5 +- src/mem/cache/prefetch/signature_path.cc | 3 +- src/mem/cache/prefetch/signature_path.hh | 3 +- src/mem/cache/prefetch/slim_ampm.cc | 7 +- src/mem/cache/prefetch/slim_ampm.hh | 3 +- .../spatio_temporal_memory_streaming.cc | 11 +- .../spatio_temporal_memory_streaming.hh | 5 +- src/mem/cache/prefetch/stride.cc | 3 +- src/mem/cache/prefetch/stride.hh | 3 +- src/mem/cache/prefetch/tagged.cc | 3 +- src/mem/cache/prefetch/tagged.hh | 3 +- 34 files changed, 332 insertions(+), 175 deletions(-) create mode 100644 src/mem/cache/cache_probe_arg.hh diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index 87c44cefb7..ce6cbe89ca 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2018-2019 ARM Limited + * Copyright (c) 2012-2013, 2018-2019, 2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -81,6 +81,7 @@ BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size) : ClockedObject(p), cpuSidePort (p.name + ".cpu_side_port", *this, "CpuSidePort"), memSidePort(p.name + ".mem_side_port", this, "MemSidePort"), + accessor(*this), mshrQueue("MSHRs", p.mshrs, 0, p.demand_mshr_reserve, p.name), writeBuffer("write buffer", p.write_buffers, p.mshrs, p.name), tags(p.tags), @@ -126,7 +127,7 @@ BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size) tags->tagsInit(); if (prefetcher) - prefetcher->setCache(this); + prefetcher->setParentInfo(system, getProbeManager(), getBlockSize()); fatal_if(compressor && !dynamic_cast(tags), "The tags of compressed cache %s must derive from CompressedTags", @@ -448,7 +449,7 @@ BaseCache::recvTimingReq(PacketPtr pkt) if (satisfied) { // notify before anything else as later handleTimingReqHit might turn // the packet in a response - ppHit->notify(pkt); + ppHit->notify(CacheAccessProbeArg(pkt,accessor)); if (prefetcher && blk && blk->wasPrefetched()) { DPRINTF(Cache, "Hit on prefetch for addr %#x (%s)\n", @@ -460,7 +461,7 @@ BaseCache::recvTimingReq(PacketPtr pkt) } else { handleTimingReqMiss(pkt, blk, forward_time, request_time); - ppMiss->notify(pkt); + ppMiss->notify(CacheAccessProbeArg(pkt,accessor)); } if (prefetcher) { @@ -557,7 +558,7 @@ BaseCache::recvTimingResp(PacketPtr pkt) writeAllocator->allocate() : mshr->allocOnFill(); blk = handleFill(pkt, blk, writebacks, allocate); assert(blk != nullptr); - ppFill->notify(pkt); + ppFill->notify(CacheAccessProbeArg(pkt, accessor)); } // Don't want to promote the Locked RMW Read until @@ -771,7 +772,8 @@ void BaseCache::updateBlockData(CacheBlk *blk, const PacketPtr cpkt, bool has_old_data) { - DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure()); + CacheDataUpdateProbeArg data_update( + regenerateBlkAddr(blk), blk->isSecure(), accessor); if (ppDataUpdate->hasListeners()) { if (has_old_data) { data_update.oldData = std::vector(blk->data, @@ -809,7 +811,8 @@ BaseCache::cmpAndSwap(CacheBlk *blk, PacketPtr pkt) assert(sizeof(uint64_t) >= pkt->getSize()); // Get a copy of the old block's contents for the probe before the update - DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure()); + CacheDataUpdateProbeArg data_update( + regenerateBlkAddr(blk), blk->isSecure(), accessor); if (ppDataUpdate->hasListeners()) { data_update.oldData = std::vector(blk->data, blk->data + (blkSize / sizeof(uint64_t))); @@ -1106,7 +1109,8 @@ BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool) if (pkt->isAtomicOp()) { // Get a copy of the old block's contents for the probe before // the update - DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure()); + CacheDataUpdateProbeArg data_update( + regenerateBlkAddr(blk), blk->isSecure(), accessor); if (ppDataUpdate->hasListeners()) { data_update.oldData = std::vector(blk->data, blk->data + (blkSize / sizeof(uint64_t))); @@ -2507,11 +2511,15 @@ BaseCache::CacheStats::regStats() void BaseCache::regProbePoints() { - ppHit = new ProbePointArg(this->getProbeManager(), "Hit"); - ppMiss = new ProbePointArg(this->getProbeManager(), "Miss"); - ppFill = new ProbePointArg(this->getProbeManager(), "Fill"); + ppHit = new ProbePointArg( + this->getProbeManager(), "Hit"); + ppMiss = new ProbePointArg( + this->getProbeManager(), "Miss"); + ppFill = new ProbePointArg( + this->getProbeManager(), "Fill"); ppDataUpdate = - new ProbePointArg(this->getProbeManager(), "Data Update"); + new ProbePointArg( + this->getProbeManager(), "Data Update"); } /////////////// diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 8a06ec2c42..aa4f4e8568 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2015-2016, 2018-2019 ARM Limited + * Copyright (c) 2012-2013, 2015-2016, 2018-2019, 2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -59,6 +59,7 @@ #include "debug/CachePort.hh" #include "enums/Clusivity.hh" #include "mem/cache/cache_blk.hh" +#include "mem/cache/cache_probe_arg.hh" #include "mem/cache/compressors/base.hh" #include "mem/cache/mshr_queue.hh" #include "mem/cache/tags/base.hh" @@ -115,28 +116,6 @@ class BaseCache : public ClockedObject NUM_BLOCKED_CAUSES }; - /** - * A data contents update is composed of the updated block's address, - * the old contents, and the new contents. - * @sa ppDataUpdate - */ - struct DataUpdate - { - /** The updated block's address. */ - Addr addr; - /** Whether the block belongs to the secure address space. */ - bool isSecure; - /** The stale data contents. If zero-sized this update is a fill. */ - std::vector oldData; - /** The new data contents. If zero-sized this is an invalidation. */ - std::vector newData; - - DataUpdate(Addr _addr, bool is_secure) - : addr(_addr), isSecure(is_secure), oldData(), newData() - { - } - }; - protected: /** @@ -336,6 +315,26 @@ class BaseCache : public ClockedObject protected: + struct CacheAccessorImpl : CacheAccessor + { + BaseCache &cache; + + CacheAccessorImpl(BaseCache &_cache) :cache(_cache) {} + + bool inCache(Addr addr, bool is_secure) const override + { return cache.inCache(addr, is_secure); } + + bool hasBeenPrefetched(Addr addr, bool is_secure) const override + { return cache.hasBeenPrefetched(addr, is_secure); } + + bool inMissQueue(Addr addr, bool is_secure) const override + { return cache.inMissQueue(addr, is_secure); } + + bool coalesce() const override + { return cache.coalesce(); } + + } accessor; + /** Miss status registers */ MSHRQueue mshrQueue; @@ -352,20 +351,20 @@ class BaseCache : public ClockedObject prefetch::Base *prefetcher; /** To probe when a cache hit occurs */ - ProbePointArg *ppHit; + ProbePointArg *ppHit; /** To probe when a cache miss occurs */ - ProbePointArg *ppMiss; + ProbePointArg *ppMiss; /** To probe when a cache fill occurs */ - ProbePointArg *ppFill; + ProbePointArg *ppFill; /** * To probe when the contents of a block are updated. Content updates * include data fills, overwrites, and invalidations, which means that * this probe partially overlaps with other probes. */ - ProbePointArg *ppDataUpdate; + ProbePointArg *ppDataUpdate; /** * The writeAllocator drive optimizations for streaming writes. diff --git a/src/mem/cache/cache_probe_arg.hh b/src/mem/cache/cache_probe_arg.hh new file mode 100644 index 0000000000..b70e0269ee --- /dev/null +++ b/src/mem/cache/cache_probe_arg.hh @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + + +#ifndef __MEM_CACHE_PROBE_ARG_HH__ +#define __MEM_CACHE_PROBE_ARG_HH__ + +#include "mem/packet.hh" + +namespace gem5 +{ + +/** + * Provides generic cache lookup functions. A cache may provide + * a CacheAccessor object to other components that need to perform + * a lookup outside the normal cache control flow. Currently this + * is used by prefetchers that perform lookups when notified by + * cache events. + */ +struct CacheAccessor +{ + /** Determine if address is in cache */ + virtual bool inCache(Addr addr, bool is_secure) const = 0; + + /** Determine if address has been prefetched */ + virtual bool hasBeenPrefetched(Addr addr, bool is_secure) const = 0; + + /** Determine if address is in cache miss queue */ + virtual bool inMissQueue(Addr addr, bool is_secure) const = 0; + + /** Determine if cache is coalescing writes */ + virtual bool coalesce() const = 0; +}; + +/** + * Information provided to probes on a cache event. + * @sa ppHit, ppMiss, ppFill in gem5::BaseCache (src/mem/cache/base.hh) + */ +class CacheAccessProbeArg +{ + public: + /** Packet that triggered the cache access*/ + PacketPtr pkt; + /** Accessor for the cache */ + CacheAccessor &cache; + + CacheAccessProbeArg(PacketPtr _pkt, CacheAccessor &_cache) + :pkt(_pkt), cache(_cache) + { + } +}; + +/** + * A data contents update is composed of the updated block's address, + * the old contents, and the new contents. + * @sa ppDataUpdate in gem5::BaseCache (src/mem/cache/base.hh) + */ +struct CacheDataUpdateProbeArg +{ + /** The updated block's address. */ + Addr addr; + /** Whether the block belongs to the secure address space. */ + bool isSecure; + /** The stale data contents. If zero-sized this update is a fill. */ + std::vector oldData; + /** The new data contents. If zero-sized this is an invalidation. */ + std::vector newData; + /** Accessor for the cache */ + CacheAccessor &accessor; + + CacheDataUpdateProbeArg(Addr _addr, bool is_secure, + CacheAccessor &_accessor) + : addr(_addr), isSecure(is_secure), oldData(), newData(), + accessor(_accessor) + { + } +}; + +} // namespace gem5 + +#endif //__MEM_CACHE_PROBE_ARG_HH__ diff --git a/src/mem/cache/compressors/frequent_values.hh b/src/mem/cache/compressors/frequent_values.hh index e7eac2644f..41103ce594 100644 --- a/src/mem/cache/compressors/frequent_values.hh +++ b/src/mem/cache/compressors/frequent_values.hh @@ -37,6 +37,7 @@ #include "base/sat_counter.hh" #include "base/types.hh" #include "mem/cache/base.hh" +#include "mem/cache/cache_probe_arg.hh" #include "mem/cache/compressors/base.hh" #include "mem/cache/compressors/encoders/huffman.hh" #include "mem/cache/prefetch/associative_set.hh" @@ -63,7 +64,7 @@ class FrequentValues : public Base private: class CompData; - using DataUpdate = BaseCache::DataUpdate; + using DataUpdate = CacheDataUpdateProbeArg; class FrequentValuesListener : public ProbeListenerArgBase { diff --git a/src/mem/cache/prefetch/access_map_pattern_matching.cc b/src/mem/cache/prefetch/access_map_pattern_matching.cc index 989f3c6be1..f53b77868f 100644 --- a/src/mem/cache/prefetch/access_map_pattern_matching.cc +++ b/src/mem/cache/prefetch/access_map_pattern_matching.cc @@ -156,7 +156,8 @@ AccessMapPatternMatching::setEntryState(AccessMapEntry &entry, void AccessMapPatternMatching::calculatePrefetch(const Base::PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { assert(addresses.empty()); @@ -262,9 +263,10 @@ AMPM::AMPM(const AMPMPrefetcherParams &p) void AMPM::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { - ampm.calculatePrefetch(pfi, addresses); + ampm.calculatePrefetch(pfi, addresses, cache); } } // namespace prefetch diff --git a/src/mem/cache/prefetch/access_map_pattern_matching.hh b/src/mem/cache/prefetch/access_map_pattern_matching.hh index 893d30dec2..b98a241b02 100644 --- a/src/mem/cache/prefetch/access_map_pattern_matching.hh +++ b/src/mem/cache/prefetch/access_map_pattern_matching.hh @@ -190,7 +190,8 @@ class AccessMapPatternMatching : public ClockedObject void startup() override; void calculatePrefetch(const Base::PrefetchInfo &pfi, - std::vector &addresses); + std::vector &addresses, + const CacheAccessor &cache); }; class AMPM : public Queued @@ -201,7 +202,8 @@ class AMPM : public Queued ~AMPM() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index e3e4b24cf2..8614a7739b 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 ARM Limited + * Copyright (c) 2013-2014, 2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -83,18 +83,19 @@ Base::PrefetchInfo::PrefetchInfo(PrefetchInfo const &pfi, Addr addr) } void -Base::PrefetchListener::notify(const PacketPtr &pkt) +Base::PrefetchListener::notify(const CacheAccessProbeArg &arg) { if (isFill) { - parent.notifyFill(pkt); + parent.notifyFill(arg); } else { - parent.probeNotify(pkt, miss); + parent.probeNotify(arg, miss); } } Base::Base(const BasePrefetcherParams &p) - : ClockedObject(p), listeners(), cache(nullptr), blkSize(p.block_size), - lBlkSize(floorLog2(blkSize)), onMiss(p.on_miss), onRead(p.on_read), + : ClockedObject(p), listeners(), system(nullptr), probeManager(nullptr), + blkSize(p.block_size), lBlkSize(floorLog2(blkSize)), + onMiss(p.on_miss), onRead(p.on_read), onWrite(p.on_write), onData(p.on_data), onInst(p.on_inst), requestorId(p.sys->getRequestorId(this)), pageBytes(p.page_bytes), @@ -107,13 +108,13 @@ Base::Base(const BasePrefetcherParams &p) } void -Base::setCache(BaseCache *_cache) +Base::setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size) { - assert(!cache); - cache = _cache; - + assert(!system && !probeManager); + system = sys; + probeManager = pm; // If the cache has a different block size from the system's, save it - blkSize = cache->getBlockSize(); + blkSize = blk_size; lBlkSize = floorLog2(blkSize); } @@ -157,7 +158,7 @@ Base::StatGroup::StatGroup(statistics::Group *parent) } bool -Base::observeAccess(const PacketPtr &pkt, bool miss) const +Base::observeAccess(const PacketPtr &pkt, bool miss, bool prefetched) const { bool fetch = pkt->req->isInstFetch(); bool read = pkt->isRead(); @@ -165,7 +166,7 @@ Base::observeAccess(const PacketPtr &pkt, bool miss) const if (!miss) { if (prefetchOnPfHit) - return hasBeenPrefetched(pkt->getAddr(), pkt->isSecure()); + return prefetched; if (!prefetchOnAccess) return false; } @@ -184,24 +185,6 @@ Base::observeAccess(const PacketPtr &pkt, bool miss) const return true; } -bool -Base::inCache(Addr addr, bool is_secure) const -{ - return cache->inCache(addr, is_secure); -} - -bool -Base::inMissQueue(Addr addr, bool is_secure) const -{ - return cache->inMissQueue(addr, is_secure); -} - -bool -Base::hasBeenPrefetched(Addr addr, bool is_secure) const -{ - return cache->hasBeenPrefetched(addr, is_secure); -} - bool Base::samePage(Addr a, Addr b) const { @@ -239,18 +222,23 @@ Base::pageIthBlockAddress(Addr page, uint32_t blockIndex) const } void -Base::probeNotify(const PacketPtr &pkt, bool miss) +Base::probeNotify(const CacheAccessProbeArg &acc, bool miss) { + const PacketPtr pkt = acc.pkt; + const CacheAccessor &cache = acc.cache; + // Don't notify prefetcher on SWPrefetch, cache maintenance // operations or for writes that we are coaslescing. if (pkt->cmd.isSWPrefetch()) return; if (pkt->req->isCacheMaintenance()) return; - if (pkt->isWrite() && cache != nullptr && cache->coalesce()) return; + if (pkt->isWrite() && cache.coalesce()) return; if (!pkt->req->hasPaddr()) { panic("Request must have a physical address"); } - if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) { + bool has_been_prefetched = + acc.cache.hasBeenPrefetched(pkt->getAddr(), pkt->isSecure()); + if (has_been_prefetched) { usefulPrefetches += 1; prefetchStats.pfUseful++; if (miss) @@ -260,13 +248,13 @@ Base::probeNotify(const PacketPtr &pkt, bool miss) } // Verify this access type is observed by prefetcher - if (observeAccess(pkt, miss)) { + if (observeAccess(pkt, miss, has_been_prefetched)) { if (useVirtualAddresses && pkt->req->hasVaddr()) { PrefetchInfo pfi(pkt, pkt->req->getVaddr(), miss); - notify(pkt, pfi); + notify(acc, pfi); } else if (!useVirtualAddresses) { PrefetchInfo pfi(pkt, pkt->req->getPaddr(), miss); - notify(pkt, pfi); + notify(acc, pfi); } } } @@ -279,14 +267,13 @@ Base::regProbeListeners() * parent cache using the probe "Miss". Also connect to "Hit", if the * cache is configured to prefetch on accesses. */ - if (listeners.empty() && cache != nullptr) { - ProbeManager *pm(cache->getProbeManager()); - listeners.push_back(new PrefetchListener(*this, pm, "Miss", false, - true)); - listeners.push_back(new PrefetchListener(*this, pm, "Fill", true, - false)); - listeners.push_back(new PrefetchListener(*this, pm, "Hit", false, - false)); + if (listeners.empty() && probeManager != nullptr) { + listeners.push_back(new PrefetchListener(*this, probeManager, + "Miss", false, true)); + listeners.push_back(new PrefetchListener(*this, probeManager, + "Fill", true, false)); + listeners.push_back(new PrefetchListener(*this, probeManager, + "Hit", false, false)); } } diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index 6bae73519c..a30e473505 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 ARM Limited + * Copyright (c) 2013-2014, 2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -52,7 +52,7 @@ #include "base/compiler.hh" #include "base/statistics.hh" #include "base/types.hh" -#include "mem/cache/cache_blk.hh" +#include "mem/cache/cache_probe_arg.hh" #include "mem/packet.hh" #include "mem/request.hh" #include "sim/byteswap.hh" @@ -62,15 +62,16 @@ namespace gem5 { -class BaseCache; struct BasePrefetcherParams; +class ProbeManager; +class System; namespace prefetch { class Base : public ClockedObject { - class PrefetchListener : public ProbeListenerArgBase + class PrefetchListener : public ProbeListenerArgBase { public: PrefetchListener(Base &_parent, ProbeManager *pm, @@ -78,7 +79,7 @@ class Base : public ClockedObject bool _miss = false) : ProbeListenerArgBase(pm, name), parent(_parent), isFill(_isFill), miss(_miss) {} - void notify(const PacketPtr &pkt) override; + void notify(const CacheAccessProbeArg &arg) override; protected: Base &parent; const bool isFill; @@ -262,8 +263,11 @@ class Base : public ClockedObject // PARAMETERS - /** Pointr to the parent cache. */ - BaseCache* cache; + /** Pointer to the parent system. */ + System* system; + + /** Pointer to the parent cache's probe manager. */ + ProbeManager *probeManager; /** The block size of the parent cache. */ unsigned blkSize; @@ -304,16 +308,9 @@ class Base : public ClockedObject * Determine if this access should be observed * @param pkt The memory request causing the event * @param miss whether this event comes from a cache miss + * @param prefetched on a hit, this indicates the block was prefetched */ - bool observeAccess(const PacketPtr &pkt, bool miss) const; - - /** Determine if address is in cache */ - bool inCache(Addr addr, bool is_secure) const; - - /** Determine if address is in cache miss queue */ - bool inMissQueue(Addr addr, bool is_secure) const; - - bool hasBeenPrefetched(Addr addr, bool is_secure) const; + bool observeAccess(const PacketPtr &pkt, bool miss, bool prefetched) const; /** Determine if addresses are on the same page */ bool samePage(Addr a, Addr b) const; @@ -370,16 +367,18 @@ class Base : public ClockedObject Base(const BasePrefetcherParams &p); virtual ~Base() = default; - virtual void setCache(BaseCache *_cache); + virtual void + setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size); /** * Notify prefetcher of cache access (may be any access or just * misses, depending on cache parameters.) */ - virtual void notify(const PacketPtr &pkt, const PrefetchInfo &pfi) = 0; + virtual void + notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi) = 0; /** Notify prefetcher of cache fill */ - virtual void notifyFill(const PacketPtr &pkt) + virtual void notifyFill(const CacheAccessProbeArg &acc) {} virtual PacketPtr getPacket() = 0; @@ -423,10 +422,10 @@ class Base : public ClockedObject /** * Process a notification event from the ProbeListener. - * @param pkt The memory request causing the event + * @param acc probe arg encapsulating the memory request causing the event * @param miss whether this event comes from a cache miss */ - void probeNotify(const PacketPtr &pkt, bool miss); + void probeNotify(const CacheAccessProbeArg &acc, bool miss); /** * Add a SimObject and a probe name to listen events from diff --git a/src/mem/cache/prefetch/bop.cc b/src/mem/cache/prefetch/bop.cc index ce2502bee6..d50e9460d4 100644 --- a/src/mem/cache/prefetch/bop.cc +++ b/src/mem/cache/prefetch/bop.cc @@ -227,7 +227,8 @@ BOP::bestOffsetLearning(Addr x) void BOP::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { Addr addr = pfi.getAddr(); Addr tag_x = tag(addr); @@ -252,8 +253,10 @@ BOP::calculatePrefetch(const PrefetchInfo &pfi, } void -BOP::notifyFill(const PacketPtr& pkt) +BOP::notifyFill(const CacheAccessProbeArg &arg) { + const PacketPtr& pkt = arg.pkt; + // Only insert into the RR right way if it's the pkt is a HWP if (!pkt->cmd.isHWPrefetch()) return; diff --git a/src/mem/cache/prefetch/bop.hh b/src/mem/cache/prefetch/bop.hh index bb1b05dfa9..09ae4ea72d 100644 --- a/src/mem/cache/prefetch/bop.hh +++ b/src/mem/cache/prefetch/bop.hh @@ -148,7 +148,7 @@ class BOP : public Queued void bestOffsetLearning(Addr); /** Update the RR right table after a prefetch fill */ - void notifyFill(const PacketPtr& pkt) override; + void notifyFill(const CacheAccessProbeArg &arg) override; public: @@ -156,7 +156,8 @@ class BOP : public Queued ~BOP() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/delta_correlating_prediction_tables.cc b/src/mem/cache/prefetch/delta_correlating_prediction_tables.cc index b59394ce25..ea59bea3c0 100644 --- a/src/mem/cache/prefetch/delta_correlating_prediction_tables.cc +++ b/src/mem/cache/prefetch/delta_correlating_prediction_tables.cc @@ -125,7 +125,8 @@ DeltaCorrelatingPredictionTables::DCPTEntry::getCandidates( void DeltaCorrelatingPredictionTables::calculatePrefetch( const Base::PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { if (!pfi.hasPC()) { DPRINTF(HWPrefetch, "Ignoring request with no PC.\n"); @@ -156,9 +157,10 @@ DCPT::DCPT(const DCPTPrefetcherParams &p) void DCPT::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { - dcpt.calculatePrefetch(pfi, addresses); + dcpt.calculatePrefetch(pfi, addresses, cache); } } // namespace prefetch diff --git a/src/mem/cache/prefetch/delta_correlating_prediction_tables.hh b/src/mem/cache/prefetch/delta_correlating_prediction_tables.hh index 0218e9138a..7280c96733 100644 --- a/src/mem/cache/prefetch/delta_correlating_prediction_tables.hh +++ b/src/mem/cache/prefetch/delta_correlating_prediction_tables.hh @@ -114,9 +114,11 @@ class DeltaCorrelatingPredictionTables : public SimObject * Computes the prefetch candidates given a prefetch event. * @param pfi The prefetch event information * @param addresses prefetch candidates generated + * @param cache accessor for cache lookups */ void calculatePrefetch(const Base::PrefetchInfo &pfi, - std::vector &addresses); + std::vector &addresses, + const CacheAccessor &cache); }; @@ -130,7 +132,8 @@ class DCPT : public Queued ~DCPT() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/indirect_memory.cc b/src/mem/cache/prefetch/indirect_memory.cc index ab84ce25a2..780879bc6a 100644 --- a/src/mem/cache/prefetch/indirect_memory.cc +++ b/src/mem/cache/prefetch/indirect_memory.cc @@ -56,7 +56,8 @@ IndirectMemory::IndirectMemory(const IndirectMemoryPrefetcherParams &p) void IndirectMemory::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { // This prefetcher requires a PC if (!pfi.hasPC()) { diff --git a/src/mem/cache/prefetch/indirect_memory.hh b/src/mem/cache/prefetch/indirect_memory.hh index da3e894cfa..877e55d63d 100644 --- a/src/mem/cache/prefetch/indirect_memory.hh +++ b/src/mem/cache/prefetch/indirect_memory.hh @@ -201,7 +201,8 @@ class IndirectMemory : public Queued ~IndirectMemory() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/irregular_stream_buffer.cc b/src/mem/cache/prefetch/irregular_stream_buffer.cc index ce30b41aa6..bf81ebedc5 100644 --- a/src/mem/cache/prefetch/irregular_stream_buffer.cc +++ b/src/mem/cache/prefetch/irregular_stream_buffer.cc @@ -66,7 +66,8 @@ IrregularStreamBuffer::IrregularStreamBuffer( void IrregularStreamBuffer::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { // This prefetcher requires a PC if (!pfi.hasPC()) { diff --git a/src/mem/cache/prefetch/irregular_stream_buffer.hh b/src/mem/cache/prefetch/irregular_stream_buffer.hh index 39373010bb..399268a5a4 100644 --- a/src/mem/cache/prefetch/irregular_stream_buffer.hh +++ b/src/mem/cache/prefetch/irregular_stream_buffer.hh @@ -137,7 +137,8 @@ class IrregularStreamBuffer : public Queued ~IrregularStreamBuffer() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/multi.cc b/src/mem/cache/prefetch/multi.cc index 1f7298f354..9cd40163e2 100644 --- a/src/mem/cache/prefetch/multi.cc +++ b/src/mem/cache/prefetch/multi.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019 ARM Limited + * Copyright (c) 2014, 2019, 2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -53,10 +53,10 @@ Multi::Multi(const MultiPrefetcherParams &p) } void -Multi::setCache(BaseCache *_cache) +Multi::setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size) { for (auto pf : prefetchers) - pf->setCache(_cache); + pf->setParentInfo(sys, pm, blk_size); } Tick diff --git a/src/mem/cache/prefetch/multi.hh b/src/mem/cache/prefetch/multi.hh index 7890f090b5..74cdaec984 100644 --- a/src/mem/cache/prefetch/multi.hh +++ b/src/mem/cache/prefetch/multi.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019 ARM Limited + * Copyright (c) 2014, 2019, 2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -56,7 +56,8 @@ class Multi : public Base Multi(const MultiPrefetcherParams &p); public: - void setCache(BaseCache *_cache) override; + void + setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size) override; PacketPtr getPacket() override; Tick nextPrefetchReadyTime() const override; @@ -65,8 +66,11 @@ class Multi : public Base * Ignore notifications since each sub-prefetcher already gets a * notification through their probes-based interface. */ - void notify(const PacketPtr &pkt, const PrefetchInfo &pfi) override {}; - void notifyFill(const PacketPtr &pkt) override {}; + void + notify(const CacheAccessProbeArg &arg, const PrefetchInfo &pfi) override + {}; + + void notifyFill(const CacheAccessProbeArg &arg) override {}; /** @} */ protected: diff --git a/src/mem/cache/prefetch/pif.cc b/src/mem/cache/prefetch/pif.cc index 79e8e6d747..581831491f 100644 --- a/src/mem/cache/prefetch/pif.cc +++ b/src/mem/cache/prefetch/pif.cc @@ -198,7 +198,8 @@ PIF::notifyRetiredInst(const Addr pc) void PIF::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { if (!pfi.hasPC()) { return; diff --git a/src/mem/cache/prefetch/pif.hh b/src/mem/cache/prefetch/pif.hh index 296087e8e0..ecb97db78d 100644 --- a/src/mem/cache/prefetch/pif.hh +++ b/src/mem/cache/prefetch/pif.hh @@ -182,7 +182,8 @@ class PIF : public Queued ~PIF() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses); + std::vector &addresses, + const CacheAccessor &cache); /** * Add a SimObject and a probe name to monitor the retired instructions diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index 1ab34d2e9b..e22d6f5eb8 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 ARM Limited + * Copyright (c) 2014-2015, 2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -94,7 +94,7 @@ Queued::DeferredPacket::finish(const Fault &fault, assert(ongoingTranslation); ongoingTranslation = false; bool failed = (fault != NoFault); - owner->translationComplete(this, failed); + owner->translationComplete(this, failed, *cache); } Queued::Queued(const QueuedPrefetcherParams &p) @@ -169,10 +169,12 @@ Queued::getMaxPermittedPrefetches(size_t total) const } void -Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi) +Queued::notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi) { Addr blk_addr = blockAddress(pfi.getAddr()); bool is_secure = pfi.isSecure(); + const PacketPtr pkt = acc.pkt; + const CacheAccessor &cache = acc.cache; // Squash queued prefetches if demand miss to same line if (queueSquash) { @@ -195,7 +197,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi) // Calculate prefetches given this access std::vector addresses; - calculatePrefetch(pfi, addresses); + calculatePrefetch(pfi, addresses, cache); // Get the maximu number of prefetches that we are allowed to generate size_t max_pfs = getMaxPermittedPrefetches(addresses.size()); @@ -210,7 +212,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi) if (!samePage(addr_prio.first, pfi.getAddr())) { statsQueued.pfSpanPage += 1; - if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) { + if (cache.hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) { statsQueued.pfUsefulSpanPage += 1; } } @@ -222,7 +224,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi) DPRINTF(HWPrefetch, "Found a pf candidate addr: %#x, " "inserting into prefetch queue.\n", new_pfi.getAddr()); // Create and insert the request - insert(pkt, new_pfi, addr_prio.second); + insert(pkt, new_pfi, addr_prio.second, cache); num_pfs += 1; if (num_pfs == max_pfs) { break; @@ -298,7 +300,8 @@ Queued::processMissingTranslations(unsigned max) } void -Queued::translationComplete(DeferredPacket *dp, bool failed) +Queued::translationComplete(DeferredPacket *dp, bool failed, + const CacheAccessor &cache) { auto it = pfqMissingTranslation.begin(); while (it != pfqMissingTranslation.end()) { @@ -315,8 +318,9 @@ Queued::translationComplete(DeferredPacket *dp, bool failed) it->translationRequest->getPaddr()); Addr target_paddr = it->translationRequest->getPaddr(); // check if this prefetch is already redundant - if (cacheSnoop && (inCache(target_paddr, it->pfInfo.isSecure()) || - inMissQueue(target_paddr, it->pfInfo.isSecure()))) { + if (cacheSnoop && + (cache.inCache(target_paddr, it->pfInfo.isSecure()) || + cache.inMissQueue(target_paddr, it->pfInfo.isSecure()))) { statsQueued.pfInCache++; DPRINTF(HWPrefetch, "Dropping redundant in " "cache/MSHR prefetch addr:%#x\n", target_paddr); @@ -382,7 +386,7 @@ Queued::createPrefetchRequest(Addr addr, PrefetchInfo const &pfi, void Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, - int32_t priority) + int32_t priority, const CacheAccessor &cache) { if (queueFilter) { if (alreadyInQueue(pfq, new_pfi, priority)) { @@ -451,8 +455,8 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, } } if (has_target_pa && cacheSnoop && - (inCache(target_paddr, new_pfi.isSecure()) || - inMissQueue(target_paddr, new_pfi.isSecure()))) { + (cache.inCache(target_paddr, new_pfi.isSecure()) || + cache.inMissQueue(target_paddr, new_pfi.isSecure()))) { statsQueued.pfInCache++; DPRINTF(HWPrefetch, "Dropping redundant in " "cache/MSHR prefetch addr:%#x\n", target_paddr); @@ -460,7 +464,7 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, } /* Create the packet and find the spot to insert it */ - DeferredPacket dpp(this, new_pfi, 0, priority); + DeferredPacket dpp(this, new_pfi, 0, priority, cache); if (has_target_pa) { Tick pf_time = curTick() + clockPeriod() * latency; dpp.createPkt(target_paddr, blkSize, requestorId, tagPrefetch, @@ -472,7 +476,7 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, } else { // Add the translation request and try to resolve it later dpp.setTranslationRequest(translation_req); - dpp.tc = cache->system->threads[translation_req->contextId()]; + dpp.tc = system->threads[translation_req->contextId()]; DPRINTF(HWPrefetch, "Prefetch queued with no translation. " "addr:%#x priority: %3d\n", new_pfi.getAddr(), priority); addToQueue(pfqMissingTranslation, dpp); diff --git a/src/mem/cache/prefetch/queued.hh b/src/mem/cache/prefetch/queued.hh index 1d1a3faef4..f3620bd826 100644 --- a/src/mem/cache/prefetch/queued.hh +++ b/src/mem/cache/prefetch/queued.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 ARM Limited + * Copyright (c) 2014-2015, 2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -75,6 +75,7 @@ class Queued : public Base RequestPtr translationRequest; ThreadContext *tc; bool ongoingTranslation; + const CacheAccessor *cache; /** * Constructor @@ -85,9 +86,10 @@ class Queued : public Base * @param prio This prefetch priority */ DeferredPacket(Queued *o, PrefetchInfo const &pfi, Tick t, - int32_t prio) : owner(o), pfInfo(pfi), tick(t), pkt(nullptr), + int32_t prio, const CacheAccessor &_cache) + : owner(o), pfInfo(pfi), tick(t), pkt(nullptr), priority(prio), translationRequest(), tc(nullptr), - ongoingTranslation(false) { + ongoingTranslation(false), cache(&_cache) { } bool operator>(const DeferredPacket& that) const @@ -192,12 +194,15 @@ class Queued : public Base Queued(const QueuedPrefetcherParams &p); virtual ~Queued(); - void notify(const PacketPtr &pkt, const PrefetchInfo &pfi) override; + void + notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi) override; - void insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, int32_t priority); + void insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, int32_t priority, + const CacheAccessor &cache); virtual void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) = 0; + std::vector &addresses, + const CacheAccessor &cache) = 0; PacketPtr getPacket() override; Tick nextPrefetchReadyTime() const override @@ -231,8 +236,10 @@ class Queued : public Base * new prefetch request. * @param dp the deferred packet that has completed the translation request * @param failed whether the translation was successful + * @param cache accessor for lookups on the cache that originated this pkt */ - void translationComplete(DeferredPacket *dp, bool failed); + void translationComplete(DeferredPacket *dp, bool failed, + const CacheAccessor &cache); /** * Checks whether the specified prefetch request is already in the diff --git a/src/mem/cache/prefetch/sbooe.cc b/src/mem/cache/prefetch/sbooe.cc index 44a10c232d..7f4c5ee04d 100644 --- a/src/mem/cache/prefetch/sbooe.cc +++ b/src/mem/cache/prefetch/sbooe.cc @@ -91,8 +91,10 @@ SBOOE::access(Addr access_line) } void -SBOOE::notifyFill(const PacketPtr& pkt) +SBOOE::notifyFill(const CacheAccessProbeArg &arg) { + const PacketPtr& pkt = arg.pkt; + // (1) Look for the address in the demands list // (2) Calculate the elapsed cycles until it was filled (curTick) // (3) Insert the latency into the latency buffer (FIFO) @@ -117,7 +119,8 @@ SBOOE::notifyFill(const PacketPtr& pkt) void SBOOE::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { const Addr pfi_addr = pfi.getAddr(); const Addr pfi_line = pfi_addr >> lBlkSize; diff --git a/src/mem/cache/prefetch/sbooe.hh b/src/mem/cache/prefetch/sbooe.hh index 7914b88f45..26384923cf 100644 --- a/src/mem/cache/prefetch/sbooe.hh +++ b/src/mem/cache/prefetch/sbooe.hh @@ -153,13 +153,14 @@ class SBOOE : public Queued bool access(Addr line); /** Update the latency buffer after a prefetch fill */ - void notifyFill(const PacketPtr& pkt) override; + void notifyFill(const CacheAccessProbeArg &arg) override; public: SBOOE(const SBOOEPrefetcherParams &p); void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/signature_path.cc b/src/mem/cache/prefetch/signature_path.cc index a36ef809ce..6d3f05bf17 100644 --- a/src/mem/cache/prefetch/signature_path.cc +++ b/src/mem/cache/prefetch/signature_path.cc @@ -227,7 +227,8 @@ SignaturePath::calculateLookaheadConfidence(PatternEntry const &sig, void SignaturePath::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { Addr request_addr = pfi.getAddr(); Addr ppn = request_addr / pageBytes; diff --git a/src/mem/cache/prefetch/signature_path.hh b/src/mem/cache/prefetch/signature_path.hh index 9613fe0886..a561cda063 100644 --- a/src/mem/cache/prefetch/signature_path.hh +++ b/src/mem/cache/prefetch/signature_path.hh @@ -287,7 +287,8 @@ class SignaturePath : public Queued ~SignaturePath() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/slim_ampm.cc b/src/mem/cache/prefetch/slim_ampm.cc index 950994a4bd..8717d0314b 100644 --- a/src/mem/cache/prefetch/slim_ampm.cc +++ b/src/mem/cache/prefetch/slim_ampm.cc @@ -43,11 +43,12 @@ SlimAMPM::SlimAMPM(const SlimAMPMPrefetcherParams &p) void SlimAMPM::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { - dcpt.calculatePrefetch(pfi, addresses); + dcpt.calculatePrefetch(pfi, addresses, cache); if (addresses.empty()) { - ampm.calculatePrefetch(pfi, addresses); + ampm.calculatePrefetch(pfi, addresses, cache); } } diff --git a/src/mem/cache/prefetch/slim_ampm.hh b/src/mem/cache/prefetch/slim_ampm.hh index 54f38d4885..04ef6ca921 100644 --- a/src/mem/cache/prefetch/slim_ampm.hh +++ b/src/mem/cache/prefetch/slim_ampm.hh @@ -62,7 +62,8 @@ class SlimAMPM : public Queued ~SlimAMPM() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc index 0e3211579c..406e444be0 100644 --- a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc +++ b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.cc @@ -63,7 +63,7 @@ STeMS::STeMS(const STeMSPrefetcherParams &p) } void -STeMS::checkForActiveGenerationsEnd() +STeMS::checkForActiveGenerationsEnd(const CacheAccessor &cache) { // This prefetcher operates attached to the L1 and it observes all // accesses, this guarantees that no evictions are missed @@ -79,8 +79,8 @@ STeMS::checkForActiveGenerationsEnd() if (seq_entry.counter > 0) { Addr cache_addr = agt_entry.paddress + seq_entry.offset * blkSize; - if (!inCache(cache_addr, sr_is_secure) && - !inMissQueue(cache_addr, sr_is_secure)) { + if (!cache.inCache(cache_addr, sr_is_secure) && + !cache.inMissQueue(cache_addr, sr_is_secure)) { generation_ended = true; pst_addr = (agt_entry.pc << spatialRegionSizeBits) + seq_entry.offset; @@ -135,7 +135,8 @@ STeMS::addToRMOB(Addr sr_addr, Addr pst_addr, unsigned int delta) void STeMS::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { if (!pfi.hasPC()) { DPRINTF(HWPrefetch, "Ignoring request with no PC.\n"); @@ -152,7 +153,7 @@ STeMS::calculatePrefetch(const PrefetchInfo &pfi, Addr sr_offset = (pfi.getAddr() % spatialRegionSize) / blkSize; // Check if any active generation has ended - checkForActiveGenerationsEnd(); + checkForActiveGenerationsEnd(cache); ActiveGenerationTableEntry *agt_entry = activeGenerationTable.findEntry(sr_addr, is_secure); diff --git a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh index cdd2788104..c6cd2f72d1 100644 --- a/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh +++ b/src/mem/cache/prefetch/spatio_temporal_memory_streaming.hh @@ -181,7 +181,7 @@ class STeMS : public Queued unsigned int lastTriggerCounter; /** Checks if the active generations have ended */ - void checkForActiveGenerationsEnd(); + void checkForActiveGenerationsEnd(const CacheAccessor &cache); /** * Adds an entry to the RMOB * @param sr_addr Spatial region address @@ -206,7 +206,8 @@ class STeMS : public Queued ~STeMS() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index 0a77b28a1c..b2e4702f20 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -118,7 +118,8 @@ Stride::allocateNewContext(int context) void Stride::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { if (!pfi.hasPC()) { DPRINTF(HWPrefetch, "Ignoring request with no PC.\n"); diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index 7e55abea21..41cadbe7d0 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -160,7 +160,8 @@ class Stride : public Queued Stride(const StridePrefetcherParams &p); void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch diff --git a/src/mem/cache/prefetch/tagged.cc b/src/mem/cache/prefetch/tagged.cc index 0d4d79b006..e34e1a692d 100644 --- a/src/mem/cache/prefetch/tagged.cc +++ b/src/mem/cache/prefetch/tagged.cc @@ -49,7 +49,8 @@ Tagged::Tagged(const TaggedPrefetcherParams &p) void Tagged::calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) + std::vector &addresses, + const CacheAccessor &cache) { Addr blkAddr = blockAddress(pfi.getAddr()); diff --git a/src/mem/cache/prefetch/tagged.hh b/src/mem/cache/prefetch/tagged.hh index 5c91f654b1..1ed11e9355 100644 --- a/src/mem/cache/prefetch/tagged.hh +++ b/src/mem/cache/prefetch/tagged.hh @@ -55,7 +55,8 @@ class Tagged : public Queued ~Tagged() = default; void calculatePrefetch(const PrefetchInfo &pfi, - std::vector &addresses) override; + std::vector &addresses, + const CacheAccessor &cache) override; }; } // namespace prefetch From becba00d9503fcd3a4874b23c0631de5c1cfe819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Mon, 23 Oct 2023 18:11:09 -0500 Subject: [PATCH 619/693] mem-cache,configs: remove extra prefetch_* params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the prefetch_on_access and prefetch_on_pf_hit from BaseCache. BasePrefetch no longer expects this params to exist in the parent. Configurations that set these parameter using the cache object were fixed. Change-Id: I9ab6a545eaf930ee41ebda74e2b6b8bad0ca35a7 Signed-off-by: Tiago Mück --- configs/common/cores/arm/O3_ARM_v7a.py | 3 +-- configs/common/cores/arm/ex5_LITTLE.py | 3 +-- configs/common/cores/arm/ex5_big.py | 3 +-- src/mem/cache/Cache.py | 9 +-------- src/mem/cache/prefetch/Prefetcher.py | 6 +++--- 5 files changed, 7 insertions(+), 17 deletions(-) diff --git a/configs/common/cores/arm/O3_ARM_v7a.py b/configs/common/cores/arm/O3_ARM_v7a.py index de258324be..5413839747 100644 --- a/configs/common/cores/arm/O3_ARM_v7a.py +++ b/configs/common/cores/arm/O3_ARM_v7a.py @@ -207,9 +207,8 @@ class O3_ARM_v7aL2(Cache): size = "1MB" assoc = 16 write_buffers = 8 - prefetch_on_access = True clusivity = "mostly_excl" # Simple stride prefetcher - prefetcher = StridePrefetcher(degree=8, latency=1) + prefetcher = StridePrefetcher(degree=8, latency=1, prefetch_on_access=True) tags = BaseSetAssoc() replacement_policy = RandomRP() diff --git a/configs/common/cores/arm/ex5_LITTLE.py b/configs/common/cores/arm/ex5_LITTLE.py index a89881436d..372e5c97b3 100644 --- a/configs/common/cores/arm/ex5_LITTLE.py +++ b/configs/common/cores/arm/ex5_LITTLE.py @@ -147,9 +147,8 @@ class L2(Cache): size = "512kB" assoc = 8 write_buffers = 16 - prefetch_on_access = True clusivity = "mostly_excl" # Simple stride prefetcher - prefetcher = StridePrefetcher(degree=1, latency=1) + prefetcher = StridePrefetcher(degree=1, latency=1, prefetch_on_access=True) tags = BaseSetAssoc() replacement_policy = RandomRP() diff --git a/configs/common/cores/arm/ex5_big.py b/configs/common/cores/arm/ex5_big.py index 7803c1e0cc..53677ce3b3 100644 --- a/configs/common/cores/arm/ex5_big.py +++ b/configs/common/cores/arm/ex5_big.py @@ -200,9 +200,8 @@ class L2(Cache): size = "2MB" assoc = 16 write_buffers = 8 - prefetch_on_access = True clusivity = "mostly_excl" # Simple stride prefetcher - prefetcher = StridePrefetcher(degree=8, latency=1) + prefetcher = StridePrefetcher(degree=8, latency=1, prefetch_on_access=True) tags = BaseSetAssoc() replacement_policy = RandomRP() diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py index d853a08cd9..9d6df7c630 100644 --- a/src/mem/cache/Cache.py +++ b/src/mem/cache/Cache.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2013, 2015, 2018 ARM Limited +# Copyright (c) 2012-2013, 2015, 2018, 2023 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -107,13 +107,6 @@ class BaseCache(ClockedObject): is_read_only = Param.Bool(False, "Is this cache read only (e.g. inst)") prefetcher = Param.BasePrefetcher(NULL, "Prefetcher attached to cache") - prefetch_on_access = Param.Bool( - False, - "Notify the hardware prefetcher on every access (not just misses)", - ) - prefetch_on_pf_hit = Param.Bool( - False, "Notify the hardware prefetcher on hit on prefetched lines" - ) tags = Param.BaseTags(BaseSetAssoc(), "Tag store") replacement_policy = Param.BaseReplacementPolicy( diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index ecc67f4857..7da1e19249 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012, 2014, 2019 ARM Limited +# Copyright (c) 2012, 2014, 2019, 2023 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -76,11 +76,11 @@ class BasePrefetcher(ClockedObject): on_data = Param.Bool(True, "Notify prefetcher on data accesses") on_inst = Param.Bool(True, "Notify prefetcher on instruction accesses") prefetch_on_access = Param.Bool( - Parent.prefetch_on_access, + False, "Notify the hardware prefetcher on every access (not just misses)", ) prefetch_on_pf_hit = Param.Bool( - Parent.prefetch_on_pf_hit, + False, "Notify the hardware prefetcher on hit on prefetched lines", ) use_virtual_addresses = Param.Bool( From d8a04f902ea6b84f24d57beb90eb6d535ba37f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Thu, 8 Sep 2022 15:55:35 -0500 Subject: [PATCH 620/693] mem-cache: add prefetch info to update probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CacheDataUpdateProbeArg has additional info to tell listeners if the block was prefetched and evicted without being used, as well as which object prefetched the block. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Change-Id: Id8ac9099ddbce6e94ee775655da23de5df25cf0f Signed-off-by: Tiago Mück --- src/mem/cache/base.cc | 11 ++++++++--- src/mem/cache/cache_probe_arg.hh | 10 ++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index ce6cbe89ca..e738167066 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -773,7 +773,8 @@ BaseCache::updateBlockData(CacheBlk *blk, const PacketPtr cpkt, bool has_old_data) { CacheDataUpdateProbeArg data_update( - regenerateBlkAddr(blk), blk->isSecure(), accessor); + regenerateBlkAddr(blk), blk->isSecure(), + blk->getSrcRequestorId(), accessor); if (ppDataUpdate->hasListeners()) { if (has_old_data) { data_update.oldData = std::vector(blk->data, @@ -790,6 +791,7 @@ BaseCache::updateBlockData(CacheBlk *blk, const PacketPtr cpkt, if (cpkt) { data_update.newData = std::vector(blk->data, blk->data + (blkSize / sizeof(uint64_t))); + data_update.hwPrefetched = blk->wasPrefetched(); } ppDataUpdate->notify(data_update); } @@ -812,7 +814,8 @@ BaseCache::cmpAndSwap(CacheBlk *blk, PacketPtr pkt) // Get a copy of the old block's contents for the probe before the update CacheDataUpdateProbeArg data_update( - regenerateBlkAddr(blk), blk->isSecure(), accessor); + regenerateBlkAddr(blk), blk->isSecure(), blk->getSrcRequestorId(), + accessor); if (ppDataUpdate->hasListeners()) { data_update.oldData = std::vector(blk->data, blk->data + (blkSize / sizeof(uint64_t))); @@ -1110,7 +1113,8 @@ BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool) // Get a copy of the old block's contents for the probe before // the update CacheDataUpdateProbeArg data_update( - regenerateBlkAddr(blk), blk->isSecure(), accessor); + regenerateBlkAddr(blk), blk->isSecure(), + blk->getSrcRequestorId(), accessor); if (ppDataUpdate->hasListeners()) { data_update.oldData = std::vector(blk->data, blk->data + (blkSize / sizeof(uint64_t))); @@ -1129,6 +1133,7 @@ BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool) if (ppDataUpdate->hasListeners()) { data_update.newData = std::vector(blk->data, blk->data + (blkSize / sizeof(uint64_t))); + data_update.hwPrefetched = blk->wasPrefetched(); ppDataUpdate->notify(data_update); } diff --git a/src/mem/cache/cache_probe_arg.hh b/src/mem/cache/cache_probe_arg.hh index b70e0269ee..49c0171e2f 100644 --- a/src/mem/cache/cache_probe_arg.hh +++ b/src/mem/cache/cache_probe_arg.hh @@ -95,17 +95,23 @@ struct CacheDataUpdateProbeArg Addr addr; /** Whether the block belongs to the secure address space. */ bool isSecure; + /** Block original requestor */ + const RequestorID requestorID; /** The stale data contents. If zero-sized this update is a fill. */ std::vector oldData; /** The new data contents. If zero-sized this is an invalidation. */ std::vector newData; + /** Set if the update is from a prefetch or evicting a prefetched + * block that was never used. */ + bool hwPrefetched; /** Accessor for the cache */ CacheAccessor &accessor; CacheDataUpdateProbeArg(Addr _addr, bool is_secure, + RequestorID _requestorID, CacheAccessor &_accessor) - : addr(_addr), isSecure(is_secure), oldData(), newData(), - accessor(_accessor) + : addr(_addr), isSecure(is_secure), requestorID(_requestorID), + oldData(), newData(), accessor(_accessor) { } }; From a63ff3c44231c054f706ab52a413bd1934136e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Thu, 8 Sep 2022 16:17:35 -0500 Subject: [PATCH 621/693] mem-cache: add prefetcher listener for evictions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Listener to data update probe notifies prefetcher of evictions. Prefetchers need to implement notifyEvict to make use of this information. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Change-Id: I052cfdeba1e40ede077554ada104522f6a0cb2c7 Signed-off-by: Tiago Mück --- src/mem/cache/prefetch/base.cc | 9 +++++++++ src/mem/cache/prefetch/base.hh | 19 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index 8614a7739b..8ecc715e89 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -92,6 +92,13 @@ Base::PrefetchListener::notify(const CacheAccessProbeArg &arg) } } +void +Base::PrefetchEvictListener::notify(const EvictionInfo &info) +{ + if (info.newData.empty()) + parent.notifyEvict(info); +} + Base::Base(const BasePrefetcherParams &p) : ClockedObject(p), listeners(), system(nullptr), probeManager(nullptr), blkSize(p.block_size), lBlkSize(floorLog2(blkSize)), @@ -274,6 +281,8 @@ Base::regProbeListeners() "Fill", true, false)); listeners.push_back(new PrefetchListener(*this, probeManager, "Hit", false, false)); + listeners.push_back(new PrefetchEvictListener(*this, probeManager, + "Data Update")); } } diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index a30e473505..f4d5cb051b 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -86,7 +86,20 @@ class Base : public ClockedObject const bool miss; }; - std::vector listeners; + using EvictionInfo = CacheDataUpdateProbeArg; + + class PrefetchEvictListener : public ProbeListenerArgBase + { + public: + PrefetchEvictListener(Base &_parent, ProbeManager *pm, + const std::string &name) + : ProbeListenerArgBase(pm, name), parent(_parent) {} + void notify(const EvictionInfo &info) override; + protected: + Base &parent; + }; + + std::vector listeners; public: @@ -381,6 +394,10 @@ class Base : public ClockedObject virtual void notifyFill(const CacheAccessProbeArg &acc) {} + /** Notify prefetcher of cache eviction */ + virtual void notifyEvict(const EvictionInfo &info) + {} + virtual PacketPtr getPacket() = 0; virtual Tick nextPrefetchReadyTime() const = 0; From 3a7192d6821ebad81367bdc778a280171a0f600d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Thu, 8 Sep 2022 16:51:41 -0500 Subject: [PATCH 622/693] mem-cache: change hasBeenPrefetched MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hasBeenPrefetched can now take a requestor id and returns true only if the block was prefetched by a prefetcher with the same id. This may be necessary to properly train multiple prefetchers attached to the same cache. If returns true if the block was prefetched by any prefetcher when the id is not provided. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Change-Id: I205e000fd5ff100e5a5d24d88bca7c6a46689ab2 Signed-off-by: Tiago Mück --- src/mem/cache/base.hh | 17 ++++++++++++----- src/mem/cache/cache_probe_arg.hh | 4 ++++ src/mem/cache/prefetch/base.cc | 3 ++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index aa4f4e8568..c2d9bc8a7b 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -327,6 +327,10 @@ class BaseCache : public ClockedObject bool hasBeenPrefetched(Addr addr, bool is_secure) const override { return cache.hasBeenPrefetched(addr, is_secure); } + bool hasBeenPrefetched(Addr addr, bool is_secure, + RequestorID requestor) const override + { return cache.hasBeenPrefetched(addr, is_secure, requestor); } + bool inMissQueue(Addr addr, bool is_secure) const override { return cache.inMissQueue(addr, is_secure); } @@ -1277,11 +1281,14 @@ class BaseCache : public ClockedObject bool hasBeenPrefetched(Addr addr, bool is_secure) const { CacheBlk *block = tags->findBlock(addr, is_secure); - if (block) { - return block->wasPrefetched(); - } else { - return false; - } + return block && block->wasPrefetched(); + } + + bool hasBeenPrefetched(Addr addr, bool is_secure, + RequestorID requestor) const { + CacheBlk *block = tags->findBlock(addr, is_secure); + return block && block->wasPrefetched() && + (block->getSrcRequestorId() == requestor); } bool inMissQueue(Addr addr, bool is_secure) const { diff --git a/src/mem/cache/cache_probe_arg.hh b/src/mem/cache/cache_probe_arg.hh index 49c0171e2f..27c7bc4041 100644 --- a/src/mem/cache/cache_probe_arg.hh +++ b/src/mem/cache/cache_probe_arg.hh @@ -59,6 +59,10 @@ struct CacheAccessor /** Determine if address has been prefetched */ virtual bool hasBeenPrefetched(Addr addr, bool is_secure) const = 0; + /** Determine if address has been prefetched by the requestor */ + virtual bool hasBeenPrefetched(Addr addr, bool is_secure, + RequestorID requestor) const = 0; + /** Determine if address is in cache miss queue */ virtual bool inMissQueue(Addr addr, bool is_secure) const = 0; diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index 8ecc715e89..f9d2624e7a 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -244,7 +244,8 @@ Base::probeNotify(const CacheAccessProbeArg &acc, bool miss) } bool has_been_prefetched = - acc.cache.hasBeenPrefetched(pkt->getAddr(), pkt->isSecure()); + acc.cache.hasBeenPrefetched(pkt->getAddr(), pkt->isSecure(), + requestorId); if (has_been_prefetched) { usefulPrefetches += 1; prefetchStats.pfUseful++; From 94d5cc17a29c7789c974a3f724b1c6a4c251cbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Thu, 8 Sep 2022 14:39:46 -0500 Subject: [PATCH 623/693] mem-ruby,mem-cache: ruby supports classic pfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds RubyPrefetcherProxy, which provides means to inject requests generated by the "classic" prefetchers into a SLICC prefetch queue. It defines defines notifyPf* functions to be used by protocols to notify a prefetcher. It also includes the probes required to interface with the classic implementation. AbstractController defines the accessor needed to snoop the caches. A followup patch will add support for RubyPrefetcherProxy in the CHI protocol. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Additional authors: Tuan Ta Change-Id: Ie908150b510f951cdd6fd0fd9c95d9760ff70fb0 Signed-off-by: Tiago Mück --- src/mem/ruby/SConscript | 3 +- src/mem/ruby/protocol/RubySlicc_Exports.sm | 4 +- src/mem/ruby/protocol/RubySlicc_Types.sm | 13 +- src/mem/ruby/protocol/RubySlicc_Util.sm | 3 +- .../slicc_interface/AbstractController.hh | 22 ++ .../ruby/slicc_interface/RubySlicc_Util.hh | 8 +- .../ruby/structures/RubyPrefetcherProxy.cc | 234 ++++++++++++++++++ .../ruby/structures/RubyPrefetcherProxy.hh | 178 +++++++++++++ src/mem/ruby/structures/SConscript | 3 +- src/mem/slicc/symbols/StateMachine.py | 1 + 10 files changed, 463 insertions(+), 6 deletions(-) create mode 100644 src/mem/ruby/structures/RubyPrefetcherProxy.cc create mode 100644 src/mem/ruby/structures/RubyPrefetcherProxy.hh diff --git a/src/mem/ruby/SConscript b/src/mem/ruby/SConscript index 1e386f922d..5e4057fe0a 100644 --- a/src/mem/ruby/SConscript +++ b/src/mem/ruby/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2021 Arm Limited +# Copyright (c) 2021,2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -111,6 +111,7 @@ MakeInclude('structures/DirectoryMemory.hh') MakeInclude('structures/PerfectCacheMemory.hh') MakeInclude('structures/PersistentTable.hh') MakeInclude('structures/RubyPrefetcher.hh') +MakeInclude('structures/RubyPrefetcherProxy.hh') MakeInclude('structures/TBEStorage.hh') if env['PROTOCOL'] == 'CHI': MakeInclude('structures/MN_TBEStorage.hh') diff --git a/src/mem/ruby/protocol/RubySlicc_Exports.sm b/src/mem/ruby/protocol/RubySlicc_Exports.sm index 2e496a8221..93d374d731 100644 --- a/src/mem/ruby/protocol/RubySlicc_Exports.sm +++ b/src/mem/ruby/protocol/RubySlicc_Exports.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 ARM Limited + * Copyright (c) 2020-2021,2023 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -51,6 +51,8 @@ external_type(Addr, primitive="yes"); external_type(Cycles, primitive="yes", default="Cycles(0)"); external_type(Tick, primitive="yes", default="0"); external_type(RequestPtr, primitive="yes", default="nullptr"); +external_type(RequestorID, primitive="yes"); +external_type(prefetch::Base, primitive="yes"); structure(WriteMask, external="yes", desc="...") { void clear(); diff --git a/src/mem/ruby/protocol/RubySlicc_Types.sm b/src/mem/ruby/protocol/RubySlicc_Types.sm index 293c731c37..2206effa29 100644 --- a/src/mem/ruby/protocol/RubySlicc_Types.sm +++ b/src/mem/ruby/protocol/RubySlicc_Types.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 ARM Limited + * Copyright (c) 2020-2021,2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -259,3 +259,14 @@ structure (RubyPrefetcher, external = "yes") { void observePfHit(Addr); void observePfMiss(Addr); } + +structure(RubyPrefetcherProxy, external = "yes") { + void notifyPfHit(RequestPtr, bool, DataBlock); + void notifyPfMiss(RequestPtr, bool, DataBlock); + void notifyPfFill(RequestPtr, DataBlock, bool); + void notifyPfEvict(Addr, bool, RequestorID); + void completePrefetch(Addr); + // SLICC controller must define its own regProbePoints and call + // this for every RubyPrefetcherProxy object present + void regProbePoints(); +} diff --git a/src/mem/ruby/protocol/RubySlicc_Util.sm b/src/mem/ruby/protocol/RubySlicc_Util.sm index 3079f20f23..104c7c034c 100644 --- a/src/mem/ruby/protocol/RubySlicc_Util.sm +++ b/src/mem/ruby/protocol/RubySlicc_Util.sm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 ARM Limited + * Copyright (c) 2021,2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -60,3 +60,4 @@ Addr makeNextStrideAddress(Addr addr, int stride); structure(BoolVec, external="yes") { } int countBoolVec(BoolVec bVec); +RequestorID getRequestorID(RequestPtr req); diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 72b679d6cf..ce6a6972af 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -367,6 +367,28 @@ class AbstractController : public ClockedObject, public Consumer void wakeUpAllBuffers(); bool serviceMemoryQueue(); + /** + * Functions needed by CacheAccessor. These are implemented in SLICC, + * thus the const& for all args to match the generated code. + */ + virtual bool inCache(const Addr &addr, const bool &is_secure) + { fatal("inCache: prefetching not supported"); return false; } + + virtual bool hasBeenPrefetched(const Addr &addr, const bool &is_secure) + { fatal("hasBeenPrefetched: prefetching not supported"); return false; } + + virtual bool hasBeenPrefetched(const Addr &addr, const bool &is_secure, + const RequestorID &requestor) + { fatal("hasBeenPrefetched: prefetching not supported"); return false; } + + virtual bool inMissQueue(const Addr &addr, const bool &is_secure) + { fatal("inMissQueue: prefetching not supported"); return false; } + + virtual bool coalesce() + { fatal("coalesce: prefetching not supported"); return false; } + + friend class RubyPrefetcherProxy; + protected: const NodeID m_version; MachineID m_machineID; diff --git a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh index edfbe4eea5..8df56c7013 100644 --- a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh +++ b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 ARM Limited + * Copyright (c) 2020-2021,2023 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -316,6 +316,12 @@ countBoolVec(BoolVec bVec) return count; } +inline RequestorID +getRequestorID(RequestPtr req) +{ + return req->requestorId(); +} + } // namespace ruby } // namespace gem5 diff --git a/src/mem/ruby/structures/RubyPrefetcherProxy.cc b/src/mem/ruby/structures/RubyPrefetcherProxy.cc new file mode 100644 index 0000000000..2a29fbc88e --- /dev/null +++ b/src/mem/ruby/structures/RubyPrefetcherProxy.cc @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + +#include "mem/ruby/structures/RubyPrefetcherProxy.hh" + +#include "debug/HWPrefetch.hh" +#include "mem/ruby/system/RubySystem.hh" + +namespace gem5 +{ + +namespace ruby +{ + +RubyPrefetcherProxy::RubyPrefetcherProxy(AbstractController* _parent, + prefetch::Base* _prefetcher, + MessageBuffer *_pf_queue) + :Named(_parent->name()), + prefetcher(_prefetcher), + cacheCntrl(_parent), + pfQueue(_pf_queue), + pfEvent([this]{ issuePrefetch(); }, name()), + ppHit(nullptr), ppMiss(nullptr), + ppFill(nullptr), ppDataUpdate(nullptr) +{ + fatal_if(!cacheCntrl, + "initializing a RubyPrefetcherProxy without a parent"); + if (prefetcher) { + fatal_if(!pfQueue, + "%s initializing a RubyPrefetcherProxy without a prefetch queue", + name()); + prefetcher->setParentInfo( + cacheCntrl->params().system, + cacheCntrl->getProbeManager(), + RubySystem::getBlockSizeBytes()); + } +} + +void +RubyPrefetcherProxy::scheduleNextPrefetch() +{ + if (pfEvent.scheduled()) + return; + + Tick next_pf_time = std::max(prefetcher->nextPrefetchReadyTime(), + cacheCntrl->clockEdge(Cycles(1))); + if (next_pf_time != MaxTick) { + DPRINTF(HWPrefetch, "Next prefetch ready at %d\n", next_pf_time); + cacheCntrl->schedule(&pfEvent, next_pf_time); + } +} + +void +RubyPrefetcherProxy::deschedulePrefetch() +{ + if (pfEvent.scheduled()) + cacheCntrl->deschedule(&pfEvent); +} + +void +RubyPrefetcherProxy::completePrefetch(Addr addr) +{ + assert(makeLineAddress(addr) == addr); + assert(issuedPfPkts.count(addr) == 1); + DPRINTF(HWPrefetch, "Prefetch request for addr %#x completed\n", addr); + delete issuedPfPkts[addr]; + issuedPfPkts.erase(addr); +} + +void +RubyPrefetcherProxy::issuePrefetch() +{ + assert(prefetcher); + assert(pfQueue); + + if (pfQueue->areNSlotsAvailable(1, curTick())) { + PacketPtr pkt = prefetcher->getPacket(); + + if (pkt) { + DPRINTF(HWPrefetch, "Next prefetch ready %s\n", pkt->print()); + unsigned blk_size = RubySystem::getBlockSizeBytes(); + Addr line_addr = pkt->getBlockAddr(blk_size); + + if (issuedPfPkts.count(line_addr) == 0) { + DPRINTF(HWPrefetch, "Issued PF request for paddr=%#x, " + "line_addr=%#x, is_write=%d\n", + pkt->getAddr(), line_addr, + pkt->needsWritable()); + + RubyRequestType req_type = pkt->needsWritable() ? + RubyRequestType_ST : RubyRequestType_LD; + + std::shared_ptr msg = + std::make_shared(cacheCntrl->clockEdge(), + pkt->getAddr(), + blk_size, + 0, // pc + req_type, + RubyAccessMode_Supervisor, + pkt, + PrefetchBit_Yes); + + // enqueue request into prefetch queue to the cache + pfQueue->enqueue(msg, cacheCntrl->clockEdge(), + cacheCntrl->cyclesToTicks(Cycles(1))); + + // track all pending PF requests + issuedPfPkts[line_addr] = pkt; + } else { + DPRINTF(HWPrefetch, "Aborted PF request for address being " + "prefetched\n"); + delete pkt; + } + } + } else { + DPRINTF(HWPrefetch, "No prefetch slots are available\n"); + } + + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfHit(const RequestPtr& req, bool is_read, + const DataBlock& data_blk) +{ + assert(ppHit); + assert(req); + Packet pkt(req, is_read ? Packet::makeReadCmd(req) : + Packet::makeWriteCmd(req)); + // NOTE: for now we only communicate physical address with prefetchers + pkt.dataStaticConst(data_blk.getData(getOffset(req->getPaddr()), + pkt.getSize())); + DPRINTF(HWPrefetch, "notify hit: %s\n", pkt.print()); + ppHit->notify(CacheAccessProbeArg(&pkt, *this)); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfMiss(const RequestPtr& req, bool is_read, + const DataBlock& data_blk) +{ + assert(ppMiss); + assert(req); + Packet pkt(req, is_read ? Packet::makeReadCmd(req) : + Packet::makeWriteCmd(req)); + // NOTE: for now we only communicate physical address with prefetchers + pkt.dataStaticConst(data_blk.getData(getOffset(req->getPaddr()), + pkt.getSize())); + DPRINTF(HWPrefetch, "notify miss: %s\n", pkt.print()); + ppMiss->notify(CacheAccessProbeArg(&pkt, *this)); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfFill(const RequestPtr& req, + const DataBlock& data_blk, + bool from_pf) +{ + assert(ppFill); + assert(req); + Packet pkt(req, Packet::makeReadCmd(req)); + if (from_pf) + pkt.cmd = Packet::Command::HardPFReq; + // NOTE: for now we only communicate physical address with prefetchers + pkt.dataStaticConst(data_blk.getData(getOffset(req->getPaddr()), + pkt.getSize())); + DPRINTF(HWPrefetch, "notify fill: %s\n", pkt.print()); + ppFill->notify(CacheAccessProbeArg(&pkt, *this)); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::notifyPfEvict(Addr blkAddr, bool hwPrefetched, + RequestorID requestorID) +{ + DPRINTF(HWPrefetch, "notify evict: %#x hw_pf=%d\n", blkAddr, hwPrefetched); + CacheDataUpdateProbeArg data_update( + blkAddr, false, requestorID, *this); + data_update.hwPrefetched = hwPrefetched; + ppDataUpdate->notify(data_update); + scheduleNextPrefetch(); +} + +void +RubyPrefetcherProxy::regProbePoints() +{ + assert(cacheCntrl); + ppHit = new ProbePointArg( + cacheCntrl->getProbeManager(), "Hit"); + ppMiss = new ProbePointArg( + cacheCntrl->getProbeManager(), "Miss"); + ppFill = new ProbePointArg( + cacheCntrl->getProbeManager(), "Fill"); + ppDataUpdate = + new ProbePointArg( + cacheCntrl->getProbeManager(), "Data Update"); +} + +} // namespace ruby +} // namespace gem5 diff --git a/src/mem/ruby/structures/RubyPrefetcherProxy.hh b/src/mem/ruby/structures/RubyPrefetcherProxy.hh new file mode 100644 index 0000000000..34c40154b6 --- /dev/null +++ b/src/mem/ruby/structures/RubyPrefetcherProxy.hh @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2023 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. + * + * 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. + */ + +#ifndef __MEM_RUBY_STRUCTURES_RUBY_PREFETCHER_WRAPPER_HH__ +#define __MEM_RUBY_STRUCTURES_RUBY_PREFETCHER_WRAPPER_HH__ + +#include + +#include "mem/cache/cache_probe_arg.hh" +#include "mem/cache/prefetch/base.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/ruby/slicc_interface/RubyRequest.hh" + +namespace gem5 +{ + +namespace ruby +{ + +/** + * This is a proxy for prefetcher class in classic memory. This wrapper + * enables a SLICC machine to interact with classic prefetchers. + * + * The expected use case for this class is to instantiate it in the SLICC + * state machine definition and provide a pointer to the prefetcher object + * (typically defined in SLICC as one of the SM's configuration parameters) + * and the prefetch queue where prefetch requests will be inserted. + * + * The SLICC SM can them use the notifyPF* functions to notify the prefetcher. + * + * Notes: + * + * This object's regProbePoints() must be called explicitly. The SLICC SM may + * defined it's own regProbePoints() to call it. + * + * completePrefetch(Addr) must be called when a request injected into the + * prefetch queue is completed. + * + * A nullptr prefetcher can be provided, in which case the notifyPf* are + * no-ops. + * + */ +class RubyPrefetcherProxy : public CacheAccessor, public Named +{ + public: + + RubyPrefetcherProxy(AbstractController* parent, + prefetch::Base* prefetcher, + MessageBuffer *pf_queue); + + /** Deschedled the ready prefetch event */ + void deschedulePrefetch(); + + /** Notifies a completed prefetch request */ + void completePrefetch(Addr addr); + + /** + * Notify PF probes hit/miss/fill + */ + void notifyPfHit(const RequestPtr& req, bool is_read, + const DataBlock& data_blk); + void notifyPfMiss(const RequestPtr& req, bool is_read, + const DataBlock& data_blk); + void notifyPfFill(const RequestPtr& req, const DataBlock& data_blk, + bool from_pf); + void notifyPfEvict(Addr blkAddr, bool hwPrefetched, + RequestorID requestorID); + + /** Registers probes. */ + void regProbePoints(); + + private: + + /** Schedule the next ready prefetch */ + void scheduleNextPrefetch(); + + /** Issue prefetch to the contoller prefetch queue */ + void issuePrefetch(); + + /** Prefetcher from classic memory */ + prefetch::Base* prefetcher; + + /** Ruby cache controller */ + AbstractController* cacheCntrl; + + /** Prefetch queue to the cache controller */ + MessageBuffer* pfQueue; + + /** List of issued prefetch request packets */ + std::unordered_map issuedPfPkts; + + /** Prefetch event */ + EventFunctionWrapper pfEvent; + + /** To probe when a cache hit occurs */ + ProbePointArg *ppHit; + + /** To probe when a cache miss occurs */ + ProbePointArg *ppMiss; + + /** To probe when a cache fill occurs */ + ProbePointArg *ppFill; + + /** + * To probe when the contents of a block are updated. Content updates + * include data fills, overwrites, and invalidations, which means that + * this probe partially overlaps with other probes. + */ + ProbePointArg *ppDataUpdate; + + public: + + /** Accessor functions */ + + bool inCache(Addr addr, bool is_secure) const override + { + return cacheCntrl->inCache(addr, is_secure); + } + + bool hasBeenPrefetched(Addr addr, bool is_secure) const override + { + return cacheCntrl->hasBeenPrefetched(addr, is_secure); + } + + bool hasBeenPrefetched(Addr addr, bool is_secure, + RequestorID requestor) const override + { + return cacheCntrl->hasBeenPrefetched(addr, is_secure, requestor); + } + + bool inMissQueue(Addr addr, bool is_secure) const override + { + return cacheCntrl->inMissQueue(addr, is_secure); + } + + bool coalesce() const override + { return cacheCntrl->coalesce(); } + +}; + +} // namespace ruby +} // namespace gem5 + +#endif // __MEM_RUBY_STRUCTURES_RUBY_PREFETCHER_WRAPPER_HH__ diff --git a/src/mem/ruby/structures/SConscript b/src/mem/ruby/structures/SConscript index cae03909c7..3a321b05f5 100644 --- a/src/mem/ruby/structures/SConscript +++ b/src/mem/ruby/structures/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2021 ARM Limited +# Copyright (c) 2021,2023 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -53,6 +53,7 @@ Source('CacheMemory.cc') Source('WireBuffer.cc') Source('PersistentTable.cc') Source('RubyPrefetcher.cc') +Source('RubyPrefetcherProxy.cc') Source('TimerTable.cc') Source('BankedArray.cc') Source('TBEStorage.cc') diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 68a1a6a8af..4910c55ce6 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -63,6 +63,7 @@ python_class_map = { "MessageBuffer": "MessageBuffer", "DMASequencer": "DMASequencer", "RubyPrefetcher": "RubyPrefetcher", + "prefetch::Base": "BasePrefetcher", "Cycles": "Cycles", "Addr": "Addr", } From 91cf58871efab95ca5303d8e06ae562c88073f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Tue, 15 Jun 2021 13:14:05 -0500 Subject: [PATCH 624/693] mem-ruby: support prefetcher in CHI protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use RubyPrefetcherProxy to support prefetchers in the CHI cache controller L1I/L1D/L2 prefechers can now be added by specifying a non-null prefetcher type when configuring a CHI_RNF. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Additional authors: Tuan Ta Change-Id: I41dc637969acaab058b22a8c9c3931fa137eeace Signed-off-by: Tiago Mück --- configs/ruby/CHI_config.py | 33 ++++++++++++------- .../ruby/protocol/chi/CHI-cache-actions.sm | 13 ++++---- src/mem/ruby/protocol/chi/CHI-cache-funcs.sm | 33 ++++++++++++------- src/mem/ruby/protocol/chi/CHI-cache.sm | 9 +++++ 4 files changed, 60 insertions(+), 28 deletions(-) diff --git a/configs/ruby/CHI_config.py b/configs/ruby/CHI_config.py index 3cccfd0676..e14396183b 100644 --- a/configs/ruby/CHI_config.py +++ b/configs/ruby/CHI_config.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021,2022 ARM Limited +# Copyright (c) 2021-2023 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -231,7 +231,8 @@ class CHI_L1Controller(CHI_Cache_Controller): super().__init__(ruby_system) self.sequencer = sequencer self.cache = cache - self.use_prefetcher = False + self.prefetcher = prefetcher + self.use_prefetcher = prefetcher != NULL self.send_evictions = True self.is_HN = False self.enable_DMT = False @@ -268,7 +269,8 @@ class CHI_L2Controller(CHI_Cache_Controller): super().__init__(ruby_system) self.sequencer = NULL self.cache = cache - self.use_prefetcher = False + self.prefetcher = prefetcher + self.use_prefetcher = prefetcher != NULL self.allow_SD = True self.is_HN = False self.enable_DMT = False @@ -304,7 +306,8 @@ class CHI_HNFController(CHI_Cache_Controller): super().__init__(ruby_system) self.sequencer = NULL self.cache = cache - self.use_prefetcher = False + self.prefetcher = prefetcher + self.use_prefetcher = prefetcher != NULL self.addr_ranges = addr_ranges self.allow_SD = True self.is_HN = True @@ -380,6 +383,7 @@ class CHI_DMAController(CHI_Cache_Controller): size = "128" assoc = 1 + self.prefetcher = NULL self.use_prefetcher = False self.cache = DummyCache() self.sequencer.dcache = NULL @@ -499,11 +503,16 @@ class CHI_RNF(CHI_Node): start_index_bit=self._block_size_bits, is_icache=False ) - # Placeholders for future prefetcher support - if l1Iprefetcher_type != None or l1Dprefetcher_type != None: - m5.fatal("Prefetching not supported yet") - l1i_pf = NULL - l1d_pf = NULL + # prefetcher wrappers + if l1Iprefetcher_type != None: + l1i_pf = l1Iprefetcher_type() + else: + l1i_pf = NULL + + if l1Dprefetcher_type != None: + l1d_pf = l1Dprefetcher_type() + else: + l1d_pf = NULL # cache controllers cpu.l1i = CHI_L1Controller( @@ -548,9 +557,11 @@ class CHI_RNF(CHI_Node): l2_cache = cache_type( start_index_bit=self._block_size_bits, is_icache=False ) + if pf_type != None: - m5.fatal("Prefetching not supported yet") - l2_pf = NULL + l2_pf = pf_type() + else: + l2_pf = NULL cpu.l2 = CHI_L2Controller(self._ruby_system, l2_cache, l2_pf) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm index 4c9498423c..a827b8b1bb 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-actions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-actions.sm @@ -3440,7 +3440,7 @@ action(Callback_ExpressPrefetchHit, desc="") { cache.profilePrefetchHit(); peek(reqRdyPort, CHIRequestMsg) { assert(in_msg.is_local_pf); - notifyPfComplete(in_msg.addr); + pfProxy.completePrefetch(in_msg.addr); } } @@ -3451,7 +3451,7 @@ action(Callback_Miss, desc="") { assert(is_valid(tbe)); if (tbe.dataValid && tbe.is_local_pf) { assert(use_prefetcher); - notifyPfComplete(tbe.addr); + pfProxy.completePrefetch(tbe.addr); } else if (tbe.dataValid && (tbe.reqType == CHIRequestType:Load)) { DPRINTF(RubySlicc, "Read data %s\n", tbe.dataBlk); @@ -3562,7 +3562,7 @@ action(Profile_Miss, desc="") { // FIXME: this dataBlk is likely to have stale data. This should be fixed // if our prefetcher uses cached data to make prefetch decisions. - notifyPfMiss(tbe.seqReq, is_read, tbe.dataBlk); + pfProxy.notifyPfMiss(tbe.seqReq, is_read, tbe.dataBlk); } } @@ -3586,7 +3586,7 @@ action(Profile_Hit, desc="") { } else { assert(isWriteReqType(tbe.reqType)); } - notifyPfHit(tbe.seqReq, is_read, tbe.dataBlk); + pfProxy.notifyPfHit(tbe.seqReq, is_read, tbe.dataBlk); cache_entry.HWPrefetched := false; } @@ -3600,10 +3600,11 @@ action(Profile_Fill, desc="") { cache_entry.HWPrefetched := tbe.is_local_pf || (tbe.is_remote_pf && (upstream_prefetch_trains_prefetcher == false)); + cache_entry.requestor := getRequestorID(tbe.seqReq); // Prefetchers that use this info require notifications from both // demand and pf fills (unlike notifyPfHit/notifyPfMiss) - notifyPfFill(tbe.seqReq, tbe.dataBlk, tbe.is_local_pf); + pfProxy.notifyPfFill(tbe.seqReq, tbe.dataBlk, tbe.is_local_pf); } } @@ -3617,7 +3618,7 @@ action(Profile_Eviction, desc="") { sequencer.evictionCallback(address); } if (use_prefetcher && is_valid(cache_entry)) { - notifyPfEvict(address, cache_entry.HWPrefetched); + pfProxy.notifyPfEvict(address, cache_entry.HWPrefetched, cache_entry.requestor); } } diff --git a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm index ed8358fea4..113f4c4871 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-funcs.sm @@ -68,12 +68,6 @@ void outgoingTransactionEnd(Addr, bool, bool); Event curTransitionEvent(); State curTransitionNextState(); -// Placeholders for future prefetch support -void notifyPfHit(RequestPtr req, bool is_read, DataBlock blk) { } -void notifyPfMiss(RequestPtr req, bool is_read, DataBlock blk) { } -void notifyPfFill(RequestPtr req, DataBlock blk, bool from_pf) { } -void notifyPfEvict(Addr blkAddr, bool hwPrefetched) { } -void notifyPfComplete(Addr addr) { } //////////////////////////////////////////////////////////////////////////// // Interface functions required by SLICC @@ -307,7 +301,11 @@ bool fromSequencer(CHIRequestType reqType) { reqType == CHIRequestType:AtomicStore; } -bool inCache(Addr addr) { +void regProbePoints() { + pfProxy.regProbePoints(); +} + +bool inCache(Addr addr, bool is_secure) { CacheEntry entry := getCacheEntry(makeLineAddress(addr)); // NOTE: we consider data for the addr to be in cache if it exists in local, // upstream, or both caches. @@ -318,7 +316,16 @@ bool inCache(Addr addr) { } } -bool hasBeenPrefetched(Addr addr) { +bool hasBeenPrefetched(Addr addr, bool is_secure, RequestorID requestor) { + CacheEntry entry := getCacheEntry(makeLineAddress(addr)); + if (is_valid(entry)) { + return entry.HWPrefetched && (entry.requestor == requestor); + } else { + return false; + } +} + +bool hasBeenPrefetched(Addr addr, bool is_secure) { CacheEntry entry := getCacheEntry(makeLineAddress(addr)); if (is_valid(entry)) { return entry.HWPrefetched; @@ -327,12 +334,16 @@ bool hasBeenPrefetched(Addr addr) { } } -bool inMissQueue(Addr addr) { +bool inMissQueue(Addr addr, bool is_secure) { Addr line_addr := makeLineAddress(addr); TBE tbe := getCurrentActiveTBE(line_addr); return is_valid(tbe); } +bool coalesce() { + return false; +} + void notifyCoalesced(Addr addr, RubyRequestType type, RequestPtr req, DataBlock data_blk, bool was_miss) { DPRINTF(RubySlicc, "notifyCoalesced(addr=%#x, type=%s, was_miss=%d)\n", @@ -347,9 +358,9 @@ void notifyCoalesced(Addr addr, RubyRequestType type, RequestPtr req, (type == RubyRequestType:Load_Linked) || (type == RubyRequestType:IFETCH); if (was_miss) { - notifyPfMiss(req, is_read, data_blk); + pfProxy.notifyPfMiss(req, is_read, data_blk); } else { - notifyPfHit(req, is_read, data_blk); + pfProxy.notifyPfHit(req, is_read, data_blk); } } } diff --git a/src/mem/ruby/protocol/chi/CHI-cache.sm b/src/mem/ruby/protocol/chi/CHI-cache.sm index f806488b45..62fb2231ff 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache.sm @@ -46,6 +46,10 @@ machine(MachineType:Cache, "Cache coherency protocol") : // happen in parallel. The cache tag latency is used for both cases. CacheMemory * cache; + // Prefetcher to insert prefetch requests + // null if the cache does not support prefetching + prefetch::Base * prefetcher; + // Additional pipeline latency modeling for the different request types // When defined, these are applied after the initial tag array read and // sending necessary snoops. @@ -568,6 +572,7 @@ machine(MachineType:Cache, "Cache coherency protocol") : State state, desc="SLICC line state"; DataBlock DataBlk, desc="data for the block"; bool HWPrefetched, default="false", desc="Set if this cache entry was prefetched"; + RequestorID requestor, desc="First requestor to fill this block"; } // Directory entry @@ -812,6 +817,10 @@ machine(MachineType:Cache, "Cache coherency protocol") : TBETable dvmSnpTBEs, template="", constructor="m_number_of_DVM_snoop_TBEs"; TBEStorage storDvmSnpTBEs, constructor="this, m_number_of_DVM_snoop_TBEs"; + // Interface to prefetchers + RubyPrefetcherProxy pfProxy, constructor="this, m_prefetcher_ptr, m_prefetchQueue_ptr"; + + // DVM data // Queue of non-sync operations that haven't been Comp-d yet. // Before a Sync operation can start, this queue must be emptied From 0f8c60bce5a50440f8d597fefe5f90ef8db9c7c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20M=C3=BCck?= Date: Tue, 28 Nov 2023 16:07:04 -0600 Subject: [PATCH 625/693] mem-ruby: add missing state for CHI Prefetch event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RUSC state is missing for the Prefetch event. Change-Id: If440ac0052100dba295708471a75a24cd234c011 Signed-off-by: Tiago Mück --- src/mem/ruby/protocol/chi/CHI-cache-transitions.sm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm index 0e8c6ec0e3..1654b9bf02 100644 --- a/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm +++ b/src/mem/ruby/protocol/chi/CHI-cache-transitions.sm @@ -515,7 +515,7 @@ transition({UD,UD_T,SD,UC,SC}, Load, BUSY_BLKD) { // the local cache entry at the end since our data is stale. If the cache is // inclusive for unique data we need to keep the block, so just bypass the // normal path. -transition({UD,UD_T,SD,UC,SC,RU,RSC,RSD,RUSD,SC_RSC,SD_RSC,SD_RSD,UC_RSC,UC_RU,UD_RU,UD_RSD,UD_RSC}, Prefetch) { +transition({UD,UD_T,SD,UC,SC,RU,RSC,RSD,RUSC,RUSD,SC_RSC,SD_RSC,SD_RSD,UC_RSC,UC_RU,UD_RU,UD_RSD,UD_RSC}, Prefetch) { Callback_ExpressPrefetchHit; Pop_ReqRdyQueue; } From 23cadf0886ae44626812f3122e280eb49b1f20fc Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 29 Nov 2023 07:41:51 -0800 Subject: [PATCH 626/693] tests: switch lulesh to use vega_x86 Change-Id: Ifbf0fdfd7d8c2bbaad0b6094090acecd1cb8055c --- .github/workflows/gpu-tests.yaml | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index 7edcab5ba5..1f25eb0f00 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -31,10 +31,28 @@ jobs: retention-days: 5 - run: echo "This job's status is ${{ job.status }}." + build-gem5-vega: + runs-on: [self-hosted, linux, x64] + container: ghcr.io/gem5/gcn-gpu:latest + steps: + - uses: actions/checkout@v3 + with: + # Scheduled workflows run on the default branch by default. We + # therefore need to explicitly checkout the develop branch. + ref: develop + - name: Build gem5 vega + run: scons build/VEGA_X86/gem5.opt -j $(nproc) --ignore-style + - uses: actions/upload-artifact@v3 + with: + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-vega + path: build/VEGA_X86/gem5.opt + retention-days: 5 + - run: echo "This job's status is ${{ job.status }}." + LULESH-tests: runs-on: [self-hosted, linux, x64] container: ghcr.io/gem5/gcn-gpu:latest - needs: build-gem5 + needs: build-gem5-vega timeout-minutes: 480 # 8 hours steps: - uses: actions/checkout@v3 @@ -43,24 +61,24 @@ jobs: # therefore need to explicitly checkout the develop branch. ref: develop - - name: Download build/GCN3_X86/gem5.opt + - name: Download build/VEGA_X86/gem5.opt uses: actions/download-artifact@v3 with: - name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 - path: build/GCN3_X86 + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-vega + path: build/VEGA_X86 # `download-artifact` does not preserve permissions so we need to set # them again. - - run: chmod u+x build/GCN3_X86/gem5.opt + - run: chmod u+x build/VEGA_X86/gem5.opt - name: Obtain LULESH # Obtains the latest LULESH compatible with this version of gem5 via # gem5 Resources. - run: build/GCN3_X86/gem5.opt util/obtain-resource.py lulesh -p lulesh + run: build/VEGA_X86/gem5.opt util/obtain-resource.py lulesh -p lulesh - name: Run LULUESH tests working-directory: ${{ github.workspace }} run: | - build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --mem-size=8GB --reg-alloc-policy=dynamic --benchmark-root="lulesh" -c \ + build/VEGA_X86/gem5.opt configs/example/apu_se.py -n3 --mem-size=8GB --reg-alloc-policy=dynamic --dgpu --gfx-version=gfx900 -c \ lulesh --options="0.01 2" HACC-tests: From 089b82b2e95a326899af7c5ae95a3c690bbf785c Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 29 Nov 2023 08:39:02 -0800 Subject: [PATCH 627/693] arch-riscv: fix tlb bug (#610) - one tlb miss was getting counted twice by the lookup function. Change-Id: I5fee08bd6e936896704e7dbbd242720b8d23b547 --- src/arch/riscv/tlb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/tlb.cc b/src/arch/riscv/tlb.cc index ac8c8ae029..69317188f8 100644 --- a/src/arch/riscv/tlb.cc +++ b/src/arch/riscv/tlb.cc @@ -292,7 +292,7 @@ TLB::doTranslate(const RequestPtr &req, ThreadContext *tc, delayed = true; return fault; } - e = lookup(vaddr, satp.asid, mode, false); + e = lookup(vaddr, satp.asid, mode, true); assert(e != nullptr); } From eb13b3231427b6e86c2714515d8f9fbccc66bfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= <66964292+aarmejach@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:45:03 +0100 Subject: [PATCH 628/693] cpu-o3: Fix discarded requests str-ld forwarding (#614) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the use of large RVV vectors (i.e., 8K or 16K bits) and a limited number of cacheLoadPorts, some loads take multiple cycles to execute. This triggered certain conditions when store-to-load forwarding happens in the middle of the execution of a load that already has outstanding packets. First, after store-to-load forwarding the request is marked as discarded and the load is immediately writtenback, which triggers a writebackDone that tries to delete the request, triggering an assert as it still has outstanding packets. This patch avoid deleting the request leaving it self owned, it will be deleted when the last packet arrives in packetReplied. Second, this patch avoid checking snoops on discarded requests by checking if the request exists. Change-Id: Icea0add0327929d3a6af7e6dd0af9945cb0d0970 Co-authored-by: Adrià Armejach --- src/cpu/o3/lsq.hh | 2 +- src/cpu/o3/lsq_unit.cc | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 130c3479fa..2ed1342eb0 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -541,7 +541,7 @@ class LSQ { flags.set(Flag::WritebackDone); /* If the lsq resources are already free */ - if (isReleased()) { + if (_numOutstandingPackets == 0 && isReleased()) { delete this; } } diff --git a/src/cpu/o3/lsq_unit.cc b/src/cpu/o3/lsq_unit.cc index 139e0de337..68fd464627 100644 --- a/src/cpu/o3/lsq_unit.cc +++ b/src/cpu/o3/lsq_unit.cc @@ -451,7 +451,7 @@ LSQUnit::checkSnoop(PacketPtr pkt) LSQRequest *request = iter->request(); // Check that this snoop didn't just invalidate our lock flag - if (ld_inst->effAddrValid() && + if (ld_inst->effAddrValid() && request && request->isCacheBlockHit(invalidate_addr, cacheBlockMask) && ld_inst->memReqFlags & Request::LLSC) { ld_inst->tcBase()->getIsaPtr()->handleLockedSnoopHit(ld_inst.get()); @@ -463,7 +463,7 @@ LSQUnit::checkSnoop(PacketPtr pkt) ld_inst = iter->instruction(); assert(ld_inst); request = iter->request(); - if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) + if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered() || !request) continue; DPRINTF(LSQUnit, "-- inst [sn:%lli] to pktAddr:%#x\n", @@ -1510,6 +1510,8 @@ LSQUnit::read(LSQRequest *request, ssize_t load_idx) // first time this load got executed. Signal the senderSate // that response packets should be discarded. request->discard(); + // Avoid checking snoops on this discarded request. + load_entry.setRequest(nullptr); } WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, From b0cefac9b2c73db246f6e8828351458df4af3b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Armejach?= <66964292+aarmejach@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:11:06 +0100 Subject: [PATCH 629/693] arch-riscv: Fix narrow datatypes in RVV isa files (#606) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some variables hava narrow datatypes that overflow on large VLEN values. For example, the maximum number of microops for LMUL=8 SEW=8 and VLEN=64K is 2^16. Change-Id: I5cce759f040884e09ce83bee7e54a62c4b42c5aa Co-authored-by: Adrià Armejach --- src/arch/riscv/insts/vector.hh | 65 ++++++------- src/arch/riscv/isa/decoder.isa | 2 +- src/arch/riscv/isa/templates/vector_arith.isa | 95 ++++++++++--------- src/arch/riscv/isa/templates/vector_mem.isa | 68 ++++++------- 4 files changed, 116 insertions(+), 114 deletions(-) diff --git a/src/arch/riscv/insts/vector.hh b/src/arch/riscv/insts/vector.hh index 4127060e4a..fb36f0809d 100644 --- a/src/arch/riscv/insts/vector.hh +++ b/src/arch/riscv/insts/vector.hh @@ -137,10 +137,10 @@ class VectorMicroInst : public RiscvMicroInst protected: uint32_t vlen; uint32_t microVl; - uint8_t microIdx; + uint32_t microIdx; uint8_t vtype; VectorMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, - uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen = 256) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen = 256) : RiscvMicroInst(mnem, _machInst, __opClass), vlen(_vlen), microVl(_microVl), @@ -178,7 +178,7 @@ class VectorArithMicroInst : public VectorMicroInst protected: VectorArithMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _microVl, - uint8_t _microIdx) + uint32_t _microIdx) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) {} @@ -204,7 +204,7 @@ class VectorVMUNARY0MicroInst : public VectorMicroInst protected: VectorVMUNARY0MicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _microVl, - uint8_t _microIdx) + uint32_t _microIdx) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) {} @@ -243,11 +243,11 @@ class VectorSlideMacroInst : public VectorMacroInst class VectorSlideMicroInst : public VectorMicroInst { protected: - uint8_t vdIdx; - uint8_t vs2Idx; + uint32_t vdIdx; + uint32_t vs2Idx; VectorSlideMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _microVl, - uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) + uint32_t _microIdx, uint32_t _vdIdx, uint32_t _vs2Idx) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) , vdIdx(_vdIdx), vs2Idx(_vs2Idx) {} @@ -263,8 +263,8 @@ class VectorMemMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VectorMemMicroInst(const char* mnem, ExtMachInst _machInst, - OpClass __opClass, uint32_t _microVl, uint8_t _microIdx, - uint32_t _offset) + OpClass __opClass, uint32_t _microVl, + uint32_t _microIdx, uint32_t _offset) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) , offset(_offset) , memAccessFlags(0) @@ -310,7 +310,7 @@ class VleMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VleMicroInst(const char *mnem, ExtMachInst _machInst,OpClass __opClass, - uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, _vlen) { @@ -327,7 +327,7 @@ class VseMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VseMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, - uint32_t _microVl, uint8_t _microIdx, uint32_t _vlen) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, _vlen) { @@ -356,7 +356,7 @@ class VlWholeMicroInst : public VectorMicroInst Request::Flags memAccessFlags; VlWholeMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint32_t _microVl, uint8_t _microIdx, + OpClass __opClass, uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen) : VectorMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, _vlen) @@ -385,7 +385,7 @@ class VsWholeMicroInst : public VectorMicroInst VsWholeMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _microVl, - uint8_t _microIdx, uint32_t _vlen) + uint32_t _microIdx, uint32_t _vlen) : VectorMicroInst(mnem, _machInst, __opClass , _microVl, _microIdx, _vlen) {} @@ -409,10 +409,10 @@ class VlStrideMacroInst : public VectorMemMacroInst class VlStrideMicroInst : public VectorMemMicroInst { protected: - uint8_t regIdx; + uint32_t regIdx; VlStrideMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _regIdx, - uint8_t _microIdx, uint32_t _microVl) + OpClass __opClass, uint32_t _regIdx, + uint32_t _microIdx, uint32_t _microVl) : VectorMemMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, 0) , regIdx(_regIdx) @@ -437,10 +437,10 @@ class VsStrideMacroInst : public VectorMemMacroInst class VsStrideMicroInst : public VectorMemMicroInst { protected: - uint8_t regIdx; + uint32_t regIdx; VsStrideMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _regIdx, - uint8_t _microIdx, uint32_t _microVl) + OpClass __opClass, uint32_t _regIdx, + uint32_t _microIdx, uint32_t _microVl) : VectorMemMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx, 0) , regIdx(_regIdx) @@ -465,13 +465,13 @@ class VlIndexMacroInst : public VectorMemMacroInst class VlIndexMicroInst : public VectorMemMicroInst { protected: - uint8_t vdRegIdx; - uint8_t vdElemIdx; - uint8_t vs2RegIdx; - uint8_t vs2ElemIdx; + uint32_t vdRegIdx; + uint32_t vdElemIdx; + uint32_t vs2RegIdx; + uint32_t vs2ElemIdx; VlIndexMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _vdRegIdx, uint8_t _vdElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + OpClass __opClass, uint32_t _vdRegIdx, uint32_t _vdElemIdx, + uint32_t _vs2RegIdx, uint32_t _vs2ElemIdx) : VectorMemMicroInst(mnem, _machInst, __opClass, 1, 0, 0) , vdRegIdx(_vdRegIdx), vdElemIdx(_vdElemIdx) @@ -497,13 +497,14 @@ class VsIndexMacroInst : public VectorMemMacroInst class VsIndexMicroInst : public VectorMemMicroInst { protected: - uint8_t vs3RegIdx; - uint8_t vs3ElemIdx; - uint8_t vs2RegIdx; - uint8_t vs2ElemIdx; + uint32_t vs3RegIdx; + uint32_t vs3ElemIdx; + uint32_t vs2RegIdx; + uint32_t vs2ElemIdx; VsIndexMicroInst(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + OpClass __opClass, uint32_t _vs3RegIdx, + uint32_t _vs3ElemIdx, uint32_t _vs2RegIdx, + uint32_t _vs2ElemIdx) : VectorMemMicroInst(mnem, _machInst, __opClass, 1, 0, 0), vs3RegIdx(_vs3RegIdx), vs3ElemIdx(_vs3ElemIdx), vs2RegIdx(_vs2RegIdx), vs2ElemIdx(_vs2ElemIdx) @@ -530,7 +531,7 @@ class VMvWholeMicroInst : public VectorArithMicroInst protected: VMvWholeMicroInst(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _microVl, - uint8_t _microIdx) + uint32_t _microIdx) : VectorArithMicroInst(mnem, _machInst, __opClass, _microVl, _microIdx) {} diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 3d1d396165..340e5b5d68 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -2446,7 +2446,7 @@ decode QUADRANT default Unknown::unknown() { for (uint32_t i = 0; i < microVl; i++) { uint32_t ei = i + vs1_idx * vs1_elems + vs1_bias; if (this->vm || elem_mask(v0, ei)) { - const uint16_t idx = Vs1_uh[i + vs1_bias] + const uint32_t idx = Vs1_uh[i + vs1_bias] - vs2_elems * vs2_idx; auto res = (Vs1_uh[i + vs1_bias] >= vlmax) ? 0 : (idx < vs2_elems) ? Vs2_vu[idx] diff --git a/src/arch/riscv/isa/templates/vector_arith.isa b/src/arch/riscv/isa/templates/vector_arith.isa index 364639a716..bce4e2c55e 100644 --- a/src/arch/riscv/isa/templates/vector_arith.isa +++ b/src/arch/riscv/isa/templates/vector_arith.isa @@ -125,7 +125,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx); + uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -136,7 +136,7 @@ def template VectorIntMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -216,7 +216,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx); + uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override; @@ -406,7 +406,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx); + uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -417,7 +417,7 @@ def template VectorIntWideningMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -596,7 +596,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -606,7 +606,7 @@ public: def template VectorFloatMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -704,7 +704,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override @@ -886,7 +886,7 @@ private: int* cnt; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx, int* cnt); + uint32_t _microIdx, int* cnt); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -897,7 +897,7 @@ def template ViotaMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx, int* cnt) + uint32_t _microVl, uint32_t _microIdx, int* cnt) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1132,7 +1132,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1143,7 +1143,7 @@ def template VectorIntMaskMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1187,8 +1187,8 @@ Fault %(vm_decl_rd)s; %(copy_old_vd)s; - const uint16_t bit_offset = vlenb / sizeof(ElemType); - const uint16_t offset = bit_offset * microIdx; + const uint32_t bit_offset = vlenb / sizeof(ElemType); + const uint32_t offset = bit_offset * microIdx; %(code)s; %(op_wb)s; @@ -1260,7 +1260,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1271,7 +1271,7 @@ def template VectorFloatMaskMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1315,8 +1315,8 @@ Fault %(vm_decl_rd)s; %(copy_old_vd)s; - const uint16_t bit_offset = vlenb / sizeof(ElemType); - const uint16_t offset = bit_offset * microIdx; + const uint32_t bit_offset = vlenb / sizeof(ElemType); + const uint32_t offset = bit_offset * microIdx; %(code)s; %(op_wb)s; @@ -1371,7 +1371,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx); + uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1381,7 +1381,7 @@ public: def template VMvWholeMicroConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1674,7 +1674,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1685,7 +1685,7 @@ def template VectorReduceMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1899,7 +1899,7 @@ template microop = new VectorNopMicroInst(_machInst); this->microops.push_back(microop); } - for (uint8_t i = 0; i < std::max(vs1_vregs, vd_vregs) && micro_vl > 0; + for (uint32_t i = 0; i < std::max(vs1_vregs, vd_vregs) && micro_vl > 0; i++) { for (uint8_t j = 0; j < vs2_vregs; j++) { microop = new %(class_name)sMicro( @@ -1930,7 +1930,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx); + uint32_t _microVl, uint32_t _microIdx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -1941,7 +1941,7 @@ def template VectorGatherMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx) + uint32_t _microVl, uint32_t _microIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -1952,14 +1952,14 @@ template [[maybe_unused]] constexpr uint32_t vd_eewb = sizeof(ElemType); [[maybe_unused]] constexpr uint32_t vs2_eewb = sizeof(ElemType); [[maybe_unused]] constexpr uint32_t vs1_eewb = sizeof(IndexType); - constexpr uint8_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; - constexpr uint8_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; + constexpr uint32_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; + constexpr uint32_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; const int8_t lmul = vtype_vlmul(vtype); const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; - [[maybe_unused]] const uint8_t vs2_idx = _microIdx % vs2_vregs; - [[maybe_unused]] const uint8_t vs1_idx = + [[maybe_unused]] const uint32_t vs2_idx = _microIdx % vs2_vregs; + [[maybe_unused]] const uint32_t vs1_idx = _microIdx / vs2_vregs / vs1_split_num; - [[maybe_unused]] const uint8_t vd_idx = + [[maybe_unused]] const uint32_t vd_idx = _microIdx / vs2_vregs / vd_split_num; %(set_dest_reg_idx)s; %(set_src_reg_idx)s; @@ -1998,24 +1998,24 @@ Fault %(vm_decl_rd)s; %(copy_old_vd)s; const uint32_t vlmax = vtype_VLMAX(vtype,vlen); - constexpr uint8_t vd_eewb = sizeof(ElemType); - constexpr uint8_t vs1_eewb = sizeof(IndexType); - constexpr uint8_t vs2_eewb = sizeof(ElemType); - constexpr uint8_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; - constexpr uint8_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; - [[maybe_unused]] const uint16_t vd_elems = vlenb / vd_eewb; - [[maybe_unused]] const uint16_t vs1_elems = vlenb / vs1_eewb; - [[maybe_unused]] const uint16_t vs2_elems = vlenb / vs2_eewb; + constexpr uint32_t vd_eewb = sizeof(ElemType); + constexpr uint32_t vs1_eewb = sizeof(IndexType); + constexpr uint32_t vs2_eewb = sizeof(ElemType); + constexpr uint32_t vs1_split_num = (vd_eewb + vs1_eewb - 1) / vs1_eewb; + constexpr uint32_t vd_split_num = (vs1_eewb + vd_eewb - 1) / vd_eewb; + [[maybe_unused]] const uint32_t vd_elems = vlenb / vd_eewb; + [[maybe_unused]] const uint32_t vs1_elems = vlenb / vs1_eewb; + [[maybe_unused]] const uint32_t vs2_elems = vlenb / vs2_eewb; [[maybe_unused]] const int8_t lmul = vtype_vlmul(vtype); [[maybe_unused]] const uint8_t vs2_vregs = lmul < 0 ? 1 : 1 << lmul; - [[maybe_unused]] const uint8_t vs2_idx = microIdx % vs2_vregs; - [[maybe_unused]] const uint8_t vs1_idx = + [[maybe_unused]] const uint32_t vs2_idx = microIdx % vs2_vregs; + [[maybe_unused]] const uint32_t vs1_idx = microIdx / vs2_vregs / vs1_split_num; - [[maybe_unused]] const uint8_t vd_idx = + [[maybe_unused]] const uint32_t vd_idx = microIdx / vs2_vregs / vd_split_num; - [[maybe_unused]] const uint16_t vs1_bias = + [[maybe_unused]] const uint32_t vs1_bias = vs1_elems * (vd_idx % vs1_split_num) / vs1_split_num; - [[maybe_unused]] const uint16_t vd_bias = + [[maybe_unused]] const uint32_t vd_bias = vd_elems * (vs1_idx % vd_split_num) / vd_split_num; %(code)s; @@ -2116,7 +2116,7 @@ private: bool* vxsatptr; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx, bool* vxsatptr); + uint32_t _microIdx, bool* vxsatptr); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -2127,7 +2127,7 @@ def template VectorIntVxsatMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx, bool* vxsatptr) + uint32_t _microVl, uint32_t _microIdx, bool* vxsatptr) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx) { @@ -2299,7 +2299,7 @@ private: bool vm; public: %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, - uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx); + uint32_t _microIdx, uint32_t _vdIdx, uint32_t _vs2Idx); Fault execute(ExecContext* xc, trace::InstRecord* traceData)const override; using %(base_class)s::generateDisassembly; }; @@ -2310,7 +2310,8 @@ def template VectorSlideMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint32_t _microVl, uint8_t _microIdx, uint8_t _vdIdx, uint8_t _vs2Idx) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vdIdx, + uint32_t _vs2Idx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vdIdx, _vs2Idx) { diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index 84cee9af73..c405304a4f 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -96,8 +96,8 @@ private: RegId srcRegIdxArr[3]; RegId destRegIdxArr[1]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _microVl, - uint8_t _microIdx, uint32_t _vlen); + %(class_name)s(ExtMachInst _machInst, uint32_t _microVl, + uint32_t _microIdx, uint32_t _vlen); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -111,8 +111,8 @@ public: def template VleMicroConstructor {{ -%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint8_t _microVl, - uint8_t _microIdx, uint32_t _vlen) +%(class_name)s::%(class_name)s(ExtMachInst _machInst, uint32_t _microVl, + uint32_t _microIdx, uint32_t _vlen) : %(base_class)s( "%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) { @@ -300,7 +300,7 @@ private: RegId destRegIdxArr[0]; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen); + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -314,7 +314,7 @@ public: def template VseMicroConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen) : %(base_class)s( "%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) { @@ -532,7 +532,7 @@ private: RegId srcRegIdxArr[2]; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen); + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -546,7 +546,7 @@ public: def template VsWholeMicroConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen) : %(base_class)s( "%(mnemonic)s", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) { @@ -666,7 +666,7 @@ private: RegId srcRegIdxArr[1]; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen); + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -680,7 +680,7 @@ public: def template VlWholeMicroConstructor {{ %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _microVl, uint8_t _microIdx, uint32_t _vlen) + uint32_t _microVl, uint32_t _microIdx, uint32_t _vlen) : %(base_class)s("%(mnemonic)s_micro", _machInst, %(op_class)s, _microVl, _microIdx, _vlen) { @@ -832,7 +832,7 @@ private: RegId srcRegIdxArr[4]; RegId destRegIdxArr[1]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + %(class_name)s(ExtMachInst _machInst, uint32_t _regIdx, uint32_t _microIdx, uint32_t _microVl); Fault execute(ExecContext *, trace::InstRecord *) const override; @@ -847,7 +847,7 @@ public: def template VlStrideMicroConstructor {{ %(class_name)s::%(class_name)s( - ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + ExtMachInst _machInst, uint32_t _regIdx, uint32_t _microIdx, uint32_t _microVl) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _regIdx, _microIdx, _microVl) @@ -1056,7 +1056,7 @@ private: RegId srcRegIdxArr[4]; RegId destRegIdxArr[0]; public: - %(class_name)s(ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + %(class_name)s(ExtMachInst _machInst, uint32_t _regIdx, uint32_t _microIdx, uint32_t _microVl); Fault execute(ExecContext *, trace::InstRecord *) const override; @@ -1071,7 +1071,7 @@ public: def template VsStrideMicroConstructor {{ %(class_name)s::%(class_name)s( - ExtMachInst _machInst, uint8_t _regIdx, uint8_t _microIdx, + ExtMachInst _machInst, uint32_t _regIdx, uint32_t _microIdx, uint32_t _microVl) : %(base_class)s("%(mnemonic)s""_micro", _machInst, %(op_class)s, _regIdx, _microIdx, _microVl) @@ -1210,12 +1210,12 @@ template microop = new VectorNopMicroInst(_machInst); this->microops.push_back(microop); } - for (uint8_t i = 0; micro_vl > 0; i++) { - for (uint8_t j = 0; j < micro_vl; ++j) { - uint8_t vdRegIdx = i / vd_split_num; - uint8_t vs2RegIdx = i / vs2_split_num; - uint8_t vdElemIdx = j + micro_vlmax * (i % vd_split_num); - uint8_t vs2ElemIdx = j + micro_vlmax * (i % vs2_split_num); + for (uint32_t i = 0; micro_vl > 0; i++) { + for (uint32_t j = 0; j < micro_vl; ++j) { + uint32_t vdRegIdx = i / vd_split_num; + uint32_t vs2RegIdx = i / vs2_split_num; + uint32_t vdElemIdx = j + micro_vlmax * (i % vd_split_num); + uint32_t vs2ElemIdx = j + micro_vlmax * (i % vs2_split_num); microop = new %(class_name)sMicro(machInst, vdRegIdx, vdElemIdx, vs2RegIdx, vs2ElemIdx); microop->setFlag(IsDelayedCommit); @@ -1246,8 +1246,8 @@ private: RegId destRegIdxArr[1]; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _vdRegIdx, uint8_t _vdElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx); + uint32_t _vdRegIdx, uint32_t _vdElemIdx, + uint32_t _vs2RegIdx, uint32_t _vs2ElemIdx); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -1262,8 +1262,8 @@ def template VlIndexMicroConstructor {{ template %(class_name)s::%(class_name)s( - ExtMachInst _machInst,uint8_t _vdRegIdx, uint8_t _vdElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + ExtMachInst _machInst,uint32_t _vdRegIdx, uint32_t _vdElemIdx, + uint32_t _vs2RegIdx, uint32_t _vs2ElemIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vdRegIdx, _vdElemIdx, _vs2RegIdx, _vs2ElemIdx) { @@ -1450,12 +1450,12 @@ template microop = new VectorNopMicroInst(_machInst); this->microops.push_back(microop); } - for (uint8_t i = 0; micro_vl > 0; i++) { - for (uint8_t j = 0; j < micro_vl; ++j) { - uint8_t vs3RegIdx = i / vs3_split_num; - uint8_t vs2RegIdx = i / vs2_split_num; - uint8_t vs3ElemIdx = j + micro_vlmax * (i % vs3_split_num); - uint8_t vs2ElemIdx = j + micro_vlmax * (i % vs2_split_num); + for (uint32_t i = 0; micro_vl > 0; i++) { + for (uint32_t j = 0; j < micro_vl; ++j) { + uint32_t vs3RegIdx = i / vs3_split_num; + uint32_t vs2RegIdx = i / vs2_split_num; + uint32_t vs3ElemIdx = j + micro_vlmax * (i % vs3_split_num); + uint32_t vs2ElemIdx = j + micro_vlmax * (i % vs2_split_num); microop = new %(class_name)sMicro(machInst, vs3RegIdx, vs3ElemIdx, vs2RegIdx, vs2ElemIdx); microop->setFlag(IsDelayedCommit); @@ -1486,8 +1486,8 @@ private: RegId destRegIdxArr[0]; public: %(class_name)s(ExtMachInst _machInst, - uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx); + uint32_t _vs3RegIdx, uint32_t _vs3ElemIdx, + uint32_t _vs2RegIdx, uint32_t _vs2ElemIdx); Fault execute(ExecContext *, trace::InstRecord *) const override; Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; @@ -1502,8 +1502,8 @@ def template VsIndexMicroConstructor {{ template %(class_name)s::%(class_name)s(ExtMachInst _machInst, - uint8_t _vs3RegIdx, uint8_t _vs3ElemIdx, - uint8_t _vs2RegIdx, uint8_t _vs2ElemIdx) + uint32_t _vs3RegIdx, uint32_t _vs3ElemIdx, + uint32_t _vs2RegIdx, uint32_t _vs2ElemIdx) : %(base_class)s("%(mnemonic)s", _machInst, %(op_class)s, _vs3RegIdx, _vs3ElemIdx, _vs2RegIdx, _vs2ElemIdx) { From 57ba3fccb7e2946071dedd0e22d75c106230ba09 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Thu, 30 Nov 2023 05:56:23 +0800 Subject: [PATCH 630/693] scons: Move CPPPATH systemc_home to "src/systemc" folder (#617) Files under src/systemc require the include path of systemc_home Change-Id: Ibcbac2762259a0b997ac444b2c63a218c27af9ee --- src/arch/arm/fastmodel/SConscript | 6 ------ src/systemc/SConscript | 5 ++++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript index 8b1ab6af05..16b2b02e3f 100644 --- a/src/arch/arm/fastmodel/SConscript +++ b/src/arch/arm/fastmodel/SConscript @@ -50,10 +50,6 @@ import os.path if env['CONF']['USE_ARM_FASTMODEL']: env.TagImplies('arm fastmodel', 'arm isa') - -systemc_home = Dir('#/src/systemc/ext/systemc_home') -env['ENV']['SYSTEMC_HOME'] = systemc_home.abspath - def extract_var(name): val = env['CONF'].get(name, None) if val is None: @@ -114,8 +110,6 @@ cpppaths = ( pvlib_home.Dir('include/fmruntime/eslapi'), pvlib_home.Dir('Iris/include'), - systemc_home.Dir('include'), - maxcore_home.Dir('AMBA-PV/include'), ) env.Append(CPPPATH=cpppaths) diff --git a/src/systemc/SConscript b/src/systemc/SConscript index 06bdb50456..4b9892a2f0 100644 --- a/src/systemc/SConscript +++ b/src/systemc/SConscript @@ -30,6 +30,9 @@ if not env['CONF']['USE_SYSTEMC']: env.UseSystemcCheck(warn=True) -env.Append(CPPPATH=Dir('ext')) +systemc_home = Dir('#/src/systemc/ext/systemc_home') +env['ENV']['SYSTEMC_HOME'] = systemc_home.abspath + +env.Append(CPPPATH=[systemc_home.Dir('include'),Dir('ext')]) SimObject('Tlm.py', sim_objects=[]) From 1d1cba297b6651c54ee2aff048da723eaa94e515 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Wed, 29 Nov 2023 14:24:48 -0800 Subject: [PATCH 631/693] scons: Add an option to reduce memory usage of ld (#601) Linking the gem5 binary consists of linking numerous object files. By default, ld optimizes for speed over for memory consumption [1]. This leads to the huge memory consumption of gem5 at the linking stage. This patch adds an option to add the `--no-keep-memory` flag to ld. According to the documentation [1], this flag optimizes the memory usage of ld. [1] https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_2.html#IDX133 Signed-off-by: Hoa Nguyen --- SConstruct | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/SConstruct b/SConstruct index 77bbd3a866..396a83b811 100755 --- a/SConstruct +++ b/SConstruct @@ -131,6 +131,8 @@ AddOption('--with-systemc-tests', action='store_true', help='Build systemc tests') AddOption('--install-hooks', action='store_true', help='Install revision control hooks non-interactively') +AddOption('--limit-ld-memory-usage', action='store_true', + help='Tell ld, the linker, to reduce memory usage.') AddOption('--gprof', action='store_true', help='Enable support for the gprof profiler') AddOption('--pprof', action='store_true', @@ -588,6 +590,14 @@ for variant_path in variant_paths: conf.CheckLinkFlag( '-Wl,--thread-count=%d' % GetOption('num_jobs')) + with gem5_scons.Configure(env) as conf: + ld_optimize_memory_usage = GetOption('limit_ld_memory_usage') + if ld_optimize_memory_usage: + if conf.CheckLinkFlag('-Wl,--no-keep-memory'): + env.Append(LINKFLAGS=['-Wl,--no-keep-memory']) + else: + error("Unable to use --no-keep-memory with the linker") + # Treat warnings as errors but white list some warnings that we # want to allow (e.g., deprecation warnings). env.Append(CCFLAGS=['-Werror', From 392086b43d7068292e440f45b54ddf240909442f Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 29 Nov 2023 14:27:23 -0800 Subject: [PATCH 632/693] stdlib, resources: removed deprecated if statement in obtain_resource for workload resources (#611) - The resources field in workload now changed to a dict of id and version from a string with just the id. There was an if statement added to support both versions in develop. Removing the if statement so that 23.1 supports the new changes only. Change-Id: Id8dc3f932f53a156e4fb609a215db7d85bd81a44 --- src/python/gem5/resources/resource.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 98c58cf832..7a6fbee31a 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -965,22 +965,14 @@ def obtain_resource( assert isinstance(key, str) value = resource_json["resources"][key] - if isinstance(value, str): - warn( - "Deprecation warning: resources field in workloads has changed" - "from { category: id } to" - "{ category: { id: id, resource_version: resource_version } }" - "The current develop branch of gem5 supports both formats" - "but this will be removed in the 23.1 release." - ) - params[key] = obtain_resource( - value, - ) - elif isinstance(value, dict): - params[key] = obtain_resource( - value["id"], - resource_version=value["resource_version"], - ) + assert isinstance(value, dict) + params[key] = obtain_resource( + value["id"], + resource_version=value["resource_version"], + resource_directory=resource_directory, + clients=clients, + gem5_version=gem5_version, + ) if "additional_params" in resource_json: for key in resource_json["additional_params"].keys(): assert isinstance(key, str) From b59a39831290fc816cf00e162f8567bacf2503ca Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 29 Nov 2023 16:02:30 -0800 Subject: [PATCH 633/693] tests: change HACC tests to VEGA_X86 Change-Id: I846229db1ab1480d79471c717b714698c3132df9 --- .github/workflows/gpu-tests.yaml | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index 1f25eb0f00..8e26873159 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -23,24 +23,6 @@ jobs: # therefore need to explicitly checkout the develop branch. ref: develop - name: Build gem5 - run: scons build/GCN3_X86/gem5.opt -j $(nproc) --ignore-style - - uses: actions/upload-artifact@v3 - with: - name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 - path: build/GCN3_X86/gem5.opt - retention-days: 5 - - run: echo "This job's status is ${{ job.status }}." - - build-gem5-vega: - runs-on: [self-hosted, linux, x64] - container: ghcr.io/gem5/gcn-gpu:latest - steps: - - uses: actions/checkout@v3 - with: - # Scheduled workflows run on the default branch by default. We - # therefore need to explicitly checkout the develop branch. - ref: develop - - name: Build gem5 vega run: scons build/VEGA_X86/gem5.opt -j $(nproc) --ignore-style - uses: actions/upload-artifact@v3 with: @@ -52,7 +34,7 @@ jobs: LULESH-tests: runs-on: [self-hosted, linux, x64] container: ghcr.io/gem5/gcn-gpu:latest - needs: build-gem5-vega + needs: build-gem5 timeout-minutes: 480 # 8 hours steps: - uses: actions/checkout@v3 @@ -95,8 +77,8 @@ jobs: - uses: actions/download-artifact@v3 with: name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 - path: build/GCN3_X86 - - run: chmod u+x build/GCN3_X86/gem5.opt + path: build/VEGA_X86 + - run: chmod u+x build/VEGA_X86/gem5.opt - name: make hip directory run: mkdir hip - name: Compile m5ops and x86 @@ -110,4 +92,4 @@ jobs: - name: Run HACC tests working-directory: ${{ github.workspace }} run: | - build/GCN3_X86/gem5.opt configs/example/apu_se.py -n3 --reg-alloc-policy=dynamic --benchmark-root=hip -c ForceTreeTest --options="0.5 0.1 64 0.1 1 N 12 rcb" + build/VEGA_X86/gem5.opt configs/example/apu_se.py -n3 --reg-alloc-policy=dynamic --benchmark-root=hip -c ForceTreeTest --options="0.5 0.1 64 0.1 1 N 12 rcb" From f256064b4a740334c521af54c6daa5d640a59735 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 29 Nov 2023 21:45:22 -0800 Subject: [PATCH 634/693] util-docker: Enforce cmake version >=3.24 for DRAMSys DRAMSys requires cmake 3.24 or greater. By default neither Ubuntu 22.04 or 20.04 delevery this by APT. In both cases wget is required. In 20.04 OpenSSL is required. Change-Id: I51a7f8a8a46e8cf1908a120adb9289aa3907ccda --- .../ubuntu-20.04_all-dependencies/Dockerfile | 13 ++++++++++++- .../ubuntu-22.04_all-dependencies/Dockerfile | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile index e7e680c6c2..055e3ea8e7 100644 --- a/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile @@ -32,7 +32,7 @@ RUN apt -y update && apt -y upgrade && \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev python-is-python3 doxygen libboost-all-dev \ libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config pip \ - python3-venv black gcc-10 g++-10 cmake python3-tk + python3-venv black gcc-10 g++-10 cmake python3-tk wget libssl-dev RUN pip install mypy pre-commit @@ -44,3 +44,14 @@ RUN update-alternatives --install \ /usr/bin/c++ c++ /usr/bin/g++-10 100 RUN update-alternatives --install \ /usr/bin/cc cc /usr/bin/gcc-10 100 + + +# DRAMSys requires cmake >= 3.24.0. +RUN wget https://github.com/Kitware/CMake/releases/download/v3.24.0/cmake-3.24.0.tar.gz \ + && tar -xzf cmake-3.24.0.tar.gz \ + && cd cmake-3.24.0 \ + && ./bootstrap \ + && make -j`nproc` \ + && make install \ + && cd .. \ + && rm -rf cmake-3.24.0.tar.gz cmake-3.24.0 diff --git a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile index 34338d9c9a..b6bd080ea7 100644 --- a/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile +++ b/util/dockerfiles/ubuntu-22.04_all-dependencies/Dockerfile @@ -31,6 +31,17 @@ RUN apt -y update && apt -y upgrade && \ apt -y install build-essential git m4 scons zlib1g zlib1g-dev \ libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ python3-dev doxygen libboost-all-dev libhdf5-serial-dev python3-pydot \ - libpng-dev libelf-dev pkg-config pip python3-venv black cmake python3-tk + libpng-dev libelf-dev pkg-config pip python3-venv black python3-tk wget RUN pip install mypy pre-commit + +# DRAMSys requires cmake >= 3.24.0. APT only provides 3.22.1 for Ubuntu 22.04. +# Therefore, we install cmake from source. +RUN wget https://github.com/Kitware/CMake/releases/download/v3.24.0/cmake-3.24.0.tar.gz \ + && tar -xzf cmake-3.24.0.tar.gz \ + && cd cmake-3.24.0 \ + && ./bootstrap \ + && make -j`nproc` \ + && make install \ + && cd .. \ + && rm -rf cmake-3.24.0.tar.gz cmake-3.24.0 From 7d67109ca2ed7422cebe4a70f4c2d114634eb33c Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 10 Oct 2023 10:57:35 -0700 Subject: [PATCH 635/693] python,misc: Add `isort` to pre-commit Change-Id: I391a8948f0817bd5c6a9fe8a4c3e4fed07a98c49 --- .pre-commit-config.yaml | 4 ++++ pyproject.toml | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index debad8cc6a..5183f38110 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,6 +68,10 @@ repos: - id: check-symlinks - id: destroyed-symlinks - id: requirements-txt-fixer + - repo: https://github.com/PyCQA/isort + rev: 5.11.5 + hooks: + - id: isort - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt rev: 0.2.3 hooks: diff --git a/pyproject.toml b/pyproject.toml index a06d464de7..d32cf5f06b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,12 @@ [tool.black] line-length = 79 include = '\.pyi?$' +[tool.isort] +profile = "black" +multi_line_output = 3 +line_length = 79 +force_grid_wrap = 2 +known_m5 = "m5" +known_underscore_m5 = "_m5,slicc" +known_gem5 = "gem5" +sections="FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,M5,UNDERSCORE_M5,GEM5,LOCALFOLDER" From d11c40dcac927b9501b61fed66b7144de648a4d8 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 29 Nov 2023 22:06:41 -0800 Subject: [PATCH 636/693] misc: Run `pre-commit run --all-files` This ensures `isort` is applied to all files in the repo. Change-Id: Ib7ced1c924ef1639542bf0d1a01c5737f6ba43e9 --- build_tools/cxx_config_cc.py | 3 +- build_tools/cxx_config_hh.py | 1 - build_tools/enum_cc.py | 1 - build_tools/enum_hh.py | 1 - build_tools/sim_object_param_struct_cc.py | 1 - build_tools/sim_object_param_struct_hh.py | 1 - configs/common/Benchmarks.py | 8 +- configs/common/CacheConfig.py | 7 +- configs/common/Caches.py | 1 + configs/common/CpuConfig.py | 2 +- configs/common/FSConfig.py | 5 +- configs/common/FileSystemConfig.py | 29 +++++-- configs/common/MemConfig.py | 8 +- configs/common/ObjectList.py | 8 +- configs/common/Options.py | 6 +- configs/common/SimpleOpts.py | 6 +- configs/common/Simulation.py | 13 ++- configs/common/SysPaths.py | 3 +- configs/common/cores/arm/O3_ARM_Etrace.py | 1 + configs/common/cores/arm/__init__.py | 2 +- configs/common/cpu2000.py | 11 ++- configs/deprecated/example/fs.py | 28 +++--- configs/deprecated/example/se.py | 28 +++--- configs/dram/lat_mem_rd.py | 10 ++- configs/dram/low_power_sweep.py | 8 +- configs/dram/sweep.py | 10 ++- configs/example/apu_se.py | 24 +++--- configs/example/arm/baremetal.py | 21 +++-- configs/example/arm/devices.py | 2 +- configs/example/arm/dist_bigLITTLE.py | 4 +- configs/example/arm/etrace_se.py | 12 +-- configs/example/arm/fs_bigLITTLE.py | 27 ++++-- configs/example/arm/fs_power.py | 9 +- configs/example/arm/ruby_fs.py | 24 +++--- configs/example/arm/starter_fs.py | 20 +++-- configs/example/arm/starter_se.py | 19 ++-- configs/example/arm/workloads.py | 10 ++- configs/example/dramsys.py | 1 - configs/example/etrace_replay.py | 13 ++- configs/example/garnet_synth_traffic.py | 7 +- configs/example/gem5_library/arm-hello.py | 10 +-- .../example/gem5_library/arm-ubuntu-run.py | 16 ++-- .../caches/octopi-cache-example.py | 17 ++-- .../riscv-hello-restore-checkpoint.py | 10 +-- .../riscv-hello-save-checkpoint.py | 11 +-- .../checkpoints/simpoints-se-checkpoint.py | 25 +++--- .../checkpoints/simpoints-se-restore.py | 26 +++--- .../gem5_library/dramsys/arm-hello-dramsys.py | 10 +-- .../gem5_library/dramsys/dramsys-traffic.py | 2 +- .../create-looppoint-checkpoints.py | 16 ++-- .../restore-looppoint-checkpoint.py | 16 ++-- .../example/gem5_library/memory_traffic.py | 8 +- configs/example/gem5_library/power-hello.py | 10 +-- configs/example/gem5_library/riscv-fs.py | 6 +- .../example/gem5_library/riscv-ubuntu-run.py | 6 +- .../example/gem5_library/riscvmatched-fs.py | 12 +-- .../gem5_library/riscvmatched-hello.py | 4 +- .../riscvmatched-microbenchmark-suite.py | 4 +- .../gem5_library/x86-gapbs-benchmarks.py | 10 +-- .../gem5_library/x86-npb-benchmarks.py | 17 ++-- .../gem5_library/x86-parsec-benchmarks.py | 8 +- .../x86-spec-cpu2006-benchmarks.py | 26 +++--- .../x86-spec-cpu2017-benchmarks.py | 26 +++--- .../x86-ubuntu-run-with-kvm-no-perf.py | 10 +-- .../gem5_library/x86-ubuntu-run-with-kvm.py | 10 +-- .../example/gem5_library/x86-ubuntu-run.py | 1 - configs/example/gpufs/DisjointNetwork.py | 6 +- configs/example/gpufs/Disjoint_VIPER.py | 8 +- configs/example/gpufs/hip_cookbook.py | 15 ++-- configs/example/gpufs/hip_rodinia.py | 17 ++-- configs/example/gpufs/hip_samples.py | 15 ++-- configs/example/gpufs/runfs.py | 16 ++-- configs/example/gpufs/system/system.py | 16 ++-- configs/example/gpufs/vega10.py | 16 ++-- configs/example/hmc_hello.py | 10 ++- configs/example/hmctest.py | 8 +- configs/example/hsaTopology.py | 24 ++++-- configs/example/lupv/run_lupv.py | 8 +- configs/example/riscv/fs_linux.py | 27 +++--- configs/example/ruby_direct_test.py | 7 +- configs/example/ruby_gpu_random_test.py | 7 +- configs/example/ruby_mem_test.py | 7 +- configs/example/ruby_random_test.py | 7 +- configs/example/sc_main.py | 5 +- configs/example/sst/riscv_fs.py | 6 +- configs/learning_gem5/part1/two_level.py | 1 + configs/learning_gem5/part3/msi_caches.py | 6 +- .../part3/ruby_caches_MI_example.py | 6 +- configs/learning_gem5/part3/ruby_test.py | 4 +- configs/learning_gem5/part3/test_caches.py | 11 ++- configs/network/Network.py | 9 +- configs/nvm/sweep.py | 10 ++- configs/nvm/sweep_hybrid.py | 10 ++- configs/ruby/AMD_Base_Constructor.py | 9 +- configs/ruby/CHI.py | 5 +- configs/ruby/CHI_config.py | 1 + configs/ruby/GPU_VIPER.py | 19 ++-- configs/ruby/Garnet_standalone.py | 8 +- configs/ruby/MESI_Three_Level.py | 16 ++-- configs/ruby/MESI_Three_Level_HTM.py | 16 ++-- configs/ruby/MESI_Two_Level.py | 11 ++- configs/ruby/MI_example.py | 11 ++- configs/ruby/MOESI_AMD_Base.py | 17 ++-- configs/ruby/MOESI_CMP_directory.py | 11 ++- configs/ruby/MOESI_CMP_token.py | 11 ++- configs/ruby/MOESI_hammer.py | 16 ++-- configs/ruby/Ruby.py | 20 +++-- configs/splash2/cluster.py | 2 +- configs/splash2/run.py | 2 +- configs/topologies/Crossbar.py | 6 +- configs/topologies/CrossbarGarnet.py | 6 +- configs/topologies/CustomMesh.py | 7 +- configs/topologies/MeshDirCorners_XY.py | 7 +- configs/topologies/Mesh_XY.py | 7 +- configs/topologies/Mesh_westfirst.py | 6 +- configs/topologies/Pt2Pt.py | 6 +- ext/testlib/__init__.py | 20 ++--- ext/testlib/configuration.py | 7 +- ext/testlib/fixture.py | 4 +- ext/testlib/handlers.py | 6 +- ext/testlib/helper.py | 5 +- ext/testlib/loader.py | 4 +- ext/testlib/main.py | 2 +- ext/testlib/query.py | 2 +- ext/testlib/result.py | 2 +- ext/testlib/runner.py | 6 +- ext/testlib/terminal.py | 4 +- ext/testlib/uid.py | 2 +- ext/testlib/wrappers.py | 5 +- site_scons/gem5_scons/__init__.py | 6 +- site_scons/gem5_scons/builders/blob.py | 11 +-- site_scons/gem5_scons/builders/config_file.py | 5 +- .../gem5_scons/builders/switching_headers.py | 5 +- site_scons/gem5_scons/kconfig.py | 3 +- site_scons/gem5_scons/util.py | 6 +- site_scons/site_tools/git.py | 4 +- src/arch/amdgpu/common/X86GPUTLB.py | 3 +- src/arch/amdgpu/vega/VegaGPUTLB.py | 5 +- src/arch/arm/ArmCPU.py | 17 ++-- src/arch/arm/ArmDecoder.py | 2 +- src/arch/arm/ArmFsWorkload.py | 6 +- src/arch/arm/ArmISA.py | 11 ++- src/arch/arm/ArmMMU.py | 5 +- src/arch/arm/ArmNativeTrace.py | 4 +- src/arch/arm/ArmPMU.py | 7 +- src/arch/arm/ArmSeWorkload.py | 3 +- src/arch/arm/ArmSemihosting.py | 5 +- src/arch/arm/ArmSystem.py | 11 ++- src/arch/arm/ArmTLB.py | 4 +- .../fastmodel/CortexA76/FastModelCortexA76.py | 27 +++--- .../fastmodel/CortexR52/FastModelCortexR52.py | 22 +++-- src/arch/arm/fastmodel/FastModel.py | 8 +- src/arch/arm/fastmodel/GIC/FastModelGIC.py | 12 +-- .../fastmodel/PL330_DMAC/FastModelPL330.py | 7 +- src/arch/arm/fastmodel/arm_fast_model.py | 1 + src/arch/arm/fastmodel/iris/Iris.py | 7 +- .../FastModelResetControllerExample.py | 5 +- src/arch/arm/kvm/ArmKvmCPU.py | 2 +- src/arch/arm/kvm/ArmV8KvmCPU.py | 2 +- src/arch/arm/kvm/BaseArmKvmCPU.py | 2 +- src/arch/arm/kvm/KvmGic.py | 6 +- src/arch/arm/tracers/ArmCapstone.py | 4 +- src/arch/arm/tracers/TarmacTrace.py | 4 +- src/arch/isa_parser/isa_parser.py | 1 + src/arch/isa_parser/operand_list.py | 8 +- src/arch/micro_asm.py | 8 +- src/arch/micro_asm_test.py | 7 +- src/arch/mips/MipsCPU.py | 8 +- src/arch/mips/MipsISA.py | 3 +- src/arch/mips/MipsSeWorkload.py | 3 +- src/arch/mips/MipsTLB.py | 5 +- src/arch/power/PowerCPU.py | 8 +- src/arch/power/PowerSeWorkload.py | 3 +- src/arch/power/PowerTLB.py | 5 +- src/arch/riscv/PMAChecker.py | 2 +- src/arch/riscv/PMP.py | 2 +- src/arch/riscv/RiscvCPU.py | 8 +- src/arch/riscv/RiscvFsWorkload.py | 8 +- src/arch/riscv/RiscvISA.py | 7 +- src/arch/riscv/RiscvMMU.py | 5 +- src/arch/riscv/RiscvSeWorkload.py | 3 +- src/arch/riscv/RiscvTLB.py | 5 +- src/arch/sparc/SparcCPU.py | 8 +- src/arch/sparc/SparcFsWorkload.py | 3 +- src/arch/sparc/SparcMMU.py | 4 +- src/arch/sparc/SparcNativeTrace.py | 5 +- src/arch/sparc/SparcSeWorkload.py | 3 +- src/arch/sparc/SparcTLB.py | 5 +- src/arch/x86/X86CPU.py | 13 ++- src/arch/x86/X86FsWorkload.py | 20 +++-- src/arch/x86/X86LocalApic.py | 5 +- src/arch/x86/X86NativeTrace.py | 5 +- src/arch/x86/X86SeWorkload.py | 3 +- src/arch/x86/X86TLB.py | 5 +- src/arch/x86/kvm/X86KvmCPU.py | 5 +- src/base/Graphics.py | 2 +- src/base/vnc/Vnc.py | 4 +- src/cpu/BaseCPU.py | 19 ++-- src/cpu/CPUTracers.py | 4 +- src/cpu/Capstone.py | 4 +- src/cpu/CheckerCPU.py | 3 +- src/cpu/CpuCluster.py | 2 +- src/cpu/DummyChecker.py | 2 +- src/cpu/FuncUnit.py | 2 +- src/cpu/InstPBTrace.py | 5 +- src/cpu/kvm/BaseKvmCPU.py | 7 +- src/cpu/kvm/KvmVM.py | 1 - src/cpu/minor/BaseMinorCPU.py | 11 ++- src/cpu/o3/BaseO3CPU.py | 7 +- src/cpu/o3/BaseO3Checker.py | 2 +- src/cpu/o3/FUPool.py | 4 +- src/cpu/o3/FuncUnitConfig.py | 5 +- src/cpu/pred/BranchPredictor.py | 5 +- src/cpu/probes/PcCountTracker.py | 4 +- src/cpu/simple/BaseAtomicSimpleCPU.py | 2 +- src/cpu/simple/BaseNonCachingSimpleCPU.py | 2 +- src/cpu/simple/BaseSimpleCPU.py | 5 +- src/cpu/simple/BaseTimingSimpleCPU.py | 3 +- src/cpu/simple/probes/SimPoint.py | 2 +- .../directedtest/RubyDirectedTester.py | 5 +- src/cpu/testers/gpu_ruby_test/CpuThread.py | 3 +- src/cpu/testers/gpu_ruby_test/DmaThread.py | 3 +- src/cpu/testers/gpu_ruby_test/GpuWavefront.py | 3 +- src/cpu/testers/memtest/MemTest.py | 3 +- src/cpu/testers/rubytest/RubyTester.py | 3 +- src/cpu/testers/traffic_gen/BaseTrafficGen.py | 2 +- src/cpu/testers/traffic_gen/GUPSGen.py | 2 +- src/cpu/testers/traffic_gen/PyTrafficGen.py | 3 +- src/cpu/testers/traffic_gen/TrafficGen.py | 2 +- src/cpu/trace/TraceCPU.py | 2 +- src/dev/BadDevice.py | 2 +- src/dev/Device.py | 3 +- src/dev/IntPin.py | 5 +- src/dev/Platform.py | 2 +- src/dev/ResetPort.py | 5 +- src/dev/amdgpu/AMDGPU.py | 15 +++- src/dev/arm/Doorbell.py | 2 +- src/dev/arm/EnergyCtrl.py | 4 +- src/dev/arm/FlashDevice.py | 3 +- src/dev/arm/GenericTimer.py | 16 +++- src/dev/arm/Gic.py | 12 +-- src/dev/arm/NoMali.py | 3 +- src/dev/arm/RealView.py | 86 +++++++++++-------- src/dev/arm/SMMUv3.py | 4 +- src/dev/arm/UFSHostDevice.py | 5 +- src/dev/arm/VExpressFastmodel.py | 10 ++- src/dev/arm/VirtIOMMIO.py | 12 +-- src/dev/arm/css/Scmi.py | 6 +- src/dev/hsa/HSADevice.py | 6 +- src/dev/hsa/HSADriver.py | 4 +- src/dev/i2c/I2C.py | 4 +- src/dev/lupio/LupioBLK.py | 1 - src/dev/lupio/LupioTTY.py | 3 +- src/dev/mips/Malta.py | 5 +- src/dev/net/Ethernet.py | 8 +- src/dev/pci/CopyEngine.py | 8 +- src/dev/pci/PciDevice.py | 6 +- src/dev/pci/PciHost.py | 6 +- src/dev/ps2/PS2.py | 2 +- src/dev/qemu/QemuFwCfg.py | 4 +- src/dev/riscv/HiFive.py | 9 +- src/dev/riscv/RTC.py | 2 +- src/dev/riscv/RiscvVirtIOMMIO.py | 9 +- src/dev/serial/Terminal.py | 5 +- src/dev/serial/Uart.py | 7 +- src/dev/sparc/T1000.py | 12 ++- src/dev/storage/DiskImage.py | 2 +- src/dev/storage/Ide.py | 7 +- src/dev/storage/SimpleDisk.py | 2 +- src/dev/virtio/VirtIO.py | 9 +- src/dev/virtio/VirtIO9P.py | 2 +- src/dev/virtio/VirtIOBlock.py | 2 +- src/dev/virtio/VirtIOConsole.py | 4 +- src/dev/virtio/VirtIORng 2.py | 2 +- src/dev/virtio/VirtIORng.py | 2 +- src/dev/x86/Cmos.py | 4 +- src/dev/x86/I8042.py | 4 +- src/dev/x86/I82094AA.py | 4 +- src/dev/x86/I8237.py | 2 +- src/dev/x86/I8254.py | 4 +- src/dev/x86/I8259.py | 7 +- src/dev/x86/Pc.py | 12 +-- src/dev/x86/PcSpeaker.py | 2 +- src/dev/x86/SouthBridge.py | 11 ++- src/dev/x86/X86Ide.py | 4 +- src/dev/x86/X86QemuFwCfg.py | 7 +- src/gpu-compute/GPU.py | 7 +- src/gpu-compute/LdsState.py | 3 +- src/learning_gem5/part2/SimpleCache.py | 2 +- src/mem/AbstractMemory.py | 2 +- src/mem/Bridge.py | 2 +- src/mem/CfiMemory.py | 7 +- src/mem/CommMonitor.py | 2 +- src/mem/DRAMSim2.py | 2 +- src/mem/DRAMSys.py | 8 +- src/mem/DRAMsim3.py | 3 +- src/mem/HBMCtrl.py | 2 +- src/mem/HMCController.py | 2 +- src/mem/HeteroMemCtrl.py | 2 +- src/mem/MemChecker.py | 2 +- src/mem/MemCtrl.py | 4 +- src/mem/MemDelay.py | 2 +- src/mem/MemInterface.py | 3 +- src/mem/NVMInterface.py | 6 +- src/mem/SerialLink.py | 2 +- src/mem/SharedMemoryServer.py | 2 +- src/mem/SimpleMemory.py | 2 +- src/mem/ThreadBridge.py | 2 +- src/mem/XBar.py | 3 +- src/mem/cache/Cache.py | 7 +- src/mem/cache/compressors/Compressors.py | 5 +- src/mem/cache/prefetch/Prefetcher.py | 7 +- src/mem/cache/tags/Tags.py | 4 +- src/mem/probes/MemFootprintProbe.py | 3 +- src/mem/probes/MemTraceProbe.py | 2 +- src/mem/probes/StackDistProbe.py | 2 +- src/mem/qos/QoSMemCtrl.py | 4 +- src/mem/qos/QoSMemSinkCtrl.py | 2 +- src/mem/qos/QoSPolicy.py | 2 +- src/mem/ruby/network/BasicRouter.py | 3 +- src/mem/ruby/network/Network.py | 4 +- src/mem/ruby/network/garnet/GarnetLink.py | 7 +- src/mem/ruby/network/garnet/GarnetNetwork.py | 6 +- src/mem/ruby/network/simple/SimpleLink.py | 9 +- src/mem/ruby/network/simple/SimpleNetwork.py | 11 ++- src/mem/ruby/slicc_interface/Controller.py | 2 +- src/mem/ruby/structures/RubyCache.py | 2 +- src/mem/ruby/structures/RubyPrefetcher.py | 5 +- src/mem/ruby/system/GPUCoalescer.py | 3 +- src/mem/ruby/system/RubySystem.py | 4 +- src/mem/ruby/system/Sequencer.py | 2 +- src/mem/ruby/system/VIPERCoalescer.py | 2 +- src/mem/slicc/ast/AST.py | 5 +- src/mem/slicc/ast/ActionDeclAST.py | 6 +- src/mem/slicc/ast/EnumDeclAST.py | 5 +- src/mem/slicc/ast/ExprStatementAST.py | 2 +- src/mem/slicc/ast/FuncCallExprAST.py | 5 +- src/mem/slicc/ast/FuncDeclAST.py | 5 +- src/mem/slicc/ast/InPortDeclAST.py | 6 +- src/mem/slicc/ast/MachineAST.py | 5 +- src/mem/slicc/ast/OutPortDeclAST.py | 6 +- src/mem/slicc/ast/StateDeclAST.py | 5 +- src/mem/slicc/ast/TypeAST.py | 1 - src/mem/slicc/ast/TypeFieldEnumAST.py | 6 +- src/mem/slicc/ast/TypeFieldStateAST.py | 5 +- src/mem/slicc/ast/VarExprAST.py | 5 +- src/mem/slicc/ast/__init__.py | 9 +- src/mem/slicc/parser.py | 5 +- src/mem/slicc/symbols/StateMachine.py | 4 +- src/mem/slicc/symbols/Symbol.py | 2 +- src/mem/slicc/symbols/Transition.py | 2 +- src/mem/slicc/symbols/Type.py | 2 +- src/mem/slicc/symbols/__init__.py | 2 +- .../gem5/components/boards/abstract_board.py | 26 ++++-- .../boards/abstract_system_board.py | 9 +- .../gem5/components/boards/arm_board.py | 67 ++++++++------- .../boards/experimental/lupv_board.py | 42 +++++---- .../components/boards/kernel_disk_workload.py | 25 +++--- .../gem5/components/boards/riscv_board.py | 42 ++++----- .../components/boards/se_binary_workload.py | 35 ++++---- .../gem5/components/boards/simple_board.py | 18 ++-- .../gem5/components/boards/test_board.py | 20 +++-- .../gem5/components/boards/x86_board.py | 59 ++++++------- .../abstract_cache_hierarchy.py | 9 +- .../chi/nodes/abstract_node.py | 18 ++-- .../cachehierarchies/chi/nodes/directory.py | 9 +- .../chi/nodes/dma_requestor.py | 7 +- .../chi/nodes/private_l1_moesi_cache.py | 8 +- .../chi/private_l1_cache_hierarchy.py | 32 ++++--- .../abstract_classic_cache_hierarchy.py | 5 +- .../classic/caches/l1dcache.py | 12 ++- .../classic/caches/l1icache.py | 6 +- .../classic/caches/l2cache.py | 13 ++- .../classic/caches/mmu_cache.py | 8 +- .../cachehierarchies/classic/no_cache.py | 17 ++-- .../classic/private_l1_cache_hierarchy.py | 17 ++-- .../private_l1_private_l2_cache_hierarchy.py | 19 ++-- .../private_l1_shared_l2_cache_hierarchy.py | 19 ++-- .../ruby/caches/abstract_l1_cache.py | 8 +- .../ruby/caches/mesi_three_level/directory.py | 7 +- .../caches/mesi_three_level/dma_controller.py | 7 +- .../ruby/caches/mesi_three_level/l1_cache.py | 16 ++-- .../ruby/caches/mesi_three_level/l2_cache.py | 14 +-- .../ruby/caches/mesi_three_level/l3_cache.py | 8 +- .../ruby/caches/mesi_two_level/directory.py | 7 +- .../caches/mesi_two_level/dma_controller.py | 4 +- .../ruby/caches/mesi_two_level/l1_cache.py | 19 ++-- .../ruby/caches/mesi_two_level/l2_cache.py | 13 +-- .../ruby/caches/mi_example/directory.py | 10 ++- .../ruby/caches/mi_example/dma_controller.py | 6 +- .../ruby/caches/mi_example/l1_cache.py | 10 ++- .../prebuilt/octopi_cache/core_complex.py | 18 ++-- .../caches/prebuilt/octopi_cache/octopi.py | 24 ++++-- .../prebuilt/octopi_cache/octopi_network.py | 2 +- .../octopi_cache/ruby_network_components.py | 6 +- .../ruby/mesi_three_level_cache_hierarchy.py | 26 +++--- .../ruby/mesi_two_level_cache_hierarchy.py | 22 +++-- .../ruby/mi_example_cache_hierarchy.py | 24 +++--- .../ruby/topologies/simple_pt2pt.py | 7 +- src/python/gem5/components/memory/__init__.py | 40 +++++---- .../memory/abstract_memory_system.py | 19 +++- .../gem5/components/memory/dramsim_3.py | 20 +++-- src/python/gem5/components/memory/dramsys.py | 14 +-- src/python/gem5/components/memory/hbm.py | 25 ++++-- src/python/gem5/components/memory/memory.py | 20 ++++- .../gem5/components/memory/multi_channel.py | 13 +-- src/python/gem5/components/memory/simple.py | 17 +++- .../gem5/components/memory/single_channel.py | 16 ++-- .../components/processors/abstract_core.py | 21 +++-- .../processors/abstract_generator.py | 7 +- .../processors/abstract_generator_core.py | 15 ++-- .../processors/abstract_processor.py | 18 ++-- .../components/processors/base_cpu_core.py | 28 +++--- .../processors/base_cpu_processor.py | 19 ++-- .../processors/complex_generator.py | 16 ++-- .../processors/complex_generator_core.py | 24 ++++-- .../gem5/components/processors/cpu_types.py | 6 +- .../components/processors/gups_generator.py | 2 +- .../processors/gups_generator_core.py | 10 ++- .../processors/gups_generator_ep.py | 4 +- .../processors/gups_generator_par.py | 7 +- .../components/processors/linear_generator.py | 12 +-- .../processors/linear_generator_core.py | 20 +++-- .../components/processors/random_generator.py | 13 ++- .../processors/random_generator_core.py | 20 +++-- .../gem5/components/processors/simple_core.py | 10 +-- .../components/processors/simple_processor.py | 14 +-- .../processors/simple_switchable_processor.py | 19 ++-- .../processors/switchable_processor.py | 16 ++-- .../processors/traffic_generator.py | 9 +- .../processors/traffic_generator_core.py | 7 +- .../gem5/prebuilt/demo/x86_demo_board.py | 8 +- .../riscvmatched/riscvmatched_board.py | 68 +++++++-------- .../riscvmatched/riscvmatched_cache.py | 22 +++-- .../riscvmatched/riscvmatched_core.py | 21 ++--- .../riscvmatched/riscvmatched_processor.py | 8 +- src/python/gem5/resources/client.py | 21 +++-- .../resources/client_api/abstract_client.py | 12 ++- .../gem5/resources/client_api/atlasclient.py | 21 ++++- .../resources/client_api/client_wrapper.py | 18 ++-- .../gem5/resources/client_api/jsonclient.py | 14 ++- src/python/gem5/resources/downloader.py | 38 ++++---- src/python/gem5/resources/elfie.py | 6 +- src/python/gem5/resources/looppoint.py | 17 ++-- src/python/gem5/resources/md5_utils.py | 2 +- src/python/gem5/resources/resource.py | 40 +++++---- src/python/gem5/resources/workload.py | 17 +++- src/python/gem5/runtime.py | 9 +- .../gem5/simulate/exit_event_generators.py | 14 ++- src/python/gem5/simulate/simulator.py | 42 +++++---- src/python/gem5/utils/filelock.py | 2 +- .../gem5/utils/multiprocessing/__init__.py | 7 +- .../utils/multiprocessing/_command_line.py | 5 +- .../gem5/utils/multiprocessing/context.py | 5 +- .../utils/multiprocessing/popen_spawn_gem5.py | 14 +-- src/python/gem5/utils/requires.py | 14 +-- src/python/gem5/utils/simpoint.py | 12 ++- src/python/m5/SimObject.py | 25 +++--- src/python/m5/__init__.py | 15 ++-- src/python/m5/debug.py | 10 ++- src/python/m5/event.py | 7 +- src/python/m5/ext/pystats/__init__.py | 4 +- src/python/m5/ext/pystats/abstract_stat.py | 4 +- src/python/m5/ext/pystats/group.py | 5 +- src/python/m5/ext/pystats/jsonloader.py | 22 +++-- .../m5/ext/pystats/serializable_stat.py | 10 ++- src/python/m5/ext/pystats/simstat.py | 7 +- src/python/m5/ext/pystats/statistic.py | 8 +- src/python/m5/main.py | 26 +++--- src/python/m5/objects/SimObject.py | 3 +- src/python/m5/options.py | 1 - src/python/m5/params.py | 33 ++++--- src/python/m5/simulate.py | 46 ++++++---- src/python/m5/stats/__init__.py | 14 +-- src/python/m5/stats/gem5stats.py | 11 ++- src/python/m5/ticks.py | 3 +- src/python/m5/trace.py | 8 +- src/python/m5/util/__init__.py | 8 +- src/python/m5/util/dot_writer.py | 15 +++- src/python/m5/util/dot_writer_ruby.py | 1 + src/python/m5/util/fdthelper.py | 5 +- src/python/m5/util/terminal_formatter.py | 4 +- src/sim/ClockDomain.py | 2 +- src/sim/ClockedObject.py | 2 +- src/sim/DVFSHandler.py | 2 +- src/sim/InstTracer.py | 2 +- src/sim/PowerDomain.py | 2 +- src/sim/PowerState.py | 2 +- src/sim/Process.py | 5 +- src/sim/RedirectPath.py | 2 +- src/sim/Root.py | 2 +- src/sim/SignalPort.py | 5 +- src/sim/SubSystem.py | 2 +- src/sim/System.py | 7 +- src/sim/VoltageDomain.py | 2 +- src/sim/Workload.py | 8 +- src/sim/power/MathExprPowerModel.py | 4 +- src/sim/power/PowerModel.py | 2 +- src/sim/power/PowerModelState.py | 2 +- src/sim/power/ThermalDomain.py | 2 +- src/sim/power/ThermalModel.py | 7 +- src/sim/probe/Probe.py | 2 +- src/systemc/Tlm.py | 5 +- src/systemc/core/SystemC.py | 5 +- src/systemc/python/systemc.py | 10 ++- src/systemc/python/tlm.py | 1 - src/systemc/tests/config.py | 7 +- src/systemc/tlm_bridge/TlmBridge.py | 6 +- tests/gem5/__init__.py | 4 +- .../configs/arm_boot_exit_run.py | 33 +++---- tests/gem5/arm_boot_tests/test_linux_boot.py | 1 - tests/gem5/asmtest/configs/riscv_asmtest.py | 18 ++-- .../configs/arm-hello-restore-checkpoint.py | 17 ++-- .../configs/arm-hello-save-checkpoint.py | 13 +-- .../configs/power-hello-restore-checkpoint.py | 16 ++-- .../configs/power-hello-save-checkpoint.py | 13 +-- .../configs/sparc-hello-restore-checkpoint.py | 16 ++-- .../configs/sparc-hello-save-checkpoint.py | 13 +-- .../configs/x86-fs-restore-checkpoint.py | 11 ++- .../configs/x86-fs-save-checkpoint.py | 7 +- .../configs/x86-hello-restore-checkpoint.py | 16 ++-- .../configs/x86-hello-save-checkpoint.py | 13 +-- .../gem5/checkpoint_tests/test-checkpoints.py | 5 +- tests/gem5/cpu_tests/run.py | 2 +- tests/gem5/fixture.py | 37 +++++--- .../gem5/fs/linux/arm/configs/arm_generic.py | 15 ++-- .../gem5/fs/linux/arm/configs/base_config.py | 17 ++-- tests/gem5/fs/linux/arm/configs/checkpoint.py | 4 +- .../linux/arm/configs/realview-minor-dual.py | 3 +- .../fs/linux/arm/configs/realview-minor.py | 3 +- .../linux/arm/configs/realview-o3-checker.py | 3 +- .../fs/linux/arm/configs/realview-o3-dual.py | 3 +- .../gem5/fs/linux/arm/configs/realview-o3.py | 3 +- .../realview-simple-atomic-checkpoint.py | 5 +- .../configs/realview-simple-atomic-dual.py | 3 +- .../arm/configs/realview-simple-atomic.py | 3 +- .../realview-simple-timing-dual-ruby.py | 3 +- .../configs/realview-simple-timing-dual.py | 3 +- .../configs/realview-simple-timing-ruby.py | 3 +- .../arm/configs/realview-simple-timing.py | 3 +- .../arm/configs/realview-switcheroo-atomic.py | 5 +- .../arm/configs/realview-switcheroo-full.py | 5 +- .../realview-switcheroo-noncaching-timing.py | 5 +- .../arm/configs/realview-switcheroo-o3.py | 5 +- .../arm/configs/realview-switcheroo-timing.py | 5 +- .../linux/arm/configs/realview64-kvm-dual.py | 8 +- .../fs/linux/arm/configs/realview64-kvm.py | 3 +- .../arm/configs/realview64-minor-dual.py | 3 +- .../fs/linux/arm/configs/realview64-minor.py | 3 +- .../arm/configs/realview64-o3-checker.py | 3 +- .../arm/configs/realview64-o3-dual-ruby.py | 3 +- .../linux/arm/configs/realview64-o3-dual.py | 3 +- .../fs/linux/arm/configs/realview64-o3.py | 3 +- .../realview64-simple-atomic-checkpoint.py | 5 +- .../configs/realview64-simple-atomic-dual.py | 3 +- .../arm/configs/realview64-simple-atomic.py | 3 +- .../realview64-simple-timing-dual-ruby.py | 3 +- .../configs/realview64-simple-timing-dual.py | 3 +- .../configs/realview64-simple-timing-ruby.py | 3 +- .../arm/configs/realview64-simple-timing.py | 3 +- .../configs/realview64-switcheroo-atomic.py | 5 +- .../arm/configs/realview64-switcheroo-full.py | 5 +- .../arm/configs/realview64-switcheroo-o3.py | 5 +- .../configs/realview64-switcheroo-timing.py | 5 +- tests/gem5/fs/linux/arm/configs/switcheroo.py | 3 +- tests/gem5/fs/linux/arm/run.py | 2 +- tests/gem5/fs/linux/arm/test.py | 3 +- .../test_gem5_library_examples.py | 5 +- .../gem5_resources/configs/download_check.py | 18 ++-- .../insttest_se/configs/simple_binary_run.py | 40 +++++---- .../configs/boot_kvm_fork_run.py | 6 +- .../configs/boot_kvm_switch_exit.py | 8 +- .../gem5/m5_util/configs/simple_binary_run.py | 41 +++++---- tests/gem5/m5_util/test_exit.py | 1 + .../m5threads_test_atomic/atomic_system.py | 8 +- tests/gem5/m5threads_test_atomic/caches.py | 13 ++- tests/gem5/memory/simple-run.py | 4 +- .../multi_isa/configs/runtime_isa_check.py | 10 ++- .../multi_isa/configs/supported_isa_check.py | 11 ++- .../configs/parsec_disk_run.py | 23 ++--- .../configs/cache_hierarchies.py | 7 +- .../configs/run_replacement_policy.py | 2 +- .../run_replacement_policy.py | 2 +- .../configs/riscv_boot_exit_run.py | 20 +++-- .../gem5/riscv_boot_tests/test_linux_boot.py | 1 - .../hello_se/configs/simple_binary_run.py | 40 +++++---- tests/gem5/se_mode/hello_se/test_hello_se.py | 4 +- tests/gem5/stats/configs/simple_binary_run.py | 40 +++++---- tests/gem5/stats/test_hdf5.py | 3 +- tests/gem5/stdlib/configs/requires_check.py | 11 ++- .../gem5/stdlib/configs/simple_binary_run.py | 40 +++++---- .../configs/simulator_exit_event_run.py | 13 ++- tests/gem5/suite.py | 17 ++-- tests/gem5/to_tick/configs/tick-exit.py | 20 ++--- tests/gem5/to_tick/configs/tick-to-max.py | 18 ++-- .../traffic_gen/configs/simple_traffic_run.py | 9 +- tests/gem5/verifier.py | 9 +- .../configs/x86_boot_exit_run.py | 29 +++---- tests/gem5/x86_boot_tests/test_linux_boot.py | 2 +- tests/main.py | 4 +- tests/pyunit/pyunit_jsonserializable_check.py | 1 + tests/pyunit/stdlib/pyunit_looppoint.py | 9 +- .../resources/pyunit_client_wrapper_checks.py | 14 +-- .../resources/pyunit_json_client_checks.py | 8 +- .../resources/pyunit_local_file_path_check.py | 5 +- .../resources/pyunit_md5_utils_check.py | 9 +- .../pyunit_obtain_resources_check.py | 17 ++-- .../pyunit_resource_specialization.py | 11 +-- .../stdlib/resources/pyunit_suite_checks.py | 11 +-- .../resources/pyunit_workload_checks.py | 19 ++-- tests/pyunit/test_run.py | 1 + tests/run.py | 6 +- util/checkpoint-tester.py | 6 +- util/checkpoint_aggregator.py | 7 +- util/cpt_upgrader.py | 10 ++- util/decode_inst_dep_trace.py | 3 +- util/decode_inst_trace.py | 3 +- util/decode_packet_trace.py | 3 +- util/encode_inst_dep_trace.py | 3 +- util/encode_packet_trace.py | 3 +- util/find_copyrights.py | 5 +- util/gem5-resources-manager/api/client.py | 10 ++- .../api/create_resources_json.py | 5 +- .../gem5-resources-manager/api/json_client.py | 8 +- .../api/mongo_client.py | 17 ++-- .../gem5_resource_cli.py | 11 +-- util/gem5-resources-manager/server.py | 38 ++++---- util/gem5-resources-manager/test/api_test.py | 13 +-- .../test/comprehensive_test.py | 11 +-- .../test/json_client_test.py | 10 +-- .../test/mongo_client_test.py | 12 ++- util/gem5-stubgen.py | 5 +- .../artifact/gem5art/artifact/__init__.py | 4 +- .../artifact/gem5art/artifact/_artifactdb.py | 18 +++- .../artifact/gem5art/artifact/artifact.py | 18 ++-- util/gem5art/artifact/setup.py | 5 +- util/gem5art/artifact/tests/test_artifact.py | 16 ++-- util/gem5art/artifact/tests/test_filedb.py | 2 +- util/gem5art/run/bin/gem5art-getruns | 5 +- util/gem5art/run/gem5art/run.py | 18 +++- util/gem5art/run/setup.py | 5 +- util/gem5art/run/tests/test_run.py | 2 +- util/gem5art/tasks/gem5art/tasks/tasks.py | 3 +- util/gem5art/tasks/setup.py | 5 +- util/gem5img.py | 18 ++-- util/gen_arm_fs_files.py | 14 +-- util/gerrit-bot/bot.py | 13 +-- util/gerrit-bot/gerrit.py | 3 +- util/git-commit-msg.py | 2 +- util/git-pre-commit.py | 15 ++-- util/maint/list_changes.py | 2 +- util/maint/show_changes_by_file.py | 5 +- util/md5.py | 6 +- util/minorview.py | 11 ++- util/minorview/blobs.py | 22 +++-- util/minorview/model.py | 15 ++-- util/minorview/view.py | 24 ++++-- util/o3-pipeview.py | 2 +- util/obtain-resource.py | 3 +- util/on-chip-network-power-area.py | 5 +- util/oprofile-top.py | 5 +- util/plot_dram/PlotPowerStates.py | 7 +- util/plot_dram/dram_lat_mem_rd_plot.py | 4 +- util/plot_dram/dram_sweep_plot.py | 6 +- util/plot_dram/lowp_dram_sweep_plot.py | 3 +- util/slicc | 5 +- util/streamline/m5stats2streamline.py | 17 ++-- util/style.py | 7 +- util/style/repo.py | 2 +- util/style/style.py | 5 +- util/style/verifiers.py | 15 ++-- .../systemc_gem5_tlm/SystemC_Example.py | 8 +- .../systemc_gem5_tlm/config.py | 2 +- .../systemc_sc_main/config.py | 7 +- .../systemc_simple_object/SystemC_Example.py | 3 +- .../systemc_simple_object/config.py | 9 +- .../systemc_within_gem5/systemc_tlm/config.py | 7 +- util/tlm/conf/tlm_elastic_slave.py | 6 +- util/tlm/conf/tlm_master.py | 4 +- .../tlm/examples/tlm_elastic_slave_with_l2.py | 6 +- util/update-copyright.py | 1 - 681 files changed, 3729 insertions(+), 2487 deletions(-) diff --git a/build_tools/cxx_config_cc.py b/build_tools/cxx_config_cc.py index f2b126b463..1a4de0339d 100644 --- a/build_tools/cxx_config_cc.py +++ b/build_tools/cxx_config_cc.py @@ -43,7 +43,6 @@ import os.path import sys import importer - from code_formatter import code_formatter parser = argparse.ArgumentParser() @@ -59,8 +58,8 @@ importer.install() module = importlib.import_module(args.modpath) sim_object = getattr(module, sim_object_name) -from m5.params import isSimObjectClass import m5.params +from m5.params import isSimObjectClass code = code_formatter() diff --git a/build_tools/cxx_config_hh.py b/build_tools/cxx_config_hh.py index 55828e37b7..dfcb02c190 100644 --- a/build_tools/cxx_config_hh.py +++ b/build_tools/cxx_config_hh.py @@ -42,7 +42,6 @@ import os.path import sys import importer - from code_formatter import code_formatter parser = argparse.ArgumentParser() diff --git a/build_tools/enum_cc.py b/build_tools/enum_cc.py index 504a1b9883..7cfd3990b9 100644 --- a/build_tools/enum_cc.py +++ b/build_tools/enum_cc.py @@ -42,7 +42,6 @@ import os.path import sys import importer - from code_formatter import code_formatter parser = argparse.ArgumentParser() diff --git a/build_tools/enum_hh.py b/build_tools/enum_hh.py index f91ffef437..dab47bfa19 100644 --- a/build_tools/enum_hh.py +++ b/build_tools/enum_hh.py @@ -42,7 +42,6 @@ import os.path import sys import importer - from code_formatter import code_formatter parser = argparse.ArgumentParser() diff --git a/build_tools/sim_object_param_struct_cc.py b/build_tools/sim_object_param_struct_cc.py index 2ef90c7420..5aca1b8711 100644 --- a/build_tools/sim_object_param_struct_cc.py +++ b/build_tools/sim_object_param_struct_cc.py @@ -42,7 +42,6 @@ import os.path import sys import importer - from code_formatter import code_formatter parser = argparse.ArgumentParser() diff --git a/build_tools/sim_object_param_struct_hh.py b/build_tools/sim_object_param_struct_hh.py index 45971669f8..c82c25921c 100644 --- a/build_tools/sim_object_param_struct_hh.py +++ b/build_tools/sim_object_param_struct_hh.py @@ -42,7 +42,6 @@ import os.path import sys import importer - from code_formatter import code_formatter parser = argparse.ArgumentParser() diff --git a/configs/common/Benchmarks.py b/configs/common/Benchmarks.py index c90e78ed61..9983a8ea84 100644 --- a/configs/common/Benchmarks.py +++ b/configs/common/Benchmarks.py @@ -24,8 +24,14 @@ # (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 common.SysPaths import script, disk, binary from os import environ as env + +from common.SysPaths import ( + binary, + disk, + script, +) + from m5.defines import buildEnv diff --git a/configs/common/CacheConfig.py b/configs/common/CacheConfig.py index 7a191570e3..723978f05c 100644 --- a/configs/common/CacheConfig.py +++ b/configs/common/CacheConfig.py @@ -40,14 +40,15 @@ # Configure the M5 cache hierarchy config in one place # +from common import ObjectList +from common.Caches import * + import m5 from m5.objects import * + from gem5.isas import ISA from gem5.runtime import get_runtime_isa -from common.Caches import * -from common import ObjectList - def _get_hwp(hwp_option): if hwp_option == None: diff --git a/configs/common/Caches.py b/configs/common/Caches.py index e25d16ca1e..ac8dc17f7d 100644 --- a/configs/common/Caches.py +++ b/configs/common/Caches.py @@ -39,6 +39,7 @@ from m5.defines import buildEnv from m5.objects import * + from gem5.isas import ISA from gem5.runtime import get_runtime_isa diff --git a/configs/common/CpuConfig.py b/configs/common/CpuConfig.py index 1672d43343..0d132b83b9 100644 --- a/configs/common/CpuConfig.py +++ b/configs/common/CpuConfig.py @@ -33,8 +33,8 @@ # (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 import fatal import m5.objects +from m5 import fatal def config_etrace(cpu_cls, cpu_list, options): diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index 5da951c93b..469101a82e 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -38,12 +38,13 @@ # (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 common import ObjectList +from common.Benchmarks import * + import m5 import m5.defines from m5.objects import * from m5.util import * -from common.Benchmarks import * -from common import ObjectList # Populate to reflect supported os types per target ISA os_types = set() diff --git a/configs/common/FileSystemConfig.py b/configs/common/FileSystemConfig.py index 9c6647c861..91d427a259 100644 --- a/configs/common/FileSystemConfig.py +++ b/configs/common/FileSystemConfig.py @@ -36,18 +36,31 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import getpass +import operator +import os +import platform +from functools import reduce +from os import ( + access, + getpid, + listdir, + makedirs, + mkdir, + stat, +) +from os.path import isdir +from os.path import join as joinpath +from pwd import getpwuid +from shutil import ( + copyfile, + rmtree, +) + import m5 from m5.objects import * from m5.util.convert import * -from functools import reduce -import operator, os, platform, getpass -from os import mkdir, makedirs, getpid, listdir, stat, access -from pwd import getpwuid -from os.path import join as joinpath -from os.path import isdir -from shutil import rmtree, copyfile - def hex_mask(terms): dec_mask = reduce(operator.or_, [2**i for i in terms], 0) diff --git a/configs/common/MemConfig.py b/configs/common/MemConfig.py index 02af2b8449..717ffa5fae 100644 --- a/configs/common/MemConfig.py +++ b/configs/common/MemConfig.py @@ -33,9 +33,12 @@ # (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 common import ( + HMC, + ObjectList, +) + import m5.objects -from common import ObjectList -from common import HMC def create_mem_intf(intf, r, i, intlv_bits, intlv_size, xor_low_bit): @@ -174,6 +177,7 @@ def config_mem(options, system): nbr_mem_ctrls = opt_mem_channels import math + from m5.util import fatal intlv_bits = int(math.log(nbr_mem_ctrls, 2)) diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index 7b926efaf5..4a893e4d14 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -34,13 +34,15 @@ # (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.runtime import get_supported_isas -import m5.objects -import m5.internal.params import inspect import sys from textwrap import TextWrapper +import m5.internal.params +import m5.objects + +from gem5.runtime import get_supported_isas + class ObjectList: """Creates a list of objects that are sub-classes of a given class.""" diff --git a/configs/common/Options.py b/configs/common/Options.py index 8344d9fd44..cd658e33c1 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -38,13 +38,13 @@ import argparse +from common import ObjectList +from common.Benchmarks import * + import m5 from m5.defines import buildEnv from m5.objects import * -from common.Benchmarks import * -from common import ObjectList - vio_9p_help = """\ Enable the Virtio 9P device and set the path to share. The default 9p path is m5ou5/9p/share, and it can be changed by setting VirtIO9p.root with --param. A diff --git a/configs/common/SimpleOpts.py b/configs/common/SimpleOpts.py index da78ec977d..7faf092bcd 100644 --- a/configs/common/SimpleOpts.py +++ b/configs/common/SimpleOpts.py @@ -34,12 +34,12 @@ from each class instead of only from the configuration script. # Module-level variable to track if we've called the parse_args function yet called_parse_args = False -# For fatal -import m5 - # import the argument parser from argparse import ArgumentParser +# For fatal +import m5 + # add the args we want to be able to control from the command line parser = ArgumentParser() diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index a2a04c3610..34825fb415 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -41,8 +41,10 @@ import sys from os import getcwd from os.path import join as joinpath -from common import CpuConfig -from common import ObjectList +from common import ( + CpuConfig, + ObjectList, +) import m5 from m5.defines import buildEnv @@ -128,9 +130,12 @@ def findCptDir(options, cptdir, testsys): the appropriate directory. """ - from os.path import isdir, exists - from os import listdir import re + from os import listdir + from os.path import ( + exists, + isdir, + ) if not isdir(cptdir): fatal("checkpoint dir %s does not exist!", cptdir) diff --git a/configs/common/SysPaths.py b/configs/common/SysPaths.py index 382740e110..f8bd6883fb 100644 --- a/configs/common/SysPaths.py +++ b/configs/common/SysPaths.py @@ -24,7 +24,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os, sys +import os +import sys config_path = os.path.dirname(os.path.abspath(__file__)) config_root = os.path.dirname(config_path) diff --git a/configs/common/cores/arm/O3_ARM_Etrace.py b/configs/common/cores/arm/O3_ARM_Etrace.py index 3315664cec..b925a86e9d 100644 --- a/configs/common/cores/arm/O3_ARM_Etrace.py +++ b/configs/common/cores/arm/O3_ARM_Etrace.py @@ -34,6 +34,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects import * + from .O3_ARM_v7a import O3_ARM_v7a_3 diff --git a/configs/common/cores/arm/__init__.py b/configs/common/cores/arm/__init__.py index 135b75f802..6c1c7e869f 100644 --- a/configs/common/cores/arm/__init__.py +++ b/configs/common/cores/arm/__init__.py @@ -33,8 +33,8 @@ # (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 pkgutil import iter_modules from importlib import import_module +from pkgutil import iter_modules _cpu_modules = [name for _, name, ispkg in iter_modules(__path__) if not ispkg] diff --git a/configs/common/cpu2000.py b/configs/common/cpu2000.py index b928152939..40dab5c820 100644 --- a/configs/common/cpu2000.py +++ b/configs/common/cpu2000.py @@ -26,8 +26,15 @@ import os import sys -from os.path import basename, exists, join as joinpath, normpath -from os.path import isdir, isfile, islink +from os.path import ( + basename, + exists, + isdir, + isfile, + islink, +) +from os.path import join as joinpath +from os.path import normpath spec_dist = os.environ.get("M5_CPU2000", "/dist/m5/cpu2000") diff --git a/configs/deprecated/example/fs.py b/configs/deprecated/example/fs.py index ce6eea7623..52354dc3a2 100644 --- a/configs/deprecated/example/fs.py +++ b/configs/deprecated/example/fs.py @@ -45,25 +45,31 @@ import sys import m5 from m5.defines import buildEnv from m5.objects import * -from m5.util import addToPath, fatal, warn +from m5.util import ( + addToPath, + fatal, + warn, +) from m5.util.fdthelper import * + from gem5.isas import ISA from gem5.runtime import get_runtime_isa addToPath("../../") -from ruby import Ruby - +from common import ( + CacheConfig, + CpuConfig, + MemConfig, + ObjectList, + Options, + Simulation, +) +from common.Benchmarks import * +from common.Caches import * from common.FSConfig import * from common.SysPaths import * -from common.Benchmarks import * -from common import Simulation -from common import CacheConfig -from common import CpuConfig -from common import MemConfig -from common import ObjectList -from common.Caches import * -from common import Options +from ruby import Ruby def cmd_line_template(): diff --git a/configs/deprecated/example/se.py b/configs/deprecated/example/se.py index 6e0aa5b919..ad610b05d3 100644 --- a/configs/deprecated/example/se.py +++ b/configs/deprecated/example/se.py @@ -41,30 +41,36 @@ # "m5 test.py" import argparse -import sys import os +import sys import m5 from m5.defines import buildEnv from m5.objects import * from m5.params import NULL -from m5.util import addToPath, fatal, warn +from m5.util import ( + addToPath, + fatal, + warn, +) + from gem5.isas import ISA from gem5.runtime import get_runtime_isa addToPath("../../") -from ruby import Ruby - -from common import Options -from common import Simulation -from common import CacheConfig -from common import CpuConfig -from common import ObjectList -from common import MemConfig -from common.FileSystemConfig import config_filesystem +from common import ( + CacheConfig, + CpuConfig, + MemConfig, + ObjectList, + Options, + Simulation, +) from common.Caches import * from common.cpu2000 import * +from common.FileSystemConfig import config_filesystem +from ruby import Ruby def get_processes(args): diff --git a/configs/dram/lat_mem_rd.py b/configs/dram/lat_mem_rd.py index 639a93dbf6..b632e72b76 100644 --- a/configs/dram/lat_mem_rd.py +++ b/configs/dram/lat_mem_rd.py @@ -33,18 +33,20 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import gzip import argparse +import gzip import os import m5 from m5.objects import * -from m5.util import addToPath from m5.stats import periodicStatDump +from m5.util import addToPath addToPath("../") -from common import ObjectList -from common import MemConfig +from common import ( + MemConfig, + ObjectList, +) addToPath("../../util") import protolib diff --git a/configs/dram/low_power_sweep.py b/configs/dram/low_power_sweep.py index 7f8591b692..5ef91d0618 100644 --- a/configs/dram/low_power_sweep.py +++ b/configs/dram/low_power_sweep.py @@ -37,13 +37,15 @@ import argparse import m5 from m5.objects import * -from m5.util import addToPath from m5.stats import periodicStatDump +from m5.util import addToPath addToPath("../") -from common import ObjectList -from common import MemConfig +from common import ( + MemConfig, + ObjectList, +) # This script aims at triggering low power state transitions in the DRAM # controller. The traffic generator is used in DRAM mode and traffic diff --git a/configs/dram/sweep.py b/configs/dram/sweep.py index ca7b70d4ed..95190a8ab8 100644 --- a/configs/dram/sweep.py +++ b/configs/dram/sweep.py @@ -33,18 +33,20 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import math import argparse +import math import m5 from m5.objects import * -from m5.util import addToPath from m5.stats import periodicStatDump +from m5.util import addToPath addToPath("../") -from common import ObjectList -from common import MemConfig +from common import ( + MemConfig, + ObjectList, +) # this script is helpful to sweep the efficiency of a specific memory # controller configuration, by varying the number of banks accessed, diff --git a/configs/example/apu_se.py b/configs/example/apu_se.py index b20779fcdb..219f8f9f29 100644 --- a/configs/example/apu_se.py +++ b/configs/example/apu_se.py @@ -27,28 +27,32 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import argparse, os, re, getpass -import math +import argparse +import getpass import glob import inspect +import math +import os +import re import m5 from m5.objects import * from m5.util import addToPath + from gem5.isas import ISA from gem5.runtime import get_runtime_isa addToPath("../") -from ruby import Ruby - -from common import Options -from common import Simulation -from common import GPUTLBOptions, GPUTLBConfig - import hsaTopology -from common import FileSystemConfig - +from common import ( + FileSystemConfig, + GPUTLBConfig, + GPUTLBOptions, + Options, + Simulation, +) +from ruby import Ruby # Adding script options parser = argparse.ArgumentParser() diff --git a/configs/example/arm/baremetal.py b/configs/example/arm/baremetal.py index fae85fa04b..a986a2c44d 100644 --- a/configs/example/arm/baremetal.py +++ b/configs/example/arm/baremetal.py @@ -39,24 +39,29 @@ Research Starter Kit on System Modeling. More information can be found at: http://www.arm.com/ResearchEnablement/SystemModeling """ +import argparse import os + import m5 -from m5.util import addToPath from m5.objects import * from m5.options import * +from m5.util import addToPath + from gem5.simulate.exit_event import ExitEvent -import argparse m5.util.addToPath("../..") -from common import SysPaths -from common import MemConfig -from common import ObjectList -from common.cores.arm import HPI -from common.cores.arm import O3_ARM_v7a - import devices import workloads +from common import ( + MemConfig, + ObjectList, + SysPaths, +) +from common.cores.arm import ( + HPI, + O3_ARM_v7a, +) # Pre-defined CPU configurations. Each tuple must be ordered as : (cpu_class, # l1_icache_class, l1_dcache_class, walk_cache_class, l2_Cache_class). Any of diff --git a/configs/example/arm/devices.py b/configs/example/arm/devices.py index 7d92f4ee36..dc62525204 100644 --- a/configs/example/arm/devices.py +++ b/configs/example/arm/devices.py @@ -39,8 +39,8 @@ import m5 from m5.objects import * m5.util.addToPath("../../") -from common.Caches import * from common import ObjectList +from common.Caches import * have_kvm = "ArmV8KvmCPU" in ObjectList.cpu_list.get_names() have_fastmodel = "FastModelCortexA76" in ObjectList.cpu_list.get_names() diff --git a/configs/example/arm/dist_bigLITTLE.py b/configs/example/arm/dist_bigLITTLE.py index 2884a5efd5..f5a816c12a 100644 --- a/configs/example/arm/dist_bigLITTLE.py +++ b/configs/example/arm/dist_bigLITTLE.py @@ -39,11 +39,11 @@ import argparse import os +import fs_bigLITTLE as bL + import m5 from m5.objects import * -import fs_bigLITTLE as bL - m5.util.addToPath("../../dist") import sw diff --git a/configs/example/arm/etrace_se.py b/configs/example/arm/etrace_se.py index 8fa971ff84..1b06ba3fdf 100644 --- a/configs/example/arm/etrace_se.py +++ b/configs/example/arm/etrace_se.py @@ -34,18 +34,18 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os -import m5 -from m5.util import addToPath -from m5.objects import * import argparse +import os import shlex +import m5 +from m5.objects import * +from m5.util import addToPath + m5.util.addToPath("../..") -from common import ObjectList - import devices +from common import ObjectList def get_processes(cmd): diff --git a/configs/example/arm/fs_bigLITTLE.py b/configs/example/arm/fs_bigLITTLE.py index 401eb0c9e7..17e9e6dd28 100644 --- a/configs/example/arm/fs_bigLITTLE.py +++ b/configs/example/arm/fs_bigLITTLE.py @@ -39,21 +39,29 @@ import argparse import os import sys + import m5 import m5.util from m5.objects import * m5.util.addToPath("../../") -from common import FSConfig -from common import SysPaths -from common import ObjectList -from common import Options -from common.cores.arm import ex5_big, ex5_LITTLE - import devices -from devices import AtomicCluster, KvmCluster, FastmodelCluster - +from common import ( + FSConfig, + ObjectList, + Options, + SysPaths, +) +from common.cores.arm import ( + ex5_big, + ex5_LITTLE, +) +from devices import ( + AtomicCluster, + FastmodelCluster, + KvmCluster, +) default_disk = "aarch64-ubuntu-trusty-headless.img" @@ -410,7 +418,8 @@ def build(options): system.generateDtb(system.workload.dtb_filename) if devices.have_fastmodel and issubclass(big_model, FastmodelCluster): - from m5 import arm_fast_model as fm, systemc as sc + from m5 import arm_fast_model as fm + from m5 import systemc as sc # setup FastModels for simulation fm.setup_simulation("cortexa76") diff --git a/configs/example/arm/fs_power.py b/configs/example/arm/fs_power.py index 0442682411..83e43eef66 100644 --- a/configs/example/arm/fs_power.py +++ b/configs/example/arm/fs_power.py @@ -39,11 +39,14 @@ import argparse import os -import m5 -from m5.objects import MathExprPowerModel, PowerModel - import fs_bigLITTLE as bL +import m5 +from m5.objects import ( + MathExprPowerModel, + PowerModel, +) + class CpuPowerOn(MathExprPowerModel): def __init__(self, cpu_path, **kwargs): diff --git a/configs/example/arm/ruby_fs.py b/configs/example/arm/ruby_fs.py index 67a8a6e0b3..a0979c1ced 100644 --- a/configs/example/arm/ruby_fs.py +++ b/configs/example/arm/ruby_fs.py @@ -33,24 +33,28 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse import os + import m5 -from m5.util import addToPath from m5.objects import * from m5.options import * -import argparse +from m5.util import addToPath m5.util.addToPath("../..") -from common import MemConfig -from common import ObjectList -from common import Options -from common import SysPaths -from common.cores.arm import O3_ARM_v7a, HPI -from ruby import Ruby - import devices - +from common import ( + MemConfig, + ObjectList, + Options, + SysPaths, +) +from common.cores.arm import ( + HPI, + O3_ARM_v7a, +) +from ruby import Ruby default_kernel = "vmlinux.arm64" default_disk = "linaro-minimal-aarch64.img" diff --git a/configs/example/arm/starter_fs.py b/configs/example/arm/starter_fs.py index 07280bd204..44f72a6291 100644 --- a/configs/example/arm/starter_fs.py +++ b/configs/example/arm/starter_fs.py @@ -38,22 +38,26 @@ Research Starter Kit on System Modeling. More information can be found at: http://www.arm.com/ResearchEnablement/SystemModeling """ +import argparse import os + import m5 -from m5.util import addToPath from m5.objects import * from m5.options import * -import argparse +from m5.util import addToPath m5.util.addToPath("../..") -from common import SysPaths -from common import ObjectList -from common import MemConfig -from common.cores.arm import O3_ARM_v7a, HPI - import devices - +from common import ( + MemConfig, + ObjectList, + SysPaths, +) +from common.cores.arm import ( + HPI, + O3_ARM_v7a, +) default_kernel = "vmlinux.arm64" default_disk = "linaro-minimal-aarch64.img" diff --git a/configs/example/arm/starter_se.py b/configs/example/arm/starter_se.py index 9834487155..33cf7b2f40 100644 --- a/configs/example/arm/starter_se.py +++ b/configs/example/arm/starter_se.py @@ -38,21 +38,22 @@ Research Starter Kit on System Modeling. More information can be found at: http://www.arm.com/ResearchEnablement/SystemModeling """ -import os -import m5 -from m5.util import addToPath -from m5.objects import * import argparse +import os import shlex +import m5 +from m5.objects import * +from m5.util import addToPath + m5.util.addToPath("../..") -from common import ObjectList -from common import MemConfig -from common.cores.arm import HPI - import devices - +from common import ( + MemConfig, + ObjectList, +) +from common.cores.arm import HPI # Pre-defined CPU configurations. Each tuple must be ordered as : (cpu_class, # l1_icache_class, l1_dcache_class, walk_cache_class, l2_Cache_class). Any of diff --git a/configs/example/arm/workloads.py b/configs/example/arm/workloads.py index d7aea2ca0a..d84657712e 100644 --- a/configs/example/arm/workloads.py +++ b/configs/example/arm/workloads.py @@ -35,13 +35,17 @@ # import inspect + +from common.ObjectList import ObjectList +from common.SysPaths import ( + binary, + disk, +) + import m5 from m5.objects import * from m5.options import * -from common.ObjectList import ObjectList -from common.SysPaths import binary, disk - class ArmBaremetal(ArmFsWorkload): """Baremetal workload""" diff --git a/configs/example/dramsys.py b/configs/example/dramsys.py index 0e8bebfb75..191e1937f7 100755 --- a/configs/example/dramsys.py +++ b/configs/example/dramsys.py @@ -25,7 +25,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 - from m5.objects import * traffic_gen = PyTrafficGen() diff --git a/configs/example/etrace_replay.py b/configs/example/etrace_replay.py index 184934fab9..7df1333f2b 100644 --- a/configs/example/etrace_replay.py +++ b/configs/example/etrace_replay.py @@ -37,13 +37,18 @@ import argparse -from m5.util import addToPath, fatal +from m5.util import ( + addToPath, + fatal, +) addToPath("../") -from common import Options -from common import Simulation -from common import MemConfig +from common import ( + MemConfig, + Options, + Simulation, +) from common.Caches import * diff --git a/configs/example/garnet_synth_traffic.py b/configs/example/garnet_synth_traffic.py index 1da82e11b8..8bbacd7a8e 100644 --- a/configs/example/garnet_synth_traffic.py +++ b/configs/example/garnet_synth_traffic.py @@ -26,11 +26,14 @@ # # Author: Tushar Krishna +import argparse +import os +import sys + import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -import os, argparse, sys addToPath("../") diff --git a/configs/example/gem5_library/arm-hello.py b/configs/example/gem5_library/arm-hello.py index 721d71c2cb..39583463e7 100644 --- a/configs/example/gem5_library/arm-hello.py +++ b/configs/example/gem5_library/arm-hello.py @@ -41,15 +41,15 @@ scons build/ARM/gem5.opt ``` """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This check ensures the gem5 binary is compiled to the ARM ISA target. If not, # an exception will be thrown. diff --git a/configs/example/gem5_library/arm-ubuntu-run.py b/configs/example/gem5_library/arm-ubuntu-run.py index 78160c9976..734fb9ee1b 100644 --- a/configs/example/gem5_library/arm-ubuntu-run.py +++ b/configs/example/gem5_library/arm-ubuntu-run.py @@ -40,18 +40,20 @@ scons build/ARM/gem5.opt -j """ -from gem5.isas import ISA -from m5.objects import ArmDefaultRelease -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.simulate.simulator import Simulator -from m5.objects import VExpress_GEM5_Foundation +from m5.objects import ( + ArmDefaultRelease, + VExpress_GEM5_Foundation, +) + from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.arm_board import ArmBoard from gem5.components.memory import DualChannelDDR4_2400 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor - +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This runs a check to ensure the gem5 binary is compiled for ARM and the # protocol is CHI. diff --git a/configs/example/gem5_library/caches/octopi-cache-example.py b/configs/example/gem5_library/caches/octopi-cache-example.py index 4a4926a174..fa19773167 100644 --- a/configs/example/gem5_library/caches/octopi-cache-example.py +++ b/configs/example/gem5_library/caches/octopi-cache-example.py @@ -38,20 +38,23 @@ scons build/ARM_MESI_Three_Level/gem5.opt -j `nproc` """ -from m5.objects import ArmDefaultRelease, VExpress_GEM5_Foundation +from m5.objects import ( + ArmDefaultRelease, + VExpress_GEM5_Foundation, +) -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.arm_board import ArmBoard -from gem5.components.memory import DualChannelDDR4_2400 -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.cpu_types import CPUTypes from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.octopi import ( OctopiCache, ) +from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol -from gem5.simulate.simulator import Simulator from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires num_ccds = 1 # CCDs num_cores_per_ccd = 8 # 8 cores/CCD diff --git a/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py b/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py index eed76e2448..aa78de5647 100644 --- a/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/riscv-hello-restore-checkpoint.py @@ -46,15 +46,15 @@ scons build/RISCV/gem5.opt ``` """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This check ensures the gem5 binary is compiled to the RISCV ISA target. # If not, an exception will be thrown. diff --git a/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py b/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py index 234153a57f..b024a3a44a 100644 --- a/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py @@ -44,15 +44,16 @@ scons build/RISCV/gem5.opt """ import argparse -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.cpu_types import CPUTypes + from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser() diff --git a/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py b/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py index 5787bf4bfc..4649f4a07e 100644 --- a/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py +++ b/configs/example/gem5_library/checkpoints/simpoints-se-checkpoint.py @@ -48,22 +48,23 @@ scons build/X86/gem5.opt """ import argparse +from pathlib import Path +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory.single_channel import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import ( + SimpointResource, + obtain_resource, +) +from gem5.resources.workload import Workload from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.exit_event_generators import save_checkpoint_generator from gem5.simulate.simulator import Simulator from gem5.utils.requires import requires -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.memory.single_channel import SingleChannelDDR3_1600 -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.cpu_types import CPUTypes -from gem5.isas import ISA -from gem5.resources.workload import Workload -from gem5.resources.resource import obtain_resource, SimpointResource -from pathlib import Path -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.simulate.exit_event_generators import ( - save_checkpoint_generator, -) requires(isa_required=ISA.X86) diff --git a/configs/example/gem5_library/checkpoints/simpoints-se-restore.py b/configs/example/gem5_library/checkpoints/simpoints-se-restore.py index d063c143a7..284289be6f 100644 --- a/configs/example/gem5_library/checkpoints/simpoints-se-restore.py +++ b/configs/example/gem5_library/checkpoints/simpoints-se-restore.py @@ -52,23 +52,29 @@ scons build/X86/gem5.opt """ -from gem5.simulate.exit_event import ExitEvent -from gem5.simulate.simulator import Simulator -from gem5.utils.requires import requires +from pathlib import Path + +from m5.stats import ( + dump, + reset, +) + +from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) -from gem5.components.boards.simple_board import SimpleBoard from gem5.components.memory import DualChannelDDR4_2400 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.resources.resource import SimpointResource, obtain_resource +from gem5.resources.resource import ( + SimpointResource, + obtain_resource, +) from gem5.resources.workload import Workload -from gem5.resources.resource import SimpointResource - -from pathlib import Path -from m5.stats import reset, dump +from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.X86) diff --git a/configs/example/gem5_library/dramsys/arm-hello-dramsys.py b/configs/example/gem5_library/dramsys/arm-hello-dramsys.py index ae2b4bb5b6..2561f98fae 100644 --- a/configs/example/gem5_library/dramsys/arm-hello-dramsys.py +++ b/configs/example/gem5_library/dramsys/arm-hello-dramsys.py @@ -33,17 +33,17 @@ DRRAMSys simulator. Please consult 'ext/dramsys/README' on how to compile correctly. If this is not done correctly this script will run with error. """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.memory import DRAMSysDDR3_1600 -from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_cache_hierarchy import ( PrivateL1CacheHierarchy, ) +from gem5.components.memory import DRAMSysDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This check ensures the gem5 binary is compiled to the ARM ISA target. If not, # an exception will be thrown. diff --git a/configs/example/gem5_library/dramsys/dramsys-traffic.py b/configs/example/gem5_library/dramsys/dramsys-traffic.py index 2f9b768696..cc10dd0657 100644 --- a/configs/example/gem5_library/dramsys/dramsys-traffic.py +++ b/configs/example/gem5_library/dramsys/dramsys-traffic.py @@ -32,8 +32,8 @@ DRRAMSys simulator. Please consult 'ext/dramsys/README' on how to compile correctly. If this is not done correctly this script will run with error. """ -from gem5.components.memory.dramsys import DRAMSysMem from gem5.components.boards.test_board import TestBoard +from gem5.components.memory.dramsys import DRAMSysMem from gem5.components.processors.linear_generator import LinearGenerator from gem5.simulate.simulator import Simulator diff --git a/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py b/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py index 4a15da55ff..b31353c681 100644 --- a/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py +++ b/configs/example/gem5_library/looppoints/create-looppoint-checkpoints.py @@ -47,22 +47,22 @@ scons build/X86/gem5.opt ``` """ -from gem5.simulate.exit_event import ExitEvent -from gem5.simulate.simulator import Simulator -from gem5.utils.requires import requires -from gem5.components.cachehierarchies.classic.no_cache import NoCache +import argparse +from pathlib import Path + from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.memory.single_channel import SingleChannelDDR3_1600 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA from gem5.resources.resource import obtain_resource -from pathlib import Path +from gem5.simulate.exit_event import ExitEvent from gem5.simulate.exit_event_generators import ( looppoint_save_checkpoint_generator, ) - -import argparse +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.X86) diff --git a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py index 4ca6ad495e..781b2f7281 100644 --- a/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py +++ b/configs/example/gem5_library/looppoints/restore-looppoint-checkpoint.py @@ -42,19 +42,23 @@ Usage """ import argparse -from gem5.simulate.exit_event import ExitEvent -from gem5.simulate.simulator import Simulator -from gem5.utils.requires import requires +from m5.stats import ( + dump, + reset, +) + +from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) -from gem5.components.boards.simple_board import SimpleBoard from gem5.components.memory import DualChannelDDR4_2400 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA from gem5.resources.resource import obtain_resource -from m5.stats import reset, dump +from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.X86) diff --git a/configs/example/gem5_library/memory_traffic.py b/configs/example/gem5_library/memory_traffic.py index d6772d1e77..4c653114fb 100644 --- a/configs/example/gem5_library/memory_traffic.py +++ b/configs/example/gem5_library/memory_traffic.py @@ -36,14 +36,12 @@ and this channel is driven with 32GiB/s of traffic for 1ms. import argparse from m5.objects import MemorySize -from gem5.components.boards.test_board import TestBoard +from gem5.components.boards.test_board import TestBoard +from gem5.components.memory.dram_interfaces.hbm import HBM_2000_4H_1x64 +from gem5.components.memory.hbm import HighBandwidthMemory from gem5.components.processors.linear_generator import LinearGenerator from gem5.components.processors.random_generator import RandomGenerator - -from gem5.components.memory.hbm import HighBandwidthMemory -from gem5.components.memory.dram_interfaces.hbm import HBM_2000_4H_1x64 - from gem5.simulate.simulator import Simulator diff --git a/configs/example/gem5_library/power-hello.py b/configs/example/gem5_library/power-hello.py index 59020643e0..8a73b6a201 100644 --- a/configs/example/gem5_library/power-hello.py +++ b/configs/example/gem5_library/power-hello.py @@ -41,15 +41,15 @@ scons build/POWER/gem5.opt ``` """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.memory import SingleChannelDDR4_2400 -from gem5.components.processors.cpu_types import CPUTypes from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This check ensures the gem5 binary is compiled to the POWER ISA target. # If not, an exception will be thrown. diff --git a/configs/example/gem5_library/riscv-fs.py b/configs/example/gem5_library/riscv-fs.py index 8a0de6c688..914d9a7023 100644 --- a/configs/example/gem5_library/riscv-fs.py +++ b/configs/example/gem5_library/riscv-fs.py @@ -40,16 +40,16 @@ Characteristics """ from gem5.components.boards.riscv_board import RiscvBoard -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) +from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.utils.requires import requires from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # Run a check to ensure the right version of gem5 is being used. requires(isa_required=ISA.RISCV) diff --git a/configs/example/gem5_library/riscv-ubuntu-run.py b/configs/example/gem5_library/riscv-ubuntu-run.py index 9b172fd501..1d31b055de 100644 --- a/configs/example/gem5_library/riscv-ubuntu-run.py +++ b/configs/example/gem5_library/riscv-ubuntu-run.py @@ -43,14 +43,14 @@ scons build/RISCV/gem5.opt import m5 from m5.objects import Root -from gem5.utils.requires import requires from gem5.components.boards.riscv_board import RiscvBoard from gem5.components.memory import DualChannelDDR4_2400 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.simulate.simulator import Simulator from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This runs a check to ensure the gem5 binary is compiled for RISCV. diff --git a/configs/example/gem5_library/riscvmatched-fs.py b/configs/example/gem5_library/riscvmatched-fs.py index 29ec76e16b..ad045cac3d 100644 --- a/configs/example/gem5_library/riscvmatched-fs.py +++ b/configs/example/gem5_library/riscvmatched-fs.py @@ -38,14 +38,14 @@ scons build/RISCV/gem5.opt ``` """ -from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard -from gem5.utils.requires import requires -from gem5.isas import ISA -from gem5.simulate.simulator import Simulator -from gem5.resources.resource import obtain_resource - import argparse +from gem5.isas import ISA +from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires + requires(isa_required=ISA.RISCV) parser = argparse.ArgumentParser( diff --git a/configs/example/gem5_library/riscvmatched-hello.py b/configs/example/gem5_library/riscvmatched-hello.py index a11ec39159..3ea13b4851 100644 --- a/configs/example/gem5_library/riscvmatched-hello.py +++ b/configs/example/gem5_library/riscvmatched-hello.py @@ -37,10 +37,10 @@ scons build/RISCV/gem5.opt ``` """ +from gem5.isas import ISA +from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator -from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard -from gem5.isas import ISA from gem5.utils.requires import requires requires(isa_required=ISA.RISCV) diff --git a/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py b/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py index 7e08355e31..2024bdddf0 100644 --- a/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py +++ b/configs/example/gem5_library/riscvmatched-microbenchmark-suite.py @@ -33,10 +33,10 @@ The print statements in the script are for illustrative purposes only, and are not required to run the script. """ +from gem5.isas import ISA +from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator -from gem5.prebuilt.riscvmatched.riscvmatched_board import RISCVMatchedBoard -from gem5.isas import ISA from gem5.utils.requires import requires requires(isa_required=ISA.RISCV) diff --git a/configs/example/gem5_library/x86-gapbs-benchmarks.py b/configs/example/gem5_library/x86-gapbs-benchmarks.py index c20d2ea4cc..d425d797a6 100644 --- a/configs/example/gem5_library/x86-gapbs-benchmarks.py +++ b/configs/example/gem5_library/x86-gapbs-benchmarks.py @@ -48,24 +48,24 @@ scons build/X86/gem5.opt """ import argparse -import time import sys +import time import m5 from m5.objects import Root -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol from gem5.resources.resource import obtain_resource -from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires( isa_required=ISA.X86, diff --git a/configs/example/gem5_library/x86-npb-benchmarks.py b/configs/example/gem5_library/x86-npb-benchmarks.py index bcc48382ac..c78c6102aa 100644 --- a/configs/example/gem5_library/x86-npb-benchmarks.py +++ b/configs/example/gem5_library/x86-npb-benchmarks.py @@ -50,22 +50,23 @@ import time import m5 from m5.objects import Root +from m5.stats.gem5stats import get_simstat +from m5.util import warn -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol from gem5.resources.resource import obtain_resource -from gem5.simulate.simulator import Simulator -from gem5.simulate.simulator import ExitEvent - -from m5.stats.gem5stats import get_simstat -from m5.util import warn +from gem5.simulate.simulator import ( + ExitEvent, + Simulator, +) +from gem5.utils.requires import requires requires( isa_required=ISA.X86, diff --git a/configs/example/gem5_library/x86-parsec-benchmarks.py b/configs/example/gem5_library/x86-parsec-benchmarks.py index 5e855b773f..71cfd4a9ef 100644 --- a/configs/example/gem5_library/x86-parsec-benchmarks.py +++ b/configs/example/gem5_library/x86-parsec-benchmarks.py @@ -50,18 +50,18 @@ import time import m5 from m5.objects import Root -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol from gem5.resources.resource import obtain_resource -from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # We check for the required gem5 build. diff --git a/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py b/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py index 63a7b6b236..18bac9671d 100644 --- a/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py +++ b/configs/example/gem5_library/x86-spec-cpu2006-benchmarks.py @@ -49,29 +49,33 @@ scons build/X86/gem5.opt """ import argparse -import time -import os import json +import os +import time import m5 from m5.objects import Root +from m5.stats.gem5stats import get_simstat +from m5.util import ( + fatal, + warn, +) -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import Resource, DiskImageResource -from gem5.simulate.simulator import Simulator +from gem5.resources.resource import ( + DiskImageResource, + Resource, +) from gem5.simulate.exit_event import ExitEvent - -from m5.stats.gem5stats import get_simstat -from m5.util import warn -from m5.util import fatal +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # We check for the required gem5 build. diff --git a/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py b/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py index 348c26f1ff..96c4a37c9e 100644 --- a/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py +++ b/configs/example/gem5_library/x86-spec-cpu2017-benchmarks.py @@ -47,29 +47,33 @@ scons build/X86/gem5.opt """ import argparse -import time -import os import json +import os +import time import m5 from m5.objects import Root +from m5.stats.gem5stats import get_simstat +from m5.util import ( + fatal, + warn, +) -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.memory import DualChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol -from gem5.resources.resource import obtain_resource, DiskImageResource -from gem5.simulate.simulator import Simulator +from gem5.resources.resource import ( + DiskImageResource, + obtain_resource, +) from gem5.simulate.exit_event import ExitEvent - -from m5.stats.gem5stats import get_simstat -from m5.util import warn -from m5.util import fatal +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # We check for the required gem5 build. diff --git a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py index 233efd92b8..632b409b16 100644 --- a/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py +++ b/configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py @@ -38,21 +38,21 @@ scons build/X86/gem5.opt -j`nproc` ``` """ -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import ( MESITwoLevelCacheHierarchy, ) from gem5.components.memory.single_channel import SingleChannelDDR4_2400 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol -from gem5.simulate.simulator import Simulator -from gem5.simulate.exit_event import ExitEvent from gem5.resources.resource import obtain_resource +from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This simulation requires using KVM with gem5 compiled for X86 simulation # and with MESI_Two_Level cache coherence protocol. diff --git a/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py b/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py index 00c00d1459..ec361dcd6e 100644 --- a/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py +++ b/configs/example/gem5_library/x86-ubuntu-run-with-kvm.py @@ -40,18 +40,18 @@ scons build/X86/gem5.opt ``` """ -from gem5.utils.requires import requires +from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.memory.single_channel import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA -from gem5.coherence_protocol import CoherenceProtocol -from gem5.simulate.simulator import Simulator -from gem5.simulate.exit_event import ExitEvent from gem5.resources.resource import obtain_resource +from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # This runs a check to ensure the gem5 binary is compiled to X86 and to the # MESI Two Level coherence protocol. diff --git a/configs/example/gem5_library/x86-ubuntu-run.py b/configs/example/gem5_library/x86-ubuntu-run.py index fe72d653f5..3b7b754b90 100644 --- a/configs/example/gem5_library/x86-ubuntu-run.py +++ b/configs/example/gem5_library/x86-ubuntu-run.py @@ -48,7 +48,6 @@ from gem5.prebuilt.demo.x86_demo_board import X86DemoBoard from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator - # Here we setup the board. The prebuilt X86DemoBoard allows for Full-System X86 # simulation. board = X86DemoBoard() diff --git a/configs/example/gpufs/DisjointNetwork.py b/configs/example/gpufs/DisjointNetwork.py index 9215691476..393ac81385 100644 --- a/configs/example/gpufs/DisjointNetwork.py +++ b/configs/example/gpufs/DisjointNetwork.py @@ -27,13 +27,13 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from m5.objects import * -from m5.util import fatal - from importlib import * from network import Network +from m5.objects import * +from m5.util import fatal + class DisjointSimple(SimpleNetwork): def __init__(self, ruby_system): diff --git a/configs/example/gpufs/Disjoint_VIPER.py b/configs/example/gpufs/Disjoint_VIPER.py index d4619c01a0..28f0768c2a 100644 --- a/configs/example/gpufs/Disjoint_VIPER.py +++ b/configs/example/gpufs/Disjoint_VIPER.py @@ -27,14 +27,14 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from example.gpufs.DisjointNetwork import * +from ruby import Ruby +from ruby.GPU_VIPER import * + from m5.defines import buildEnv from m5.objects import * from m5.util import fatal -from example.gpufs.DisjointNetwork import * -from ruby.GPU_VIPER import * -from ruby import Ruby - class DummySystem: def __init__(self, mem_ranges): diff --git a/configs/example/gpufs/hip_cookbook.py b/configs/example/gpufs/hip_cookbook.py index 6a7bb428db..0b2c084a4f 100644 --- a/configs/example/gpufs/hip_cookbook.py +++ b/configs/example/gpufs/hip_cookbook.py @@ -27,18 +27,21 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import m5 -import runfs -import tempfile import argparse -import sys import os +import sys +import tempfile +import runfs from amd import AmdGPUOptions -from common import Options -from common import GPUTLBOptions +from common import ( + GPUTLBOptions, + Options, +) from ruby import Ruby +import m5 + cookbook_runscript = """\ export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH export HSA_ENABLE_INTERRUPT=0 diff --git a/configs/example/gpufs/hip_rodinia.py b/configs/example/gpufs/hip_rodinia.py index b8a7858fcd..d93bf957fb 100644 --- a/configs/example/gpufs/hip_rodinia.py +++ b/configs/example/gpufs/hip_rodinia.py @@ -27,19 +27,22 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import m5 -import runfs -import base64 -import tempfile import argparse -import sys +import base64 import os +import sys +import tempfile +import runfs from amd import AmdGPUOptions -from common import Options -from common import GPUTLBOptions +from common import ( + GPUTLBOptions, + Options, +) from ruby import Ruby +import m5 + rodinia_runscript = """\ export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH export HSA_ENABLE_INTERRUPT=0 diff --git a/configs/example/gpufs/hip_samples.py b/configs/example/gpufs/hip_samples.py index 9f83c2550e..86fdd0e61d 100644 --- a/configs/example/gpufs/hip_samples.py +++ b/configs/example/gpufs/hip_samples.py @@ -27,18 +27,21 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import m5 -import runfs -import tempfile import argparse -import sys import os +import sys +import tempfile +import runfs from amd import AmdGPUOptions -from common import Options -from common import GPUTLBOptions +from common import ( + GPUTLBOptions, + Options, +) from ruby import Ruby +import m5 + samples_runscript = """\ export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH export HSA_ENABLE_INTERRUPT=0 diff --git a/configs/example/gpufs/runfs.py b/configs/example/gpufs/runfs.py index 8192503373..9dcc1187f3 100644 --- a/configs/example/gpufs/runfs.py +++ b/configs/example/gpufs/runfs.py @@ -29,8 +29,8 @@ # System includes import argparse -import math import hashlib +import math # gem5 related import m5 @@ -39,13 +39,15 @@ from m5.util import addToPath # gem5 options and objects addToPath("../../") -from ruby import Ruby -from common import Simulation -from common import ObjectList -from common import Options -from common import GPUTLBOptions -from common import GPUTLBConfig from amd import AmdGPUOptions +from common import ( + GPUTLBConfig, + GPUTLBOptions, + ObjectList, + Options, + Simulation, +) +from ruby import Ruby # GPU FS related from system.system import makeGpuFSSystem diff --git a/configs/example/gpufs/system/system.py b/configs/example/gpufs/system/system.py index ee0e0c0fbf..2803e10fb4 100644 --- a/configs/example/gpufs/system/system.py +++ b/configs/example/gpufs/system/system.py @@ -27,18 +27,18 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from common import ( + GPUTLBConfig, + Simulation, +) +from common.Benchmarks import * +from common.FSConfig import * +from example.gpufs.Disjoint_VIPER import * +from ruby import Ruby from system.amdgpu import * from m5.util import panic -from common.Benchmarks import * -from common.FSConfig import * -from common import GPUTLBConfig -from common import Simulation -from ruby import Ruby - -from example.gpufs.Disjoint_VIPER import * - def makeGpuFSSystem(args): # Boot options are standard gem5 options plus: diff --git a/configs/example/gpufs/vega10.py b/configs/example/gpufs/vega10.py index 9eff5a2974..ae74efd39b 100644 --- a/configs/example/gpufs/vega10.py +++ b/configs/example/gpufs/vega10.py @@ -27,19 +27,21 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import m5 -import runfs -import base64 -import tempfile import argparse -import sys +import base64 import os +import sys +import tempfile +import runfs from amd import AmdGPUOptions -from common import Options -from common import GPUTLBOptions +from common import ( + GPUTLBOptions, + Options, +) from ruby import Ruby +import m5 demo_runscript_without_checkpoint = """\ export LD_LIBRARY_PATH=/opt/rocm/lib:$LD_LIBRARY_PATH diff --git a/configs/example/hmc_hello.py b/configs/example/hmc_hello.py index bb1711b977..b2e9af1f60 100644 --- a/configs/example/hmc_hello.py +++ b/configs/example/hmc_hello.py @@ -30,19 +30,21 @@ # # Author: Éder F. Zulian -import sys import argparse +import sys import m5 from m5.objects import * from m5.util import * + from gem5.runtime import get_runtime_isa addToPath("../") -from common import MemConfig -from common import HMC - +from common import ( + HMC, + MemConfig, +) pd = "Simple 'hello world' example using HMC as main memory" parser = argparse.ArgumentParser(description=pd) diff --git a/configs/example/hmctest.py b/configs/example/hmctest.py index eca3c28465..8218da87cf 100644 --- a/configs/example/hmctest.py +++ b/configs/example/hmctest.py @@ -1,6 +1,6 @@ -import sys import argparse import subprocess +import sys from pprint import pprint import m5 @@ -9,8 +9,10 @@ from m5.util import * addToPath("../") -from common import MemConfig -from common import HMC +from common import ( + HMC, + MemConfig, +) def add_options(parser): diff --git a/configs/example/hsaTopology.py b/configs/example/hsaTopology.py index 909b9ef519..2dcbdeca01 100644 --- a/configs/example/hsaTopology.py +++ b/configs/example/hsaTopology.py @@ -27,14 +27,26 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -import m5 - import operator -from os import mkdir, makedirs, getpid, listdir, fsync -from os.path import join as joinpath +from os import ( + fsync, + getpid, + listdir, + makedirs, + mkdir, +) from os.path import isdir -from shutil import rmtree, copyfile -from m5.util.convert import toFrequency, toMemorySize +from os.path import join as joinpath +from shutil import ( + copyfile, + rmtree, +) + +import m5 +from m5.util.convert import ( + toFrequency, + toMemorySize, +) def file_append(path, contents): diff --git a/configs/example/lupv/run_lupv.py b/configs/example/lupv/run_lupv.py index e106d051e7..4be6b924a5 100644 --- a/configs/example/lupv/run_lupv.py +++ b/configs/example/lupv/run_lupv.py @@ -33,18 +33,18 @@ Characteristics * Automatically generates the DTB file """ +import argparse + import m5 from m5.objects import Root from gem5.components.boards.experimental.lupv_board import LupvBoard from gem5.components.memory.single_channel import SingleChannelDDR3_1600 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.utils.requires import requires from gem5.resources.resource import obtain_resource - -import argparse +from gem5.utils.requires import requires # Run a check to ensure the right version of gem5 is being used. requires(isa_required=ISA.RISCV) diff --git a/configs/example/riscv/fs_linux.py b/configs/example/riscv/fs_linux.py index 949c7e2623..075b4a0069 100644 --- a/configs/example/riscv/fs_linux.py +++ b/configs/example/riscv/fs_linux.py @@ -45,23 +45,28 @@ from os import path import m5 from m5.defines import buildEnv from m5.objects import * -from m5.util import addToPath, fatal, warn +from m5.util import ( + addToPath, + fatal, + warn, +) from m5.util.fdthelper import * addToPath("../../") -from ruby import Ruby - +from common import ( + CacheConfig, + CpuConfig, + MemConfig, + ObjectList, + Options, + Simulation, +) +from common.Benchmarks import * +from common.Caches import * from common.FSConfig import * from common.SysPaths import * -from common.Benchmarks import * -from common import Simulation -from common import CacheConfig -from common import CpuConfig -from common import MemConfig -from common import ObjectList -from common.Caches import * -from common import Options +from ruby import Ruby # ------------------------- Usage Instructions ------------------------- # # Common system confirguration options (cpu types, num cpus, checkpointing diff --git a/configs/example/ruby_direct_test.py b/configs/example/ruby_direct_test.py index edbeed4cc7..25139b7253 100644 --- a/configs/example/ruby_direct_test.py +++ b/configs/example/ruby_direct_test.py @@ -25,11 +25,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse +import os +import sys + import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -import os, argparse, sys addToPath("../") diff --git a/configs/example/ruby_gpu_random_test.py b/configs/example/ruby_gpu_random_test.py index 25d5a51892..17915c6a6d 100644 --- a/configs/example/ruby_gpu_random_test.py +++ b/configs/example/ruby_gpu_random_test.py @@ -27,11 +27,14 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +import argparse +import os +import sys + import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -import os, argparse, sys addToPath("../") diff --git a/configs/example/ruby_mem_test.py b/configs/example/ruby_mem_test.py index 9ad6a1b7ad..6a9e8c313c 100644 --- a/configs/example/ruby_mem_test.py +++ b/configs/example/ruby_mem_test.py @@ -25,11 +25,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse +import os +import sys + import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -import os, argparse, sys addToPath("../") diff --git a/configs/example/ruby_random_test.py b/configs/example/ruby_random_test.py index 816864be91..ed1b971a9b 100644 --- a/configs/example/ruby_random_test.py +++ b/configs/example/ruby_random_test.py @@ -25,11 +25,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse +import os +import sys + import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -import os, argparse, sys addToPath("../") diff --git a/configs/example/sc_main.py b/configs/example/sc_main.py index 4a1482d87d..141ac173ac 100755 --- a/configs/example/sc_main.py +++ b/configs/example/sc_main.py @@ -26,7 +26,10 @@ import sys import m5 -from m5.objects import SystemC_Kernel, Root +from m5.objects import ( + Root, + SystemC_Kernel, +) # pylint:disable=unused-variable diff --git a/configs/example/sst/riscv_fs.py b/configs/example/sst/riscv_fs.py index c82ad9a6b9..74cb179114 100644 --- a/configs/example/sst/riscv_fs.py +++ b/configs/example/sst/riscv_fs.py @@ -24,15 +24,15 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse +from os import path + import m5 from m5.objects import * -from os import path # For downloading the disk image from gem5.resources.resource import obtain_resource -import argparse - def generateMemNode(state, mem_range): node = FdtNode(f"memory@{int(mem_range.start):x}") diff --git a/configs/learning_gem5/part1/two_level.py b/configs/learning_gem5/part1/two_level.py index c6f4f4872f..a105faeca3 100644 --- a/configs/learning_gem5/part1/two_level.py +++ b/configs/learning_gem5/part1/two_level.py @@ -42,6 +42,7 @@ import m5 # import all of the SimObjects from m5.objects import * + from gem5.runtime import get_runtime_isa # Add the common scripts to our path diff --git a/configs/learning_gem5/part3/msi_caches.py b/configs/learning_gem5/part3/msi_caches.py index f628cca96d..0945dc2bbd 100644 --- a/configs/learning_gem5/part3/msi_caches.py +++ b/configs/learning_gem5/part3/msi_caches.py @@ -37,9 +37,11 @@ IMPORTANT: If you modify this file, it's likely that the Learning gem5 book import math from m5.defines import buildEnv -from m5.util import fatal, panic - from m5.objects import * +from m5.util import ( + fatal, + panic, +) class MyCacheSystem(RubySystem): diff --git a/configs/learning_gem5/part3/ruby_caches_MI_example.py b/configs/learning_gem5/part3/ruby_caches_MI_example.py index aec54b1068..eecaded31f 100644 --- a/configs/learning_gem5/part3/ruby_caches_MI_example.py +++ b/configs/learning_gem5/part3/ruby_caches_MI_example.py @@ -39,9 +39,11 @@ IMPORTANT: If you modify this file, it's likely that the Learning gem5 book import math from m5.defines import buildEnv -from m5.util import fatal, panic - from m5.objects import * +from m5.util import ( + fatal, + panic, +) class MyCacheSystem(RubySystem): diff --git a/configs/learning_gem5/part3/ruby_test.py b/configs/learning_gem5/part3/ruby_test.py index 5b00e1169e..67ac697bb3 100644 --- a/configs/learning_gem5/part3/ruby_test.py +++ b/configs/learning_gem5/part3/ruby_test.py @@ -33,14 +33,14 @@ IMPORTANT: If you modify this file, it's likely that the Learning gem5 book """ +from test_caches import TestCacheSystem + # import the m5 (gem5) library created when gem5 is built import m5 # import all of the SimObjects from m5.objects import * -from test_caches import TestCacheSystem - # create the system we are going to simulate system = System() diff --git a/configs/learning_gem5/part3/test_caches.py b/configs/learning_gem5/part3/test_caches.py index ebd646ffab..4e8e8febda 100644 --- a/configs/learning_gem5/part3/test_caches.py +++ b/configs/learning_gem5/part3/test_caches.py @@ -34,12 +34,15 @@ IMPORTANT: If you modify this file, it's likely that the Learning gem5 book """ +from msi_caches import ( + DirController, + L1Cache, + MyNetwork, +) + from m5.defines import buildEnv -from m5.util import fatal - from m5.objects import * - -from msi_caches import L1Cache, DirController, MyNetwork +from m5.util import fatal class TestCacheSystem(RubySystem): diff --git a/configs/network/Network.py b/configs/network/Network.py index dbac88c246..0973809c33 100644 --- a/configs/network/Network.py +++ b/configs/network/Network.py @@ -25,10 +25,15 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from m5.util import addToPath, fatal, warn +from m5.objects import * +from m5.util import ( + addToPath, + fatal, + warn, +) def define_options(parser): diff --git a/configs/nvm/sweep.py b/configs/nvm/sweep.py index b569cb35b5..d5d23ad76a 100644 --- a/configs/nvm/sweep.py +++ b/configs/nvm/sweep.py @@ -33,18 +33,20 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import math import argparse +import math import m5 from m5.objects import * -from m5.util import addToPath from m5.stats import periodicStatDump +from m5.util import addToPath addToPath("../") -from common import ObjectList -from common import MemConfig +from common import ( + MemConfig, + ObjectList, +) # this script is helpful to sweep the efficiency of a specific memory # controller configuration, by varying the number of banks accessed, diff --git a/configs/nvm/sweep_hybrid.py b/configs/nvm/sweep_hybrid.py index d1e2994268..669f847eb1 100644 --- a/configs/nvm/sweep_hybrid.py +++ b/configs/nvm/sweep_hybrid.py @@ -33,18 +33,20 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import math import argparse +import math import m5 from m5.objects import * -from m5.util import addToPath from m5.stats import periodicStatDump +from m5.util import addToPath addToPath("../") -from common import ObjectList -from common import MemConfig +from common import ( + MemConfig, + ObjectList, +) # this script is helpful to sweep the efficiency of a specific memory # controller configuration, by varying the number of banks accessed, diff --git a/configs/ruby/AMD_Base_Constructor.py b/configs/ruby/AMD_Base_Constructor.py index ec06fbad34..ff4246a7e0 100644 --- a/configs/ruby/AMD_Base_Constructor.py +++ b/configs/ruby/AMD_Base_Constructor.py @@ -28,10 +28,15 @@ # POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from m5.util import addToPath, convert +from m5.objects import * +from m5.util import ( + addToPath, + convert, +) + from .CntrlBase import * addToPath("../") diff --git a/configs/ruby/CHI.py b/configs/ruby/CHI.py index 2487f696fd..cb8fe64664 100644 --- a/configs/ruby/CHI.py +++ b/configs/ruby/CHI.py @@ -34,8 +34,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * + from .Ruby import create_topology @@ -53,8 +54,8 @@ def define_options(parser): def read_config_file(file): """Read file as a module and return it""" - import types import importlib.machinery + import types loader = importlib.machinery.SourceFileLoader("chi_configs", file) chi_configs = types.ModuleType(loader.name) diff --git a/configs/ruby/CHI_config.py b/configs/ruby/CHI_config.py index 3cccfd0676..9c7391c0ec 100644 --- a/configs/ruby/CHI_config.py +++ b/configs/ruby/CHI_config.py @@ -46,6 +46,7 @@ node to router binding. See configs/example/noc_config/2x4.py for an example. """ import math + import m5 from m5.objects import * diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index 665f739b4b..d853c2ef54 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -28,15 +28,22 @@ # POSSIBILITY OF SUCH DAMAGE. import math + +from common import ( + FileSystemConfig, + MemConfig, + ObjectList, +) + import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -from .Ruby import create_topology -from .Ruby import send_evicts -from common import ObjectList -from common import MemConfig -from common import FileSystemConfig + +from .Ruby import ( + create_topology, + send_evicts, +) addToPath("../") diff --git a/configs/ruby/Garnet_standalone.py b/configs/ruby/Garnet_standalone.py index eb481bb4ad..8329295574 100644 --- a/configs/ruby/Garnet_standalone.py +++ b/configs/ruby/Garnet_standalone.py @@ -26,10 +26,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 -from m5.objects import * from m5.defines import buildEnv +from m5.objects import * from m5.util import addToPath -from .Ruby import create_topology, create_directories + +from .Ruby import ( + create_directories, + create_topology, +) # diff --git a/configs/ruby/MESI_Three_Level.py b/configs/ruby/MESI_Three_Level.py index 077c461b69..e0de4e0636 100644 --- a/configs/ruby/MESI_Three_Level.py +++ b/configs/ruby/MESI_Three_Level.py @@ -28,13 +28,19 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math -import m5 -from m5.objects import * -from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts + from common import FileSystemConfig +import m5 +from m5.defines import buildEnv +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) + # # Declare caches used by the protocol diff --git a/configs/ruby/MESI_Three_Level_HTM.py b/configs/ruby/MESI_Three_Level_HTM.py index f2c2ecfd9f..e6c4e81f91 100644 --- a/configs/ruby/MESI_Three_Level_HTM.py +++ b/configs/ruby/MESI_Three_Level_HTM.py @@ -28,13 +28,19 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math -import m5 -from m5.objects import * -from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts + from common import FileSystemConfig +import m5 +from m5.defines import buildEnv +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) + # # Declare caches used by the protocol diff --git a/configs/ruby/MESI_Two_Level.py b/configs/ruby/MESI_Two_Level.py index 7326a6cab8..500afbc199 100644 --- a/configs/ruby/MESI_Two_Level.py +++ b/configs/ruby/MESI_Two_Level.py @@ -26,11 +26,16 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) # diff --git a/configs/ruby/MI_example.py b/configs/ruby/MI_example.py index 7adf5b8ebd..ba0d446840 100644 --- a/configs/ruby/MI_example.py +++ b/configs/ruby/MI_example.py @@ -26,11 +26,16 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) # diff --git a/configs/ruby/MOESI_AMD_Base.py b/configs/ruby/MOESI_AMD_Base.py index 2c7d743ede..aeab96a85f 100644 --- a/configs/ruby/MOESI_AMD_Base.py +++ b/configs/ruby/MOESI_AMD_Base.py @@ -28,14 +28,19 @@ # POSSIBILITY OF SUCH DAMAGE. import math -import m5 -from m5.objects import * -from m5.defines import buildEnv -from m5.util import addToPath -from .Ruby import create_topology -from .Ruby import send_evicts + from common import FileSystemConfig +import m5 +from m5.defines import buildEnv +from m5.objects import * +from m5.util import addToPath + +from .Ruby import ( + create_topology, + send_evicts, +) + addToPath("../") from topologies.Cluster import Cluster diff --git a/configs/ruby/MOESI_CMP_directory.py b/configs/ruby/MOESI_CMP_directory.py index ecee4a464e..700967f98a 100644 --- a/configs/ruby/MOESI_CMP_directory.py +++ b/configs/ruby/MOESI_CMP_directory.py @@ -38,11 +38,16 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) # diff --git a/configs/ruby/MOESI_CMP_token.py b/configs/ruby/MOESI_CMP_token.py index 89852e07c3..b6ee7a3875 100644 --- a/configs/ruby/MOESI_CMP_token.py +++ b/configs/ruby/MOESI_CMP_token.py @@ -26,11 +26,16 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) # diff --git a/configs/ruby/MOESI_hammer.py b/configs/ruby/MOESI_hammer.py index 6ed6a2d50f..f0e1c3730f 100644 --- a/configs/ruby/MOESI_hammer.py +++ b/configs/ruby/MOESI_hammer.py @@ -26,13 +26,19 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math -import m5 -from m5.objects import * -from m5.defines import buildEnv -from .Ruby import create_topology, create_directories -from .Ruby import send_evicts + from common import FileSystemConfig +import m5 +from m5.defines import buildEnv +from m5.objects import * + +from .Ruby import ( + create_directories, + create_topology, + send_evicts, +) + # # Declare caches used by the protocol diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index a7aeb6b16f..ae30d55077 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -38,21 +38,27 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import math + import m5 -from m5.objects import * from m5.defines import buildEnv -from m5.util import addToPath, fatal +from m5.objects import * +from m5.util import ( + addToPath, + fatal, +) + from gem5.isas import ISA from gem5.runtime import get_runtime_isa addToPath("../") -from common import ObjectList -from common import MemConfig -from common import FileSystemConfig - -from topologies import * +from common import ( + FileSystemConfig, + MemConfig, + ObjectList, +) from network import Network +from topologies import * def define_options(parser): diff --git a/configs/splash2/cluster.py b/configs/splash2/cluster.py index f7157d98c2..c43067e29c 100644 --- a/configs/splash2/cluster.py +++ b/configs/splash2/cluster.py @@ -28,8 +28,8 @@ # # "m5 test.py" -import os import argparse +import os import sys import m5 diff --git a/configs/splash2/run.py b/configs/splash2/run.py index 4bc2cf653d..e53983d4b1 100644 --- a/configs/splash2/run.py +++ b/configs/splash2/run.py @@ -27,8 +27,8 @@ # Splash2 Run Script # -import os import argparse +import os import sys import m5 diff --git a/configs/topologies/Crossbar.py b/configs/topologies/Crossbar.py index 45929b18ed..f6d4e545ec 100644 --- a/configs/topologies/Crossbar.py +++ b/configs/topologies/Crossbar.py @@ -24,11 +24,11 @@ # (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.params import * -from m5.objects import * - from topologies.BaseTopology import SimpleTopology +from m5.objects import * +from m5.params import * + class Crossbar(SimpleTopology): description = "Crossbar" diff --git a/configs/topologies/CrossbarGarnet.py b/configs/topologies/CrossbarGarnet.py index 603e1dfd35..74d69e846f 100644 --- a/configs/topologies/CrossbarGarnet.py +++ b/configs/topologies/CrossbarGarnet.py @@ -24,11 +24,11 @@ # (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.params import * -from m5.objects import * - from topologies.BaseTopology import SimpleTopology +from m5.objects import * +from m5.params import * + class CrossbarGarnet(SimpleTopology): description = "CrossbarGarnet" diff --git a/configs/topologies/CustomMesh.py b/configs/topologies/CustomMesh.py index 0f0d6765cf..f440e00887 100644 --- a/configs/topologies/CustomMesh.py +++ b/configs/topologies/CustomMesh.py @@ -36,11 +36,10 @@ import math -from m5.util import fatal -from m5.params import * -from m5.objects import * - from m5.defines import buildEnv +from m5.objects import * +from m5.params import * +from m5.util import fatal if buildEnv["PROTOCOL"] == "CHI": import ruby.CHI_config as CHI diff --git a/configs/topologies/MeshDirCorners_XY.py b/configs/topologies/MeshDirCorners_XY.py index 1f6eb4297b..afab634bde 100644 --- a/configs/topologies/MeshDirCorners_XY.py +++ b/configs/topologies/MeshDirCorners_XY.py @@ -24,13 +24,12 @@ # (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.params import * -from m5.objects import * - from common import FileSystemConfig - from topologies.BaseTopology import SimpleTopology +from m5.objects import * +from m5.params import * + # Creates a Mesh topology with 4 directories, one at each corner. # One L1 (and L2, depending on the protocol) are connected to each router. # XY routing is enforced (using link weights) to guarantee deadlock freedom. diff --git a/configs/topologies/Mesh_XY.py b/configs/topologies/Mesh_XY.py index e5402d3d83..6a01793b12 100644 --- a/configs/topologies/Mesh_XY.py +++ b/configs/topologies/Mesh_XY.py @@ -25,13 +25,12 @@ # (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.params import * -from m5.objects import * - from common import FileSystemConfig - from topologies.BaseTopology import SimpleTopology +from m5.objects import * +from m5.params import * + # Creates a generic Mesh assuming an equal number of cache # and directory controllers. # XY routing is enforced (using link weights) diff --git a/configs/topologies/Mesh_westfirst.py b/configs/topologies/Mesh_westfirst.py index 45702b759a..a9ed5c145e 100644 --- a/configs/topologies/Mesh_westfirst.py +++ b/configs/topologies/Mesh_westfirst.py @@ -25,11 +25,11 @@ # (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.params import * -from m5.objects import * - from topologies.BaseTopology import SimpleTopology +from m5.objects import * +from m5.params import * + # Creates a generic Mesh assuming an equal number of cache # and directory controllers. # West-first routing is enforced (using link weights) diff --git a/configs/topologies/Pt2Pt.py b/configs/topologies/Pt2Pt.py index 8d85b31f1e..1268751370 100644 --- a/configs/topologies/Pt2Pt.py +++ b/configs/topologies/Pt2Pt.py @@ -25,11 +25,11 @@ # (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.params import * -from m5.objects import * - from topologies.BaseTopology import SimpleTopology +from m5.objects import * +from m5.params import * + class Pt2Pt(SimpleTopology): description = "Pt2Pt" diff --git a/ext/testlib/__init__.py b/ext/testlib/__init__.py index 2fad890b65..d2dad35eff 100644 --- a/ext/testlib/__init__.py +++ b/ext/testlib/__init__.py @@ -27,18 +27,18 @@ # Authors: Sean Wilson -from .state import * -from .runner import * -from .test_util import * -from .suite import * -from .loader import * -from .fixture import * -from .configuration import * -from .main import main +# TODO Remove this as an export, users should getcwd from os +from os import getcwd # TODO Remove this awkward bootstrap # FIXME from gem5 import * -# TODO Remove this as an export, users should getcwd from os -from os import getcwd +from .configuration import * +from .fixture import * +from .loader import * +from .main import main +from .runner import * +from .state import * +from .suite import * +from .test_util import * diff --git a/ext/testlib/configuration.py b/ext/testlib/configuration.py index a635b6d3a9..60c0c17654 100644 --- a/ext/testlib/configuration.py +++ b/ext/testlib/configuration.py @@ -82,10 +82,13 @@ import argparse import copy import os import re - from pickle import HIGHEST_PROTOCOL as highest_pickle_protocol -from testlib.helper import absdirpath, AttrDict, FrozenAttrDict +from testlib.helper import ( + AttrDict, + FrozenAttrDict, + absdirpath, +) class UninitialzedAttributeException(Exception): diff --git a/ext/testlib/fixture.py b/ext/testlib/fixture.py index 16fc39c29f..14d42c4724 100644 --- a/ext/testlib/fixture.py +++ b/ext/testlib/fixture.py @@ -26,11 +26,11 @@ # # Authors: Sean Wilson +from typing import Optional + import testlib.helper as helper from testlib.configuration import constants -from typing import Optional - class SkipException(Exception): def __init__(self, fixture, testitem): diff --git a/ext/testlib/handlers.py b/ext/testlib/handlers.py index 6a6f654355..283e04f170 100644 --- a/ext/testlib/handlers.py +++ b/ext/testlib/handlers.py @@ -37,14 +37,16 @@ import sys import threading import time import traceback +from queue import ( + Empty, + Queue, +) import testlib.helper as helper import testlib.log as log import testlib.result as result import testlib.state as state import testlib.terminal as terminal - -from queue import Queue, Empty from testlib.configuration import constants diff --git a/ext/testlib/helper.py b/ext/testlib/helper.py index 0fd0cf539e..a66ce8ad2c 100644 --- a/ext/testlib/helper.py +++ b/ext/testlib/helper.py @@ -41,9 +41,6 @@ """ Helper classes for writing tests with this test library. """ -from collections import namedtuple -from collections.abc import MutableSet - import difflib import errno import os @@ -54,6 +51,8 @@ import subprocess import tempfile import threading import time +from collections import namedtuple +from collections.abc import MutableSet class TimedWaitPID: diff --git a/ext/testlib/loader.py b/ext/testlib/loader.py index 192632adab..d74f76181d 100644 --- a/ext/testlib/loader.py +++ b/ext/testlib/loader.py @@ -70,12 +70,12 @@ import re import sys import traceback +import testlib.fixture as fixture_mod import testlib.log as log import testlib.suite as suite_mod import testlib.test_util as test_mod -import testlib.fixture as fixture_mod -import testlib.wrappers as wrappers import testlib.uid as uid +import testlib.wrappers as wrappers class DuplicateTestItemException(Exception): diff --git a/ext/testlib/main.py b/ext/testlib/main.py index fdd4c17b2f..d93f167a77 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -26,8 +26,8 @@ # # Authors: Sean Wilson -import os import itertools +import os import testlib.configuration as configuration import testlib.handlers as handlers diff --git a/ext/testlib/query.py b/ext/testlib/query.py index ead567a360..b2c21f8fb4 100644 --- a/ext/testlib/query.py +++ b/ext/testlib/query.py @@ -26,8 +26,8 @@ # # Authors: Sean Wilson -import testlib.terminal as terminal import testlib.log as log +import testlib.terminal as terminal # TODO Refactor print logic out of this so the objects diff --git a/ext/testlib/result.py b/ext/testlib/result.py index b6977d3542..73c8cea5d5 100644 --- a/ext/testlib/result.py +++ b/ext/testlib/result.py @@ -42,9 +42,9 @@ import os import pickle import xml.sax.saxutils -from testlib.configuration import config import testlib.helper as helper import testlib.state as state +from testlib.configuration import config def _create_uid_index(iterable): diff --git a/ext/testlib/runner.py b/ext/testlib/runner.py index 1e3512af2b..540acb35df 100644 --- a/ext/testlib/runner.py +++ b/ext/testlib/runner.py @@ -43,9 +43,11 @@ import traceback import testlib.helper as helper import testlib.log as log - -from testlib.state import Status, Result from testlib.fixture import SkipException +from testlib.state import ( + Result, + Status, +) def compute_aggregate_result(iterable): diff --git a/ext/testlib/terminal.py b/ext/testlib/terminal.py index f295aa2dc4..fa3531093e 100644 --- a/ext/testlib/terminal.py +++ b/ext/testlib/terminal.py @@ -24,10 +24,10 @@ # # Author: Steve Reinhardt -import sys import fcntl -import termios import struct +import sys +import termios # Intended usage example: # diff --git a/ext/testlib/uid.py b/ext/testlib/uid.py index 84403f80fe..70d653bc20 100644 --- a/ext/testlib/uid.py +++ b/ext/testlib/uid.py @@ -26,8 +26,8 @@ # # Authors: Sean Wilson -import os import itertools +import os import testlib.configuration as configuration diff --git a/ext/testlib/wrappers.py b/ext/testlib/wrappers.py index 936d9b604d..4e1be80427 100644 --- a/ext/testlib/wrappers.py +++ b/ext/testlib/wrappers.py @@ -45,7 +45,10 @@ loaded by the testlib :class:`testlib.loader.Loader`. import itertools import testlib.uid as uid -from testlib.state import Status, Result +from testlib.state import ( + Result, + Status, +) class TestCaseMetadata: diff --git a/site_scons/gem5_scons/__init__.py b/site_scons/gem5_scons/__init__.py index 3638d9c561..bed4b48157 100644 --- a/site_scons/gem5_scons/__init__.py +++ b/site_scons/gem5_scons/__init__.py @@ -45,11 +45,11 @@ import sys import tempfile import textwrap -from gem5_scons.util import get_termcap -from gem5_scons.configure import Configure -from gem5_scons.defaults import EnvDefaults import SCons.Node.Python import SCons.Script +from gem5_scons.configure import Configure +from gem5_scons.defaults import EnvDefaults +from gem5_scons.util import get_termcap termcap = get_termcap() diff --git a/site_scons/gem5_scons/builders/blob.py b/site_scons/gem5_scons/builders/blob.py index f4e6d3a0ea..74d5b85259 100644 --- a/site_scons/gem5_scons/builders/blob.py +++ b/site_scons/gem5_scons/builders/blob.py @@ -39,12 +39,13 @@ import os.path -from gem5_scons import Transform, MakeAction -from blob import bytesToCppArray - -from code_formatter import code_formatter - import SCons.Node.Python +from blob import bytesToCppArray +from code_formatter import code_formatter +from gem5_scons import ( + MakeAction, + Transform, +) def build_blob(target, source, env): diff --git a/site_scons/gem5_scons/builders/config_file.py b/site_scons/gem5_scons/builders/config_file.py index 7ee5e4d658..28eb975631 100755 --- a/site_scons/gem5_scons/builders/config_file.py +++ b/site_scons/gem5_scons/builders/config_file.py @@ -38,7 +38,10 @@ # (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_scons import Transform, MakeAction +from gem5_scons import ( + MakeAction, + Transform, +) ################################################### # diff --git a/site_scons/gem5_scons/builders/switching_headers.py b/site_scons/gem5_scons/builders/switching_headers.py index 92bd613508..497179422f 100755 --- a/site_scons/gem5_scons/builders/switching_headers.py +++ b/site_scons/gem5_scons/builders/switching_headers.py @@ -40,7 +40,10 @@ import os.path -from gem5_scons import Transform, MakeAction +from gem5_scons import ( + MakeAction, + Transform, +) ################################################### # diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index 42b2eec482..b3b49d27c5 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -25,9 +25,10 @@ import os -from . import error import kconfiglib +from . import error + _kconfig_helpers = { "DEFCONFIG_PY": "defconfig.py", "GUICONFIG_PY": "guiconfig.py", diff --git a/site_scons/gem5_scons/util.py b/site_scons/gem5_scons/util.py index ee8efdc49a..be0a5a5880 100644 --- a/site_scons/gem5_scons/util.py +++ b/site_scons/gem5_scons/util.py @@ -66,7 +66,11 @@ def readCommand(cmd, **kwargs): :returns: command stdout :rtype: string """ - from subprocess import Popen, PIPE, STDOUT + from subprocess import ( + PIPE, + STDOUT, + Popen, + ) if isinstance(cmd, str): cmd = cmd.split() diff --git a/site_scons/site_tools/git.py b/site_scons/site_tools/git.py index 362c20b105..40e5d6267e 100644 --- a/site_scons/site_tools/git.py +++ b/site_scons/site_tools/git.py @@ -38,10 +38,10 @@ # (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 asyncio import subprocess import os -import sys import subprocess +import sys +from asyncio import subprocess import gem5_scons.util import SCons.Script diff --git a/src/arch/amdgpu/common/X86GPUTLB.py b/src/arch/amdgpu/common/X86GPUTLB.py index 59cc549d17..407443b8d7 100644 --- a/src/arch/amdgpu/common/X86GPUTLB.py +++ b/src/arch/amdgpu/common/X86GPUTLB.py @@ -28,10 +28,9 @@ # POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * - -from m5.objects.ClockedObject import ClockedObject from m5.SimObject import SimObject diff --git a/src/arch/amdgpu/vega/VegaGPUTLB.py b/src/arch/amdgpu/vega/VegaGPUTLB.py index 96b940c544..6ef9630d18 100644 --- a/src/arch/amdgpu/vega/VegaGPUTLB.py +++ b/src/arch/amdgpu/vega/VegaGPUTLB.py @@ -28,11 +28,10 @@ # POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv +from m5.objects.AMDGPU import AMDGPUDevice +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * - -from m5.objects.ClockedObject import ClockedObject -from m5.objects.AMDGPU import AMDGPUDevice from m5.SimObject import SimObject diff --git a/src/arch/arm/ArmCPU.py b/src/arch/arm/ArmCPU.py index 52c3ba8a0a..35ed712cba 100644 --- a/src/arch/arm/ArmCPU.py +++ b/src/arch/arm/ArmCPU.py @@ -23,18 +23,17 @@ # (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.proxy import Self - -from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU -from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU -from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU -from m5.objects.BaseO3CPU import BaseO3CPU -from m5.objects.BaseO3Checker import BaseO3Checker -from m5.objects.BaseMinorCPU import BaseMinorCPU from m5.objects.ArmDecoder import ArmDecoder -from m5.objects.ArmMMU import ArmMMU from m5.objects.ArmInterrupts import ArmInterrupts from m5.objects.ArmISA import ArmISA +from m5.objects.ArmMMU import ArmMMU +from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU +from m5.objects.BaseMinorCPU import BaseMinorCPU +from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU +from m5.objects.BaseO3Checker import BaseO3Checker +from m5.objects.BaseO3CPU import BaseO3CPU +from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU +from m5.proxy import Self class ArmCPU: diff --git a/src/arch/arm/ArmDecoder.py b/src/arch/arm/ArmDecoder.py index d4b82e3f4f..f92c81debe 100644 --- a/src/arch/arm/ArmDecoder.py +++ b/src/arch/arm/ArmDecoder.py @@ -35,8 +35,8 @@ # (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.params import * from m5.objects.InstDecoder import InstDecoder +from m5.params import * class ArmDecoder(InstDecoder): diff --git a/src/arch/arm/ArmFsWorkload.py b/src/arch/arm/ArmFsWorkload.py index a9474fe119..6d2804cb9b 100644 --- a/src/arch/arm/ArmFsWorkload.py +++ b/src/arch/arm/ArmFsWorkload.py @@ -33,10 +33,10 @@ # (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.params import * -from m5.options import * -from m5.SimObject import * from m5.objects.Workload import KernelWorkload +from m5.options import * +from m5.params import * +from m5.SimObject import * class ArmMachineType(Enum): diff --git a/src/arch/arm/ArmISA.py b/src/arch/arm/ArmISA.py index 97c2609f50..8e8d2b641c 100644 --- a/src/arch/arm/ArmISA.py +++ b/src/arch/arm/ArmISA.py @@ -33,13 +33,16 @@ # (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.ArmPMU import ArmPMU +from m5.objects.ArmSystem import ( + ArmRelease, + SmeVectorLength, + SveVectorLength, +) +from m5.objects.BaseISA import BaseISA from m5.params import * from m5.proxy import * - from m5.SimObject import SimObject -from m5.objects.ArmPMU import ArmPMU -from m5.objects.ArmSystem import SveVectorLength, SmeVectorLength, ArmRelease -from m5.objects.BaseISA import BaseISA # Enum for DecoderFlavor diff --git a/src/arch/arm/ArmMMU.py b/src/arch/arm/ArmMMU.py index e2e548b1b3..8cafc2c624 100644 --- a/src/arch/arm/ArmMMU.py +++ b/src/arch/arm/ArmMMU.py @@ -36,7 +36,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.ArmSystem import ArmRelease -from m5.objects.ArmTLB import ArmTLB, ArmStage2TLB +from m5.objects.ArmTLB import ( + ArmStage2TLB, + ArmTLB, +) from m5.objects.BaseMMU import BaseMMU from m5.objects.ClockedObject import ClockedObject from m5.params import * diff --git a/src/arch/arm/ArmNativeTrace.py b/src/arch/arm/ArmNativeTrace.py index 0c795a6426..09462e1bf6 100644 --- a/src/arch/arm/ArmNativeTrace.py +++ b/src/arch/arm/ArmNativeTrace.py @@ -24,9 +24,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.CPUTracers import NativeTrace +from m5.params import * +from m5.SimObject import SimObject class ArmNativeTrace(NativeTrace): diff --git a/src/arch/arm/ArmPMU.py b/src/arch/arm/ArmPMU.py index 3fd619b55d..27a7fa224d 100644 --- a/src/arch/arm/ArmPMU.py +++ b/src/arch/arm/ArmPMU.py @@ -35,11 +35,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv -from m5.SimObject import * +from m5.objects.Gic import ( + ArmInterruptPin, + ArmPPI, +) from m5.params import * from m5.params import isNullPointer from m5.proxy import * -from m5.objects.Gic import ArmInterruptPin, ArmPPI +from m5.SimObject import * from m5.util.fdthelper import * diff --git a/src/arch/arm/ArmSeWorkload.py b/src/arch/arm/ArmSeWorkload.py index 1bf4e3edf3..e01853baeb 100644 --- a/src/arch/arm/ArmSeWorkload.py +++ b/src/arch/arm/ArmSeWorkload.py @@ -23,9 +23,8 @@ # (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.params import * - from m5.objects.Workload import SEWorkload +from m5.params import * class ArmSEWorkload(SEWorkload): diff --git a/src/arch/arm/ArmSemihosting.py b/src/arch/arm/ArmSemihosting.py index 54322cdec0..8c8375e208 100644 --- a/src/arch/arm/ArmSemihosting.py +++ b/src/arch/arm/ArmSemihosting.py @@ -33,11 +33,10 @@ # (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.params import * -from m5.SimObject import * - from m5.objects.Serial import SerialDevice from m5.objects.Terminal import Terminal +from m5.params import * +from m5.SimObject import * class ArmSemihosting(SimObject): diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index f66c9c83d2..dc138cafc3 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -33,16 +33,15 @@ # (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.params import * +from typing import Any + +from m5.objects.ArmSemihosting import ArmSemihosting +from m5.objects.System import System from m5.options import * +from m5.params import * from m5.SimObject import * from m5.util.fdthelper import * -from m5.objects.System import System -from m5.objects.ArmSemihosting import ArmSemihosting - -from typing import Any - class SveVectorLength(UInt8): min = 1 diff --git a/src/arch/arm/ArmTLB.py b/src/arch/arm/ArmTLB.py index 8475a56b5b..c868a322f1 100644 --- a/src/arch/arm/ArmTLB.py +++ b/src/arch/arm/ArmTLB.py @@ -35,10 +35,10 @@ # (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.SimObject import SimObject +from m5.objects.BaseTLB import BaseTLB from m5.params import * from m5.proxy import * -from m5.objects.BaseTLB import BaseTLB +from m5.SimObject import SimObject class ArmLookupLevel(Enum): diff --git a/src/arch/arm/fastmodel/CortexA76/FastModelCortexA76.py b/src/arch/arm/fastmodel/CortexA76/FastModelCortexA76.py index f690fb5097..4c332f88ad 100644 --- a/src/arch/arm/fastmodel/CortexA76/FastModelCortexA76.py +++ b/src/arch/arm/fastmodel/CortexA76/FastModelCortexA76.py @@ -23,20 +23,25 @@ # (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.ArmInterrupts import ArmInterrupts +from m5.objects.ArmISA import ArmISA +from m5.objects.FastModel import ( + AmbaInitiatorSocket, + AmbaTargetSocket, +) +from m5.objects.FastModelGIC import Gicv3CommsTargetSocket +from m5.objects.Gic import ArmPPI +from m5.objects.IntPin import IntSinkPin +from m5.objects.Iris import IrisBaseCPU +from m5.objects.ResetPort import ResetResponsePort +from m5.objects.SystemC import SystemC_ScModule from m5.params import * from m5.proxy import * from m5.SimObject import SimObject - -from m5.objects.ArmInterrupts import ArmInterrupts -from m5.objects.ArmISA import ArmISA -from m5.objects.FastModel import AmbaInitiatorSocket, AmbaTargetSocket -from m5.objects.FastModelGIC import Gicv3CommsTargetSocket -from m5.objects.ResetPort import ResetResponsePort -from m5.objects.IntPin import IntSinkPin -from m5.objects.Gic import ArmPPI -from m5.objects.Iris import IrisBaseCPU -from m5.objects.SystemC import SystemC_ScModule -from m5.util.fdthelper import FdtNode, FdtPropertyWords +from m5.util.fdthelper import ( + FdtNode, + FdtPropertyWords, +) class FastModelCortexA76(IrisBaseCPU): diff --git a/src/arch/arm/fastmodel/CortexR52/FastModelCortexR52.py b/src/arch/arm/fastmodel/CortexR52/FastModelCortexR52.py index fe81e72bd0..acf5087867 100644 --- a/src/arch/arm/fastmodel/CortexR52/FastModelCortexR52.py +++ b/src/arch/arm/fastmodel/CortexR52/FastModelCortexR52.py @@ -23,18 +23,24 @@ # (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.ArmInterrupts import ArmInterrupts +from m5.objects.ArmISA import ArmISA +from m5.objects.FastModel import ( + AmbaInitiatorSocket, + AmbaTargetSocket, +) +from m5.objects.IntPin import ( + IntSinkPin, + IntSourcePin, + VectorIntSinkPin, +) +from m5.objects.Iris import IrisBaseCPU +from m5.objects.ResetPort import ResetResponsePort +from m5.objects.SystemC import SystemC_ScModule from m5.params import * from m5.proxy import * from m5.SimObject import SimObject -from m5.objects.ArmInterrupts import ArmInterrupts -from m5.objects.ArmISA import ArmISA -from m5.objects.FastModel import AmbaInitiatorSocket, AmbaTargetSocket -from m5.objects.ResetPort import ResetResponsePort -from m5.objects.IntPin import IntSourcePin, IntSinkPin, VectorIntSinkPin -from m5.objects.Iris import IrisBaseCPU -from m5.objects.SystemC import SystemC_ScModule - class FastModelCortexR52(IrisBaseCPU): type = "FastModelCortexR52" diff --git a/src/arch/arm/fastmodel/FastModel.py b/src/arch/arm/fastmodel/FastModel.py index 8ba537623a..3ba5d8bb78 100644 --- a/src/arch/arm/fastmodel/FastModel.py +++ b/src/arch/arm/fastmodel/FastModel.py @@ -23,12 +23,14 @@ # (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.SystemC import SystemC_ScModule +from m5.objects.Tlm import ( + TlmInitiatorSocket, + TlmTargetSocket, +) from m5.params import * from m5.proxy import * -from m5.objects.SystemC import SystemC_ScModule -from m5.objects.Tlm import TlmInitiatorSocket, TlmTargetSocket - def AMBA_TARGET_ROLE(width): return "AMBA TARGET %d" % width diff --git a/src/arch/arm/fastmodel/GIC/FastModelGIC.py b/src/arch/arm/fastmodel/GIC/FastModelGIC.py index b1a9a3c8a1..9d0b5e0fcc 100644 --- a/src/arch/arm/fastmodel/GIC/FastModelGIC.py +++ b/src/arch/arm/fastmodel/GIC/FastModelGIC.py @@ -35,15 +35,17 @@ # (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.params import * -from m5.util.fdthelper import * -from m5.SimObject import SimObject - -from m5.objects.FastModel import AmbaInitiatorSocket, AmbaTargetSocket +from m5.objects.FastModel import ( + AmbaInitiatorSocket, + AmbaTargetSocket, +) from m5.objects.Gic import BaseGic from m5.objects.IntPin import VectorIntSourcePin from m5.objects.ResetPort import ResetResponsePort from m5.objects.SystemC import SystemC_ScModule +from m5.params import * +from m5.SimObject import SimObject +from m5.util.fdthelper import * GICV3_COMMS_TARGET_ROLE = "GICV3 COMMS TARGET" GICV3_COMMS_INITIATOR_ROLE = "GICV3 COMMS INITIATOR" diff --git a/src/arch/arm/fastmodel/PL330_DMAC/FastModelPL330.py b/src/arch/arm/fastmodel/PL330_DMAC/FastModelPL330.py index 21ead525d3..23b6f711a0 100644 --- a/src/arch/arm/fastmodel/PL330_DMAC/FastModelPL330.py +++ b/src/arch/arm/fastmodel/PL330_DMAC/FastModelPL330.py @@ -23,11 +23,14 @@ # (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.params import * -from m5.objects.FastModel import AmbaInitiatorSocket, AmbaTargetSocket +from m5.objects.FastModel import ( + AmbaInitiatorSocket, + AmbaTargetSocket, +) from m5.objects.IntPin import IntSourcePin from m5.objects.ResetPort import ResetResponsePort from m5.objects.SystemC import SystemC_ScModule +from m5.params import * class FastModelPL330(SystemC_ScModule): diff --git a/src/arch/arm/fastmodel/arm_fast_model.py b/src/arch/arm/fastmodel/arm_fast_model.py index 45a97d7957..df7b1b63b7 100644 --- a/src/arch/arm/fastmodel/arm_fast_model.py +++ b/src/arch/arm/fastmodel/arm_fast_model.py @@ -29,6 +29,7 @@ import os import socket from m5.defines import buildEnv + import _m5.arm_fast_model ARM_LICENSE_ENV = "ARMLMD_LICENSE_FILE" diff --git a/src/arch/arm/fastmodel/iris/Iris.py b/src/arch/arm/fastmodel/iris/Iris.py index c38db908cc..5129136077 100644 --- a/src/arch/arm/fastmodel/iris/Iris.py +++ b/src/arch/arm/fastmodel/iris/Iris.py @@ -35,14 +35,13 @@ # (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.params import * -from m5.proxy import * - from m5.objects.BaseCPU import BaseCPU from m5.objects.BaseInterrupts import BaseInterrupts from m5.objects.BaseISA import BaseISA -from m5.objects.BaseTLB import BaseTLB from m5.objects.BaseMMU import BaseMMU +from m5.objects.BaseTLB import BaseTLB +from m5.params import * +from m5.proxy import * class IrisTLB(BaseTLB): diff --git a/src/arch/arm/fastmodel/reset_controller/FastModelResetControllerExample.py b/src/arch/arm/fastmodel/reset_controller/FastModelResetControllerExample.py index 225c5d917b..e2507cbf4c 100644 --- a/src/arch/arm/fastmodel/reset_controller/FastModelResetControllerExample.py +++ b/src/arch/arm/fastmodel/reset_controller/FastModelResetControllerExample.py @@ -23,12 +23,11 @@ # (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.params import * -from m5.proxy import * - from m5.objects.Device import BasicPioDevice from m5.objects.IntPin import IntSourcePin from m5.objects.Iris import IrisBaseCPU +from m5.params import * +from m5.proxy import * class FastModelResetControllerExample(BasicPioDevice): diff --git a/src/arch/arm/kvm/ArmKvmCPU.py b/src/arch/arm/kvm/ArmKvmCPU.py index 56770a5b0a..d3829f5c71 100644 --- a/src/arch/arm/kvm/ArmKvmCPU.py +++ b/src/arch/arm/kvm/ArmKvmCPU.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.BaseKvmCPU import BaseKvmCPU +from m5.params import * class ArmKvmCPU(BaseKvmCPU): diff --git a/src/arch/arm/kvm/ArmV8KvmCPU.py b/src/arch/arm/kvm/ArmV8KvmCPU.py index a6d83bb610..39f9d0d1ba 100644 --- a/src/arch/arm/kvm/ArmV8KvmCPU.py +++ b/src/arch/arm/kvm/ArmV8KvmCPU.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.BaseArmKvmCPU import BaseArmKvmCPU +from m5.params import * class ArmV8KvmCPU(BaseArmKvmCPU): diff --git a/src/arch/arm/kvm/BaseArmKvmCPU.py b/src/arch/arm/kvm/BaseArmKvmCPU.py index f896256063..415cf78a9e 100644 --- a/src/arch/arm/kvm/BaseArmKvmCPU.py +++ b/src/arch/arm/kvm/BaseArmKvmCPU.py @@ -33,10 +33,10 @@ # (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.params import * from m5.objects.ArmCPU import ArmCPU from m5.objects.ArmMMU import ArmMMU from m5.objects.BaseKvmCPU import BaseKvmCPU +from m5.params import * class BaseArmKvmCPU(BaseKvmCPU, ArmCPU): diff --git a/src/arch/arm/kvm/KvmGic.py b/src/arch/arm/kvm/KvmGic.py index 1002d3c2f5..a9e1e9341d 100644 --- a/src/arch/arm/kvm/KvmGic.py +++ b/src/arch/arm/kvm/KvmGic.py @@ -33,11 +33,13 @@ # (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.Gic import ( + GicV2, + Gicv3, +) from m5.params import * from m5.proxy import * -from m5.objects.Gic import GicV2, Gicv3 - class MuxingKvmGicV2(GicV2): type = "MuxingKvmGicV2" diff --git a/src/arch/arm/tracers/ArmCapstone.py b/src/arch/arm/tracers/ArmCapstone.py index 7f1b6a9e8a..0bceb6dbd6 100644 --- a/src/arch/arm/tracers/ArmCapstone.py +++ b/src/arch/arm/tracers/ArmCapstone.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.Capstone import CapstoneDisassembler +from m5.params import * +from m5.SimObject import SimObject class ArmCapstoneDisassembler(CapstoneDisassembler): diff --git a/src/arch/arm/tracers/TarmacTrace.py b/src/arch/arm/tracers/TarmacTrace.py index 82c447aada..e28b19bee4 100644 --- a/src/arch/arm/tracers/TarmacTrace.py +++ b/src/arch/arm/tracers/TarmacTrace.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.InstTracer import InstTracer +from m5.params import * +from m5.SimObject import SimObject class TarmacParser(InstTracer): diff --git a/src/arch/isa_parser/isa_parser.py b/src/arch/isa_parser/isa_parser.py index b0b2485cac..0b74d00f29 100755 --- a/src/arch/isa_parser/isa_parser.py +++ b/src/arch/isa_parser/isa_parser.py @@ -46,6 +46,7 @@ import traceback from types import * from grammar import Grammar + from .operand_list import * from .operand_types import * from .util import * diff --git a/src/arch/isa_parser/operand_list.py b/src/arch/isa_parser/operand_list.py index 29062893ec..2fe0ef1739 100755 --- a/src/arch/isa_parser/operand_list.py +++ b/src/arch/isa_parser/operand_list.py @@ -37,8 +37,12 @@ # (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 .util import assignRE, commentRE, stringRE -from .util import error +from .util import ( + assignRE, + commentRE, + error, + stringRE, +) class OperandList: diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index ec890cbe6d..0329800896 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -25,15 +25,17 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os -import sys import re +import sys import traceback # get type names from types import * -from ply import lex -from ply import yacc +from ply import ( + lex, + yacc, +) ########################################################################## # diff --git a/src/arch/micro_asm_test.py b/src/arch/micro_asm_test.py index b6b8918b2d..29724aa2d7 100755 --- a/src/arch/micro_asm_test.py +++ b/src/arch/micro_asm_test.py @@ -24,7 +24,12 @@ # (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 micro_asm import MicroAssembler, CombinationalMacroop, RomMacroop, Rom +from micro_asm import ( + CombinationalMacroop, + MicroAssembler, + Rom, + RomMacroop, +) class Bah: diff --git a/src/arch/mips/MipsCPU.py b/src/arch/mips/MipsCPU.py index 53b134ad79..558bbf8733 100644 --- a/src/arch/mips/MipsCPU.py +++ b/src/arch/mips/MipsCPU.py @@ -24,14 +24,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU -from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU -from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU -from m5.objects.BaseO3CPU import BaseO3CPU from m5.objects.BaseMinorCPU import BaseMinorCPU +from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU +from m5.objects.BaseO3CPU import BaseO3CPU +from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU from m5.objects.MipsDecoder import MipsDecoder -from m5.objects.MipsMMU import MipsMMU from m5.objects.MipsInterrupts import MipsInterrupts from m5.objects.MipsISA import MipsISA +from m5.objects.MipsMMU import MipsMMU class MipsCPU: diff --git a/src/arch/mips/MipsISA.py b/src/arch/mips/MipsISA.py index 01075dd1b0..f3eb85b8ed 100644 --- a/src/arch/mips/MipsISA.py +++ b/src/arch/mips/MipsISA.py @@ -33,11 +33,10 @@ # (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.BaseISA import BaseISA from m5.params import * from m5.proxy import * -from m5.objects.BaseISA import BaseISA - class MipsISA(BaseISA): type = "MipsISA" diff --git a/src/arch/mips/MipsSeWorkload.py b/src/arch/mips/MipsSeWorkload.py index b5f20cd892..ba73c112a4 100644 --- a/src/arch/mips/MipsSeWorkload.py +++ b/src/arch/mips/MipsSeWorkload.py @@ -23,9 +23,8 @@ # (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.params import * - from m5.objects.Workload import SEWorkload +from m5.params import * class MipsSEWorkload(SEWorkload): diff --git a/src/arch/mips/MipsTLB.py b/src/arch/mips/MipsTLB.py index 2051c662e0..43906f11d3 100644 --- a/src/arch/mips/MipsTLB.py +++ b/src/arch/mips/MipsTLB.py @@ -26,10 +26,9 @@ # (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.SimObject import SimObject -from m5.params import * - from m5.objects.BaseTLB import BaseTLB +from m5.params import * +from m5.SimObject import SimObject class MipsTLB(BaseTLB): diff --git a/src/arch/power/PowerCPU.py b/src/arch/power/PowerCPU.py index f19c6f6a2f..b634a78c4a 100644 --- a/src/arch/power/PowerCPU.py +++ b/src/arch/power/PowerCPU.py @@ -24,14 +24,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU -from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU -from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU -from m5.objects.BaseO3CPU import BaseO3CPU from m5.objects.BaseMinorCPU import BaseMinorCPU +from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU +from m5.objects.BaseO3CPU import BaseO3CPU +from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU from m5.objects.PowerDecoder import PowerDecoder -from m5.objects.PowerMMU import PowerMMU from m5.objects.PowerInterrupts import PowerInterrupts from m5.objects.PowerISA import PowerISA +from m5.objects.PowerMMU import PowerMMU class PowerCPU: diff --git a/src/arch/power/PowerSeWorkload.py b/src/arch/power/PowerSeWorkload.py index 162104d0dd..4a4116be4b 100644 --- a/src/arch/power/PowerSeWorkload.py +++ b/src/arch/power/PowerSeWorkload.py @@ -23,9 +23,8 @@ # (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.params import * - from m5.objects.Workload import SEWorkload +from m5.params import * class PowerSEWorkload(SEWorkload): diff --git a/src/arch/power/PowerTLB.py b/src/arch/power/PowerTLB.py index 32c4a68940..9217f24d30 100644 --- a/src/arch/power/PowerTLB.py +++ b/src/arch/power/PowerTLB.py @@ -26,10 +26,9 @@ # (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.SimObject import SimObject -from m5.params import * - from m5.objects.BaseTLB import BaseTLB +from m5.params import * +from m5.SimObject import SimObject class PowerTLB(BaseTLB): diff --git a/src/arch/riscv/PMAChecker.py b/src/arch/riscv/PMAChecker.py index 581560bd56..c456569b32 100644 --- a/src/arch/riscv/PMAChecker.py +++ b/src/arch/riscv/PMAChecker.py @@ -35,9 +35,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class PMAChecker(SimObject): diff --git a/src/arch/riscv/PMP.py b/src/arch/riscv/PMP.py index a3844c99fd..dc0608d643 100644 --- a/src/arch/riscv/PMP.py +++ b/src/arch/riscv/PMP.py @@ -24,9 +24,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class PMP(SimObject): diff --git a/src/arch/riscv/RiscvCPU.py b/src/arch/riscv/RiscvCPU.py index 1c77045c67..2b1b053b48 100644 --- a/src/arch/riscv/RiscvCPU.py +++ b/src/arch/riscv/RiscvCPU.py @@ -24,14 +24,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU -from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU -from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU -from m5.objects.BaseO3CPU import BaseO3CPU from m5.objects.BaseMinorCPU import BaseMinorCPU +from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU +from m5.objects.BaseO3CPU import BaseO3CPU +from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU from m5.objects.RiscvDecoder import RiscvDecoder -from m5.objects.RiscvMMU import RiscvMMU from m5.objects.RiscvInterrupts import RiscvInterrupts from m5.objects.RiscvISA import RiscvISA +from m5.objects.RiscvMMU import RiscvMMU class RiscvCPU: diff --git a/src/arch/riscv/RiscvFsWorkload.py b/src/arch/riscv/RiscvFsWorkload.py index a71dc1acaf..36580a5498 100644 --- a/src/arch/riscv/RiscvFsWorkload.py +++ b/src/arch/riscv/RiscvFsWorkload.py @@ -27,10 +27,12 @@ # (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.params import * - from m5.objects.System import System -from m5.objects.Workload import Workload, KernelWorkload +from m5.objects.Workload import ( + KernelWorkload, + Workload, +) +from m5.params import * class RiscvBareMetal(Workload): diff --git a/src/arch/riscv/RiscvISA.py b/src/arch/riscv/RiscvISA.py index bce7f2497f..d4dcf663b7 100644 --- a/src/arch/riscv/RiscvISA.py +++ b/src/arch/riscv/RiscvISA.py @@ -39,9 +39,12 @@ # (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.params import Enum, UInt32 -from m5.params import Param from m5.objects.BaseISA import BaseISA +from m5.params import ( + Enum, + Param, + UInt32, +) class RiscvVectorLength(UInt32): diff --git a/src/arch/riscv/RiscvMMU.py b/src/arch/riscv/RiscvMMU.py index 312244a85d..6ef4182c88 100644 --- a/src/arch/riscv/RiscvMMU.py +++ b/src/arch/riscv/RiscvMMU.py @@ -35,12 +35,11 @@ # (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.params import * - from m5.objects.BaseMMU import BaseMMU -from m5.objects.RiscvTLB import RiscvTLB from m5.objects.PMAChecker import PMAChecker from m5.objects.PMP import PMP +from m5.objects.RiscvTLB import RiscvTLB +from m5.params import * class RiscvMMU(BaseMMU): diff --git a/src/arch/riscv/RiscvSeWorkload.py b/src/arch/riscv/RiscvSeWorkload.py index 5df6b786c3..45aa79ed5b 100644 --- a/src/arch/riscv/RiscvSeWorkload.py +++ b/src/arch/riscv/RiscvSeWorkload.py @@ -23,9 +23,8 @@ # (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.params import * - from m5.objects.Workload import SEWorkload +from m5.params import * class RiscvSEWorkload(SEWorkload): diff --git a/src/arch/riscv/RiscvTLB.py b/src/arch/riscv/RiscvTLB.py index e943d8ddab..05a1c71b19 100644 --- a/src/arch/riscv/RiscvTLB.py +++ b/src/arch/riscv/RiscvTLB.py @@ -28,11 +28,10 @@ # (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.params import * -from m5.proxy import * - from m5.objects.BaseTLB import BaseTLB from m5.objects.ClockedObject import ClockedObject +from m5.params import * +from m5.proxy import * class RiscvPagetableWalker(ClockedObject): diff --git a/src/arch/sparc/SparcCPU.py b/src/arch/sparc/SparcCPU.py index 44d9ceed08..fdc17729e2 100644 --- a/src/arch/sparc/SparcCPU.py +++ b/src/arch/sparc/SparcCPU.py @@ -24,14 +24,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU -from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU -from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU -from m5.objects.BaseO3CPU import BaseO3CPU from m5.objects.BaseMinorCPU import BaseMinorCPU +from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU +from m5.objects.BaseO3CPU import BaseO3CPU +from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU from m5.objects.SparcDecoder import SparcDecoder -from m5.objects.SparcMMU import SparcMMU from m5.objects.SparcInterrupts import SparcInterrupts from m5.objects.SparcISA import SparcISA +from m5.objects.SparcMMU import SparcMMU class SparcCPU: diff --git a/src/arch/sparc/SparcFsWorkload.py b/src/arch/sparc/SparcFsWorkload.py index ba70dcfa59..89b17a82f9 100644 --- a/src/arch/sparc/SparcFsWorkload.py +++ b/src/arch/sparc/SparcFsWorkload.py @@ -24,9 +24,8 @@ # (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.params import * - from m5.objects.Workload import Workload +from m5.params import * class SparcFsWorkload(Workload): diff --git a/src/arch/sparc/SparcMMU.py b/src/arch/sparc/SparcMMU.py index 1202594fc6..a00be60685 100644 --- a/src/arch/sparc/SparcMMU.py +++ b/src/arch/sparc/SparcMMU.py @@ -35,10 +35,10 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.BaseMMU import BaseMMU from m5.objects.SparcTLB import SparcTLB +from m5.params import * +from m5.SimObject import SimObject class SparcMMU(BaseMMU): diff --git a/src/arch/sparc/SparcNativeTrace.py b/src/arch/sparc/SparcNativeTrace.py index 0a93126f2c..9b215e19c6 100644 --- a/src/arch/sparc/SparcNativeTrace.py +++ b/src/arch/sparc/SparcNativeTrace.py @@ -24,10 +24,9 @@ # (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.SimObject import SimObject -from m5.params import * - from m5.objects.CPUTracers import NativeTrace +from m5.params import * +from m5.SimObject import SimObject class SparcNativeTrace(NativeTrace): diff --git a/src/arch/sparc/SparcSeWorkload.py b/src/arch/sparc/SparcSeWorkload.py index 3dbd341801..060bf21005 100644 --- a/src/arch/sparc/SparcSeWorkload.py +++ b/src/arch/sparc/SparcSeWorkload.py @@ -23,9 +23,8 @@ # (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.params import * - from m5.objects.Workload import SEWorkload +from m5.params import * class SparcSEWorkload(SEWorkload): diff --git a/src/arch/sparc/SparcTLB.py b/src/arch/sparc/SparcTLB.py index e834d62000..6b43d69cfc 100644 --- a/src/arch/sparc/SparcTLB.py +++ b/src/arch/sparc/SparcTLB.py @@ -24,10 +24,9 @@ # (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.SimObject import SimObject -from m5.params import * - from m5.objects.BaseTLB import BaseTLB +from m5.params import * +from m5.SimObject import SimObject class SparcTLB(BaseTLB): diff --git a/src/arch/x86/X86CPU.py b/src/arch/x86/X86CPU.py index bd39f6d0f5..ac3398bb6d 100644 --- a/src/arch/x86/X86CPU.py +++ b/src/arch/x86/X86CPU.py @@ -23,19 +23,18 @@ # (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.proxy import Self - from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU -from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU -from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU -from m5.objects.BaseO3CPU import BaseO3CPU from m5.objects.BaseMinorCPU import BaseMinorCPU +from m5.objects.BaseNonCachingSimpleCPU import BaseNonCachingSimpleCPU +from m5.objects.BaseO3CPU import BaseO3CPU +from m5.objects.BaseTimingSimpleCPU import BaseTimingSimpleCPU from m5.objects.FuncUnit import * from m5.objects.FUPool import * from m5.objects.X86Decoder import X86Decoder -from m5.objects.X86MMU import X86MMU -from m5.objects.X86LocalApic import X86LocalApic from m5.objects.X86ISA import X86ISA +from m5.objects.X86LocalApic import X86LocalApic +from m5.objects.X86MMU import X86MMU +from m5.proxy import Self class X86CPU: diff --git a/src/arch/x86/X86FsWorkload.py b/src/arch/x86/X86FsWorkload.py index 277a37988e..6cff4211ae 100644 --- a/src/arch/x86/X86FsWorkload.py +++ b/src/arch/x86/X86FsWorkload.py @@ -33,13 +33,21 @@ # (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.params import * - -from m5.objects.E820 import X86E820Table, X86E820Entry -from m5.objects.SMBios import X86SMBiosSMBiosTable -from m5.objects.IntelMP import X86IntelMPFloatingPointer, X86IntelMPConfigTable from m5.objects.ACPI import X86ACPIRSDP -from m5.objects.Workload import KernelWorkload, Workload +from m5.objects.E820 import ( + X86E820Entry, + X86E820Table, +) +from m5.objects.IntelMP import ( + X86IntelMPConfigTable, + X86IntelMPFloatingPointer, +) +from m5.objects.SMBios import X86SMBiosSMBiosTable +from m5.objects.Workload import ( + KernelWorkload, + Workload, +) +from m5.params import * class X86BareMetalWorkload(Workload): diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py index d7defce7e5..8b7d9a831d 100644 --- a/src/arch/x86/X86LocalApic.py +++ b/src/arch/x86/X86LocalApic.py @@ -37,12 +37,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv -from m5.params import * -from m5.proxy import * - from m5.objects.BaseInterrupts import BaseInterrupts from m5.objects.ClockDomain import DerivedClockDomain from m5.objects.IntPin import IntSinkPin +from m5.params import * +from m5.proxy import * class X86LocalApic(BaseInterrupts): diff --git a/src/arch/x86/X86NativeTrace.py b/src/arch/x86/X86NativeTrace.py index d0b94ecc40..773071674d 100644 --- a/src/arch/x86/X86NativeTrace.py +++ b/src/arch/x86/X86NativeTrace.py @@ -24,10 +24,9 @@ # (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.SimObject import SimObject -from m5.params import * - from m5.objects.CPUTracers import NativeTrace +from m5.params import * +from m5.SimObject import SimObject class X86NativeTrace(NativeTrace): diff --git a/src/arch/x86/X86SeWorkload.py b/src/arch/x86/X86SeWorkload.py index 6674bdb9a5..e8e75a3ec3 100644 --- a/src/arch/x86/X86SeWorkload.py +++ b/src/arch/x86/X86SeWorkload.py @@ -23,9 +23,8 @@ # (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.params import * - from m5.objects.Workload import SEWorkload +from m5.params import * class X86EmuLinux(SEWorkload): diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py index 8532ddf8c6..8c3c65cce3 100644 --- a/src/arch/x86/X86TLB.py +++ b/src/arch/x86/X86TLB.py @@ -33,11 +33,10 @@ # (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.params import * -from m5.proxy import * - from m5.objects.BaseTLB import BaseTLB from m5.objects.ClockedObject import ClockedObject +from m5.params import * +from m5.proxy import * class X86PagetableWalker(ClockedObject): diff --git a/src/arch/x86/kvm/X86KvmCPU.py b/src/arch/x86/kvm/X86KvmCPU.py index df32fe8b40..6f50ba2511 100644 --- a/src/arch/x86/kvm/X86KvmCPU.py +++ b/src/arch/x86/kvm/X86KvmCPU.py @@ -24,12 +24,11 @@ # (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.params import * -from m5.SimObject import * - from m5.objects.BaseKvmCPU import BaseKvmCPU from m5.objects.X86CPU import X86CPU from m5.objects.X86MMU import X86MMU +from m5.params import * +from m5.SimObject import * class X86KvmCPU(BaseKvmCPU, X86CPU): diff --git a/src/base/Graphics.py b/src/base/Graphics.py index b58e287129..824a3c4a9d 100644 --- a/src/base/Graphics.py +++ b/src/base/Graphics.py @@ -33,8 +33,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject # Image Formats: diff --git a/src/base/vnc/Vnc.py b/src/base/vnc/Vnc.py index e7012ecb06..5ee03c3f8b 100644 --- a/src/base/vnc/Vnc.py +++ b/src/base/vnc/Vnc.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.Graphics import * +from m5.params import * +from m5.SimObject import SimObject class VncInput(SimObject): diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 900c0ae626..9ba60ef1b8 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -40,20 +40,19 @@ import sys -from m5.SimObject import * from m5.defines import buildEnv -from m5.params import * -from m5.proxy import * -from m5.util.fdthelper import * - -from m5.objects.ClockedObject import ClockedObject -from m5.objects.XBar import L2XBar -from m5.objects.InstTracer import InstTracer -from m5.objects.CPUTracers import ExeTracer -from m5.objects.SubSystem import SubSystem from m5.objects.ClockDomain import * +from m5.objects.ClockedObject import ClockedObject +from m5.objects.CPUTracers import ExeTracer +from m5.objects.InstTracer import InstTracer from m5.objects.Platform import Platform from m5.objects.ResetPort import ResetResponsePort +from m5.objects.SubSystem import SubSystem +from m5.objects.XBar import L2XBar +from m5.params import * +from m5.proxy import * +from m5.SimObject import * +from m5.util.fdthelper import * default_tracer = ExeTracer() diff --git a/src/cpu/CPUTracers.py b/src/cpu/CPUTracers.py index f491a0ef43..ce6c3b4e33 100644 --- a/src/cpu/CPUTracers.py +++ b/src/cpu/CPUTracers.py @@ -24,9 +24,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.InstTracer import InstTracer +from m5.params import * +from m5.SimObject import SimObject class ExeTracer(InstTracer): diff --git a/src/cpu/Capstone.py b/src/cpu/Capstone.py index 4b6b5fd84a..ac6e0b7e95 100644 --- a/src/cpu/Capstone.py +++ b/src/cpu/Capstone.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.InstTracer import InstDisassembler +from m5.params import * +from m5.SimObject import SimObject class CapstoneDisassembler(InstDisassembler): diff --git a/src/cpu/CheckerCPU.py b/src/cpu/CheckerCPU.py index beb04b79e1..9cd0ce4c33 100644 --- a/src/cpu/CheckerCPU.py +++ b/src/cpu/CheckerCPU.py @@ -24,9 +24,8 @@ # (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.params import * - from m5.objects.BaseCPU import BaseCPU +from m5.params import * from m5.SimObject import SimObject diff --git a/src/cpu/CpuCluster.py b/src/cpu/CpuCluster.py index 42a71122a3..c26bc653af 100644 --- a/src/cpu/CpuCluster.py +++ b/src/cpu/CpuCluster.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.SubSystem import SubSystem +from m5.params import * class CpuCluster(SubSystem): diff --git a/src/cpu/DummyChecker.py b/src/cpu/DummyChecker.py index 916d25a92a..7176498e6c 100644 --- a/src/cpu/DummyChecker.py +++ b/src/cpu/DummyChecker.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.CheckerCPU import CheckerCPU +from m5.params import * class DummyChecker(CheckerCPU): diff --git a/src/cpu/FuncUnit.py b/src/cpu/FuncUnit.py index 012dfd0ee4..cba3eda878 100644 --- a/src/cpu/FuncUnit.py +++ b/src/cpu/FuncUnit.py @@ -36,8 +36,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject class OpClass(Enum): diff --git a/src/cpu/InstPBTrace.py b/src/cpu/InstPBTrace.py index 167443d3cd..ca50ed4644 100644 --- a/src/cpu/InstPBTrace.py +++ b/src/cpu/InstPBTrace.py @@ -24,10 +24,9 @@ # (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.SimObject import SimObject -from m5.params import * - from m5.objects.InstTracer import InstTracer +from m5.params import * +from m5.SimObject import SimObject class InstPBTrace(InstTracer): diff --git a/src/cpu/kvm/BaseKvmCPU.py b/src/cpu/kvm/BaseKvmCPU.py index 610663fa41..2c90acf3e8 100644 --- a/src/cpu/kvm/BaseKvmCPU.py +++ b/src/cpu/kvm/BaseKvmCPU.py @@ -33,12 +33,11 @@ # (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.SimObject import * -from m5.params import * -from m5.proxy import * - from m5.objects.BaseCPU import BaseCPU from m5.objects.KvmVM import KvmVM +from m5.params import * +from m5.proxy import * +from m5.SimObject import * class BaseKvmCPU(BaseCPU): diff --git a/src/cpu/kvm/KvmVM.py b/src/cpu/kvm/KvmVM.py index cdb826cf6c..5198de10f2 100644 --- a/src/cpu/kvm/KvmVM.py +++ b/src/cpu/kvm/KvmVM.py @@ -35,7 +35,6 @@ from m5.params import * from m5.proxy import * - from m5.SimObject import SimObject diff --git a/src/cpu/minor/BaseMinorCPU.py b/src/cpu/minor/BaseMinorCPU.py index c20a310447..7110caac2c 100644 --- a/src/cpu/minor/BaseMinorCPU.py +++ b/src/cpu/minor/BaseMinorCPU.py @@ -37,15 +37,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv +from m5.objects.BaseCPU import BaseCPU +from m5.objects.BranchPredictor import * +from m5.objects.DummyChecker import DummyChecker +from m5.objects.FuncUnit import OpClass +from m5.objects.TimingExpr import TimingExpr from m5.params import * from m5.proxy import * from m5.SimObject import SimObject -from m5.objects.BaseCPU import BaseCPU -from m5.objects.DummyChecker import DummyChecker -from m5.objects.BranchPredictor import * -from m5.objects.TimingExpr import TimingExpr - -from m5.objects.FuncUnit import OpClass class MinorOpClass(SimObject): diff --git a/src/cpu/o3/BaseO3CPU.py b/src/cpu/o3/BaseO3CPU.py index 2e1a602e4c..dfb1068c7c 100644 --- a/src/cpu/o3/BaseO3CPU.py +++ b/src/cpu/o3/BaseO3CPU.py @@ -37,14 +37,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv -from m5.params import * -from m5.proxy import * - from m5.objects.BaseCPU import BaseCPU -from m5.objects.FUPool import * # from m5.objects.O3Checker import O3Checker from m5.objects.BranchPredictor import * +from m5.objects.FUPool import * +from m5.params import * +from m5.proxy import * class SMTFetchPolicy(ScopedEnum): diff --git a/src/cpu/o3/BaseO3Checker.py b/src/cpu/o3/BaseO3Checker.py index 7b480f8057..cda6dad57e 100644 --- a/src/cpu/o3/BaseO3Checker.py +++ b/src/cpu/o3/BaseO3Checker.py @@ -24,8 +24,8 @@ # (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.params import * from m5.objects.CheckerCPU import CheckerCPU +from m5.params import * class BaseO3Checker(CheckerCPU): diff --git a/src/cpu/o3/FUPool.py b/src/cpu/o3/FUPool.py index 4e18094ef4..67f523787b 100644 --- a/src/cpu/o3/FUPool.py +++ b/src/cpu/o3/FUPool.py @@ -36,10 +36,10 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.FuncUnit import * from m5.objects.FuncUnitConfig import * +from m5.params import * +from m5.SimObject import SimObject class FUPool(SimObject): diff --git a/src/cpu/o3/FuncUnitConfig.py b/src/cpu/o3/FuncUnitConfig.py index 7ba49c93bf..617cef9749 100644 --- a/src/cpu/o3/FuncUnitConfig.py +++ b/src/cpu/o3/FuncUnitConfig.py @@ -36,11 +36,10 @@ # (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.SimObject import SimObject from m5.defines import buildEnv -from m5.params import * - from m5.objects.FuncUnit import * +from m5.params import * +from m5.SimObject import SimObject class IntALU(FUDesc): diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index 8589fe5d51..3ac333934e 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -37,11 +37,10 @@ # (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.SimObject import * +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * - -from m5.objects.ClockedObject import ClockedObject +from m5.SimObject import * class BranchType(Enum): diff --git a/src/cpu/probes/PcCountTracker.py b/src/cpu/probes/PcCountTracker.py index 259ec68f8e..6106970436 100644 --- a/src/cpu/probes/PcCountTracker.py +++ b/src/cpu/probes/PcCountTracker.py @@ -24,10 +24,10 @@ # (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 SimObject +from m5.objects.Probe import ProbeListenerObject from m5.params import * from m5.util.pybind import * -from m5.objects.Probe import ProbeListenerObject -from m5.objects import SimObject class PcCountTrackerManager(SimObject): diff --git a/src/cpu/simple/BaseAtomicSimpleCPU.py b/src/cpu/simple/BaseAtomicSimpleCPU.py index 4ee53aef0f..27367bd0cf 100644 --- a/src/cpu/simple/BaseAtomicSimpleCPU.py +++ b/src/cpu/simple/BaseAtomicSimpleCPU.py @@ -36,9 +36,9 @@ # (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.params import * from m5.objects.BaseSimpleCPU import BaseSimpleCPU from m5.objects.SimPoint import SimPoint +from m5.params import * class BaseAtomicSimpleCPU(BaseSimpleCPU): diff --git a/src/cpu/simple/BaseNonCachingSimpleCPU.py b/src/cpu/simple/BaseNonCachingSimpleCPU.py index 58a7324068..787b4fccb0 100644 --- a/src/cpu/simple/BaseNonCachingSimpleCPU.py +++ b/src/cpu/simple/BaseNonCachingSimpleCPU.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.BaseAtomicSimpleCPU import BaseAtomicSimpleCPU +from m5.params import * class BaseNonCachingSimpleCPU(BaseAtomicSimpleCPU): diff --git a/src/cpu/simple/BaseSimpleCPU.py b/src/cpu/simple/BaseSimpleCPU.py index fe7ad751a7..d4816700c0 100644 --- a/src/cpu/simple/BaseSimpleCPU.py +++ b/src/cpu/simple/BaseSimpleCPU.py @@ -25,11 +25,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv -from m5.params import * - from m5.objects.BaseCPU import BaseCPU -from m5.objects.DummyChecker import DummyChecker from m5.objects.BranchPredictor import * +from m5.objects.DummyChecker import DummyChecker +from m5.params import * class BaseSimpleCPU(BaseCPU): diff --git a/src/cpu/simple/BaseTimingSimpleCPU.py b/src/cpu/simple/BaseTimingSimpleCPU.py index 5761816fa7..6b1a1a7699 100644 --- a/src/cpu/simple/BaseTimingSimpleCPU.py +++ b/src/cpu/simple/BaseTimingSimpleCPU.py @@ -24,9 +24,8 @@ # (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.params import * - from m5.objects.BaseSimpleCPU import BaseSimpleCPU +from m5.params import * class BaseTimingSimpleCPU(BaseSimpleCPU): diff --git a/src/cpu/simple/probes/SimPoint.py b/src/cpu/simple/probes/SimPoint.py index 6f2f13ba74..73a716760f 100644 --- a/src/cpu/simple/probes/SimPoint.py +++ b/src/cpu/simple/probes/SimPoint.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.Probe import ProbeListenerObject +from m5.params import * class SimPoint(ProbeListenerObject): diff --git a/src/cpu/testers/directedtest/RubyDirectedTester.py b/src/cpu/testers/directedtest/RubyDirectedTester.py index b9297b058b..d01b0bdee2 100644 --- a/src/cpu/testers/directedtest/RubyDirectedTester.py +++ b/src/cpu/testers/directedtest/RubyDirectedTester.py @@ -24,11 +24,10 @@ # (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.SimObject import SimObject +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * - -from m5.objects.ClockedObject import ClockedObject +from m5.SimObject import SimObject class DirectedGenerator(SimObject): diff --git a/src/cpu/testers/gpu_ruby_test/CpuThread.py b/src/cpu/testers/gpu_ruby_test/CpuThread.py index f40df272a4..e74301b677 100644 --- a/src/cpu/testers/gpu_ruby_test/CpuThread.py +++ b/src/cpu/testers/gpu_ruby_test/CpuThread.py @@ -27,11 +27,10 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.objects.TesterThread import TesterThread from m5.params import * from m5.proxy import * -from m5.objects.TesterThread import TesterThread - class CpuThread(TesterThread): type = "CpuThread" diff --git a/src/cpu/testers/gpu_ruby_test/DmaThread.py b/src/cpu/testers/gpu_ruby_test/DmaThread.py index 0a3dbc7289..c1b9b91a43 100644 --- a/src/cpu/testers/gpu_ruby_test/DmaThread.py +++ b/src/cpu/testers/gpu_ruby_test/DmaThread.py @@ -27,11 +27,10 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.objects.TesterThread import TesterThread from m5.params import * from m5.proxy import * -from m5.objects.TesterThread import TesterThread - class DmaThread(TesterThread): type = "DmaThread" diff --git a/src/cpu/testers/gpu_ruby_test/GpuWavefront.py b/src/cpu/testers/gpu_ruby_test/GpuWavefront.py index 625af91fa4..2a22f4d7c7 100644 --- a/src/cpu/testers/gpu_ruby_test/GpuWavefront.py +++ b/src/cpu/testers/gpu_ruby_test/GpuWavefront.py @@ -27,11 +27,10 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.objects.TesterThread import TesterThread from m5.params import * from m5.proxy import * -from m5.objects.TesterThread import TesterThread - class GpuWavefront(TesterThread): type = "GpuWavefront" diff --git a/src/cpu/testers/memtest/MemTest.py b/src/cpu/testers/memtest/MemTest.py index 2d6a0e33c5..db22d86e4e 100644 --- a/src/cpu/testers/memtest/MemTest.py +++ b/src/cpu/testers/memtest/MemTest.py @@ -36,11 +36,10 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject - class MemTest(ClockedObject): type = "MemTest" diff --git a/src/cpu/testers/rubytest/RubyTester.py b/src/cpu/testers/rubytest/RubyTester.py index a90cfe1f82..e613eff79c 100644 --- a/src/cpu/testers/rubytest/RubyTester.py +++ b/src/cpu/testers/rubytest/RubyTester.py @@ -25,11 +25,10 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject - class RubyTester(ClockedObject): type = "RubyTester" diff --git a/src/cpu/testers/traffic_gen/BaseTrafficGen.py b/src/cpu/testers/traffic_gen/BaseTrafficGen.py index 7fdfda22e5..48700e0747 100644 --- a/src/cpu/testers/traffic_gen/BaseTrafficGen.py +++ b/src/cpu/testers/traffic_gen/BaseTrafficGen.py @@ -33,9 +33,9 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject # Types of Stream Generators. diff --git a/src/cpu/testers/traffic_gen/GUPSGen.py b/src/cpu/testers/traffic_gen/GUPSGen.py index 6b8b3f72df..747a8de994 100644 --- a/src/cpu/testers/traffic_gen/GUPSGen.py +++ b/src/cpu/testers/traffic_gen/GUPSGen.py @@ -25,9 +25,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject class GUPSGen(ClockedObject): diff --git a/src/cpu/testers/traffic_gen/PyTrafficGen.py b/src/cpu/testers/traffic_gen/PyTrafficGen.py index c3a660f053..be61ec1e56 100644 --- a/src/cpu/testers/traffic_gen/PyTrafficGen.py +++ b/src/cpu/testers/traffic_gen/PyTrafficGen.py @@ -34,9 +34,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv -from m5.SimObject import * - from m5.objects.BaseTrafficGen import * +from m5.SimObject import * class PyTrafficGen(BaseTrafficGen): diff --git a/src/cpu/testers/traffic_gen/TrafficGen.py b/src/cpu/testers/traffic_gen/TrafficGen.py index 15190120cc..d5242099d1 100644 --- a/src/cpu/testers/traffic_gen/TrafficGen.py +++ b/src/cpu/testers/traffic_gen/TrafficGen.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.BaseTrafficGen import * +from m5.params import * # The behaviour of this traffic generator is specified in a diff --git a/src/cpu/trace/TraceCPU.py b/src/cpu/trace/TraceCPU.py index 5e82fd9f9f..7b053e569f 100644 --- a/src/cpu/trace/TraceCPU.py +++ b/src/cpu/trace/TraceCPU.py @@ -33,9 +33,9 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject class TraceCPU(ClockedObject): diff --git a/src/dev/BadDevice.py b/src/dev/BadDevice.py index 2b630c087e..f31ecc346e 100644 --- a/src/dev/BadDevice.py +++ b/src/dev/BadDevice.py @@ -24,8 +24,8 @@ # (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.params import * from m5.objects.Device import BasicPioDevice +from m5.params import * class BadDevice(BasicPioDevice): diff --git a/src/dev/Device.py b/src/dev/Device.py index 7f8428e6ff..15a68c3eaa 100644 --- a/src/dev/Device.py +++ b/src/dev/Device.py @@ -36,12 +36,11 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * from m5.util.fdthelper import * -from m5.objects.ClockedObject import ClockedObject - class PioDevice(ClockedObject): type = "PioDevice" diff --git a/src/dev/IntPin.py b/src/dev/IntPin.py index 61c645af2f..d66e172433 100644 --- a/src/dev/IntPin.py +++ b/src/dev/IntPin.py @@ -23,7 +23,10 @@ # (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.params import Port, VectorPort +from m5.params import ( + Port, + VectorPort, +) INT_SOURCE_ROLE = "Int Source Pin" INT_SINK_ROLE = "Int Sink Pin" diff --git a/src/dev/Platform.py b/src/dev/Platform.py index 5a18f83010..5680eb6cbf 100644 --- a/src/dev/Platform.py +++ b/src/dev/Platform.py @@ -24,9 +24,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class Platform(SimObject): diff --git a/src/dev/ResetPort.py b/src/dev/ResetPort.py index 467771a258..1c952ed380 100644 --- a/src/dev/ResetPort.py +++ b/src/dev/ResetPort.py @@ -23,7 +23,10 @@ # (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.params import Port, VectorPort +from m5.params import ( + Port, + VectorPort, +) RESET_REQUEST_ROLE = "Reset Request" RESET_RESPONSE_ROLE = "Reset Response" diff --git a/src/dev/amdgpu/AMDGPU.py b/src/dev/amdgpu/AMDGPU.py index 7873794109..0370f09e01 100644 --- a/src/dev/amdgpu/AMDGPU.py +++ b/src/dev/amdgpu/AMDGPU.py @@ -27,12 +27,19 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.objects.ClockedObject import ClockedObject +from m5.objects.Device import ( + DmaDevice, + DmaVirtDevice, +) +from m5.objects.PciDevice import ( + PciDevice, + PciLegacyIoBar, + PciMemBar, + PciMemUpperBar, +) from m5.params import * from m5.proxy import * -from m5.objects.PciDevice import PciDevice -from m5.objects.PciDevice import PciMemBar, PciMemUpperBar, PciLegacyIoBar -from m5.objects.Device import DmaDevice, DmaVirtDevice -from m5.objects.ClockedObject import ClockedObject # PCI device model for an AMD Vega 10 based GPU. The PCI codes and BARs diff --git a/src/dev/arm/Doorbell.py b/src/dev/arm/Doorbell.py index 106a184902..3832553924 100644 --- a/src/dev/arm/Doorbell.py +++ b/src/dev/arm/Doorbell.py @@ -33,8 +33,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject class Doorbell(SimObject): diff --git a/src/dev/arm/EnergyCtrl.py b/src/dev/arm/EnergyCtrl.py index 91296143c8..6a9cf99608 100644 --- a/src/dev/arm/EnergyCtrl.py +++ b/src/dev/arm/EnergyCtrl.py @@ -33,10 +33,10 @@ # (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.params import * -from m5.SimObject import SimObject from m5.objects.Device import BasicPioDevice +from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject from m5.util.fdthelper import * diff --git a/src/dev/arm/FlashDevice.py b/src/dev/arm/FlashDevice.py index 7bd365a2ba..795e735d7c 100644 --- a/src/dev/arm/FlashDevice.py +++ b/src/dev/arm/FlashDevice.py @@ -33,11 +33,10 @@ # (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.AbstractNVM import * from m5.params import * from m5.proxy import * -from m5.objects.AbstractNVM import * - # Distribution of the data. # sequential: sequential (address n+1 is likely to be on the same plane as n) diff --git a/src/dev/arm/GenericTimer.py b/src/dev/arm/GenericTimer.py index 4b104ade92..fe7c1f5988 100644 --- a/src/dev/arm/GenericTimer.py +++ b/src/dev/arm/GenericTimer.py @@ -33,12 +33,22 @@ # (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.SimObject import SimObject from m5.objects.Device import PioDevice -from m5.params import Param, MaxAddr, NULL, VectorParam +from m5.params import ( + NULL, + MaxAddr, + Param, + VectorParam, +) from m5.proxy import Parent +from m5.SimObject import SimObject from m5.util import fatal -from m5.util.fdthelper import FdtNode, FdtProperty, FdtPropertyWords, FdtState +from m5.util.fdthelper import ( + FdtNode, + FdtProperty, + FdtPropertyWords, + FdtState, +) class SystemCounter(SimObject): diff --git a/src/dev/arm/Gic.py b/src/dev/arm/Gic.py index 6fd8eb235f..6cb03c8cb9 100644 --- a/src/dev/arm/Gic.py +++ b/src/dev/arm/Gic.py @@ -33,14 +33,16 @@ # (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.Device import ( + BasicPioDevice, + PioDevice, +) +from m5.objects.IntPin import IntSourcePin +from m5.objects.Platform import Platform from m5.params import * from m5.proxy import * -from m5.util.fdthelper import * from m5.SimObject import SimObject - -from m5.objects.Device import PioDevice, BasicPioDevice -from m5.objects.Platform import Platform -from m5.objects.IntPin import IntSourcePin +from m5.util.fdthelper import * class BaseGic(PioDevice): diff --git a/src/dev/arm/NoMali.py b/src/dev/arm/NoMali.py index c7d0d4259c..ea20cdf3a3 100644 --- a/src/dev/arm/NoMali.py +++ b/src/dev/arm/NoMali.py @@ -33,10 +33,9 @@ # (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.params import * - from m5.objects.Device import BasicPioDevice from m5.objects.Gic import * +from m5.params import * class NoMaliGpuType(Enum): diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index e71f6cee5a..a0540ec50c 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -37,48 +37,66 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv +from m5.objects.ArmSystem import ArmExtension +from m5.objects.CfiMemory import CfiMemory +from m5.objects.ClockDomain import ( + ClockDomain, + SrcClockDomain, +) +from m5.objects.ClockedObject import ClockedObject +from m5.objects.Device import ( + BadAddr, + BasicPioDevice, + DmaDevice, + IsaFake, + PioDevice, +) +from m5.objects.Display import ( + Display, + Display1080p, +) +from m5.objects.EnergyCtrl import EnergyCtrl +from m5.objects.Ethernet import ( + IGbE_e1000, + IGbE_igb, + NSGigE, +) +from m5.objects.GenericTimer import * +from m5.objects.Gic import * +from m5.objects.Graphics import ImageFormat +from m5.objects.Ide import * +from m5.objects.MHU import ( + MHU, + Ap2ScpDoorbell, + Scp2ApDoorbell, +) +from m5.objects.PciDevice import ( + PciIoBar, + PciLegacyIoBar, +) +from m5.objects.PciHost import * +from m5.objects.Platform import Platform +from m5.objects.PS2 import * +from m5.objects.Scmi import * +from m5.objects.SimpleMemory import SimpleMemory +from m5.objects.SMMUv3 import SMMUv3 +from m5.objects.SubSystem import SubSystem +from m5.objects.Terminal import Terminal +from m5.objects.Uart import Uart +from m5.objects.VirtIOMMIO import MmioVirtIO +from m5.objects.VoltageDomain import VoltageDomain from m5.params import * from m5.proxy import * from m5.util.fdthelper import * -from m5.objects.ArmSystem import ArmExtension -from m5.objects.ClockDomain import ClockDomain, SrcClockDomain -from m5.objects.VoltageDomain import VoltageDomain -from m5.objects.Device import ( - BasicPioDevice, - PioDevice, - IsaFake, - BadAddr, - DmaDevice, -) -from m5.objects.PciHost import * -from m5.objects.Ethernet import NSGigE, IGbE_igb, IGbE_e1000 -from m5.objects.Ide import * -from m5.objects.Platform import Platform -from m5.objects.Terminal import Terminal -from m5.objects.Uart import Uart -from m5.objects.SimpleMemory import SimpleMemory -from m5.objects.GenericTimer import * -from m5.objects.Gic import * -from m5.objects.MHU import MHU, Scp2ApDoorbell, Ap2ScpDoorbell -from m5.objects.EnergyCtrl import EnergyCtrl -from m5.objects.ClockedObject import ClockedObject -from m5.objects.SubSystem import SubSystem -from m5.objects.Graphics import ImageFormat -from m5.objects.ClockedObject import ClockedObject -from m5.objects.PS2 import * -from m5.objects.VirtIOMMIO import MmioVirtIO -from m5.objects.Display import Display, Display1080p -from m5.objects.Scmi import * -from m5.objects.SMMUv3 import SMMUv3 -from m5.objects.PciDevice import PciLegacyIoBar, PciIoBar - -from m5.objects.CfiMemory import CfiMemory # Platforms with KVM support should generally use in-kernel GIC # emulation. Use a GIC model that automatically switches between # gem5's GIC model and KVM's GIC model if KVM is available. try: - from m5.objects.KvmGic import MuxingKvmGicV2, MuxingKvmGicV3 + from m5.objects.KvmGic import ( + MuxingKvmGicV2, + MuxingKvmGicV3, + ) kvm_gicv2_class = MuxingKvmGicV2 kvm_gicv3_class = MuxingKvmGicV3 diff --git a/src/dev/arm/SMMUv3.py b/src/dev/arm/SMMUv3.py index 46fad3bf68..28c2c6fe24 100644 --- a/src/dev/arm/SMMUv3.py +++ b/src/dev/arm/SMMUv3.py @@ -33,11 +33,11 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.util.fdthelper import * from m5.SimObject import * -from m5.objects.ClockedObject import ClockedObject +from m5.util.fdthelper import * class SMMUv3DeviceInterface(ClockedObject): diff --git a/src/dev/arm/UFSHostDevice.py b/src/dev/arm/UFSHostDevice.py index 46ed7ddd24..3de0684487 100644 --- a/src/dev/arm/UFSHostDevice.py +++ b/src/dev/arm/UFSHostDevice.py @@ -34,10 +34,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import sys + +from m5.objects.AbstractNVM import * +from m5.objects.Device import DmaDevice from m5.params import * from m5.proxy import * -from m5.objects.Device import DmaDevice -from m5.objects.AbstractNVM import * class UFSHostDevice(DmaDevice): diff --git a/src/dev/arm/VExpressFastmodel.py b/src/dev/arm/VExpressFastmodel.py index 0dfddb7735..1135bd8b92 100644 --- a/src/dev/arm/VExpressFastmodel.py +++ b/src/dev/arm/VExpressFastmodel.py @@ -23,9 +23,15 @@ # (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.FastModelGIC import FastModelGIC, SCFastModelGIC +from m5.objects.FastModelGIC import ( + FastModelGIC, + SCFastModelGIC, +) from m5.objects.Gic import ArmSPI -from m5.objects.RealView import VExpress_GEM5_Base, HDLcd +from m5.objects.RealView import ( + HDLcd, + VExpress_GEM5_Base, +) from m5.objects.SubSystem import SubSystem diff --git a/src/dev/arm/VirtIOMMIO.py b/src/dev/arm/VirtIOMMIO.py index eecd703e3a..d51f2aa69d 100644 --- a/src/dev/arm/VirtIOMMIO.py +++ b/src/dev/arm/VirtIOMMIO.py @@ -35,13 +35,15 @@ # (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.SimObject import SimObject -from m5.params import * -from m5.proxy import * - from m5.objects.Device import BasicPioDevice from m5.objects.Gic import ArmInterruptPin -from m5.objects.VirtIO import VirtIODeviceBase, VirtIODummyDevice +from m5.objects.VirtIO import ( + VirtIODeviceBase, + VirtIODummyDevice, +) +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject class MmioVirtIO(BasicPioDevice): diff --git a/src/dev/arm/css/Scmi.py b/src/dev/arm/css/Scmi.py index 1246e69343..4ae616d209 100644 --- a/src/dev/arm/css/Scmi.py +++ b/src/dev/arm/css/Scmi.py @@ -33,12 +33,12 @@ # (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.Doorbell import Doorbell +from m5.objects.Scp import Scp from m5.params import * from m5.proxy import * -from m5.objects.Scp import Scp -from m5.objects.Doorbell import Doorbell -from m5.util.fdthelper import * from m5.SimObject import SimObject +from m5.util.fdthelper import * class ScmiChannel(SimObject): diff --git a/src/dev/hsa/HSADevice.py b/src/dev/hsa/HSADevice.py index b22269d5bb..ed3b2d8086 100644 --- a/src/dev/hsa/HSADevice.py +++ b/src/dev/hsa/HSADevice.py @@ -27,11 +27,11 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from m5.SimObject import SimObject -from m5.params import * -from m5.proxy import * from m5.objects.Device import DmaVirtDevice from m5.objects.VegaGPUTLB import VegaPagetableWalker +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject class HSAPacketProcessor(DmaVirtDevice): diff --git a/src/dev/hsa/HSADriver.py b/src/dev/hsa/HSADriver.py index c3e12df4d2..99c81ecc86 100644 --- a/src/dev/hsa/HSADriver.py +++ b/src/dev/hsa/HSADriver.py @@ -27,10 +27,10 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from m5.SimObject import SimObject +from m5.objects.Process import EmulatedDriver from m5.params import * from m5.proxy import * -from m5.objects.Process import EmulatedDriver +from m5.SimObject import SimObject class HSADriver(EmulatedDriver): diff --git a/src/dev/i2c/I2C.py b/src/dev/i2c/I2C.py index 1d3de26d29..df0743f5d8 100644 --- a/src/dev/i2c/I2C.py +++ b/src/dev/i2c/I2C.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.Device import BasicPioDevice +from m5.params import * +from m5.SimObject import SimObject class I2CDevice(SimObject): diff --git a/src/dev/lupio/LupioBLK.py b/src/dev/lupio/LupioBLK.py index e230e23fed..a41a6f249a 100644 --- a/src/dev/lupio/LupioBLK.py +++ b/src/dev/lupio/LupioBLK.py @@ -25,7 +25,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.Device import DmaDevice - from m5.params import Param from m5.proxy import Parent diff --git a/src/dev/lupio/LupioTTY.py b/src/dev/lupio/LupioTTY.py index ff35004481..6c0f2efff5 100644 --- a/src/dev/lupio/LupioTTY.py +++ b/src/dev/lupio/LupioTTY.py @@ -24,11 +24,10 @@ # (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.Device import BasicPioDevice from m5.params import Param from m5.proxy import Parent -from m5.objects.Device import BasicPioDevice - class LupioTTY(BasicPioDevice): type = "LupioTTY" diff --git a/src/dev/mips/Malta.py b/src/dev/mips/Malta.py index 9199bd5b3f..a8def0b0c0 100755 --- a/src/dev/mips/Malta.py +++ b/src/dev/mips/Malta.py @@ -24,13 +24,12 @@ # (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.params import * -from m5.proxy import * - from m5.objects.BadDevice import BadDevice from m5.objects.Device import BasicPioDevice from m5.objects.Platform import Platform from m5.objects.Uart import Uart8250 +from m5.params import * +from m5.proxy import * class MaltaCChip(BasicPioDevice): diff --git a/src/dev/net/Ethernet.py b/src/dev/net/Ethernet.py index 72f2061b2b..495e7da211 100644 --- a/src/dev/net/Ethernet.py +++ b/src/dev/net/Ethernet.py @@ -37,10 +37,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv -from m5.SimObject import SimObject +from m5.objects.PciDevice import ( + PciDevice, + PciIoBar, + PciMemBar, +) from m5.params import * from m5.proxy import * -from m5.objects.PciDevice import PciDevice, PciIoBar, PciMemBar +from m5.SimObject import SimObject ETHERNET_ROLE = "ETHERNET" Port.compat(ETHERNET_ROLE, ETHERNET_ROLE) diff --git a/src/dev/pci/CopyEngine.py b/src/dev/pci/CopyEngine.py index 821f7c5cf0..89d01e19b3 100644 --- a/src/dev/pci/CopyEngine.py +++ b/src/dev/pci/CopyEngine.py @@ -24,11 +24,13 @@ # (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.SimObject import SimObject +from m5.objects.PciDevice import ( + PciDevice, + PciMemBar, +) from m5.params import * from m5.proxy import * - -from m5.objects.PciDevice import PciDevice, PciMemBar +from m5.SimObject import SimObject class CopyEngine(PciDevice): diff --git a/src/dev/pci/PciDevice.py b/src/dev/pci/PciDevice.py index 8466101287..f8c0c1ba6e 100644 --- a/src/dev/pci/PciDevice.py +++ b/src/dev/pci/PciDevice.py @@ -36,11 +36,11 @@ # (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.SimObject import SimObject -from m5.params import * -from m5.proxy import * from m5.objects.Device import DmaDevice from m5.objects.PciHost import PciHost +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject class PciBar(SimObject): diff --git a/src/dev/pci/PciHost.py b/src/dev/pci/PciHost.py index 58f8eb5a78..5fef19eb92 100644 --- a/src/dev/pci/PciHost.py +++ b/src/dev/pci/PciHost.py @@ -33,11 +33,11 @@ # (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.SimObject import SimObject -from m5.params import * -from m5.proxy import * from m5.objects.Device import PioDevice from m5.objects.Platform import Platform +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject class PciHost(PioDevice): diff --git a/src/dev/ps2/PS2.py b/src/dev/ps2/PS2.py index 9a0b16495f..6aa3373535 100644 --- a/src/dev/ps2/PS2.py +++ b/src/dev/ps2/PS2.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class PS2Device(SimObject): diff --git a/src/dev/qemu/QemuFwCfg.py b/src/dev/qemu/QemuFwCfg.py index bb237b9bfc..a71a07e52f 100644 --- a/src/dev/qemu/QemuFwCfg.py +++ b/src/dev/qemu/QemuFwCfg.py @@ -23,9 +23,9 @@ # (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.params import * -from m5.objects.SimObject import SimObject from m5.objects.Device import PioDevice +from m5.objects.SimObject import SimObject +from m5.params import * class QemuFwCfgItem(SimObject): diff --git a/src/dev/riscv/HiFive.py b/src/dev/riscv/HiFive.py index c3d51aa5e7..04b2672ea8 100755 --- a/src/dev/riscv/HiFive.py +++ b/src/dev/riscv/HiFive.py @@ -35,19 +35,18 @@ # (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.Platform import Platform -from m5.objects.PMAChecker import PMAChecker from m5.objects.Clint import Clint +from m5.objects.PciHost import GenericPciHost +from m5.objects.Platform import Platform from m5.objects.Plic import Plic +from m5.objects.PMAChecker import PMAChecker from m5.objects.RTC import RiscvRTC -from m5.objects.Uart import RiscvUart8250 from m5.objects.Terminal import Terminal +from m5.objects.Uart import RiscvUart8250 from m5.params import * from m5.proxy import * from m5.util.fdthelper import * -from m5.objects.PciHost import GenericPciHost - class GenericRiscvPciHost(GenericPciHost): type = "GenericRiscvPciHost" diff --git a/src/dev/riscv/RTC.py b/src/dev/riscv/RTC.py index a6559eaf48..66f691e79c 100644 --- a/src/dev/riscv/RTC.py +++ b/src/dev/riscv/RTC.py @@ -33,10 +33,10 @@ # (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.IntPin import IntSourcePin from m5.params import * from m5.proxy import * from m5.SimObject import SimObject -from m5.objects.IntPin import IntSourcePin class RiscvRTC(SimObject): diff --git a/src/dev/riscv/RiscvVirtIOMMIO.py b/src/dev/riscv/RiscvVirtIOMMIO.py index 17019502fa..7a343715ad 100644 --- a/src/dev/riscv/RiscvVirtIOMMIO.py +++ b/src/dev/riscv/RiscvVirtIOMMIO.py @@ -34,13 +34,12 @@ # (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.SimObject import SimObject -from m5.params import * -from m5.proxy import * -from m5.util.fdthelper import * - from m5.objects.PlicDevice import PlicIntDevice from m5.objects.VirtIO import VirtIODummyDevice +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject +from m5.util.fdthelper import * class RiscvMmioVirtIO(PlicIntDevice): diff --git a/src/dev/serial/Terminal.py b/src/dev/serial/Terminal.py index a08a18fe1e..28abf7572a 100644 --- a/src/dev/serial/Terminal.py +++ b/src/dev/serial/Terminal.py @@ -36,11 +36,10 @@ # (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.SimObject import SimObject +from m5.objects.Serial import SerialDevice from m5.params import * from m5.proxy import * - -from m5.objects.Serial import SerialDevice +from m5.SimObject import SimObject class TerminalDump(ScopedEnum): diff --git a/src/dev/serial/Uart.py b/src/dev/serial/Uart.py index fb0d91efa4..7de6582ba0 100644 --- a/src/dev/serial/Uart.py +++ b/src/dev/serial/Uart.py @@ -36,13 +36,12 @@ # (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.defines import buildEnv +from m5.objects.Device import BasicPioDevice +from m5.objects.Serial import SerialDevice from m5.params import * from m5.proxy import * from m5.util.fdthelper import * -from m5.defines import buildEnv - -from m5.objects.Device import BasicPioDevice -from m5.objects.Serial import SerialDevice class Uart(BasicPioDevice): diff --git a/src/dev/sparc/T1000.py b/src/dev/sparc/T1000.py index d797c5fc13..b4042ecb9f 100644 --- a/src/dev/sparc/T1000.py +++ b/src/dev/sparc/T1000.py @@ -24,13 +24,17 @@ # (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.params import * -from m5.proxy import * - -from m5.objects.Device import BasicPioDevice, PioDevice, IsaFake, BadAddr +from m5.objects.Device import ( + BadAddr, + BasicPioDevice, + IsaFake, + PioDevice, +) from m5.objects.Platform import Platform from m5.objects.Terminal import Terminal from m5.objects.Uart import Uart8250 +from m5.params import * +from m5.proxy import * class MmDisk(BasicPioDevice): diff --git a/src/dev/storage/DiskImage.py b/src/dev/storage/DiskImage.py index e7657e556c..c02d65fbef 100644 --- a/src/dev/storage/DiskImage.py +++ b/src/dev/storage/DiskImage.py @@ -24,8 +24,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject class DiskImage(SimObject): diff --git a/src/dev/storage/Ide.py b/src/dev/storage/Ide.py index 7498a52ecb..348e9e3d7b 100644 --- a/src/dev/storage/Ide.py +++ b/src/dev/storage/Ide.py @@ -24,9 +24,12 @@ # (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.SimObject import SimObject +from m5.objects.PciDevice import ( + PciDevice, + PciIoBar, +) from m5.params import * -from m5.objects.PciDevice import PciDevice, PciIoBar +from m5.SimObject import SimObject class IdeID(Enum): diff --git a/src/dev/storage/SimpleDisk.py b/src/dev/storage/SimpleDisk.py index 252ce38a42..21ff037630 100644 --- a/src/dev/storage/SimpleDisk.py +++ b/src/dev/storage/SimpleDisk.py @@ -24,9 +24,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class SimpleDisk(SimObject): diff --git a/src/dev/virtio/VirtIO.py b/src/dev/virtio/VirtIO.py index 1d652bca64..a009745caf 100644 --- a/src/dev/virtio/VirtIO.py +++ b/src/dev/virtio/VirtIO.py @@ -35,11 +35,14 @@ # (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.SimObject import SimObject +from m5.objects.Device import PioDevice +from m5.objects.PciDevice import ( + PciDevice, + PciIoBar, +) from m5.params import * from m5.proxy import * -from m5.objects.Device import PioDevice -from m5.objects.PciDevice import PciDevice, PciIoBar +from m5.SimObject import SimObject class VirtIODeviceBase(SimObject): diff --git a/src/dev/virtio/VirtIO9P.py b/src/dev/virtio/VirtIO9P.py index b6611713b7..37c9e481cb 100644 --- a/src/dev/virtio/VirtIO9P.py +++ b/src/dev/virtio/VirtIO9P.py @@ -35,9 +35,9 @@ # (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.VirtIO import VirtIODeviceBase from m5.params import * from m5.proxy import * -from m5.objects.VirtIO import VirtIODeviceBase class VirtIO9PBase(VirtIODeviceBase): diff --git a/src/dev/virtio/VirtIOBlock.py b/src/dev/virtio/VirtIOBlock.py index 6a75c00956..bc9394cf2f 100644 --- a/src/dev/virtio/VirtIOBlock.py +++ b/src/dev/virtio/VirtIOBlock.py @@ -35,9 +35,9 @@ # (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.VirtIO import VirtIODeviceBase from m5.params import * from m5.proxy import * -from m5.objects.VirtIO import VirtIODeviceBase class VirtIOBlock(VirtIODeviceBase): diff --git a/src/dev/virtio/VirtIOConsole.py b/src/dev/virtio/VirtIOConsole.py index 72826aa6fb..b1f5e850e7 100644 --- a/src/dev/virtio/VirtIOConsole.py +++ b/src/dev/virtio/VirtIOConsole.py @@ -35,10 +35,10 @@ # (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.Serial import SerialDevice +from m5.objects.VirtIO import VirtIODeviceBase from m5.params import * from m5.proxy import * -from m5.objects.VirtIO import VirtIODeviceBase -from m5.objects.Serial import SerialDevice class VirtIOConsole(VirtIODeviceBase): diff --git a/src/dev/virtio/VirtIORng 2.py b/src/dev/virtio/VirtIORng 2.py index 925fccdabe..5d5db04992 100644 --- a/src/dev/virtio/VirtIORng 2.py +++ b/src/dev/virtio/VirtIORng 2.py @@ -36,9 +36,9 @@ # (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.VirtIO import VirtIODeviceBase from m5.params import * from m5.proxy import * -from m5.objects.VirtIO import VirtIODeviceBase class VirtIORng(VirtIODeviceBase): diff --git a/src/dev/virtio/VirtIORng.py b/src/dev/virtio/VirtIORng.py index 925fccdabe..5d5db04992 100644 --- a/src/dev/virtio/VirtIORng.py +++ b/src/dev/virtio/VirtIORng.py @@ -36,9 +36,9 @@ # (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.VirtIO import VirtIODeviceBase from m5.params import * from m5.proxy import * -from m5.objects.VirtIO import VirtIODeviceBase class VirtIORng(VirtIODeviceBase): diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py index ccc14de8c1..049cc4ea33 100644 --- a/src/dev/x86/Cmos.py +++ b/src/dev/x86/Cmos.py @@ -24,10 +24,10 @@ # (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.params import * -from m5.proxy import * from m5.objects.Device import BasicPioDevice from m5.objects.IntPin import IntSourcePin +from m5.params import * +from m5.proxy import * class Cmos(BasicPioDevice): diff --git a/src/dev/x86/I8042.py b/src/dev/x86/I8042.py index 0dae054588..e357ac91f3 100644 --- a/src/dev/x86/I8042.py +++ b/src/dev/x86/I8042.py @@ -24,11 +24,11 @@ # (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.params import * -from m5.proxy import * from m5.objects.Device import PioDevice from m5.objects.IntPin import IntSourcePin from m5.objects.PS2 import * +from m5.params import * +from m5.proxy import * class I8042(PioDevice): diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index 228bc5a5eb..45ee9a3d2b 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -24,10 +24,10 @@ # (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.params import * -from m5.proxy import * from m5.objects.Device import BasicPioDevice from m5.objects.IntPin import VectorIntSinkPin +from m5.params import * +from m5.proxy import * class I82094AA(BasicPioDevice): diff --git a/src/dev/x86/I8237.py b/src/dev/x86/I8237.py index b8a8a8ce51..60f472f48c 100644 --- a/src/dev/x86/I8237.py +++ b/src/dev/x86/I8237.py @@ -24,9 +24,9 @@ # (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.Device import BasicPioDevice from m5.params import * from m5.proxy import * -from m5.objects.Device import BasicPioDevice class I8237(BasicPioDevice): diff --git a/src/dev/x86/I8254.py b/src/dev/x86/I8254.py index 545f13739a..660bee0e62 100644 --- a/src/dev/x86/I8254.py +++ b/src/dev/x86/I8254.py @@ -24,10 +24,10 @@ # (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.params import * -from m5.proxy import * from m5.objects.Device import BasicPioDevice from m5.objects.IntPin import IntSourcePin +from m5.params import * +from m5.proxy import * class I8254(BasicPioDevice): diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py index 5fcef01f3c..6791c57be2 100644 --- a/src/dev/x86/I8259.py +++ b/src/dev/x86/I8259.py @@ -24,10 +24,13 @@ # (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.Device import BasicPioDevice +from m5.objects.IntPin import ( + IntSourcePin, + VectorIntSinkPin, +) from m5.params import * from m5.proxy import * -from m5.objects.Device import BasicPioDevice -from m5.objects.IntPin import IntSourcePin, VectorIntSinkPin class X86I8259CascadeMode(Enum): diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py index 0039d67230..fd51e14268 100644 --- a/src/dev/x86/Pc.py +++ b/src/dev/x86/Pc.py @@ -24,16 +24,18 @@ # (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.params import * -from m5.proxy import * - -from m5.objects.Device import IsaFake, BadAddr +from m5.objects.Device import ( + BadAddr, + IsaFake, +) +from m5.objects.PciHost import GenericPciHost from m5.objects.Platform import Platform from m5.objects.SouthBridge import SouthBridge from m5.objects.Terminal import Terminal from m5.objects.Uart import Uart8250 -from m5.objects.PciHost import GenericPciHost from m5.objects.XBar import IOXBar +from m5.params import * +from m5.proxy import * def x86IOAddress(port): diff --git a/src/dev/x86/PcSpeaker.py b/src/dev/x86/PcSpeaker.py index 3337b6a07b..1ca7d25967 100644 --- a/src/dev/x86/PcSpeaker.py +++ b/src/dev/x86/PcSpeaker.py @@ -24,9 +24,9 @@ # (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.Device import BasicPioDevice from m5.params import * from m5.proxy import * -from m5.objects.Device import BasicPioDevice class PcSpeaker(BasicPioDevice): diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index 670f687175..ec117c917b 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -24,17 +24,20 @@ # (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.params import * -from m5.proxy import * from m5.objects.Cmos import Cmos from m5.objects.I8042 import I8042 -from m5.objects.I82094AA import I82094AA from m5.objects.I8237 import I8237 from m5.objects.I8254 import I8254 from m5.objects.I8259 import I8259 -from m5.objects.PciDevice import PciLegacyIoBar, PciIoBar +from m5.objects.I82094AA import I82094AA +from m5.objects.PciDevice import ( + PciIoBar, + PciLegacyIoBar, +) from m5.objects.PcSpeaker import PcSpeaker from m5.objects.X86Ide import X86IdeController +from m5.params import * +from m5.proxy import * from m5.SimObject import SimObject diff --git a/src/dev/x86/X86Ide.py b/src/dev/x86/X86Ide.py index 9ae0704503..50ac43e396 100644 --- a/src/dev/x86/X86Ide.py +++ b/src/dev/x86/X86Ide.py @@ -23,11 +23,11 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.Ide import IdeController from m5.objects.IntPin import IntSourcePin from m5.objects.PciDevice import PciLegacyIoBar +from m5.params import * +from m5.SimObject import SimObject class X86IdeController(IdeController): diff --git a/src/dev/x86/X86QemuFwCfg.py b/src/dev/x86/X86QemuFwCfg.py index 4998f9a8b5..b9451f4f50 100644 --- a/src/dev/x86/X86QemuFwCfg.py +++ b/src/dev/x86/X86QemuFwCfg.py @@ -23,9 +23,12 @@ # (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.params import * from m5.objects.E820 import X86E820Entry -from m5.objects.QemuFwCfg import QemuFwCfgIo, QemuFwCfgItem +from m5.objects.QemuFwCfg import ( + QemuFwCfgIo, + QemuFwCfgItem, +) +from m5.params import * def x86IOAddress(port): diff --git a/src/gpu-compute/GPU.py b/src/gpu-compute/GPU.py index 1b6c6a7494..3c294648a9 100644 --- a/src/gpu-compute/GPU.py +++ b/src/gpu-compute/GPU.py @@ -29,16 +29,15 @@ from m5.citations import add_citation from m5.defines import buildEnv -from m5.params import * -from m5.proxy import * -from m5.SimObject import SimObject - from m5.objects.Bridge import Bridge from m5.objects.ClockedObject import ClockedObject from m5.objects.Device import DmaVirtDevice from m5.objects.LdsState import LdsState from m5.objects.Process import EmulatedDriver from m5.objects.VegaGPUTLB import VegaPagetableWalker +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject class PrefetchType(Enum): diff --git a/src/gpu-compute/LdsState.py b/src/gpu-compute/LdsState.py index c81859331c..e57ed9cc5b 100644 --- a/src/gpu-compute/LdsState.py +++ b/src/gpu-compute/LdsState.py @@ -28,11 +28,10 @@ # POSSIBILITY OF SUCH DAMAGE. from m5.defines import buildEnv +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject - class LdsState(ClockedObject): type = "LdsState" diff --git a/src/learning_gem5/part2/SimpleCache.py b/src/learning_gem5/part2/SimpleCache.py index 6cdce84580..86c09fc09d 100644 --- a/src/learning_gem5/part2/SimpleCache.py +++ b/src/learning_gem5/part2/SimpleCache.py @@ -24,9 +24,9 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject class SimpleCache(ClockedObject): diff --git a/src/mem/AbstractMemory.py b/src/mem/AbstractMemory.py index 7ab24bc118..57e47adcb1 100644 --- a/src/mem/AbstractMemory.py +++ b/src/mem/AbstractMemory.py @@ -36,8 +36,8 @@ # (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.params import * from m5.objects.ClockedObject import ClockedObject +from m5.params import * class AbstractMemory(ClockedObject): diff --git a/src/mem/Bridge.py b/src/mem/Bridge.py index 8131d62ef8..ff89d742b6 100644 --- a/src/mem/Bridge.py +++ b/src/mem/Bridge.py @@ -36,8 +36,8 @@ # (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.params import * from m5.objects.ClockedObject import ClockedObject +from m5.params import * class Bridge(ClockedObject): diff --git a/src/mem/CfiMemory.py b/src/mem/CfiMemory.py index c8de9e511e..5af534a6a9 100644 --- a/src/mem/CfiMemory.py +++ b/src/mem/CfiMemory.py @@ -36,9 +36,12 @@ # (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.params import * from m5.objects.AbstractMemory import AbstractMemory -from m5.util.fdthelper import FdtNode, FdtPropertyWords +from m5.params import * +from m5.util.fdthelper import ( + FdtNode, + FdtPropertyWords, +) class CfiMemory(AbstractMemory): diff --git a/src/mem/CommMonitor.py b/src/mem/CommMonitor.py index e0040b74e0..739ecad8bf 100644 --- a/src/mem/CommMonitor.py +++ b/src/mem/CommMonitor.py @@ -33,9 +33,9 @@ # (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.System import System from m5.params import * from m5.proxy import * -from m5.objects.System import System from m5.SimObject import SimObject diff --git a/src/mem/DRAMSim2.py b/src/mem/DRAMSim2.py index 037baaa8b5..032fd80a35 100644 --- a/src/mem/DRAMSim2.py +++ b/src/mem/DRAMSim2.py @@ -35,8 +35,8 @@ from citations import add_citation -from m5.params import * from m5.objects.AbstractMemory import * +from m5.params import * # A wrapper for DRAMSim2 multi-channel memory controller diff --git a/src/mem/DRAMSys.py b/src/mem/DRAMSys.py index 4b2df67dde..04c7a66487 100644 --- a/src/mem/DRAMSys.py +++ b/src/mem/DRAMSys.py @@ -25,13 +25,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.citations import add_citation - -from m5.SimObject import * +from m5.objects.AbstractMemory import * +from m5.objects.Tlm import TlmTargetSocket from m5.params import * from m5.proxy import * - -from m5.objects.Tlm import TlmTargetSocket -from m5.objects.AbstractMemory import * +from m5.SimObject import * class DRAMSys(AbstractMemory): diff --git a/src/mem/DRAMsim3.py b/src/mem/DRAMsim3.py index de70293258..3500c18ecd 100644 --- a/src/mem/DRAMsim3.py +++ b/src/mem/DRAMsim3.py @@ -34,9 +34,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.citations import add_citation - -from m5.params import * from m5.objects.AbstractMemory import * +from m5.params import * # A wrapper for DRAMSim3 multi-channel memory controller diff --git a/src/mem/HBMCtrl.py b/src/mem/HBMCtrl.py index 45d89a76c9..292ad40ff0 100644 --- a/src/mem/HBMCtrl.py +++ b/src/mem/HBMCtrl.py @@ -24,9 +24,9 @@ # (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.MemCtrl import * from m5.params import * from m5.proxy import * -from m5.objects.MemCtrl import * # HBMCtrl manages two pseudo channels of HBM2 diff --git a/src/mem/HMCController.py b/src/mem/HMCController.py index ba5495b71f..dfae48374b 100644 --- a/src/mem/HMCController.py +++ b/src/mem/HMCController.py @@ -36,8 +36,8 @@ # (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.params import * from m5.objects.XBar import * +from m5.params import * # References: # [1] http://www.open-silicon.com/open-silicon-ips/hmc/ diff --git a/src/mem/HeteroMemCtrl.py b/src/mem/HeteroMemCtrl.py index 8bddc94086..f54da2ec91 100644 --- a/src/mem/HeteroMemCtrl.py +++ b/src/mem/HeteroMemCtrl.py @@ -38,9 +38,9 @@ # (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.MemCtrl import * from m5.params import * from m5.proxy import * -from m5.objects.MemCtrl import * # HeteroMemCtrl controls a dram and an nvm interface diff --git a/src/mem/MemChecker.py b/src/mem/MemChecker.py index fcee653265..4fab7b9a7a 100644 --- a/src/mem/MemChecker.py +++ b/src/mem/MemChecker.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class MemChecker(SimObject): diff --git a/src/mem/MemCtrl.py b/src/mem/MemCtrl.py index eca15877e5..215ae271eb 100644 --- a/src/mem/MemCtrl.py +++ b/src/mem/MemCtrl.py @@ -38,10 +38,10 @@ # (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.citations import add_citation +from m5.objects.QoSMemCtrl import * from m5.params import * from m5.proxy import * -from m5.objects.QoSMemCtrl import * -from m5.citations import add_citation # Enum for memory scheduling algorithms, currently First-Come diff --git a/src/mem/MemDelay.py b/src/mem/MemDelay.py index eb4aaa7bf1..52124f0b56 100644 --- a/src/mem/MemDelay.py +++ b/src/mem/MemDelay.py @@ -33,8 +33,8 @@ # (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.params import * from m5.objects.ClockedObject import ClockedObject +from m5.params import * class MemDelay(ClockedObject): diff --git a/src/mem/MemInterface.py b/src/mem/MemInterface.py index 424e6320ac..512acab405 100644 --- a/src/mem/MemInterface.py +++ b/src/mem/MemInterface.py @@ -38,11 +38,10 @@ # (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.AbstractMemory import AbstractMemory from m5.params import * from m5.proxy import * -from m5.objects.AbstractMemory import AbstractMemory - # Enum for the address mapping. With Ch, Ra, Ba, Ro and Co denoting # channel, rank, bank, row and column, respectively, and going from diff --git a/src/mem/NVMInterface.py b/src/mem/NVMInterface.py index 66b1f9401e..8289fd29c7 100644 --- a/src/mem/NVMInterface.py +++ b/src/mem/NVMInterface.py @@ -33,11 +33,11 @@ # (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.params import * -from m5.proxy import * +from m5.objects.DRAMInterface import AddrMap from m5.objects.MemCtrl import MemCtrl from m5.objects.MemInterface import MemInterface -from m5.objects.DRAMInterface import AddrMap +from m5.params import * +from m5.proxy import * # The following interface aims to model byte-addressable NVM diff --git a/src/mem/SerialLink.py b/src/mem/SerialLink.py index 6b767050d6..66d87786f2 100644 --- a/src/mem/SerialLink.py +++ b/src/mem/SerialLink.py @@ -37,8 +37,8 @@ # (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.params import * from m5.objects.ClockedObject import ClockedObject +from m5.params import * # SerialLink is a simple variation of the Bridge class, with the ability to # account for the latency of packet serialization. diff --git a/src/mem/SharedMemoryServer.py b/src/mem/SharedMemoryServer.py index 97004224de..b0461b614d 100644 --- a/src/mem/SharedMemoryServer.py +++ b/src/mem/SharedMemoryServer.py @@ -1,6 +1,6 @@ -from m5.SimObject import SimObject from m5.params import Param from m5.proxy import Parent +from m5.SimObject import SimObject class SharedMemoryServer(SimObject): diff --git a/src/mem/SimpleMemory.py b/src/mem/SimpleMemory.py index fefda187f2..e0256d7df1 100644 --- a/src/mem/SimpleMemory.py +++ b/src/mem/SimpleMemory.py @@ -36,8 +36,8 @@ # (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.params import * from m5.objects.AbstractMemory import * +from m5.params import * class SimpleMemory(AbstractMemory): diff --git a/src/mem/ThreadBridge.py b/src/mem/ThreadBridge.py index f0ee0897ce..9f76655976 100644 --- a/src/mem/ThreadBridge.py +++ b/src/mem/ThreadBridge.py @@ -23,8 +23,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject class ThreadBridge(SimObject): diff --git a/src/mem/XBar.py b/src/mem/XBar.py index d0becc22a8..927d3bbe36 100644 --- a/src/mem/XBar.py +++ b/src/mem/XBar.py @@ -36,13 +36,12 @@ # (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.ClockedObject import ClockedObject from m5.objects.System import System from m5.params import * from m5.proxy import * from m5.SimObject import SimObject -from m5.objects.ClockedObject import ClockedObject - class BaseXBar(ClockedObject): type = "BaseXBar" diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py index d853a08cd9..ed4851e69a 100644 --- a/src/mem/cache/Cache.py +++ b/src/mem/cache/Cache.py @@ -36,15 +36,14 @@ # (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.params import * -from m5.proxy import * -from m5.SimObject import SimObject - from m5.objects.ClockedObject import ClockedObject from m5.objects.Compressors import BaseCacheCompressor from m5.objects.Prefetcher import BasePrefetcher from m5.objects.ReplacementPolicies import * from m5.objects.Tags import * +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject # Enum for cache clusivity, currently mostly inclusive or mostly diff --git a/src/mem/cache/compressors/Compressors.py b/src/mem/cache/compressors/Compressors.py index eef5f77a18..8bd9a1a6a2 100644 --- a/src/mem/cache/compressors/Compressors.py +++ b/src/mem/cache/compressors/Compressors.py @@ -24,13 +24,12 @@ # (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.IndexingPolicies import * +from m5.objects.ReplacementPolicies import * from m5.params import * from m5.proxy import * from m5.SimObject import * -from m5.objects.IndexingPolicies import * -from m5.objects.ReplacementPolicies import * - class BaseCacheCompressor(SimObject): type = "BaseCacheCompressor" diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index ecc67f4857..0a8c91d538 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -36,13 +36,12 @@ # (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.SimObject import * -from m5.params import * -from m5.proxy import * - from m5.objects.ClockedObject import ClockedObject from m5.objects.IndexingPolicies import * from m5.objects.ReplacementPolicies import * +from m5.params import * +from m5.proxy import * +from m5.SimObject import * class HWPProbeEvent: diff --git a/src/mem/cache/tags/Tags.py b/src/mem/cache/tags/Tags.py index ade187fa39..2717373829 100644 --- a/src/mem/cache/tags/Tags.py +++ b/src/mem/cache/tags/Tags.py @@ -33,10 +33,10 @@ # (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.params import * -from m5.proxy import * from m5.objects.ClockedObject import ClockedObject from m5.objects.IndexingPolicies import * +from m5.params import * +from m5.proxy import * class BaseTags(ClockedObject): diff --git a/src/mem/probes/MemFootprintProbe.py b/src/mem/probes/MemFootprintProbe.py index 707a8b688f..46831415f5 100644 --- a/src/mem/probes/MemFootprintProbe.py +++ b/src/mem/probes/MemFootprintProbe.py @@ -34,11 +34,10 @@ # (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.BaseMemProbe import BaseMemProbe from m5.params import * from m5.proxy import * -from m5.objects.BaseMemProbe import BaseMemProbe - class MemFootprintProbe(BaseMemProbe): type = "MemFootprintProbe" diff --git a/src/mem/probes/MemTraceProbe.py b/src/mem/probes/MemTraceProbe.py index d848e9ed61..6820e0732e 100644 --- a/src/mem/probes/MemTraceProbe.py +++ b/src/mem/probes/MemTraceProbe.py @@ -33,9 +33,9 @@ # (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.BaseMemProbe import BaseMemProbe from m5.params import * from m5.proxy import * -from m5.objects.BaseMemProbe import BaseMemProbe class MemTraceProbe(BaseMemProbe): diff --git a/src/mem/probes/StackDistProbe.py b/src/mem/probes/StackDistProbe.py index 5b44d9d333..a62fb5a5b5 100644 --- a/src/mem/probes/StackDistProbe.py +++ b/src/mem/probes/StackDistProbe.py @@ -33,9 +33,9 @@ # (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.BaseMemProbe import BaseMemProbe from m5.params import * from m5.proxy import * -from m5.objects.BaseMemProbe import BaseMemProbe class StackDistProbe(BaseMemProbe): diff --git a/src/mem/qos/QoSMemCtrl.py b/src/mem/qos/QoSMemCtrl.py index 86ed03196f..280d1d1e1b 100644 --- a/src/mem/qos/QoSMemCtrl.py +++ b/src/mem/qos/QoSMemCtrl.py @@ -33,10 +33,10 @@ # (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.params import * -from m5.proxy import * from m5.objects.ClockedObject import ClockedObject from m5.objects.QoSTurnaround import * +from m5.params import * +from m5.proxy import * # QoS Queue Selection policy used to select packets among same-QoS queues diff --git a/src/mem/qos/QoSMemSinkCtrl.py b/src/mem/qos/QoSMemSinkCtrl.py index dac0fb5be6..8eed316d28 100644 --- a/src/mem/qos/QoSMemSinkCtrl.py +++ b/src/mem/qos/QoSMemSinkCtrl.py @@ -35,9 +35,9 @@ # # Author: Matteo Andreozzi -from m5.params import * from m5.objects.QoSMemCtrl import * from m5.objects.QoSMemSinkInterface import * +from m5.params import * class QoSMemSinkCtrl(QoSMemCtrl): diff --git a/src/mem/qos/QoSPolicy.py b/src/mem/qos/QoSPolicy.py index ef44121567..0736d0367d 100644 --- a/src/mem/qos/QoSPolicy.py +++ b/src/mem/qos/QoSPolicy.py @@ -33,8 +33,8 @@ # (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.SimObject import * from m5.params import * +from m5.SimObject import * # QoS scheduler policy used to serve incoming transaction diff --git a/src/mem/ruby/network/BasicRouter.py b/src/mem/ruby/network/BasicRouter.py index 933470daec..ee74eaa1f4 100644 --- a/src/mem/ruby/network/BasicRouter.py +++ b/src/mem/ruby/network/BasicRouter.py @@ -24,9 +24,8 @@ # (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.params import * - from m5.objects.ClockedObject import ClockedObject +from m5.params import * class BasicRouter(ClockedObject): diff --git a/src/mem/ruby/network/Network.py b/src/mem/ruby/network/Network.py index 3e9f549f89..72934efa30 100644 --- a/src/mem/ruby/network/Network.py +++ b/src/mem/ruby/network/Network.py @@ -24,10 +24,10 @@ # (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.BasicLink import BasicLink +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject -from m5.objects.BasicLink import BasicLink class RubyNetwork(ClockedObject): diff --git a/src/mem/ruby/network/garnet/GarnetLink.py b/src/mem/ruby/network/garnet/GarnetLink.py index 3cc44e4614..5cd9abe71f 100644 --- a/src/mem/ruby/network/garnet/GarnetLink.py +++ b/src/mem/ruby/network/garnet/GarnetLink.py @@ -25,10 +25,13 @@ # (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.BasicLink import ( + BasicExtLink, + BasicIntLink, +) +from m5.objects.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject -from m5.objects.BasicLink import BasicIntLink, BasicExtLink class CDCType(Enum): diff --git a/src/mem/ruby/network/garnet/GarnetNetwork.py b/src/mem/ruby/network/garnet/GarnetNetwork.py index bf5a0bad33..b735260b4d 100644 --- a/src/mem/ruby/network/garnet/GarnetNetwork.py +++ b/src/mem/ruby/network/garnet/GarnetNetwork.py @@ -29,11 +29,11 @@ # from m5.citations import add_citation -from m5.params import * -from m5.proxy import * -from m5.objects.Network import RubyNetwork from m5.objects.BasicRouter import BasicRouter from m5.objects.ClockedObject import ClockedObject +from m5.objects.Network import RubyNetwork +from m5.params import * +from m5.proxy import * class GarnetNetwork(RubyNetwork): diff --git a/src/mem/ruby/network/simple/SimpleLink.py b/src/mem/ruby/network/simple/SimpleLink.py index 0d3f20698d..83aa2fbe71 100644 --- a/src/mem/ruby/network/simple/SimpleLink.py +++ b/src/mem/ruby/network/simple/SimpleLink.py @@ -36,12 +36,15 @@ # (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.BasicLink import ( + BasicExtLink, + BasicIntLink, +) +from m5.objects.MessageBuffer import MessageBuffer from m5.params import * from m5.proxy import * -from m5.util import fatal from m5.SimObject import SimObject -from m5.objects.BasicLink import BasicIntLink, BasicExtLink -from m5.objects.MessageBuffer import MessageBuffer +from m5.util import fatal class SimpleExtLink(BasicExtLink): diff --git a/src/mem/ruby/network/simple/SimpleNetwork.py b/src/mem/ruby/network/simple/SimpleNetwork.py index aa553deee3..e52333b24d 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.py +++ b/src/mem/ruby/network/simple/SimpleNetwork.py @@ -36,14 +36,13 @@ # (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.params import * -from m5.proxy import * - -from m5.util import fatal -from m5.SimObject import SimObject -from m5.objects.Network import RubyNetwork from m5.objects.BasicRouter import BasicRouter from m5.objects.MessageBuffer import MessageBuffer +from m5.objects.Network import RubyNetwork +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject +from m5.util import fatal class SimpleNetwork(RubyNetwork): diff --git a/src/mem/ruby/slicc_interface/Controller.py b/src/mem/ruby/slicc_interface/Controller.py index 42447f1cca..ef8a0afbf1 100644 --- a/src/mem/ruby/slicc_interface/Controller.py +++ b/src/mem/ruby/slicc_interface/Controller.py @@ -36,9 +36,9 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject class RubyController(ClockedObject): diff --git a/src/mem/ruby/structures/RubyCache.py b/src/mem/ruby/structures/RubyCache.py index 7446ac3de0..2f457f5c4a 100644 --- a/src/mem/ruby/structures/RubyCache.py +++ b/src/mem/ruby/structures/RubyCache.py @@ -24,9 +24,9 @@ # (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.ReplacementPolicies import * from m5.params import * from m5.proxy import * -from m5.objects.ReplacementPolicies import * from m5.SimObject import SimObject diff --git a/src/mem/ruby/structures/RubyPrefetcher.py b/src/mem/ruby/structures/RubyPrefetcher.py index cea6ec9604..d4189ae7d5 100644 --- a/src/mem/ruby/structures/RubyPrefetcher.py +++ b/src/mem/ruby/structures/RubyPrefetcher.py @@ -36,11 +36,10 @@ # (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.SimObject import SimObject +from m5.objects.System import System from m5.params import * from m5.proxy import * - -from m5.objects.System import System +from m5.SimObject import SimObject class RubyPrefetcher(SimObject): diff --git a/src/mem/ruby/system/GPUCoalescer.py b/src/mem/ruby/system/GPUCoalescer.py index fcf49e38b7..d69314eb54 100644 --- a/src/mem/ruby/system/GPUCoalescer.py +++ b/src/mem/ruby/system/GPUCoalescer.py @@ -27,11 +27,10 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.objects.Sequencer import * from m5.params import * from m5.proxy import * -from m5.objects.Sequencer import * - class RubyGPUCoalescer(RubyPort): type = "RubyGPUCoalescer" diff --git a/src/mem/ruby/system/RubySystem.py b/src/mem/ruby/system/RubySystem.py index 64e39bda4c..5dbcde90ec 100644 --- a/src/mem/ruby/system/RubySystem.py +++ b/src/mem/ruby/system/RubySystem.py @@ -24,10 +24,10 @@ # (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.params import * -from m5.proxy import * from m5.objects.ClockedObject import ClockedObject from m5.objects.SimpleMemory import * +from m5.params import * +from m5.proxy import * class RubySystem(ClockedObject): diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py index eb1003692f..3f570fb952 100644 --- a/src/mem/ruby/system/Sequencer.py +++ b/src/mem/ruby/system/Sequencer.py @@ -37,9 +37,9 @@ # (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.ClockedObject import ClockedObject from m5.params import * from m5.proxy import * -from m5.objects.ClockedObject import ClockedObject class RubyPort(ClockedObject): diff --git a/src/mem/ruby/system/VIPERCoalescer.py b/src/mem/ruby/system/VIPERCoalescer.py index af43cddb2c..d2411f858c 100644 --- a/src/mem/ruby/system/VIPERCoalescer.py +++ b/src/mem/ruby/system/VIPERCoalescer.py @@ -27,9 +27,9 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from m5.objects.GPUCoalescer import * from m5.params import * from m5.proxy import * -from m5.objects.GPUCoalescer import * class VIPERCoalescer(RubyGPUCoalescer): diff --git a/src/mem/slicc/ast/AST.py b/src/mem/slicc/ast/AST.py index ff8e3326ad..52700f9dc9 100644 --- a/src/mem/slicc/ast/AST.py +++ b/src/mem/slicc/ast/AST.py @@ -25,7 +25,10 @@ # (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 slicc.util import PairContainer, Location +from slicc.util import ( + Location, + PairContainer, +) class AST(PairContainer): diff --git a/src/mem/slicc/ast/ActionDeclAST.py b/src/mem/slicc/ast/ActionDeclAST.py index ff6a4ff9d5..375f4109c1 100644 --- a/src/mem/slicc/ast/ActionDeclAST.py +++ b/src/mem/slicc/ast/ActionDeclAST.py @@ -26,7 +26,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.DeclAST import DeclAST -from slicc.symbols import Action, Type, Var +from slicc.symbols import ( + Action, + Type, + Var, +) class ActionDeclAST(DeclAST): diff --git a/src/mem/slicc/ast/EnumDeclAST.py b/src/mem/slicc/ast/EnumDeclAST.py index 19eb1eeddd..f7ff5c3cfd 100644 --- a/src/mem/slicc/ast/EnumDeclAST.py +++ b/src/mem/slicc/ast/EnumDeclAST.py @@ -26,7 +26,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.DeclAST import DeclAST -from slicc.symbols import Func, Type +from slicc.symbols import ( + Func, + Type, +) class EnumDeclAST(DeclAST): diff --git a/src/mem/slicc/ast/ExprStatementAST.py b/src/mem/slicc/ast/ExprStatementAST.py index 9545ef3e41..2aa7456816 100644 --- a/src/mem/slicc/ast/ExprStatementAST.py +++ b/src/mem/slicc/ast/ExprStatementAST.py @@ -26,8 +26,8 @@ # (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 slicc.ast.StatementAST import StatementAST from slicc.ast.LocalVariableAST import LocalVariableAST +from slicc.ast.StatementAST import StatementAST from slicc.symbols import Type diff --git a/src/mem/slicc/ast/FuncCallExprAST.py b/src/mem/slicc/ast/FuncCallExprAST.py index 01b604c8bf..b807a5f933 100644 --- a/src/mem/slicc/ast/FuncCallExprAST.py +++ b/src/mem/slicc/ast/FuncCallExprAST.py @@ -39,7 +39,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.ExprAST import ExprAST -from slicc.symbols import Func, Type +from slicc.symbols import ( + Func, + Type, +) class FuncCallExprAST(ExprAST): diff --git a/src/mem/slicc/ast/FuncDeclAST.py b/src/mem/slicc/ast/FuncDeclAST.py index 38898ff9e5..2e28dfd75c 100644 --- a/src/mem/slicc/ast/FuncDeclAST.py +++ b/src/mem/slicc/ast/FuncDeclAST.py @@ -26,7 +26,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.DeclAST import DeclAST -from slicc.symbols import Func, Type +from slicc.symbols import ( + Func, + Type, +) class FuncDeclAST(DeclAST): diff --git a/src/mem/slicc/ast/InPortDeclAST.py b/src/mem/slicc/ast/InPortDeclAST.py index 2cbf3bb617..6f1c121075 100644 --- a/src/mem/slicc/ast/InPortDeclAST.py +++ b/src/mem/slicc/ast/InPortDeclAST.py @@ -39,7 +39,11 @@ from slicc.ast.DeclAST import DeclAST from slicc.ast.TypeAST import TypeAST -from slicc.symbols import Func, Type, Var +from slicc.symbols import ( + Func, + Type, + Var, +) class InPortDeclAST(DeclAST): diff --git a/src/mem/slicc/ast/MachineAST.py b/src/mem/slicc/ast/MachineAST.py index 0d9c0ec31b..a6cb8a93ee 100644 --- a/src/mem/slicc/ast/MachineAST.py +++ b/src/mem/slicc/ast/MachineAST.py @@ -26,7 +26,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.DeclAST import DeclAST -from slicc.symbols import StateMachine, Type +from slicc.symbols import ( + StateMachine, + Type, +) class MachineAST(DeclAST): diff --git a/src/mem/slicc/ast/OutPortDeclAST.py b/src/mem/slicc/ast/OutPortDeclAST.py index e21a4a6fa7..e6899c8700 100644 --- a/src/mem/slicc/ast/OutPortDeclAST.py +++ b/src/mem/slicc/ast/OutPortDeclAST.py @@ -27,8 +27,10 @@ from slicc.ast.DeclAST import DeclAST from slicc.ast.TypeAST import TypeAST -from slicc.symbols import Var -from slicc.symbols import Type +from slicc.symbols import ( + Type, + Var, +) class OutPortDeclAST(DeclAST): diff --git a/src/mem/slicc/ast/StateDeclAST.py b/src/mem/slicc/ast/StateDeclAST.py index 3ff3ab4e89..1455c50599 100644 --- a/src/mem/slicc/ast/StateDeclAST.py +++ b/src/mem/slicc/ast/StateDeclAST.py @@ -25,7 +25,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.DeclAST import DeclAST -from slicc.symbols import Func, Type +from slicc.symbols import ( + Func, + Type, +) class StateDeclAST(DeclAST): diff --git a/src/mem/slicc/ast/TypeAST.py b/src/mem/slicc/ast/TypeAST.py index 92c3190fe2..7da9a21593 100644 --- a/src/mem/slicc/ast/TypeAST.py +++ b/src/mem/slicc/ast/TypeAST.py @@ -26,7 +26,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.AST import AST - from slicc.symbols import Type diff --git a/src/mem/slicc/ast/TypeFieldEnumAST.py b/src/mem/slicc/ast/TypeFieldEnumAST.py index 68dd0cd0fa..6a8fe2f191 100644 --- a/src/mem/slicc/ast/TypeFieldEnumAST.py +++ b/src/mem/slicc/ast/TypeFieldEnumAST.py @@ -26,7 +26,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.TypeFieldAST import TypeFieldAST -from slicc.symbols import Event, State, RequestType +from slicc.symbols import ( + Event, + RequestType, + State, +) class TypeFieldEnumAST(TypeFieldAST): diff --git a/src/mem/slicc/ast/TypeFieldStateAST.py b/src/mem/slicc/ast/TypeFieldStateAST.py index b04a708f21..4bef5136d4 100644 --- a/src/mem/slicc/ast/TypeFieldStateAST.py +++ b/src/mem/slicc/ast/TypeFieldStateAST.py @@ -25,7 +25,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.TypeFieldAST import TypeFieldAST -from slicc.symbols import Event, State +from slicc.symbols import ( + Event, + State, +) class TypeFieldStateAST(TypeFieldAST): diff --git a/src/mem/slicc/ast/VarExprAST.py b/src/mem/slicc/ast/VarExprAST.py index 3c4023e8fe..8431dd132c 100644 --- a/src/mem/slicc/ast/VarExprAST.py +++ b/src/mem/slicc/ast/VarExprAST.py @@ -27,7 +27,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from slicc.ast.ExprAST import ExprAST -from slicc.symbols import Type, Var +from slicc.symbols import ( + Type, + Var, +) class VarExprAST(ExprAST): diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py index 247546fb8f..86f9b09479 100644 --- a/src/mem/slicc/ast/__init__.py +++ b/src/mem/slicc/ast/__init__.py @@ -36,13 +36,13 @@ # (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 slicc.ast.AST import * - # actual ASTs from slicc.ast.ActionDeclAST import * from slicc.ast.AssignStatementAST import * +from slicc.ast.AST import * from slicc.ast.CheckAllocateStatementAST import * from slicc.ast.CheckNextCycleAST import * +from slicc.ast.CheckProbeStatementAST import * from slicc.ast.DeclAST import * from slicc.ast.DeclListAST import * from slicc.ast.DeferEnqueueingStatementAST import * @@ -63,8 +63,8 @@ from slicc.ast.MachineAST import * from slicc.ast.MemberExprAST import * from slicc.ast.MethodCallExprAST import * from slicc.ast.NewExprAST import * -from slicc.ast.OodAST import * from slicc.ast.ObjDeclAST import * +from slicc.ast.OodAST import * from slicc.ast.OperatorExprAST import * from slicc.ast.OutPortDeclAST import * from slicc.ast.PairAST import * @@ -72,7 +72,6 @@ from slicc.ast.PairListAST import * from slicc.ast.PeekStatementAST import * from slicc.ast.ReturnStatementAST import * from slicc.ast.StallAndWaitStatementAST import * -from slicc.ast.WakeupPortStatementAST import * from slicc.ast.StateDeclAST import * from slicc.ast.StatementAST import * from slicc.ast.StatementListAST import * @@ -84,4 +83,4 @@ from slicc.ast.TypeFieldAST import * from slicc.ast.TypeFieldEnumAST import * from slicc.ast.TypeFieldStateAST import * from slicc.ast.VarExprAST import * -from slicc.ast.CheckProbeStatementAST import * +from slicc.ast.WakeupPortStatementAST import * diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index af47ddb639..dba82d8480 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -42,7 +42,10 @@ import re import sys from code_formatter import code_formatter -from grammar import Grammar, ParseError +from grammar import ( + Grammar, + ParseError, +) import slicc.ast as ast import slicc.util as util diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 68a1a6a8af..078e666d26 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -38,12 +38,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import re from collections import OrderedDict +import slicc.generate.html as html from slicc.symbols.Symbol import Symbol from slicc.symbols.Var import Var -import slicc.generate.html as html -import re python_class_map = { "int": "Int", diff --git a/src/mem/slicc/symbols/Symbol.py b/src/mem/slicc/symbols/Symbol.py index 74863724d2..261aac5720 100644 --- a/src/mem/slicc/symbols/Symbol.py +++ b/src/mem/slicc/symbols/Symbol.py @@ -44,8 +44,8 @@ class Symbol(PairContainer): def __init__(self, symtab, ident, location, pairs=None): super().__init__() - from slicc.util import Location from slicc.symbols import SymbolTable + from slicc.util import Location if not isinstance(symtab, SymbolTable): raise AttributeError diff --git a/src/mem/slicc/symbols/Transition.py b/src/mem/slicc/symbols/Transition.py index 385065f972..67e05c6997 100644 --- a/src/mem/slicc/symbols/Transition.py +++ b/src/mem/slicc/symbols/Transition.py @@ -25,8 +25,8 @@ # (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 slicc.symbols.Symbol import Symbol from slicc.symbols.State import WildcardState +from slicc.symbols.Symbol import Symbol class Transition(Symbol): diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py index 7010461e0c..535a4165b3 100644 --- a/src/mem/slicc/symbols/Type.py +++ b/src/mem/slicc/symbols/Type.py @@ -39,9 +39,9 @@ from collections import OrderedDict -from slicc.util import PairContainer from slicc.symbols.Symbol import Symbol from slicc.symbols.Var import Var +from slicc.util import PairContainer class DataMember(Var): diff --git a/src/mem/slicc/symbols/__init__.py b/src/mem/slicc/symbols/__init__.py index e4ce4826fa..58e039f988 100644 --- a/src/mem/slicc/symbols/__init__.py +++ b/src/mem/slicc/symbols/__init__.py @@ -27,8 +27,8 @@ from slicc.symbols.Action import Action from slicc.symbols.Event import Event from slicc.symbols.Func import Func -from slicc.symbols.State import State from slicc.symbols.RequestType import RequestType +from slicc.symbols.State import State from slicc.symbols.StateMachine import StateMachine from slicc.symbols.Symbol import Symbol from slicc.symbols.SymbolTable import SymbolTable diff --git a/src/python/gem5/components/boards/abstract_board.py b/src/python/gem5/components/boards/abstract_board.py index aba080e239..7d251e8296 100644 --- a/src/python/gem5/components/boards/abstract_board.py +++ b/src/python/gem5/components/boards/abstract_board.py @@ -24,23 +24,33 @@ # (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 ABCMeta, abstractmethod import inspect - -from .mem_mode import MemMode, mem_mode_to_string -from ...resources.resource import WorkloadResource +from abc import ( + ABCMeta, + abstractmethod, +) +from typing import ( + List, + Optional, + Sequence, + Tuple, +) from m5.objects import ( AddrRange, - System, - Port, - IOXBar, ClockDomain, + IOXBar, + Port, SrcClockDomain, + System, VoltageDomain, ) -from typing import List, Optional, Sequence, Tuple +from ...resources.resource import WorkloadResource +from .mem_mode import ( + MemMode, + mem_mode_to_string, +) class AbstractBoard: diff --git a/src/python/gem5/components/boards/abstract_system_board.py b/src/python/gem5/components/boards/abstract_system_board.py index 2812b37260..471a9458cd 100644 --- a/src/python/gem5/components/boards/abstract_system_board.py +++ b/src/python/gem5/components/boards/abstract_system_board.py @@ -26,10 +26,13 @@ from abc import ABCMeta -from .abstract_board import AbstractBoard -from ...utils.override import overrides +from m5.objects import ( + SimObject, + System, +) -from m5.objects import System, SimObject +from ...utils.override import overrides +from .abstract_board import AbstractBoard class AbstractSystemBoard(System, AbstractBoard): diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index 032a863fd3..e976d71836 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -24,43 +24,48 @@ # (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 ( - Port, - IOXBar, - Bridge, - BadAddr, - Terminal, - PciVirtIO, - VncServer, - AddrRange, - ArmSystem, - ArmRelease, - ArmFsLinux, - VirtIOBlock, - CowDiskImage, - RawDiskImage, - VoltageDomain, - SrcClockDomain, - ArmDefaultRelease, - VExpress_GEM5_Base, - VExpress_GEM5_Foundation, - SimObject, +import os +from abc import ABCMeta +from typing import ( + List, + Sequence, + Tuple, ) -import os import m5 -from abc import ABCMeta +from m5.objects import ( + AddrRange, + ArmDefaultRelease, + ArmFsLinux, + ArmRelease, + ArmSystem, + BadAddr, + Bridge, + CowDiskImage, + IOXBar, + PciVirtIO, + Port, + RawDiskImage, + SimObject, + SrcClockDomain, + Terminal, + VExpress_GEM5_Base, + VExpress_GEM5_Foundation, + VirtIOBlock, + VncServer, + VoltageDomain, +) + from ...isas import ISA -from ...utils.requires import requires -from ...utils.override import overrides -from typing import List, Sequence, Tuple -from .abstract_board import AbstractBoard from ...resources.resource import AbstractResource -from .kernel_disk_workload import KernelDiskWorkload -from ..cachehierarchies.classic.no_cache import NoCache -from ..processors.abstract_processor import AbstractProcessor -from ..memory.abstract_memory_system import AbstractMemorySystem +from ...utils.override import overrides +from ...utils.requires import requires from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy +from ..cachehierarchies.classic.no_cache import NoCache +from ..memory.abstract_memory_system import AbstractMemorySystem +from ..processors.abstract_processor import AbstractProcessor +from .abstract_board import AbstractBoard +from .kernel_disk_workload import KernelDiskWorkload class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index 85843b89e2..a27d57e902 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -27,42 +27,31 @@ import os from typing import List -from ....utils.override import overrides -from ..abstract_system_board import AbstractSystemBoard -from ...processors.abstract_processor import AbstractProcessor -from ...memory.abstract_memory_system import AbstractMemorySystem -from ...cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy -from ..kernel_disk_workload import KernelDiskWorkload -from ....resources.resource import AbstractResource -from ....isas import ISA - import m5 from m5.objects import ( - Bridge, - PMAChecker, - RiscvLinux, - RiscvRTC, AddrRange, - IOXBar, + Bridge, Clint, - Plic, - Terminal, + CowDiskImage, + Frequency, + IOXBar, LupioBLK, LupioIPI, LupioPIC, LupioRNG, LupioRTC, + LupioSYS, LupioTMR, LupioTTY, - LupioSYS, LupV, - AddrRange, - CowDiskImage, - RawDiskImage, - Frequency, + Plic, + PMAChecker, Port, + RawDiskImage, + RiscvLinux, + RiscvRTC, + Terminal, ) - from m5.util.fdthelper import ( Fdt, FdtNode, @@ -72,6 +61,15 @@ from m5.util.fdthelper import ( FdtState, ) +from ....isas import ISA +from ....resources.resource import AbstractResource +from ....utils.override import overrides +from ...cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy +from ...memory.abstract_memory_system import AbstractMemorySystem +from ...processors.abstract_processor import AbstractProcessor +from ..abstract_system_board import AbstractSystemBoard +from ..kernel_disk_workload import KernelDiskWorkload + class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): """ diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 72b143e6ff..16c196208b 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -24,22 +24,25 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import os from abc import abstractmethod - -from .abstract_board import AbstractBoard -from ...resources.resource import ( - DiskImageResource, - BootloaderResource, - CheckpointResource, - KernelResource, +from pathlib import Path +from typing import ( + List, + Optional, + Union, ) -from typing import List, Optional, Union -import os -from pathlib import Path - import m5 +from ...resources.resource import ( + BootloaderResource, + CheckpointResource, + DiskImageResource, + KernelResource, +) +from .abstract_board import AbstractBoard + class KernelDiskWorkload: """ diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 5e5af815a4..0ce9d0192b 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -26,41 +26,28 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os - from typing import List -from ...utils.override import overrides -from .abstract_system_board import AbstractSystemBoard -from .kernel_disk_workload import KernelDiskWorkload -from ..processors.abstract_processor import AbstractProcessor -from ..memory.abstract_memory_system import AbstractMemorySystem -from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy -from ...resources.resource import AbstractResource - -from ...isas import ISA - import m5 - from m5.objects import ( + AddrRange, BadAddr, Bridge, - PMAChecker, - RiscvLinux, - AddrRange, - IOXBar, - RiscvRTC, - HiFive, - GenericRiscvPciHost, - IGbE_e1000, CowDiskImage, + Frequency, + GenericRiscvPciHost, + HiFive, + IGbE_e1000, + IOXBar, + PMAChecker, + Port, RawDiskImage, + RiscvLinux, RiscvMmioVirtIO, + RiscvRTC, VirtIOBlock, VirtIORng, - Frequency, - Port, ) - from m5.util.fdthelper import ( Fdt, FdtNode, @@ -70,6 +57,15 @@ from m5.util.fdthelper import ( FdtState, ) +from ...isas import ISA +from ...resources.resource import AbstractResource +from ...utils.override import overrides +from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy +from ..memory.abstract_memory_system import AbstractMemorySystem +from ..processors.abstract_processor import AbstractProcessor +from .abstract_system_board import AbstractSystemBoard +from .kernel_disk_workload import KernelDiskWorkload + class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): """ diff --git a/src/python/gem5/components/boards/se_binary_workload.py b/src/python/gem5/components/boards/se_binary_workload.py index cba268b2df..0c13ffedd1 100644 --- a/src/python/gem5/components/boards/se_binary_workload.py +++ b/src/python/gem5/components/boards/se_binary_workload.py @@ -24,27 +24,32 @@ # (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_board import AbstractBoard - -from ...resources.resource import ( - FileResource, - AbstractResource, - BinaryResource, - CheckpointResource, - SimpointResource, - SimpointDirectoryResource, +from pathlib import Path +from typing import ( + List, + Optional, + Union, ) -from ..processors.switchable_processor import SwitchableProcessor +from m5.objects import ( + Process, + SEWorkload, +) +from m5.util import warn from gem5.resources.elfie import ELFieInfo from gem5.resources.looppoint import Looppoint -from m5.objects import SEWorkload, Process - -from typing import Optional, List, Union -from m5.util import warn -from pathlib import Path +from ...resources.resource import ( + AbstractResource, + BinaryResource, + CheckpointResource, + FileResource, + SimpointDirectoryResource, + SimpointResource, +) +from ..processors.switchable_processor import SwitchableProcessor +from .abstract_board import AbstractBoard class SEBinaryWorkload: diff --git a/src/python/gem5/components/boards/simple_board.py b/src/python/gem5/components/boards/simple_board.py index 2e4122e061..1891dfd345 100644 --- a/src/python/gem5/components/boards/simple_board.py +++ b/src/python/gem5/components/boards/simple_board.py @@ -24,16 +24,20 @@ # (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 AddrRange, IOXBar, Port +from typing import List +from m5.objects import ( + AddrRange, + IOXBar, + Port, +) + +from ...utils.override import overrides +from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy +from ..memory.abstract_memory_system import AbstractMemorySystem +from ..processors.abstract_processor import AbstractProcessor from .abstract_system_board import AbstractSystemBoard from .se_binary_workload import SEBinaryWorkload -from ..processors.abstract_processor import AbstractProcessor -from ..memory.abstract_memory_system import AbstractMemorySystem -from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy -from ...utils.override import overrides - -from typing import List class SimpleBoard(AbstractSystemBoard, SEBinaryWorkload): diff --git a/src/python/gem5/components/boards/test_board.py b/src/python/gem5/components/boards/test_board.py index dea5adab56..0c0407f888 100644 --- a/src/python/gem5/components/boards/test_board.py +++ b/src/python/gem5/components/boards/test_board.py @@ -24,17 +24,23 @@ # (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 Port, IOXBar, AddrRange +from typing import ( + List, + Optional, +) + +from m5.objects import ( + AddrRange, + IOXBar, + Port, +) from ...utils.override import overrides +from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy +from ..memory.abstract_memory_system import AbstractMemorySystem +from ..processors.abstract_generator import AbstractGenerator from .abstract_board import AbstractBoard from .abstract_system_board import AbstractSystemBoard -from ..processors.abstract_generator import AbstractGenerator -from ..memory.abstract_memory_system import AbstractMemorySystem -from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy - - -from typing import List, Optional class TestBoard(AbstractSystemBoard): diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index e7e65ecf71..764688da60 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -25,40 +25,41 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from .kernel_disk_workload import KernelDiskWorkload -from ...resources.resource import AbstractResource -from ...utils.override import overrides -from .abstract_system_board import AbstractSystemBoard -from ...isas import ISA - -from m5.objects import ( - Pc, - AddrRange, - X86FsLinux, - Addr, - X86SMBiosBiosInformation, - X86IntelMPProcessor, - X86IntelMPIOAPIC, - X86IntelMPBus, - X86IntelMPBusHierarchy, - X86IntelMPIOIntAssignment, - X86E820Entry, - Bridge, - IOXBar, - IdeDisk, - CowDiskImage, - RawDiskImage, - BaseXBar, - Port, +from typing import ( + List, + Sequence, ) +from m5.objects import ( + Addr, + AddrRange, + BaseXBar, + Bridge, + CowDiskImage, + IdeDisk, + IOXBar, + Pc, + Port, + RawDiskImage, + X86E820Entry, + X86FsLinux, + X86IntelMPBus, + X86IntelMPBusHierarchy, + X86IntelMPIOAPIC, + X86IntelMPIOIntAssignment, + X86IntelMPProcessor, + X86SMBiosBiosInformation, +) from m5.util.convert import toMemorySize -from ..processors.abstract_processor import AbstractProcessor -from ..memory.abstract_memory_system import AbstractMemorySystem +from ...isas import ISA +from ...resources.resource import AbstractResource +from ...utils.override import overrides from ..cachehierarchies.abstract_cache_hierarchy import AbstractCacheHierarchy - -from typing import List, Sequence +from ..memory.abstract_memory_system import AbstractMemorySystem +from ..processors.abstract_processor import AbstractProcessor +from .abstract_system_board import AbstractSystemBoard +from .kernel_disk_workload import KernelDiskWorkload class X86Board(AbstractSystemBoard, KernelDiskWorkload): diff --git a/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py index 8d59a383f1..d8722a1df7 100644 --- a/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py @@ -24,12 +24,15 @@ # (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 ABCMeta, abstractmethod - -from ..boards.abstract_board import AbstractBoard +from abc import ( + ABCMeta, + abstractmethod, +) from m5.objects import SubSystem +from ..boards.abstract_board import AbstractBoard + class AbstractCacheHierarchy(SubSystem): __metaclass__ = ABCMeta diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py index ed8c3e0d5a..beb0d467d1 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/abstract_node.py @@ -24,14 +24,18 @@ # (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 +from abc import abstractmethod + +from m5.objects import ( + Cache_Controller, + MessageBuffer, + RubyNetwork, +) + +from gem5.components.processors.abstract_core import AbstractCore +from gem5.components.processors.cpu_types import CPUTypes +from gem5.isas import ISA class TriggerMessageBuffer(MessageBuffer): diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py index b93112a620..7d7a16cd5f 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py @@ -24,9 +24,14 @@ # (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 ( + NULL, + ClockDomain, + RubyCache, + RubyNetwork, +) -from m5.objects import ClockDomain, NULL, RubyCache, RubyNetwork +from .abstract_node import AbstractNode class SimpleDirectory(AbstractNode): diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py index f6b63e0649..2997c33ce7 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py @@ -24,13 +24,16 @@ # (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 ( + ClockDomain, + RubyCache, +) + 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): 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 index 2f618491ca..477c0f9b63 100644 --- 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 @@ -24,13 +24,17 @@ # (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 ( + ClockDomain, + RubyCache, + RubyNetwork, +) + 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__( 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 index 7be9239331..92b240da26 100644 --- a/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py @@ -27,30 +27,34 @@ 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 m5.objects import ( + NULL, + RubyPortProxy, + RubySequencer, + RubySystem, ) +from m5.objects.SubSystem import SubSystem + +from gem5.coherence_protocol import CoherenceProtocol +from gem5.components.boards.abstract_board import AbstractBoard from gem5.components.cachehierarchies.abstract_cache_hierarchy import ( AbstractCacheHierarchy, ) -from gem5.coherence_protocol import CoherenceProtocol -from gem5.isas import 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.abstract_ruby_cache_hierarchy import ( + AbstractRubyCacheHierarchy, +) from gem5.components.cachehierarchies.ruby.topologies.simple_pt2pt import ( SimplePt2Pt, ) +from gem5.components.processors.abstract_core import AbstractCore +from gem5.isas import ISA +from gem5.utils.override import overrides +from gem5.utils.requires import requires -from .nodes.private_l1_moesi_cache import PrivateL1MOESICache -from .nodes.dma_requestor import DMARequestor from .nodes.directory import SimpleDirectory +from .nodes.dma_requestor import DMARequestor from .nodes.memory_controller import MemoryController - -from m5.objects import NULL, RubySystem, RubySequencer, RubyPortProxy +from .nodes.private_l1_moesi_cache import PrivateL1MOESICache class PrivateL1CacheHierarchy(AbstractRubyCacheHierarchy): diff --git a/src/python/gem5/components/cachehierarchies/classic/abstract_classic_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/abstract_classic_cache_hierarchy.py index 3423c9ca9a..7531b2a3f1 100644 --- a/src/python/gem5/components/cachehierarchies/classic/abstract_classic_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/abstract_classic_cache_hierarchy.py @@ -25,11 +25,12 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import abstractmethod -from ....utils.override import overrides -from ..abstract_cache_hierarchy import AbstractCacheHierarchy from m5.objects import Port +from ....utils.override import overrides +from ..abstract_cache_hierarchy import AbstractCacheHierarchy + class AbstractClassicCacheHierarchy(AbstractCacheHierarchy): """ diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py b/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py index da4a4ead9b..6165870129 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py @@ -24,12 +24,16 @@ # (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 .....utils.override import * - -from m5.objects import Cache, BasePrefetcher, StridePrefetcher - from typing import Type +from m5.objects import ( + BasePrefetcher, + Cache, + StridePrefetcher, +) + +from .....utils.override import * + class L1DCache(Cache): """ diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py b/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py index f1ac89cf1d..d5130b2b28 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py @@ -26,7 +26,11 @@ from typing import Type -from m5.objects import Cache, BasePrefetcher, StridePrefetcher +from m5.objects import ( + BasePrefetcher, + Cache, + StridePrefetcher, +) from .....utils.override import * diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/l2cache.py b/src/python/gem5/components/cachehierarchies/classic/caches/l2cache.py index 86b69855b6..aa796f4ceb 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/l2cache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/l2cache.py @@ -24,12 +24,17 @@ # (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 .....utils.override import * - -from m5.objects import Cache, Clusivity, BasePrefetcher, StridePrefetcher - from typing import Type +from m5.objects import ( + BasePrefetcher, + Cache, + Clusivity, + StridePrefetcher, +) + +from .....utils.override import * + class L2Cache(Cache): """ diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py b/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py index a6eb43cfb4..2da494aa6c 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py @@ -24,9 +24,13 @@ # (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 .....utils.override import * +from m5.objects import ( + BasePrefetcher, + Cache, + StridePrefetcher, +) -from m5.objects import Cache, BasePrefetcher, StridePrefetcher +from .....utils.override import * class MMUCache(Cache): diff --git a/src/python/gem5/components/cachehierarchies/classic/no_cache.py b/src/python/gem5/components/cachehierarchies/classic/no_cache.py index b7af6ed02f..b43e6f69cb 100644 --- a/src/python/gem5/components/cachehierarchies/classic/no_cache.py +++ b/src/python/gem5/components/cachehierarchies/classic/no_cache.py @@ -24,14 +24,19 @@ # (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_classic_cache_hierarchy import AbstractClassicCacheHierarchy -from ..abstract_cache_hierarchy import AbstractCacheHierarchy -from ...boards.abstract_board import AbstractBoard +from m5.objects import ( + BadAddr, + BaseXBar, + Bridge, + Port, + SystemXBar, +) + from ....isas import ISA - -from m5.objects import Bridge, BaseXBar, SystemXBar, BadAddr, Port - from ....utils.override import * +from ...boards.abstract_board import AbstractBoard +from ..abstract_cache_hierarchy import AbstractCacheHierarchy +from .abstract_classic_cache_hierarchy import AbstractClassicCacheHierarchy class NoCache(AbstractClassicCacheHierarchy): diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py index 9a40c39550..b5be4905df 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py @@ -24,17 +24,22 @@ # (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 ( + BadAddr, + BaseXBar, + Cache, + Port, + SystemXBar, +) + +from ....isas import ISA +from ....utils.override import * +from ...boards.abstract_board import AbstractBoard from ..abstract_cache_hierarchy import AbstractCacheHierarchy from .abstract_classic_cache_hierarchy import AbstractClassicCacheHierarchy from .caches.l1dcache import L1DCache from .caches.l1icache import L1ICache from .caches.mmu_cache import MMUCache -from ...boards.abstract_board import AbstractBoard -from ....isas import ISA - -from m5.objects import Cache, BaseXBar, SystemXBar, BadAddr, Port - -from ....utils.override import * class PrivateL1CacheHierarchy(AbstractClassicCacheHierarchy): 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 b27ced916c..748f7e1f5c 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 @@ -24,18 +24,25 @@ # (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 ( + BadAddr, + BaseXBar, + Cache, + L2XBar, + Port, + SystemXBar, +) + +from ....isas import ISA +from ....utils.override import * +from ...boards.abstract_board import AbstractBoard from ..abstract_cache_hierarchy import AbstractCacheHierarchy -from .abstract_classic_cache_hierarchy import AbstractClassicCacheHierarchy from ..abstract_two_level_cache_hierarchy import AbstractTwoLevelCacheHierarchy +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 -from ...boards.abstract_board import AbstractBoard -from ....isas import ISA -from m5.objects import Cache, L2XBar, BaseXBar, SystemXBar, BadAddr, Port - -from ....utils.override import * class PrivateL1PrivateL2CacheHierarchy( diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py index be2dfbe79c..68671738c8 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py @@ -24,18 +24,25 @@ # (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 ( + BadAddr, + BaseXBar, + Cache, + L2XBar, + Port, + SystemXBar, +) + +from ....isas import ISA +from ....utils.override import * +from ...boards.abstract_board import AbstractBoard from ..abstract_cache_hierarchy import AbstractCacheHierarchy -from .abstract_classic_cache_hierarchy import AbstractClassicCacheHierarchy from ..abstract_two_level_cache_hierarchy import AbstractTwoLevelCacheHierarchy +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 -from ...boards.abstract_board import AbstractBoard -from ....isas import ISA -from m5.objects import Cache, L2XBar, BaseXBar, SystemXBar, BadAddr, Port - -from ....utils.override import * class PrivateL1SharedL2CacheHierarchy( diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py index 237cd606df..a9944c4d03 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/abstract_l1_cache.py @@ -24,14 +24,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import math from abc import abstractmethod -from .....isas import ISA -from ....processors.cpu_types import CPUTypes -from ....processors.abstract_core import AbstractCore from m5.objects import L1Cache_Controller -import math +from .....isas import ISA +from ....processors.abstract_core import AbstractCore +from ....processors.cpu_types import CPUTypes class AbstractL1Cache(L1Cache_Controller): diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py index 58676daaf0..4840e3b264 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/directory.py @@ -24,11 +24,14 @@ # (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 ( + MessageBuffer, + RubyDirectoryMemory, +) + from ......utils.override import overrides from ..abstract_directory import AbstractDirectory -from m5.objects import MessageBuffer, RubyDirectoryMemory - class Directory(AbstractDirectory): def __init__(self, network, cache_line_size, mem_range, port): diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/dma_controller.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/dma_controller.py index f731869f54..145757c15a 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/dma_controller.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/dma_controller.py @@ -24,9 +24,12 @@ # (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 ......utils.override import overrides +from m5.objects import ( + DMA_Controller, + MessageBuffer, +) -from m5.objects import MessageBuffer, DMA_Controller +from ......utils.override import overrides class DMAController(DMA_Controller): diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py index 0d7f436193..6d203f978a 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l1_cache.py @@ -24,20 +24,20 @@ # (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 .....processors.abstract_core import AbstractCore -from ......isas import ISA -from ......utils.override import * +import math from m5.objects import ( - MessageBuffer, - RubyPrefetcher, - RubyCache, - ClockDomain, LRURP, + ClockDomain, L0Cache_Controller, + MessageBuffer, + RubyCache, + RubyPrefetcher, ) -import math +from ......isas import ISA +from ......utils.override import * +from .....processors.abstract_core import AbstractCore # L0Cache_Controller is the ruby backend's terminology corresponding to diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py index 280c2e4110..ff2b8e3dd9 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l2_cache.py @@ -24,19 +24,19 @@ # (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 .....processors.abstract_core import AbstractCore -from ......isas import ISA -from ......utils.override import * +import math from m5.objects import ( - MessageBuffer, - RubyPrefetcher, - RubyCache, ClockDomain, L1Cache_Controller, + MessageBuffer, + RubyCache, + RubyPrefetcher, ) -import math +from ......isas import ISA +from ......utils.override import * +from .....processors.abstract_core import AbstractCore # L1Cache_Controller is ruby backend's terminology corresponding to diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py index 4b05166752..8509a35cfc 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_three_level/l3_cache.py @@ -24,10 +24,14 @@ # (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 MessageBuffer, RubyCache, L2Cache_Controller - import math +from m5.objects import ( + L2Cache_Controller, + MessageBuffer, + RubyCache, +) + # L2Cache_Controller is ruby backend's terminology corresponding to # L3 cache in stdlib. diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py index 58676daaf0..4840e3b264 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/directory.py @@ -24,11 +24,14 @@ # (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 ( + MessageBuffer, + RubyDirectoryMemory, +) + from ......utils.override import overrides from ..abstract_directory import AbstractDirectory -from m5.objects import MessageBuffer, RubyDirectoryMemory - class Directory(AbstractDirectory): def __init__(self, network, cache_line_size, mem_range, port): diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/dma_controller.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/dma_controller.py index ab76d4cb5e..aa7a5ad778 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/dma_controller.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/dma_controller.py @@ -24,11 +24,11 @@ # (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 MessageBuffer + from ......utils.override import overrides from ..abstract_dma_controller import AbstractDMAController -from m5.objects import MessageBuffer - class DMAController(AbstractDMAController): def __init__(self, network, cache_line_size): diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l1_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l1_cache.py index 0e0e333da9..7787644c9b 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l1_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l1_cache.py @@ -24,15 +24,20 @@ # (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 .....processors.abstract_core import AbstractCore -from ......isas import ISA -from ..abstract_l1_cache import AbstractL1Cache -from ......utils.override import * - -from m5.objects import MessageBuffer, RubyPrefetcher, RubyCache, ClockDomain - import math +from m5.objects import ( + ClockDomain, + MessageBuffer, + RubyCache, + RubyPrefetcher, +) + +from ......isas import ISA +from ......utils.override import * +from .....processors.abstract_core import AbstractCore +from ..abstract_l1_cache import AbstractL1Cache + class L1Cache(AbstractL1Cache): def __init__( diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l2_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l2_cache.py index 81ef4dbe90..4f7c923c54 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l2_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mesi_two_level/l2_cache.py @@ -24,13 +24,16 @@ # (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_l2_cache import AbstractL2Cache -from ......utils.override import * - -from m5.objects import MessageBuffer, RubyCache - import math +from m5.objects import ( + MessageBuffer, + RubyCache, +) + +from ......utils.override import * +from ..abstract_l2_cache import AbstractL2Cache + class L2Cache(AbstractL2Cache): def __init__( diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py index 0e7cddf6fe..3d1ae54104 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/directory.py @@ -24,11 +24,13 @@ # (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_directory import AbstractDirectory +from m5.objects import ( + MessageBuffer, + RubyDirectoryMemory, +) + from ......utils.override import overrides - - -from m5.objects import MessageBuffer, RubyDirectoryMemory +from ..abstract_directory import AbstractDirectory class Directory(AbstractDirectory): diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/dma_controller.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/dma_controller.py index fb6895f4f8..b9c1f4a60f 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/dma_controller.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/dma_controller.py @@ -24,11 +24,11 @@ # (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_dma_controller import AbstractDMAController -from ......utils.override import overrides - from m5.objects import MessageBuffer +from ......utils.override import overrides +from ..abstract_dma_controller import AbstractDMAController + class DMAController(AbstractDMAController): """ diff --git a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/l1_cache.py b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/l1_cache.py index 1368b92bfc..2feae222d8 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/l1_cache.py +++ b/src/python/gem5/components/cachehierarchies/ruby/caches/mi_example/l1_cache.py @@ -24,13 +24,17 @@ # (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 ( + ClockDomain, + MessageBuffer, + RubyCache, +) + +from ......isas import ISA from ......utils.override import overrides from .....processors.abstract_core import AbstractCore -from ......isas import ISA from ..abstract_l1_cache import AbstractL1Cache -from m5.objects import MessageBuffer, RubyCache, ClockDomain - class L1Cache(AbstractL1Cache): def __init__( 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 index f056d76f98..9aa0dc4a36 100644 --- 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 @@ -24,11 +24,17 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from typing import List, Tuple +from typing import ( + List, + Tuple, +) + +from m5.objects import ( + RubySequencer, + SubSystem, +) -from gem5.isas import ISA from gem5.components.boards.abstract_board import AbstractBoard -from gem5.components.processors.abstract_core import AbstractCore from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l1_cache import ( L1Cache, ) @@ -38,14 +44,14 @@ from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l2_cache impo from gem5.components.cachehierarchies.ruby.caches.mesi_three_level.l3_cache import ( L3Cache, ) - -from m5.objects import SubSystem, RubySequencer +from gem5.components.processors.abstract_core import AbstractCore +from gem5.isas import ISA from .ruby_network_components import ( - RubyRouter, RubyExtLink, RubyIntLink, RubyNetworkComponent, + RubyRouter, ) 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 index 09ee69e011..f7d4d63de1 100644 --- 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 @@ -24,26 +24,32 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from ...abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy -from ....abstract_three_level_cache_hierarchy import ( - AbstractThreeLevelCacheHierarchy, +from m5.objects import ( + DMASequencer, + RubyPortProxy, + RubySystem, ) + from ......coherence_protocol import CoherenceProtocol from ......components.boards.abstract_board import AbstractBoard -from ......utils.requires import requires - from ......components.cachehierarchies.ruby.caches.mesi_three_level.directory import ( Directory, ) from ......components.cachehierarchies.ruby.caches.mesi_three_level.dma_controller import ( DMAController, ) - -from m5.objects import RubySystem, DMASequencer, RubyPortProxy - +from ......utils.requires import requires +from ....abstract_three_level_cache_hierarchy import ( + AbstractThreeLevelCacheHierarchy, +) +from ...abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy from .core_complex import CoreComplex from .octopi_network import OctopiNetwork -from .ruby_network_components import RubyRouter, RubyExtLink, RubyIntLink +from .ruby_network_components import ( + RubyExtLink, + RubyIntLink, + RubyRouter, +) # CoreComplex sub-systems own the L1, L2, L3 controllers 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 index 8e5befabf7..c175a24778 100644 --- 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 @@ -27,9 +27,9 @@ from m5.objects import SimpleNetwork from .ruby_network_components import ( + RubyIntLink, RubyNetworkComponent, RubyRouter, - RubyIntLink, ) 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 index 8a413ea59d..70cfe4242d 100644 --- 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 @@ -24,7 +24,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from m5.objects import Switch, SimpleIntLink, SimpleExtLink +from m5.objects import ( + SimpleExtLink, + SimpleIntLink, + Switch, +) class RubyNetworkComponent: 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 2a8ce30cda..039ba8fb7a 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 @@ -25,23 +25,27 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from .abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy +from m5.objects import ( + DMASequencer, + RubyPortProxy, + RubySequencer, + RubySystem, +) + +from ....coherence_protocol import CoherenceProtocol +from ....isas import ISA +from ....utils.requires import requires +from ...boards.abstract_board import AbstractBoard from ..abstract_three_level_cache_hierarchy import ( AbstractThreeLevelCacheHierarchy, ) -from ....coherence_protocol import CoherenceProtocol -from ....isas import ISA -from ...boards.abstract_board import AbstractBoard -from ....utils.requires import requires - -from .topologies.simple_pt2pt import SimplePt2Pt +from .abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy +from .caches.mesi_three_level.directory import Directory +from .caches.mesi_three_level.dma_controller import DMAController from .caches.mesi_three_level.l1_cache import L1Cache from .caches.mesi_three_level.l2_cache import L2Cache from .caches.mesi_three_level.l3_cache import L3Cache -from .caches.mesi_three_level.directory import Directory -from .caches.mesi_three_level.dma_controller import DMAController - -from m5.objects import RubySystem, RubySequencer, DMASequencer, RubyPortProxy +from .topologies.simple_pt2pt import SimplePt2Pt class MESIThreeLevelCacheHierarchy( diff --git a/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py index 8c7bba4ed4..083e4d43fe 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/ruby/mesi_two_level_cache_hierarchy.py @@ -25,20 +25,24 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from .abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy -from ..abstract_two_level_cache_hierarchy import AbstractTwoLevelCacheHierarchy +from m5.objects import ( + DMASequencer, + RubyPortProxy, + RubySequencer, + RubySystem, +) + from ....coherence_protocol import CoherenceProtocol from ....isas import ISA -from ...boards.abstract_board import AbstractBoard from ....utils.requires import requires - -from .topologies.simple_pt2pt import SimplePt2Pt -from .caches.mesi_two_level.l1_cache import L1Cache -from .caches.mesi_two_level.l2_cache import L2Cache +from ...boards.abstract_board import AbstractBoard +from ..abstract_two_level_cache_hierarchy import AbstractTwoLevelCacheHierarchy +from .abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy from .caches.mesi_two_level.directory import Directory from .caches.mesi_two_level.dma_controller import DMAController - -from m5.objects import RubySystem, RubySequencer, DMASequencer, RubyPortProxy +from .caches.mesi_two_level.l1_cache import L1Cache +from .caches.mesi_two_level.l2_cache import L2Cache +from .topologies.simple_pt2pt import SimplePt2Pt class MESITwoLevelCacheHierarchy( diff --git a/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py index 93b19591cc..328fb0f998 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/ruby/mi_example_cache_hierarchy.py @@ -24,20 +24,24 @@ # (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 .caches.mi_example.l1_cache import L1Cache -from .caches.mi_example.dma_controller import DMAController -from .caches.mi_example.directory import Directory -from .topologies.simple_pt2pt import SimplePt2Pt -from .abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy -from ..abstract_cache_hierarchy import AbstractCacheHierarchy -from ...boards.abstract_board import AbstractBoard +from m5.objects import ( + DMASequencer, + RubyPortProxy, + RubySequencer, + RubySystem, +) + from ....coherence_protocol import CoherenceProtocol from ....isas import ISA from ....utils.override import overrides from ....utils.requires import requires - - -from m5.objects import RubySystem, RubySequencer, DMASequencer, RubyPortProxy +from ...boards.abstract_board import AbstractBoard +from ..abstract_cache_hierarchy import AbstractCacheHierarchy +from .abstract_ruby_cache_hierarchy import AbstractRubyCacheHierarchy +from .caches.mi_example.directory import Directory +from .caches.mi_example.dma_controller import DMAController +from .caches.mi_example.l1_cache import L1Cache +from .topologies.simple_pt2pt import SimplePt2Pt class MIExampleCacheHierarchy(AbstractRubyCacheHierarchy): diff --git a/src/python/gem5/components/cachehierarchies/ruby/topologies/simple_pt2pt.py b/src/python/gem5/components/cachehierarchies/ruby/topologies/simple_pt2pt.py index 649f027d72..65c3ad51c2 100644 --- a/src/python/gem5/components/cachehierarchies/ruby/topologies/simple_pt2pt.py +++ b/src/python/gem5/components/cachehierarchies/ruby/topologies/simple_pt2pt.py @@ -24,7 +24,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from m5.objects import SimpleNetwork, Switch, SimpleExtLink, SimpleIntLink +from m5.objects import ( + SimpleExtLink, + SimpleIntLink, + SimpleNetwork, + Switch, +) class SimplePt2Pt(SimpleNetwork): diff --git a/src/python/gem5/components/memory/__init__.py b/src/python/gem5/components/memory/__init__.py index 546d5d98ed..49a8cb8173 100644 --- a/src/python/gem5/components/memory/__init__.py +++ b/src/python/gem5/components/memory/__init__.py @@ -24,26 +24,32 @@ # (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 .single_channel import SingleChannelDDR3_1600 -from .single_channel import SingleChannelDDR3_2133 -from .single_channel import SingleChannelDDR4_2400 -from .single_channel import SingleChannelHBM -from .single_channel import SingleChannelLPDDR3_1600 -from .single_channel import DIMM_DDR5_4400 -from .single_channel import DIMM_DDR5_6400 -from .single_channel import DIMM_DDR5_8400 -from .multi_channel import DualChannelDDR3_1600 -from .multi_channel import DualChannelDDR3_2133 -from .multi_channel import DualChannelDDR4_2400 -from .multi_channel import DualChannelLPDDR3_1600 from .hbm import HBM2Stack +from .multi_channel import ( + DualChannelDDR3_1600, + DualChannelDDR3_2133, + DualChannelDDR4_2400, + DualChannelLPDDR3_1600, +) +from .single_channel import ( + DIMM_DDR5_4400, + DIMM_DDR5_6400, + DIMM_DDR5_8400, + SingleChannelDDR3_1600, + SingleChannelDDR3_2133, + SingleChannelDDR4_2400, + SingleChannelHBM, + SingleChannelLPDDR3_1600, +) try: - from .dramsys import DRAMSysMem - from .dramsys import DRAMSysDDR4_1866 - from .dramsys import DRAMSysDDR3_1600 - from .dramsys import DRAMSysLPDDR4_3200 - from .dramsys import DRAMSysHBM2 + from .dramsys import ( + DRAMSysDDR3_1600, + DRAMSysDDR4_1866, + DRAMSysHBM2, + DRAMSysLPDDR4_3200, + DRAMSysMem, + ) except: # In the case that DRAMSys is not compiled into the gem5 binary, importing # DRAMSys components will fail. This try-exception statement is needed to diff --git a/src/python/gem5/components/memory/abstract_memory_system.py b/src/python/gem5/components/memory/abstract_memory_system.py index cfbf6ac01c..e985cf1d9b 100644 --- a/src/python/gem5/components/memory/abstract_memory_system.py +++ b/src/python/gem5/components/memory/abstract_memory_system.py @@ -24,14 +24,25 @@ # (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 ABCMeta, abstractmethod -from typing import Tuple, Sequence, List +from abc import ( + ABCMeta, + abstractmethod, +) +from typing import ( + List, + Sequence, + Tuple, +) +from m5.objects import ( + AddrRange, + MemCtrl, + Port, + SubSystem, +) from ..boards.abstract_board import AbstractBoard -from m5.objects import AddrRange, Port, SubSystem, MemCtrl - class AbstractMemorySystem(SubSystem): __metaclass__ = ABCMeta diff --git a/src/python/gem5/components/memory/dramsim_3.py b/src/python/gem5/components/memory/dramsim_3.py index f154ba354f..fd99df9dbd 100644 --- a/src/python/gem5/components/memory/dramsim_3.py +++ b/src/python/gem5/components/memory/dramsim_3.py @@ -1,8 +1,19 @@ -import m5 -import os import configparser +import os +from typing import ( + List, + Optional, + Sequence, + Tuple, +) -from m5.objects import DRAMsim3, AddrRange, Port, MemCtrl +import m5 +from m5.objects import ( + AddrRange, + DRAMsim3, + MemCtrl, + Port, +) from m5.util.convert import toMemorySize from ...utils.override import overrides @@ -10,9 +21,6 @@ from ..boards.abstract_board import AbstractBoard from .abstract_memory_system import AbstractMemorySystem -from typing import Optional, Tuple, Sequence, List - - def config_ds3(mem_type: str, num_chnls: int) -> Tuple[str, str]: """ This function creates a config file that will be used to create a memory diff --git a/src/python/gem5/components/memory/dramsys.py b/src/python/gem5/components/memory/dramsys.py index a09d2fa0fc..25e1c84b5a 100644 --- a/src/python/gem5/components/memory/dramsys.py +++ b/src/python/gem5/components/memory/dramsys.py @@ -24,15 +24,20 @@ # (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 Tuple, Sequence, List, Optional from pathlib import Path +from typing import ( + List, + Optional, + Sequence, + Tuple, +) from m5.objects import ( - DRAMSys, AddrRange, - Port, - MemCtrl, + DRAMSys, Gem5ToTlmBridge32, + MemCtrl, + Port, SystemC_Kernel, ) from m5.util.convert import toMemorySize @@ -41,7 +46,6 @@ from ...utils.override import overrides from ..boards.abstract_board import AbstractBoard from .abstract_memory_system import AbstractMemorySystem - DEFAULT_DRAMSYS_DIRECTORY = Path("ext/dramsys/DRAMSys") diff --git a/src/python/gem5/components/memory/hbm.py b/src/python/gem5/components/memory/hbm.py index 3f0716c14b..7d59caa478 100644 --- a/src/python/gem5/components/memory/hbm.py +++ b/src/python/gem5/components/memory/hbm.py @@ -27,14 +27,29 @@ """ HBM2 memory system using HBMCtrl """ -from .memory import ChanneledMemory -from .abstract_memory_system import AbstractMemorySystem from math import log +from typing import ( + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from m5.objects import ( + AddrRange, + DRAMInterface, + HBMCtrl, + Port, +) + from ...utils.override import overrides -from m5.objects import AddrRange, DRAMInterface, HBMCtrl, Port -from typing import Type, Optional, Union, Sequence, Tuple -from .memory import _try_convert +from .abstract_memory_system import AbstractMemorySystem from .dram_interfaces.hbm import HBM_2000_4H_1x64 +from .memory import ( + ChanneledMemory, + _try_convert, +) class HighBandwidthMemory(ChanneledMemory): diff --git a/src/python/gem5/components/memory/memory.py b/src/python/gem5/components/memory/memory.py index e7e6cf46e3..6742da2c3f 100644 --- a/src/python/gem5/components/memory/memory.py +++ b/src/python/gem5/components/memory/memory.py @@ -28,12 +28,26 @@ """ from math import log -from ...utils.override import overrides +from typing import ( + List, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from m5.objects import ( + AddrRange, + DRAMInterface, + MemCtrl, + Port, +) from m5.util.convert import toMemorySize + +from ...utils.override import overrides from ..boards.abstract_board import AbstractBoard from .abstract_memory_system import AbstractMemorySystem -from m5.objects import AddrRange, DRAMInterface, MemCtrl, Port -from typing import Type, Sequence, Tuple, List, Optional, Union def _try_convert(val, cls): diff --git a/src/python/gem5/components/memory/multi_channel.py b/src/python/gem5/components/memory/multi_channel.py index 1f14190c97..59d06fba1f 100644 --- a/src/python/gem5/components/memory/multi_channel.py +++ b/src/python/gem5/components/memory/multi_channel.py @@ -24,14 +24,17 @@ # (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 .memory import ChanneledMemory -from .abstract_memory_system import AbstractMemorySystem - from typing import Optional -from .dram_interfaces.ddr3 import DDR3_1600_8x8, DDR3_2133_8x8 + +from .abstract_memory_system import AbstractMemorySystem +from .dram_interfaces.ddr3 import ( + DDR3_1600_8x8, + DDR3_2133_8x8, +) from .dram_interfaces.ddr4 import DDR4_2400_8x8 -from .dram_interfaces.lpddr3 import LPDDR3_1600_1x32 from .dram_interfaces.hbm import HBM_1000_4H_1x64 +from .dram_interfaces.lpddr3 import LPDDR3_1600_1x32 +from .memory import ChanneledMemory def DualChannelDDR3_1600( diff --git a/src/python/gem5/components/memory/simple.py b/src/python/gem5/components/memory/simple.py index b650a68ba4..a849641135 100644 --- a/src/python/gem5/components/memory/simple.py +++ b/src/python/gem5/components/memory/simple.py @@ -27,12 +27,23 @@ """Simple memory controllers """ -from ...utils.override import overrides +from typing import ( + List, + Sequence, + Tuple, +) + +from m5.objects import ( + AddrRange, + MemCtrl, + Port, + SimpleMemory, +) from m5.util.convert import toMemorySize -from typing import List, Sequence, Tuple + +from ...utils.override import overrides from ..boards.abstract_board import AbstractBoard from .abstract_memory_system import AbstractMemorySystem -from m5.objects import AddrRange, MemCtrl, Port, SimpleMemory class SingleChannelSimpleMemory(AbstractMemorySystem): diff --git a/src/python/gem5/components/memory/single_channel.py b/src/python/gem5/components/memory/single_channel.py index 9235bbd52d..0efb2979a5 100644 --- a/src/python/gem5/components/memory/single_channel.py +++ b/src/python/gem5/components/memory/single_channel.py @@ -24,16 +24,22 @@ # (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 .memory import ChanneledMemory -from .abstract_memory_system import AbstractMemorySystem - from typing import Optional -from .dram_interfaces.ddr5 import DDR5_4400_4x8, DDR5_6400_4x8, DDR5_8400_4x8 +from .abstract_memory_system import AbstractMemorySystem +from .dram_interfaces.ddr3 import ( + DDR3_1600_8x8, + DDR3_2133_8x8, +) from .dram_interfaces.ddr4 import DDR4_2400_8x8 +from .dram_interfaces.ddr5 import ( + DDR5_4400_4x8, + DDR5_6400_4x8, + DDR5_8400_4x8, +) from .dram_interfaces.hbm import HBM_1000_4H_1x128 from .dram_interfaces.lpddr3 import LPDDR3_1600_1x32 -from .dram_interfaces.ddr3 import DDR3_1600_8x8, DDR3_2133_8x8 +from .memory import ChanneledMemory def SingleChannelDDR3_1600( diff --git a/src/python/gem5/components/processors/abstract_core.py b/src/python/gem5/components/processors/abstract_core.py index 8259df8a8b..dcde782ce1 100644 --- a/src/python/gem5/components/processors/abstract_core.py +++ b/src/python/gem5/components/processors/abstract_core.py @@ -24,14 +24,25 @@ # (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 ABCMeta, abstractmethod -from typing import Optional, List +from abc import ( + ABCMeta, + abstractmethod, +) +from typing import ( + List, + Optional, +) + +from m5.objects import ( + BaseMMU, + PcCountTrackerManager, + Port, + SubSystem, +) +from m5.params import PcCountPair from ...isas import ISA -from m5.objects import BaseMMU, Port, SubSystem, PcCountTrackerManager -from m5.params import PcCountPair - class AbstractCore(SubSystem): __metaclass__ = ABCMeta diff --git a/src/python/gem5/components/processors/abstract_generator.py b/src/python/gem5/components/processors/abstract_generator.py index 30e8f17970..0f9acc48ac 100644 --- a/src/python/gem5/components/processors/abstract_generator.py +++ b/src/python/gem5/components/processors/abstract_generator.py @@ -25,14 +25,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import abstractmethod +from typing import List + from ...utils.override import overrides +from ..boards.abstract_board import AbstractBoard from ..boards.mem_mode import MemMode from .abstract_generator_core import AbstractGeneratorCore - from .abstract_processor import AbstractProcessor -from ..boards.abstract_board import AbstractBoard - -from typing import List def partition_range( diff --git a/src/python/gem5/components/processors/abstract_generator_core.py b/src/python/gem5/components/processors/abstract_generator_core.py index b49e86ee19..ff4285b810 100644 --- a/src/python/gem5/components/processors/abstract_generator_core.py +++ b/src/python/gem5/components/processors/abstract_generator_core.py @@ -26,14 +26,17 @@ from abc import abstractmethod -from m5.objects import Port, PortTerminator -from ...utils.override import overrides - -from .abstract_core import AbstractCore -from ...isas import ISA - from typing import Optional +from m5.objects import ( + Port, + PortTerminator, +) + +from ...isas import ISA +from ...utils.override import overrides +from .abstract_core import AbstractCore + class AbstractGeneratorCore(AbstractCore): """The abstract generator core diff --git a/src/python/gem5/components/processors/abstract_processor.py b/src/python/gem5/components/processors/abstract_processor.py index 8978513562..b34da25906 100644 --- a/src/python/gem5/components/processors/abstract_processor.py +++ b/src/python/gem5/components/processors/abstract_processor.py @@ -24,17 +24,21 @@ # (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 ABCMeta, abstractmethod - -from ...utils.requires import requires -from .abstract_core import AbstractCore +from abc import ( + ABCMeta, + abstractmethod, +) +from typing import ( + List, + Optional, +) from m5.objects import SubSystem -from ..boards.abstract_board import AbstractBoard from ...isas import ISA - -from typing import List, Optional +from ...utils.requires import requires +from ..boards.abstract_board import AbstractBoard +from .abstract_core import AbstractCore class AbstractProcessor(SubSystem): diff --git a/src/python/gem5/components/processors/base_cpu_core.py b/src/python/gem5/components/processors/base_cpu_core.py index 58d06024bc..710a91f1b8 100644 --- a/src/python/gem5/components/processors/base_cpu_core.py +++ b/src/python/gem5/components/processors/base_cpu_core.py @@ -24,24 +24,26 @@ # (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 Optional, List -from ...utils.requires import requires -from .abstract_core import AbstractCore +from typing import ( + List, + Optional, +) + +from m5.objects import ( + BaseCPU, + BaseMMU, + PcCountTracker, + PcCountTrackerManager, + Port, + Process, +) +from m5.params import PcCountPair from ...isas import ISA from ...runtime import get_runtime_isa from ...utils.override import overrides from ...utils.requires import requires - -from m5.objects import ( - BaseMMU, - Port, - BaseCPU, - Process, - PcCountTracker, - PcCountTrackerManager, -) -from m5.params import PcCountPair +from .abstract_core import AbstractCore class BaseCPUCore(AbstractCore): diff --git a/src/python/gem5/components/processors/base_cpu_processor.py b/src/python/gem5/components/processors/base_cpu_processor.py index d097682d26..23e37cd262 100644 --- a/src/python/gem5/components/processors/base_cpu_processor.py +++ b/src/python/gem5/components/processors/base_cpu_processor.py @@ -25,23 +25,22 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from .base_cpu_core import BaseCPUCore -from ..boards.mem_mode import MemMode -from ...utils.override import overrides -from ..boards.mem_mode import MemMode -from .abstract_processor import AbstractProcessor -from ..boards.abstract_board import AbstractBoard - from typing import List -from m5.util import warn from m5.objects import ( - BaseO3CPU, - BaseMinorCPU, BaseAtomicSimpleCPU, + BaseMinorCPU, BaseNonCachingSimpleCPU, + BaseO3CPU, BaseTimingSimpleCPU, ) +from m5.util import warn + +from ...utils.override import overrides +from ..boards.abstract_board import AbstractBoard +from ..boards.mem_mode import MemMode +from .abstract_processor import AbstractProcessor +from .base_cpu_core import BaseCPUCore class BaseCPUProcessor(AbstractProcessor): diff --git a/src/python/gem5/components/processors/complex_generator.py b/src/python/gem5/components/processors/complex_generator.py index 81b94f0c14..9d4c1b33b7 100644 --- a/src/python/gem5/components/processors/complex_generator.py +++ b/src/python/gem5/components/processors/complex_generator.py @@ -24,12 +24,18 @@ # (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 ...utils.override import overrides -from .complex_generator_core import ComplexGeneratorCore -from .abstract_generator import AbstractGenerator -from .abstract_generator import partition_range +from typing import ( + Any, + Iterator, + List, +) -from typing import Iterator, List, Any +from ...utils.override import overrides +from .abstract_generator import ( + AbstractGenerator, + partition_range, +) +from .complex_generator_core import ComplexGeneratorCore class ComplexGenerator(AbstractGenerator): diff --git a/src/python/gem5/components/processors/complex_generator_core.py b/src/python/gem5/components/processors/complex_generator_core.py index 92f62ded09..058f009df8 100644 --- a/src/python/gem5/components/processors/complex_generator_core.py +++ b/src/python/gem5/components/processors/complex_generator_core.py @@ -24,17 +24,25 @@ # (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 Iterator, Any -from m5.ticks import fromSeconds -from m5.util.convert import toLatency, toMemoryBandwidth -from m5.objects import PyTrafficGen, Port +from enum import Enum +from typing import ( + Any, + Iterator, +) -from .abstract_core import AbstractCore -from .abstract_generator_core import AbstractGeneratorCore +from m5.objects import ( + Port, + PyTrafficGen, +) +from m5.ticks import fromSeconds +from m5.util.convert import ( + toLatency, + toMemoryBandwidth, +) from ...utils.override import overrides - -from enum import Enum +from .abstract_core import AbstractCore +from .abstract_generator_core import AbstractGeneratorCore class TrafficModes(Enum): diff --git a/src/python/gem5/components/processors/cpu_types.py b/src/python/gem5/components/processors/cpu_types.py index d2bf6548ed..aa3f822300 100644 --- a/src/python/gem5/components/processors/cpu_types.py +++ b/src/python/gem5/components/processors/cpu_types.py @@ -24,11 +24,11 @@ # (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 ..boards.mem_mode import MemMode - +import os from enum import Enum from typing import Set -import os + +from ..boards.mem_mode import MemMode class CPUTypes(Enum): diff --git a/src/python/gem5/components/processors/gups_generator.py b/src/python/gem5/components/processors/gups_generator.py index 76ea9e64b4..beccd339a7 100644 --- a/src/python/gem5/components/processors/gups_generator.py +++ b/src/python/gem5/components/processors/gups_generator.py @@ -28,8 +28,8 @@ from typing import Optional from m5.objects import Addr -from ...utils.override import overrides +from ...utils.override import overrides from .abstract_generator import AbstractGenerator from .gups_generator_core import GUPSGeneratorCore diff --git a/src/python/gem5/components/processors/gups_generator_core.py b/src/python/gem5/components/processors/gups_generator_core.py index 0090c72847..5bb4ec44d2 100644 --- a/src/python/gem5/components/processors/gups_generator_core.py +++ b/src/python/gem5/components/processors/gups_generator_core.py @@ -26,10 +26,18 @@ from typing import Optional + +from m5.objects import ( + Addr, + GUPSGen, + Port, + SrcClockDomain, + VoltageDomain, +) + from ...utils.override import overrides from .abstract_core import AbstractCore from .abstract_generator_core import AbstractGeneratorCore -from m5.objects import Port, GUPSGen, Addr, SrcClockDomain, VoltageDomain class GUPSGeneratorCore(AbstractGeneratorCore): diff --git a/src/python/gem5/components/processors/gups_generator_ep.py b/src/python/gem5/components/processors/gups_generator_ep.py index 68c9dcea04..bd6adde3e5 100644 --- a/src/python/gem5/components/processors/gups_generator_ep.py +++ b/src/python/gem5/components/processors/gups_generator_ep.py @@ -26,9 +26,11 @@ from typing import Optional + from m5.objects import Addr -from ...utils.override import overrides from m5.util.convert import toMemorySize + +from ...utils.override import overrides from .abstract_generator import AbstractGenerator from .gups_generator_core import GUPSGeneratorCore diff --git a/src/python/gem5/components/processors/gups_generator_par.py b/src/python/gem5/components/processors/gups_generator_par.py index 5f6485b9e2..5db0459dbc 100644 --- a/src/python/gem5/components/processors/gups_generator_par.py +++ b/src/python/gem5/components/processors/gups_generator_par.py @@ -26,12 +26,13 @@ from typing import Optional -from m5.objects import Addr -from ...utils.override import overrides +from m5.objects import Addr + +from ...utils.override import overrides +from ..boards.abstract_board import AbstractBoard from ..boards.mem_mode import MemMode from .abstract_generator import AbstractGenerator -from ..boards.abstract_board import AbstractBoard from .gups_generator_core import GUPSGeneratorCore diff --git a/src/python/gem5/components/processors/linear_generator.py b/src/python/gem5/components/processors/linear_generator.py index 32587d40c2..13779a0f6d 100644 --- a/src/python/gem5/components/processors/linear_generator.py +++ b/src/python/gem5/components/processors/linear_generator.py @@ -24,13 +24,15 @@ # (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 ...utils.override import overrides -from .linear_generator_core import LinearGeneratorCore -from .abstract_generator import AbstractGenerator -from .abstract_generator import partition_range - from typing import List +from ...utils.override import overrides +from .abstract_generator import ( + AbstractGenerator, + partition_range, +) +from .linear_generator_core import LinearGeneratorCore + class LinearGenerator(AbstractGenerator): def __init__( diff --git a/src/python/gem5/components/processors/linear_generator_core.py b/src/python/gem5/components/processors/linear_generator_core.py index b91b44d6aa..11fdde3a15 100644 --- a/src/python/gem5/components/processors/linear_generator_core.py +++ b/src/python/gem5/components/processors/linear_generator_core.py @@ -24,16 +24,22 @@ # (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.ticks import fromSeconds -from m5.util.convert import toLatency, toMemoryBandwidth -from m5.objects import PyTrafficGen, Port, BaseTrafficGen +from typing import Iterator -from .abstract_core import AbstractCore -from .abstract_generator_core import AbstractGeneratorCore +from m5.objects import ( + BaseTrafficGen, + Port, + PyTrafficGen, +) +from m5.ticks import fromSeconds +from m5.util.convert import ( + toLatency, + toMemoryBandwidth, +) from ...utils.override import overrides - -from typing import Iterator +from .abstract_core import AbstractCore +from .abstract_generator_core import AbstractGeneratorCore class LinearGeneratorCore(AbstractGeneratorCore): diff --git a/src/python/gem5/components/processors/random_generator.py b/src/python/gem5/components/processors/random_generator.py index ca7ed98f89..496aaf8606 100644 --- a/src/python/gem5/components/processors/random_generator.py +++ b/src/python/gem5/components/processors/random_generator.py @@ -24,15 +24,14 @@ # (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 ...utils.override import overrides -from ..boards.mem_mode import MemMode -from .random_generator_core import RandomGeneratorCore - -from .abstract_generator import AbstractGenerator -from ..boards.abstract_board import AbstractBoard - from typing import List +from ...utils.override import overrides +from ..boards.abstract_board import AbstractBoard +from ..boards.mem_mode import MemMode +from .abstract_generator import AbstractGenerator +from .random_generator_core import RandomGeneratorCore + class RandomGenerator(AbstractGenerator): def __init__( diff --git a/src/python/gem5/components/processors/random_generator_core.py b/src/python/gem5/components/processors/random_generator_core.py index b5aced620d..aa440ce2d7 100644 --- a/src/python/gem5/components/processors/random_generator_core.py +++ b/src/python/gem5/components/processors/random_generator_core.py @@ -24,16 +24,22 @@ # (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.ticks import fromSeconds -from m5.util.convert import toLatency, toMemoryBandwidth -from m5.objects import PyTrafficGen, Port, BaseTrafficGen +from typing import Iterator -from .abstract_core import AbstractCore -from .abstract_generator_core import AbstractGeneratorCore +from m5.objects import ( + BaseTrafficGen, + Port, + PyTrafficGen, +) +from m5.ticks import fromSeconds +from m5.util.convert import ( + toLatency, + toMemoryBandwidth, +) from ...utils.override import overrides - -from typing import Iterator +from .abstract_core import AbstractCore +from .abstract_generator_core import AbstractGeneratorCore class RandomGeneratorCore(AbstractGeneratorCore): diff --git a/src/python/gem5/components/processors/simple_core.py b/src/python/gem5/components/processors/simple_core.py index 65c0f0ec83..a79cf5c165 100644 --- a/src/python/gem5/components/processors/simple_core.py +++ b/src/python/gem5/components/processors/simple_core.py @@ -24,15 +24,15 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import importlib +import platform from typing import Optional + +from ...isas import ISA +from ...runtime import get_runtime_isa from ...utils.requires import requires from .base_cpu_core import BaseCPUCore from .cpu_types import CPUTypes -from ...isas import ISA -from ...utils.requires import requires -from ...runtime import get_runtime_isa -import importlib -import platform class SimpleCore(BaseCPUCore): diff --git a/src/python/gem5/components/processors/simple_processor.py b/src/python/gem5/components/processors/simple_processor.py index 510e37df0e..4b569b1f77 100644 --- a/src/python/gem5/components/processors/simple_processor.py +++ b/src/python/gem5/components/processors/simple_processor.py @@ -25,15 +25,15 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from m5.util import warn -from .base_cpu_processor import BaseCPUProcessor -from ..processors.simple_core import SimpleCore - -from .cpu_types import CPUTypes -from ...isas import ISA - from typing import Optional +from m5.util import warn + +from ...isas import ISA +from ..processors.simple_core import SimpleCore +from .base_cpu_processor import BaseCPUProcessor +from .cpu_types import CPUTypes + class SimpleProcessor(BaseCPUProcessor): """ diff --git a/src/python/gem5/components/processors/simple_switchable_processor.py b/src/python/gem5/components/processors/simple_switchable_processor.py index e3978412c3..62fc83c4fe 100644 --- a/src/python/gem5/components/processors/simple_switchable_processor.py +++ b/src/python/gem5/components/processors/simple_switchable_processor.py @@ -24,17 +24,20 @@ # (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 ..boards.mem_mode import MemMode -from ..boards.abstract_board import AbstractBoard -from ..processors.simple_core import SimpleCore -from ..processors.cpu_types import CPUTypes, get_mem_mode -from .switchable_processor import SwitchableProcessor -from ...isas import ISA +from typing import Optional + from m5.util import warn +from ...isas import ISA from ...utils.override import * - -from typing import Optional +from ..boards.abstract_board import AbstractBoard +from ..boards.mem_mode import MemMode +from ..processors.cpu_types import ( + CPUTypes, + get_mem_mode, +) +from ..processors.simple_core import SimpleCore +from .switchable_processor import SwitchableProcessor class SimpleSwitchableProcessor(SwitchableProcessor): diff --git a/src/python/gem5/components/processors/switchable_processor.py b/src/python/gem5/components/processors/switchable_processor.py index 88e5f4cc47..e226702999 100644 --- a/src/python/gem5/components/processors/switchable_processor.py +++ b/src/python/gem5/components/processors/switchable_processor.py @@ -25,17 +25,19 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from .simple_core import SimpleCore -from .abstract_core import AbstractCore -from .cpu_types import CPUTypes +from typing import ( + Dict, + List, +) import m5 -from typing import Dict, List - -from .abstract_processor import AbstractProcessor -from ..boards.abstract_board import AbstractBoard from ...utils.override import * +from ..boards.abstract_board import AbstractBoard +from .abstract_core import AbstractCore +from .abstract_processor import AbstractProcessor +from .cpu_types import CPUTypes +from .simple_core import SimpleCore class SwitchableProcessor(AbstractProcessor): diff --git a/src/python/gem5/components/processors/traffic_generator.py b/src/python/gem5/components/processors/traffic_generator.py index b4c400a64a..c38a053bb0 100644 --- a/src/python/gem5/components/processors/traffic_generator.py +++ b/src/python/gem5/components/processors/traffic_generator.py @@ -24,13 +24,12 @@ # (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 ...utils.override import overrides -from .traffic_generator_core import TrafficGeneratorCore - -from .abstract_generator import AbstractGenerator - from typing import List +from ...utils.override import overrides +from .abstract_generator import AbstractGenerator +from .traffic_generator_core import TrafficGeneratorCore + class TrafficGenerator(AbstractGenerator): def __init__( diff --git a/src/python/gem5/components/processors/traffic_generator_core.py b/src/python/gem5/components/processors/traffic_generator_core.py index d542352481..0260d9e72a 100644 --- a/src/python/gem5/components/processors/traffic_generator_core.py +++ b/src/python/gem5/components/processors/traffic_generator_core.py @@ -25,11 +25,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from m5.objects import Port, TrafficGen +from m5.objects import ( + Port, + TrafficGen, +) +from ...utils.override import overrides from .abstract_core import AbstractCore from .abstract_generator_core import AbstractGeneratorCore -from ...utils.override import overrides class TrafficGeneratorCore(AbstractGeneratorCore): diff --git a/src/python/gem5/prebuilt/demo/x86_demo_board.py b/src/python/gem5/prebuilt/demo/x86_demo_board.py index eb38bb3e95..084f1eeffe 100644 --- a/src/python/gem5/prebuilt/demo/x86_demo_board.py +++ b/src/python/gem5/prebuilt/demo/x86_demo_board.py @@ -26,14 +26,14 @@ from m5.util import warn -from ...components.processors.cpu_types import CPUTypes +from ...coherence_protocol import CoherenceProtocol from ...components.boards.x86_board import X86Board -from ...components.memory.single_channel import SingleChannelDDR3_1600 -from ...components.processors.simple_processor import SimpleProcessor from ...components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import ( MESITwoLevelCacheHierarchy, ) -from ...coherence_protocol import CoherenceProtocol +from ...components.memory.single_channel import SingleChannelDDR3_1600 +from ...components.processors.cpu_types import CPUTypes +from ...components.processors.simple_processor import SimpleProcessor from ...isas import ISA from ...utils.requires import requires diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index a4e639801d..55efe2dabc 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -27,42 +27,30 @@ import os import re - -from typing import List, Optional - -from gem5.utils.override import overrides -from gem5.components.boards.abstract_system_board import AbstractSystemBoard -from gem5.components.boards.kernel_disk_workload import KernelDiskWorkload -from gem5.components.boards.se_binary_workload import SEBinaryWorkload -from gem5.resources.resource import AbstractResource -from gem5.components.memory import SingleChannelDDR4_2400 -from gem5.utils.requires import requires -from gem5.isas import ISA -from .riscvmatched_cache import RISCVMatchedCacheHierarchy -from .riscvmatched_processor import U74Processor -from gem5.isas import ISA - -import m5 - -from m5.objects import ( - BadAddr, - Bridge, - PMAChecker, - RiscvLinux, - AddrRange, - IOXBar, - RiscvRTC, - HiFive, - IGbE_e1000, - CowDiskImage, - RawDiskImage, - RiscvMmioVirtIO, - VirtIOBlock, - VirtIORng, - Frequency, - Port, +from typing import ( + List, + Optional, ) +import m5 +from m5.objects import ( + AddrRange, + BadAddr, + Bridge, + CowDiskImage, + Frequency, + HiFive, + IGbE_e1000, + IOXBar, + PMAChecker, + Port, + RawDiskImage, + RiscvLinux, + RiscvMmioVirtIO, + RiscvRTC, + VirtIOBlock, + VirtIORng, +) from m5.util.fdthelper import ( Fdt, FdtNode, @@ -72,6 +60,18 @@ from m5.util.fdthelper import ( FdtState, ) +from gem5.components.boards.abstract_system_board import AbstractSystemBoard +from gem5.components.boards.kernel_disk_workload import KernelDiskWorkload +from gem5.components.boards.se_binary_workload import SEBinaryWorkload +from gem5.components.memory import SingleChannelDDR4_2400 +from gem5.isas import ISA +from gem5.resources.resource import AbstractResource +from gem5.utils.override import overrides +from gem5.utils.requires import requires + +from .riscvmatched_cache import RISCVMatchedCacheHierarchy +from .riscvmatched_processor import U74Processor + def U74Memory(): """ diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py index dce1c5a964..213b4e7b1e 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py @@ -24,25 +24,33 @@ # (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 Type + +from m5.objects import ( + BadAddr, + BaseXBar, + Cache, + L2XBar, + Port, + SystemXBar, +) + +from gem5.components.boards.abstract_board import AbstractBoard from gem5.components.cachehierarchies.abstract_cache_hierarchy import ( AbstractCacheHierarchy, ) -from gem5.components.cachehierarchies.classic.abstract_classic_cache_hierarchy import ( - AbstractClassicCacheHierarchy, -) from gem5.components.cachehierarchies.abstract_two_level_cache_hierarchy import ( AbstractTwoLevelCacheHierarchy, ) +from gem5.components.cachehierarchies.classic.abstract_classic_cache_hierarchy import ( + AbstractClassicCacheHierarchy, +) from gem5.components.cachehierarchies.classic.caches.l1dcache import L1DCache from gem5.components.cachehierarchies.classic.caches.l1icache import L1ICache from gem5.components.cachehierarchies.classic.caches.l2cache import L2Cache from gem5.components.cachehierarchies.classic.caches.mmu_cache import MMUCache -from gem5.components.boards.abstract_board import AbstractBoard from gem5.isas import ISA -from m5.objects import Cache, L2XBar, BaseXBar, SystemXBar, BadAddr, Port - from gem5.utils.override import * -from typing import Type class RISCVMatchedCacheHierarchy( diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py index 19dc2f2e8c..1c7ea38ac1 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py @@ -25,20 +25,21 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from typing import Optional -from gem5.utils.requires import requires + +from m5.objects import ( + BaseCPU, + BaseMMU, + Port, + Process, +) +from m5.objects.BaseMinorCPU import * +from m5.objects.RiscvCPU import RiscvMinorCPU + from gem5.components.processors.base_cpu_core import BaseCPUCore from gem5.components.processors.cpu_types import CPUTypes from gem5.isas import ISA from gem5.utils.override import overrides -from m5.objects.RiscvCPU import RiscvMinorCPU -from m5.objects import ( - BaseMMU, - Port, - BaseCPU, - Process, -) -from m5.objects.BaseMinorCPU import * -from gem5.isas import ISA +from gem5.utils.requires import requires class U74IntFU(MinorDefaultIntFU): diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_processor.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_processor.py index 838f810073..a1c9d5b8c2 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_processor.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_processor.py @@ -24,14 +24,14 @@ # (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.utils.override import overrides -from gem5.components.boards.mem_mode import MemMode - from m5.util import warn +from gem5.components.boards.abstract_board import AbstractBoard +from gem5.components.boards.mem_mode import MemMode from gem5.components.processors.base_cpu_processor import BaseCPUProcessor from gem5.components.processors.cpu_types import CPUTypes -from gem5.components.boards.abstract_board import AbstractBoard +from gem5.utils.override import overrides + from .riscvmatched_core import U74Core diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py index 74475caec2..3428b037e0 100644 --- a/src/python/gem5/resources/client.py +++ b/src/python/gem5/resources/client.py @@ -25,14 +25,25 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import json -from pathlib import Path import os -from typing import Optional, Dict, List -from .client_api.client_wrapper import ClientWrapper -from gem5.gem5_default_config import config -from m5.util import inform, warn +from pathlib import Path +from typing import ( + Dict, + List, + Optional, +) + +from m5.util import ( + inform, + warn, +) + from _m5 import core +from gem5.gem5_default_config import config + +from .client_api.client_wrapper import ClientWrapper + def getFileContent(file_path: Path) -> Dict: """ diff --git a/src/python/gem5/resources/client_api/abstract_client.py b/src/python/gem5/resources/client_api/abstract_client.py index 0365b5ca60..b58ac1efe2 100644 --- a/src/python/gem5/resources/client_api/abstract_client.py +++ b/src/python/gem5/resources/client_api/abstract_client.py @@ -24,9 +24,17 @@ # (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 ABC, abstractmethod -from typing import Any, Dict, List, Optional import urllib.parse +from abc import ( + ABC, + abstractmethod, +) +from typing import ( + Any, + Dict, + List, + Optional, +) class AbstractClient(ABC): diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py index 7b1d263936..75adcf764d 100644 --- a/src/python/gem5/resources/client_api/atlasclient.py +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -24,14 +24,27 @@ # (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 urllib import request, parse -from typing import Optional, Dict, Union, Type, Tuple, List, Any +import itertools import json import time -import itertools -from .abstract_client import AbstractClient +from typing import ( + Any, + Dict, + List, + Optional, + Tuple, + Type, + Union, +) +from urllib import ( + parse, + request, +) + from m5.util import warn +from .abstract_client import AbstractClient + class AtlasClientHttpJsonRequestError(Exception): def __init__( diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index 9ddd69e2df..0777535ca2 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -24,13 +24,21 @@ # (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 .jsonclient import JSONClient -from .atlasclient import AtlasClient -from _m5 import core -from typing import Optional, Dict, List, Tuple import itertools -from m5.util import warn import sys +from typing import ( + Dict, + List, + Optional, + Tuple, +) + +from m5.util import warn + +from _m5 import core + +from .atlasclient import AtlasClient +from .jsonclient import JSONClient class ClientWrapper: diff --git a/src/python/gem5/resources/client_api/jsonclient.py b/src/python/gem5/resources/client_api/jsonclient.py index 9e837131b0..7ed15ccbe1 100644 --- a/src/python/gem5/resources/client_api/jsonclient.py +++ b/src/python/gem5/resources/client_api/jsonclient.py @@ -26,12 +26,22 @@ import json from pathlib import Path +from typing import ( + Any, + Dict, + List, + Optional, + Tuple, + Type, + Union, +) from urllib import request -from typing import Optional, Dict, Union, Type, Tuple, List, Any -from .abstract_client import AbstractClient from urllib.error import URLError + from m5.util import warn +from .abstract_client import AbstractClient + class JSONClient(AbstractClient): def __init__(self, path: str): diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index e9b4980b53..632980ef4d 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -24,29 +24,36 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import urllib.request -import urllib.parse -import os -import shutil import gzip -import time +import os import random -from pathlib import Path +import shutil import tarfile +import time +import urllib.parse +import urllib.request +from pathlib import Path +from typing import ( + Dict, + List, + Optional, +) from urllib.error import HTTPError from urllib.parse import urlparse -from typing import List, Optional, Dict from _m5 import core -from .client import ( - get_resource_json_obj, - list_resources as client_list_resources, -) -from .md5_utils import md5_file, md5_dir -from ..utils.progress_bar import tqdm, progress_hook - from ..utils.filelock import FileLock +from ..utils.progress_bar import ( + progress_hook, + tqdm, +) +from .client import get_resource_json_obj +from .client import list_resources as client_list_resources +from .md5_utils import ( + md5_dir, + md5_file, +) """ This Python module contains functions used to download, list, and obtain @@ -86,10 +93,11 @@ def _download(url: str, download_to: str, max_attempts: int = 6) -> None: # If the "use_proxy" variable is specified we setup a socks5 # connection. - import socks import socket import ssl + import socks + IP_ADDR, host_port = use_proxy.split(":") PORT = int(host_port) socks.set_default_proxy(socks.SOCKS5, IP_ADDR, PORT) diff --git a/src/python/gem5/resources/elfie.py b/src/python/gem5/resources/elfie.py index ae51388d62..15afd718c1 100644 --- a/src/python/gem5/resources/elfie.py +++ b/src/python/gem5/resources/elfie.py @@ -24,11 +24,11 @@ # (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.params import PcCountPair -from m5.objects import PcCountTrackerManager - from typing import List +from m5.objects import PcCountTrackerManager +from m5.params import PcCountPair + class ELFieInfo: """Stores information to load/run ELFies diff --git a/src/python/gem5/resources/looppoint.py b/src/python/gem5/resources/looppoint.py index 6e26efefdc..80ae43ce9f 100644 --- a/src/python/gem5/resources/looppoint.py +++ b/src/python/gem5/resources/looppoint.py @@ -24,15 +24,20 @@ # (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.params import PcCountPair -from m5.objects import PcCountTrackerManager -import m5 - -import os import csv import json +import os from pathlib import Path -from typing import List, Optional, Dict, Union +from typing import ( + Dict, + List, + Optional, + Union, +) + +import m5 +from m5.objects import PcCountTrackerManager +from m5.params import PcCountPair class LooppointRegionPC: diff --git a/src/python/gem5/resources/md5_utils.py b/src/python/gem5/resources/md5_utils.py index a371274fef..a3d4e886f9 100644 --- a/src/python/gem5/resources/md5_utils.py +++ b/src/python/gem5/resources/md5_utils.py @@ -25,9 +25,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import hashlib from pathlib import Path from typing import Type -import hashlib def _md5_update_from_file( diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 98c58cf832..89741f0566 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -24,31 +24,39 @@ # (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 ABCMeta import json import os +from abc import ABCMeta from pathlib import Path -from m5.util import warn, fatal -from _m5 import core - -from .downloader import get_resource - -from .looppoint import LooppointCsvLoader, LooppointJsonLoader -from ..isas import ISA, get_isa_from_str - from typing import ( - Optional, - Dict, - Union, - Type, - Tuple, - List, Any, - Set, + Dict, Generator, + List, + Optional, + Set, + Tuple, + Type, + Union, ) +from m5.util import ( + fatal, + warn, +) + +from _m5 import core + +from ..isas import ( + ISA, + get_isa_from_str, +) from .client import get_resource_json_obj +from .downloader import get_resource +from .looppoint import ( + LooppointCsvLoader, + LooppointJsonLoader, +) """ Resources are items needed to run a simulation, such as a disk image, kernel, diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index bdb596921f..ef1ffbbb8c 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -24,13 +24,22 @@ # (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 .resource import obtain_resource, WorkloadResource -from .client import get_resource_json_obj +from typing import ( + Any, + Dict, + List, + Optional, +) -from _m5 import core from m5.util import warn -from typing import Dict, Any, List, Optional +from _m5 import core + +from .client import get_resource_json_obj +from .resource import ( + WorkloadResource, + obtain_resource, +) def CustomWorkload(function: str, parameters: Dict[str, Any]): diff --git a/src/python/gem5/runtime.py b/src/python/gem5/runtime.py index 9118237f37..717e4a8c2b 100644 --- a/src/python/gem5/runtime.py +++ b/src/python/gem5/runtime.py @@ -28,12 +28,17 @@ This file contains functions to extract gem5 runtime information. """ +from typing import Set + from m5.defines import buildEnv from m5.util import warn -from .isas import ISA, get_isa_from_str, get_isas_str_set from .coherence_protocol import CoherenceProtocol -from typing import Set +from .isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) def get_supported_isas() -> Set[ISA]: diff --git a/src/python/gem5/simulate/exit_event_generators.py b/src/python/gem5/simulate/exit_event_generators.py index 6f0e0a1eac..a8a5940746 100644 --- a/src/python/gem5/simulate/exit_event_generators.py +++ b/src/python/gem5/simulate/exit_event_generators.py @@ -24,14 +24,20 @@ # (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 Generator, Optional +from pathlib import Path +from typing import ( + Generator, + Optional, +) + import m5.stats +from m5.util import warn + +from gem5.resources.looppoint import Looppoint + from ..components.processors.abstract_processor import AbstractProcessor from ..components.processors.switchable_processor import SwitchableProcessor from ..resources.resource import SimpointResource -from gem5.resources.looppoint import Looppoint -from m5.util import warn -from pathlib import Path """ In this package we store generators for simulation exit events. diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index 5470202830..dcab20ebd4 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -24,29 +24,37 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import m5 -import m5.ticks -from m5.stats import addStatVisitor -from m5.ext.pystats.simstat import SimStat -from m5.objects import Root -from m5.util import warn - import os import sys from pathlib import Path -from typing import Optional, List, Tuple, Dict, Generator, Union, Callable - -from .exit_event_generators import ( - warn_default_decorator, - exit_generator, - switch_generator, - save_checkpoint_generator, - reset_stats_generator, - dump_stats_generator, +from typing import ( + Callable, + Dict, + Generator, + List, + Optional, + Tuple, + Union, ) -from .exit_event import ExitEvent + +import m5 +import m5.ticks +from m5.ext.pystats.simstat import SimStat +from m5.objects import Root +from m5.stats import addStatVisitor +from m5.util import warn + from ..components.boards.abstract_board import AbstractBoard from ..components.processors.switchable_processor import SwitchableProcessor +from .exit_event import ExitEvent +from .exit_event_generators import ( + dump_stats_generator, + exit_generator, + reset_stats_generator, + save_checkpoint_generator, + switch_generator, + warn_default_decorator, +) class Simulator: diff --git a/src/python/gem5/utils/filelock.py b/src/python/gem5/utils/filelock.py index 309a9f868b..215b340ebb 100644 --- a/src/python/gem5/utils/filelock.py +++ b/src/python/gem5/utils/filelock.py @@ -23,9 +23,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import errno import os import time -import errno class FileLockException(Exception): diff --git a/src/python/gem5/utils/multiprocessing/__init__.py b/src/python/gem5/utils/multiprocessing/__init__.py index 680aeac314..07a55250fa 100644 --- a/src/python/gem5/utils/multiprocessing/__init__.py +++ b/src/python/gem5/utils/multiprocessing/__init__.py @@ -24,9 +24,10 @@ # (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 .context import Process - -from .context import gem5Context +from .context import ( + Process, + gem5Context, +) Pool = gem5Context().Pool diff --git a/src/python/gem5/utils/multiprocessing/_command_line.py b/src/python/gem5/utils/multiprocessing/_command_line.py index f68277540d..0baf198506 100644 --- a/src/python/gem5/utils/multiprocessing/_command_line.py +++ b/src/python/gem5/utils/multiprocessing/_command_line.py @@ -32,7 +32,10 @@ multiprocessing module (i.e., cpython/Lib/multiprocessing/). """ import sys -from multiprocessing import spawn, util +from multiprocessing import ( + spawn, + util, +) def _gem5_args_for_multiprocessing(name): diff --git a/src/python/gem5/utils/multiprocessing/context.py b/src/python/gem5/utils/multiprocessing/context.py index 0fc48e2789..03b554548d 100644 --- a/src/python/gem5/utils/multiprocessing/context.py +++ b/src/python/gem5/utils/multiprocessing/context.py @@ -30,7 +30,10 @@ Some code inspired by the Python standard library implementation of the multiprocessing module (i.e., cpython/Lib/multiprocessing/). """ -from multiprocessing import context, process +from multiprocessing import ( + context, + process, +) from multiprocessing.context import DefaultContext diff --git a/src/python/gem5/utils/multiprocessing/popen_spawn_gem5.py b/src/python/gem5/utils/multiprocessing/popen_spawn_gem5.py index 13fb3362fc..b40b8b4eeb 100644 --- a/src/python/gem5/utils/multiprocessing/popen_spawn_gem5.py +++ b/src/python/gem5/utils/multiprocessing/popen_spawn_gem5.py @@ -33,11 +33,15 @@ multiprocessing module (i.e., cpython/Lib/multiprocessing/). import io import os - -from multiprocessing.context import reduction, set_spawning_popen -from multiprocessing import popen_spawn_posix -from multiprocessing import spawn -from multiprocessing import util +from multiprocessing import ( + popen_spawn_posix, + spawn, + util, +) +from multiprocessing.context import ( + reduction, + set_spawning_popen, +) from ._command_line import get_command_line diff --git a/src/python/gem5/utils/requires.py b/src/python/gem5/utils/requires.py index 9d271aafa2..461a60ddd8 100644 --- a/src/python/gem5/utils/requires.py +++ b/src/python/gem5/utils/requires.py @@ -24,12 +24,16 @@ # (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 ..runtime import get_runtime_coherence_protocol, get_supported_isas -from ..isas import ISA -from ..coherence_protocol import CoherenceProtocol -from typing import Optional -import os import inspect +import os +from typing import Optional + +from ..coherence_protocol import CoherenceProtocol +from ..isas import ISA +from ..runtime import ( + get_runtime_coherence_protocol, + get_supported_isas, +) def _get_exception_str(msg: str): diff --git a/src/python/gem5/utils/simpoint.py b/src/python/gem5/utils/simpoint.py index 0d1af4b1cf..b8c31d309c 100644 --- a/src/python/gem5/utils/simpoint.py +++ b/src/python/gem5/utils/simpoint.py @@ -24,9 +24,17 @@ # (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.util import fatal, warn from pathlib import Path -from typing import List, Tuple +from typing import ( + List, + Tuple, +) + +from m5.util import ( + fatal, + warn, +) + from gem5.resources.resource import SimpointResource diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 31b0f5d180..3b80a09507 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -38,38 +38,39 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import sys -from types import FunctionType, MethodType, ModuleType -from functools import wraps import inspect +import sys +from functools import wraps +from types import ( + FunctionType, + MethodType, + ModuleType, +) import m5 -from m5.util import * -from m5.util.pybind import * - from m5.citations import gem5_citations # Use the pyfdt and not the helper class, because the fdthelper # relies on the SimObject definition from m5.ext.pyfdt import pyfdt +# There are a few things we need that aren't in params.__all__ since +# normal users don't need them # Have to import params up top since Param is referenced on initial # load (when SimObject class references Param to create a class # variable, the 'name' param)... from m5.params import * - -# There are a few things we need that aren't in params.__all__ since -# normal users don't need them from m5.params import ( ParamDesc, + Port, + SimObjectVector, VectorParamDesc, isNullPointer, - SimObjectVector, - Port, ) - from m5.proxy import * from m5.proxy import isproxy +from m5.util import * +from m5.util.pybind import * ##################################################################### # diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index f029adffdc..a7bcf7a833 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -40,18 +40,19 @@ except ImportError: in_gem5 = False if in_gem5: - from . import SimObject - from . import core - from . import defines - from . import objects - from . import params - from . import stats + from . import ( + SimObject, + core, + defines, + objects, + params, + stats, + ) if defines.buildEnv["USE_SYSTEMC"]: from . import systemc from . import tlm from . import util - from .event import * from .main import main from .simulate import * diff --git a/src/python/m5/debug.py b/src/python/m5/debug.py index 09a032aa50..c4ae167989 100644 --- a/src/python/m5/debug.py +++ b/src/python/m5/debug.py @@ -26,11 +26,15 @@ from collections.abc import Mapping -import _m5.debug -from _m5.debug import SimpleFlag, CompoundFlag -from _m5.debug import schedBreak from m5.util import printList +import _m5.debug +from _m5.debug import ( + CompoundFlag, + SimpleFlag, + schedBreak, +) + def help(): sorted_flags = sorted(flags.items(), key=lambda kv: kv[0]) diff --git a/src/python/m5/event.py b/src/python/m5/event.py index 7c3f9a7c42..0f4cb8d947 100644 --- a/src/python/m5/event.py +++ b/src/python/m5/event.py @@ -39,11 +39,14 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 -import _m5.event +import _m5.event from _m5.event import GlobalSimLoopExitEvent as SimExit from _m5.event import PyEvent as Event -from _m5.event import getEventQueue, setEventQueue +from _m5.event import ( + getEventQueue, + setEventQueue, +) mainq = None diff --git a/src/python/m5/ext/pystats/__init__.py b/src/python/m5/ext/pystats/__init__.py index 32cee43296..0d15ee1ad1 100644 --- a/src/python/m5/ext/pystats/__init__.py +++ b/src/python/m5/ext/pystats/__init__.py @@ -25,13 +25,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from .abstract_stat import AbstractStat -from .serializable_stat import SerializableStat from .group import Group +from .jsonloader import JsonLoader +from .serializable_stat import SerializableStat from .simstat import SimStat from .statistic import Statistic from .storagetype import StorageType from .timeconversion import TimeConversion -from .jsonloader import JsonLoader __all__ = [ "AbstractStat", diff --git a/src/python/m5/ext/pystats/abstract_stat.py b/src/python/m5/ext/pystats/abstract_stat.py index f2a75fca1e..d5b99b259e 100644 --- a/src/python/m5/ext/pystats/abstract_stat.py +++ b/src/python/m5/ext/pystats/abstract_stat.py @@ -24,8 +24,6 @@ # (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 .serializable_stat import SerializableStat - import re from typing import ( Callable, @@ -35,6 +33,8 @@ from typing import ( Union, ) +from .serializable_stat import SerializableStat + class AbstractStat(SerializableStat): """ diff --git a/src/python/m5/ext/pystats/group.py b/src/python/m5/ext/pystats/group.py index 0b71663565..bc292c9d0b 100644 --- a/src/python/m5/ext/pystats/group.py +++ b/src/python/m5/ext/pystats/group.py @@ -33,7 +33,10 @@ from typing import ( ) from .abstract_stat import AbstractStat -from .statistic import Scalar, Statistic +from .statistic import ( + Scalar, + Statistic, +) from .timeconversion import TimeConversion diff --git a/src/python/m5/ext/pystats/jsonloader.py b/src/python/m5/ext/pystats/jsonloader.py index 7461f8d7a8..f83c2caa68 100644 --- a/src/python/m5/ext/pystats/jsonloader.py +++ b/src/python/m5/ext/pystats/jsonloader.py @@ -24,12 +24,24 @@ # (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 json.decoder import JSONDecodeError -from .simstat import SimStat -from .statistic import Scalar, Distribution, Accumulator, Statistic -from .group import Group, Vector import json -from typing import IO, Union +from json.decoder import JSONDecodeError +from typing import ( + IO, + Union, +) + +from .group import ( + Group, + Vector, +) +from .simstat import SimStat +from .statistic import ( + Accumulator, + Distribution, + Scalar, + Statistic, +) class JsonLoader(json.JSONDecoder): diff --git a/src/python/m5/ext/pystats/serializable_stat.py b/src/python/m5/ext/pystats/serializable_stat.py index c4de181e70..bb63b2a044 100644 --- a/src/python/m5/ext/pystats/serializable_stat.py +++ b/src/python/m5/ext/pystats/serializable_stat.py @@ -24,9 +24,15 @@ # (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 datetime import datetime import json -from typing import Dict, List, Union, Any, IO +from datetime import datetime +from typing import ( + IO, + Any, + Dict, + List, + Union, +) from .storagetype import StorageType diff --git a/src/python/m5/ext/pystats/simstat.py b/src/python/m5/ext/pystats/simstat.py index c7c28f419a..06858bb9ad 100644 --- a/src/python/m5/ext/pystats/simstat.py +++ b/src/python/m5/ext/pystats/simstat.py @@ -25,7 +25,12 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from datetime import datetime -from typing import Dict, List, Optional, Union +from typing import ( + Dict, + List, + Optional, + Union, +) from .abstract_stat import AbstractStat from .group import Group diff --git a/src/python/m5/ext/pystats/statistic.py b/src/python/m5/ext/pystats/statistic.py index 4111bde23e..019ec8a042 100644 --- a/src/python/m5/ext/pystats/statistic.py +++ b/src/python/m5/ext/pystats/statistic.py @@ -25,7 +25,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from abc import ABC -from typing import Any, Iterable, Optional, Union, List +from typing import ( + Any, + Iterable, + List, + Optional, + Union, +) from .abstract_stat import AbstractStat from .storagetype import StorageType diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 31eaf83690..e346b16a5c 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -379,18 +379,24 @@ def _check_tracing(): def main(): import m5 + from m5.util.terminal_formatter import TerminalFormatter + import _m5.core - from . import core - from . import debug - from . import defines - from . import event - from . import info - from . import stats - from . import trace - - from .util import inform, panic, isInteractive - from m5.util.terminal_formatter import TerminalFormatter + from . import ( + core, + debug, + defines, + event, + info, + stats, + trace, + ) + from .util import ( + inform, + isInteractive, + panic, + ) options, arguments = parse_options() diff --git a/src/python/m5/objects/SimObject.py b/src/python/m5/objects/SimObject.py index 6cf44d07c2..af6b0998b9 100644 --- a/src/python/m5/objects/SimObject.py +++ b/src/python/m5/objects/SimObject.py @@ -23,8 +23,7 @@ # (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.SimObject import * - # The ByteOrder enum is defined in params. Expose it here so we can declare it # to SCons, since there's no normal SimObject file to make it a part of. from m5.params import ByteOrder +from m5.SimObject import * diff --git a/src/python/m5/options.py b/src/python/m5/options.py index aac7d1ac74..a4928960cc 100644 --- a/src/python/m5/options.py +++ b/src/python/m5/options.py @@ -26,7 +26,6 @@ import optparse import sys - from optparse import * diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 86a33c739d..32723a7860 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -56,13 +56,15 @@ import copy import datetime +import math import re import sys import time -import math -from . import proxy -from . import ticks +from . import ( + proxy, + ticks, +) from .util import * @@ -1099,10 +1101,12 @@ class HostSocket(ParamValue): self.value = value def getValue(self): - from _m5.socket import listenSocketEmptyConfig - from _m5.socket import listenSocketInetConfig - from _m5.socket import listenSocketUnixFileConfig - from _m5.socket import listenSocketUnixAbstractConfig + from _m5.socket import ( + listenSocketEmptyConfig, + listenSocketInetConfig, + listenSocketUnixAbstractConfig, + listenSocketUnixFileConfig, + ) if isinstance(self.value, str): if self.value[0] == "@": @@ -1443,8 +1447,16 @@ time_formats = [ def parse_time(value): - from time import gmtime, strptime, struct_time, time - from datetime import datetime, date + from datetime import ( + date, + datetime, + ) + from time import ( + gmtime, + strptime, + struct_time, + time, + ) if isinstance(value, struct_time): return value @@ -1483,9 +1495,10 @@ class Time(ParamValue): return value def getValue(self): - from _m5.core import tm import calendar + from _m5.core import tm + return tm.gmtime(calendar.timegm(self.value)) def __str__(self): diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index d619697247..c2a0eebb22 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -41,22 +41,31 @@ import atexit import os import sys -# import the wrapped C++ functions -import _m5.drain -import _m5.core -from _m5.stats import updateEvents as updateStatEvents - -from . import stats -from . import SimObject -from . import ticks -from . import objects -from . import params -from .citations import gather_citations -from m5.util.dot_writer import do_dot, do_dvfs_dot +from m5.util.dot_writer import ( + do_dot, + do_dvfs_dot, +) from m5.util.dot_writer_ruby import do_ruby_dot -from .util import fatal, warn -from .util import attrdict +import _m5.core + +# import the wrapped C++ functions +import _m5.drain +from _m5.stats import updateEvents as updateStatEvents + +from . import ( + SimObject, + objects, + params, + stats, + ticks, +) +from .citations import gather_citations +from .util import ( + attrdict, + fatal, + warn, +) # define a MaxTick parameter, unsigned 64 bit MaxTick = 2**64 - 1 @@ -482,6 +491,9 @@ def fork(simout="%(parent)s.f%(fork_seq)i"): return pid -from _m5.core import disableAllListeners, listenersDisabled -from _m5.core import listenersLoopbackOnly -from _m5.core import curTick +from _m5.core import ( + curTick, + disableAllListeners, + listenersDisabled, + listenersLoopbackOnly, +) diff --git a/src/python/m5/stats/__init__.py b/src/python/m5/stats/__init__.py index ce7a2d267d..de129c1817 100644 --- a/src/python/m5/stats/__init__.py +++ b/src/python/m5/stats/__init__.py @@ -38,16 +38,20 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 - -import _m5.stats from m5.objects import Root from m5.params import isNullPointer -from .gem5stats import JsonOutputVistor -from m5.util import attrdict, fatal +from m5.util import ( + attrdict, + fatal, +) + +import _m5.stats # Stat exports -from _m5.stats import schedStatEvent as schedEvent from _m5.stats import periodicStatDump +from _m5.stats import schedStatEvent as schedEvent + +from .gem5stats import JsonOutputVistor outputList = [] diff --git a/src/python/m5/stats/gem5stats.py b/src/python/m5/stats/gem5stats.py index 07636e3e3f..2d79015627 100644 --- a/src/python/m5/stats/gem5stats.py +++ b/src/python/m5/stats/gem5stats.py @@ -30,14 +30,19 @@ the Python Stats model. """ from datetime import datetime -from typing import IO, List, Union +from typing import ( + IO, + List, + Union, +) -import _m5.stats -from m5.objects import * from m5.ext.pystats.group import * from m5.ext.pystats.simstat import * from m5.ext.pystats.statistic import * from m5.ext.pystats.storagetype import * +from m5.objects import * + +import _m5.stats class JsonOutputVistor: diff --git a/src/python/m5/ticks.py b/src/python/m5/ticks.py index 7ec84c3709..c44ac7a13f 100644 --- a/src/python/m5/ticks.py +++ b/src/python/m5/ticks.py @@ -25,8 +25,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import decimal - import sys + from m5.util import warn @@ -39,6 +39,7 @@ def fixGlobalFrequency(): def setGlobalFrequency(ticksPerSecond): from m5.util import convert + import _m5.core if isinstance(ticksPerSecond, int): diff --git a/src/python/m5/trace.py b/src/python/m5/trace.py index 759f96e5bf..6aa88e7644 100644 --- a/src/python/m5/trace.py +++ b/src/python/m5/trace.py @@ -25,4 +25,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Export native methods to Python -from _m5.trace import output, activate, ignore, disable, enable +from _m5.trace import ( + activate, + disable, + enable, + ignore, + output, +) diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py index e1c9bd226a..3fab2d8931 100644 --- a/src/python/m5/util/__init__.py +++ b/src/python/m5/util/__init__.py @@ -40,12 +40,14 @@ import os import re import sys - from functools import wraps from . import convert - -from .attrdict import attrdict, multiattrdict, optiondict +from .attrdict import ( + attrdict, + multiattrdict, + optiondict, +) from .multidict import multidict diff --git a/src/python/m5/util/dot_writer.py b/src/python/m5/util/dot_writer.py index 59886480a5..1257470306 100644 --- a/src/python/m5/util/dot_writer.py +++ b/src/python/m5/util/dot_writer.py @@ -53,9 +53,18 @@ # ##################################################################### -import m5, os, re -from m5.SimObject import isRoot, isSimObjectVector -from m5.params import PortRef, isNullPointer +import os +import re + +import m5 +from m5.params import ( + PortRef, + isNullPointer, +) +from m5.SimObject import ( + isRoot, + isSimObjectVector, +) from m5.util import warn try: diff --git a/src/python/m5/util/dot_writer_ruby.py b/src/python/m5/util/dot_writer_ruby.py index fa21ae1a01..be5d406278 100644 --- a/src/python/m5/util/dot_writer_ruby.py +++ b/src/python/m5/util/dot_writer_ruby.py @@ -36,6 +36,7 @@ # Creates a visual representation of a Ruby network topology import os + import m5 from m5.util import warn diff --git a/src/python/m5/util/fdthelper.py b/src/python/m5/util/fdthelper.py index 1f565df270..8a265d1d4e 100644 --- a/src/python/m5/util/fdthelper.py +++ b/src/python/m5/util/fdthelper.py @@ -35,9 +35,10 @@ # # Author: Glenn Bergmans -from m5.ext.pyfdt import pyfdt -import re import os +import re + +from m5.ext.pyfdt import pyfdt from m5.SimObject import SimObject from m5.util import fatal diff --git a/src/python/m5/util/terminal_formatter.py b/src/python/m5/util/terminal_formatter.py index da441b1188..a8a8e21914 100644 --- a/src/python/m5/util/terminal_formatter.py +++ b/src/python/m5/util/terminal_formatter.py @@ -34,7 +34,9 @@ class TerminalFormatter: self.__text_width = min(max_width, self.__terminal_size()[0]) def __terminal_size(self): - import fcntl, termios, struct + import fcntl + import struct + import termios h, w, hp, wp = struct.unpack( "HHHH", diff --git a/src/sim/ClockDomain.py b/src/sim/ClockDomain.py index 34380f916b..4c4c6e765f 100644 --- a/src/sim/ClockDomain.py +++ b/src/sim/ClockDomain.py @@ -34,8 +34,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.params import * -from m5.SimObject import SimObject from m5.proxy import * +from m5.SimObject import SimObject # Abstract clock domain diff --git a/src/sim/ClockedObject.py b/src/sim/ClockedObject.py index 5d1656e520..75a9fae597 100644 --- a/src/sim/ClockedObject.py +++ b/src/sim/ClockedObject.py @@ -34,9 +34,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.PowerState import PowerState -from m5.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class ClockedObject(SimObject): diff --git a/src/sim/DVFSHandler.py b/src/sim/DVFSHandler.py index 13c649dbb0..41aaffc897 100644 --- a/src/sim/DVFSHandler.py +++ b/src/sim/DVFSHandler.py @@ -34,8 +34,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.params import * -from m5.SimObject import SimObject from m5.proxy import * +from m5.SimObject import SimObject # The handler in its current form is design to be centeralized, one per system diff --git a/src/sim/InstTracer.py b/src/sim/InstTracer.py index c8b3673d47..4470cd1125 100644 --- a/src/sim/InstTracer.py +++ b/src/sim/InstTracer.py @@ -36,8 +36,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject class InstDisassembler(SimObject): diff --git a/src/sim/PowerDomain.py b/src/sim/PowerDomain.py index 64018e6d15..cda7a300ee 100644 --- a/src/sim/PowerDomain.py +++ b/src/sim/PowerDomain.py @@ -36,8 +36,8 @@ import sys -from m5.params import * from m5.objects.PowerState import PowerState +from m5.params import * # A power domain groups multiple ClockedObjects and creates a diff --git a/src/sim/PowerState.py b/src/sim/PowerState.py index 9c9fe03a5a..5e6d900710 100644 --- a/src/sim/PowerState.py +++ b/src/sim/PowerState.py @@ -34,9 +34,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -from m5.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject # Enumerate set of allowed power states that can be used by a clocked object. diff --git a/src/sim/Process.py b/src/sim/Process.py index 0b87b09485..0f911f9f65 100644 --- a/src/sim/Process.py +++ b/src/sim/Process.py @@ -24,10 +24,11 @@ # (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.SimObject import * +from os import getcwd + from m5.params import * from m5.proxy import * -from os import getcwd +from m5.SimObject import * class Process(SimObject): diff --git a/src/sim/RedirectPath.py b/src/sim/RedirectPath.py index c6c63e2558..91ed5891da 100644 --- a/src/sim/RedirectPath.py +++ b/src/sim/RedirectPath.py @@ -24,9 +24,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class RedirectPath(SimObject): diff --git a/src/sim/Root.py b/src/sim/Root.py index 5ad42da668..fae560491f 100644 --- a/src/sim/Root.py +++ b/src/sim/Root.py @@ -26,8 +26,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject from m5.util import fatal diff --git a/src/sim/SignalPort.py b/src/sim/SignalPort.py index fc529a8b45..bdb6d5eae1 100644 --- a/src/sim/SignalPort.py +++ b/src/sim/SignalPort.py @@ -23,7 +23,10 @@ # (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.params import Port, VectorPort +from m5.params import ( + Port, + VectorPort, +) SIGNAL_SOURCE_ROLE_TEMPLATE = "Signal source <%s>" SIGNAL_SINK_ROLE_TEMPLATE = "Signal sink <%s>" diff --git a/src/sim/SubSystem.py b/src/sim/SubSystem.py index 49f70d5b8a..19df9d2b83 100644 --- a/src/sim/SubSystem.py +++ b/src/sim/SubSystem.py @@ -33,8 +33,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject # An empty simobject. Used for organizing simobjects diff --git a/src/sim/System.py b/src/sim/System.py index eb1280f248..fb6ff8622c 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -37,13 +37,12 @@ # (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.SimObject import * -from m5.params import * -from m5.proxy import * - from m5.objects.DVFSHandler import * from m5.objects.SimpleMemory import * from m5.objects.Workload import StubWorkload +from m5.params import * +from m5.proxy import * +from m5.SimObject import * class MemoryMode(Enum): diff --git a/src/sim/VoltageDomain.py b/src/sim/VoltageDomain.py index 79116edfd3..9d2c503a81 100644 --- a/src/sim/VoltageDomain.py +++ b/src/sim/VoltageDomain.py @@ -33,8 +33,8 @@ # (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.SimObject import SimObject from m5.params import * +from m5.SimObject import SimObject class VoltageDomain(SimObject): diff --git a/src/sim/Workload.py b/src/sim/Workload.py index 31ea7382dd..998c6c13d6 100644 --- a/src/sim/Workload.py +++ b/src/sim/Workload.py @@ -23,10 +23,12 @@ # (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.params import * -from m5.SimObject import SimObject, cxxMethod - from m5.objects.SimpleMemory import * +from m5.params import * +from m5.SimObject import ( + SimObject, + cxxMethod, +) class Workload(SimObject): diff --git a/src/sim/power/MathExprPowerModel.py b/src/sim/power/MathExprPowerModel.py index 6f335980a4..baa5b0dae6 100644 --- a/src/sim/power/MathExprPowerModel.py +++ b/src/sim/power/MathExprPowerModel.py @@ -33,9 +33,9 @@ # (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.SimObject import SimObject -from m5.params import * from m5.objects.PowerModelState import PowerModelState +from m5.params import * +from m5.SimObject import SimObject # Represents a power model for a simobj diff --git a/src/sim/power/PowerModel.py b/src/sim/power/PowerModel.py index f45f24a3cc..df09672966 100644 --- a/src/sim/power/PowerModel.py +++ b/src/sim/power/PowerModel.py @@ -33,9 +33,9 @@ # (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.SimObject import * from m5.params import * from m5.proxy import Parent +from m5.SimObject import * # Enum for a type of power model diff --git a/src/sim/power/PowerModelState.py b/src/sim/power/PowerModelState.py index ba7bd44915..2a427242fa 100644 --- a/src/sim/power/PowerModelState.py +++ b/src/sim/power/PowerModelState.py @@ -33,8 +33,8 @@ # (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.SimObject import * from m5.params import * +from m5.SimObject import * # Represents a power model for a simobj diff --git a/src/sim/power/ThermalDomain.py b/src/sim/power/ThermalDomain.py index ff5fdaff3f..eace9c101d 100644 --- a/src/sim/power/ThermalDomain.py +++ b/src/sim/power/ThermalDomain.py @@ -33,8 +33,8 @@ # (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.SimObject import * from m5.params import * +from m5.SimObject import * # Represents a group of simobj which produce heat diff --git a/src/sim/power/ThermalModel.py b/src/sim/power/ThermalModel.py index 0d45a384c6..823a72ea4f 100644 --- a/src/sim/power/ThermalModel.py +++ b/src/sim/power/ThermalModel.py @@ -33,11 +33,10 @@ # (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.SimObject import * -from m5.objects.ClockedObject import ClockedObject - -from m5.params import * from m5.objects import ThermalDomain +from m5.objects.ClockedObject import ClockedObject +from m5.params import * +from m5.SimObject import * # Represents a thermal node diff --git a/src/sim/probe/Probe.py b/src/sim/probe/Probe.py index 006149a0b9..38664213fb 100644 --- a/src/sim/probe/Probe.py +++ b/src/sim/probe/Probe.py @@ -35,9 +35,9 @@ # (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.SimObject import SimObject from m5.params import * from m5.proxy import * +from m5.SimObject import SimObject class ProbeListenerObject(SimObject): diff --git a/src/systemc/Tlm.py b/src/systemc/Tlm.py index 5b43a3b557..da4e4763b4 100644 --- a/src/systemc/Tlm.py +++ b/src/systemc/Tlm.py @@ -23,7 +23,10 @@ # (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.params import Port, VectorPort +from m5.params import ( + Port, + VectorPort, +) def TLM_TARGET_ROLE(width): diff --git a/src/systemc/core/SystemC.py b/src/systemc/core/SystemC.py index a51c33f86f..75f59db597 100644 --- a/src/systemc/core/SystemC.py +++ b/src/systemc/core/SystemC.py @@ -23,7 +23,10 @@ # (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.SimObject import SimObject, cxxMethod +from m5.SimObject import ( + SimObject, + cxxMethod, +) # This class represents the systemc kernel. There should be exactly one in the diff --git a/src/systemc/python/systemc.py b/src/systemc/python/systemc.py index f5a364a006..d6c90534dc 100644 --- a/src/systemc/python/systemc.py +++ b/src/systemc/python/systemc.py @@ -24,10 +24,12 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import _m5.systemc - -from _m5.systemc import sc_main -from _m5.systemc import sc_time -from _m5.systemc import sc_main_result_code, sc_main_result_str +from _m5.systemc import ( + sc_main, + sc_main_result_code, + sc_main_result_str, + sc_time, +) class ScMainResult: diff --git a/src/systemc/python/tlm.py b/src/systemc/python/tlm.py index 7b342811f6..e5ec7426f0 100644 --- a/src/systemc/python/tlm.py +++ b/src/systemc/python/tlm.py @@ -24,7 +24,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import _m5.systemc - from _m5.systemc import tlm_global_quantum diff --git a/src/systemc/tests/config.py b/src/systemc/tests/config.py index 1c2e021830..0be50d12c9 100755 --- a/src/systemc/tests/config.py +++ b/src/systemc/tests/config.py @@ -24,12 +24,15 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse -import m5 import os import re import sys -from m5.objects import SystemC_Kernel, Root +import m5 +from m5.objects import ( + Root, + SystemC_Kernel, +) # pylint:disable=unused-variable diff --git a/src/systemc/tlm_bridge/TlmBridge.py b/src/systemc/tlm_bridge/TlmBridge.py index 546b4c0790..bc0491132e 100644 --- a/src/systemc/tlm_bridge/TlmBridge.py +++ b/src/systemc/tlm_bridge/TlmBridge.py @@ -24,11 +24,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects.SystemC import SystemC_ScModule +from m5.objects.Tlm import ( + TlmInitiatorSocket, + TlmTargetSocket, +) from m5.params import * from m5.proxy import * -from m5.objects.Tlm import TlmTargetSocket, TlmInitiatorSocket - class Gem5ToTlmBridgeBase(SystemC_ScModule): type = "Gem5ToTlmBridgeBase" diff --git a/tests/gem5/__init__.py b/tests/gem5/__init__.py index 0955469d08..0526afd962 100644 --- a/tests/gem5/__init__.py +++ b/tests/gem5/__init__.py @@ -24,8 +24,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import testlib.suite import testlib.fixture +import testlib.suite -from .suite import * from .fixture import * +from .suite import * diff --git a/tests/gem5/arm_boot_tests/configs/arm_boot_exit_run.py b/tests/gem5/arm_boot_tests/configs/arm_boot_exit_run.py index ffb41459f5..61931d1a7e 100644 --- a/tests/gem5/arm_boot_tests/configs/arm_boot_exit_run.py +++ b/tests/gem5/arm_boot_tests/configs/arm_boot_exit_run.py @@ -33,24 +33,27 @@ Characteristics * Runs exclusively on the ARM ISA with the classic caches """ -from gem5.isas import ISA -from m5.objects import ArmDefaultRelease -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.simulate.simulator import Simulator -from m5.objects import VExpress_GEM5_Foundation -from gem5.coherence_protocol import CoherenceProtocol -from gem5.components.boards.arm_board import ArmBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, - CPUTypes, -) - import argparse import importlib +from m5.objects import ( + ArmDefaultRelease, + VExpress_GEM5_Foundation, +) + +from gem5.coherence_protocol import CoherenceProtocol +from gem5.components.boards.arm_board import ArmBoard +from gem5.components.processors.cpu_types import ( + CPUTypes, + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires + parser = argparse.ArgumentParser( description="A script to run the ARM boot exit tests." ) diff --git a/tests/gem5/arm_boot_tests/test_linux_boot.py b/tests/gem5/arm_boot_tests/test_linux_boot.py index 23921ef403..074f3364b5 100644 --- a/tests/gem5/arm_boot_tests/test_linux_boot.py +++ b/tests/gem5/arm_boot_tests/test_linux_boot.py @@ -25,7 +25,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import re - from typing import Optional from testlib import * diff --git a/tests/gem5/asmtest/configs/riscv_asmtest.py b/tests/gem5/asmtest/configs/riscv_asmtest.py index e98ec1bd49..d6582e4698 100644 --- a/tests/gem5/asmtest/configs/riscv_asmtest.py +++ b/tests/gem5/asmtest/configs/riscv_asmtest.py @@ -31,19 +31,19 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import obtain_resource -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.memory import SingleChannelDDR3_1600 +import argparse + from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import ( + get_cpu_type_from_str, + get_cpu_types_str_set, +) from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator from gem5.isas import ISA - -import argparse +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator parser = argparse.ArgumentParser( description="A gem5 script for testing RISC-V instructions" diff --git a/tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py index 0ce9a7606a..f5dfe4cfc8 100644 --- a/tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/arm-hello-restore-checkpoint.py @@ -34,19 +34,20 @@ runs the rest of "arm-hello64-static" binary simulation. This configuration serves as a test of restoring a checkpoint with ARM ISA. """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource, CheckpointResource - +from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes - +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import ( + CheckpointResource, + obtain_resource, +) +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.ARM) diff --git a/tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py index a731b38a58..16fc2a00f0 100644 --- a/tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/arm-hello-save-checkpoint.py @@ -25,17 +25,18 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource + +from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser() diff --git a/tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py index 05479bcca7..bd717f3c62 100644 --- a/tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/power-hello-restore-checkpoint.py @@ -33,16 +33,18 @@ runs the rest of "power-hello" binary simulation. This configuration serves as a test of restoring a checkpoint with POWER ISA. """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource, CheckpointResource -from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator +from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes - +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import ( + CheckpointResource, + obtain_resource, +) +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.POWER) diff --git a/tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py index 6fb99a2534..594d6610e0 100644 --- a/tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/power-hello-save-checkpoint.py @@ -32,15 +32,16 @@ with POWER ISA. """ import argparse -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.cachehierarchies.classic.no_cache import NoCache + from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator +from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser() diff --git a/tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py index 0bc2e122cd..447c6bd325 100644 --- a/tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/sparc-hello-restore-checkpoint.py @@ -33,16 +33,18 @@ runs the rest of "sparc-hello" binary simulation. This configuration serves as a test of restoring a checkpoint with SPARC ISA. """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource, CheckpointResource -from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator +from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes - +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import ( + CheckpointResource, + obtain_resource, +) +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.SPARC) diff --git a/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py index ab216588aa..f85ff41dbc 100644 --- a/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/sparc-hello-save-checkpoint.py @@ -32,15 +32,16 @@ with SPARC ISA. """ import argparse -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource -from gem5.components.cachehierarchies.classic.no_cache import NoCache + from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator +from gem5.components.cachehierarchies.classic.no_cache import NoCache from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser() 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 0a3264d576..f2909b36f6 100644 --- a/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-fs-restore-checkpoint.py @@ -34,16 +34,19 @@ 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.memory import SingleChannelDDR3_1600 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) +from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.resources.resource import ( + CheckpointResource, + obtain_resource, +) from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires # Run a check to ensure the right version of gem5 is being used. requires(isa_required=ISA.X86) 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 891130af2b..fb800209e0 100644 --- a/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-fs-save-checkpoint.py @@ -32,17 +32,18 @@ with X86 ISA in fs mode. """ import argparse + from gem5.components.boards.x86_board import X86Board -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.processors.simple_processor import SimpleProcessor from gem5.components.cachehierarchies.classic.private_l1_private_l2_cache_hierarchy import ( PrivateL1PrivateL2CacheHierarchy, ) +from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor from gem5.isas import ISA -from gem5.utils.requires import requires from gem5.resources.resource import obtain_resource from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser() diff --git a/tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py index c60675eb24..5a36a01e35 100644 --- a/tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-hello-restore-checkpoint.py @@ -33,18 +33,20 @@ runs the rest of "x86-hello64-static" binary simulation. This configuration serves as a test of restoring a checkpoint with X86 ISA. """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource, CheckpointResource +from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_cache_hierarchy import ( PrivateL1CacheHierarchy, ) -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes - +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import ( + CheckpointResource, + obtain_resource, +) +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires requires(isa_required=ISA.X86) diff --git a/tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py b/tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py index 5611e795d4..bc35e581df 100644 --- a/tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py +++ b/tests/gem5/checkpoint_tests/configs/x86-hello-save-checkpoint.py @@ -32,17 +32,18 @@ with X86 ISA. """ import argparse -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import obtain_resource + +from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.private_l1_cache_hierarchy import ( PrivateL1CacheHierarchy, ) -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser() diff --git a/tests/gem5/checkpoint_tests/test-checkpoints.py b/tests/gem5/checkpoint_tests/test-checkpoints.py index 7a6c18d626..f18cf29289 100644 --- a/tests/gem5/checkpoint_tests/test-checkpoints.py +++ b/tests/gem5/checkpoint_tests/test-checkpoints.py @@ -28,9 +28,10 @@ This runs simple tests to ensure the examples in `configs/example/gem5_library` still function. They simply check the simulation completed. """ -from testlib import * -import re import os +import re + +from testlib import * if config.bin_path: resource_path = config.bin_path diff --git a/tests/gem5/cpu_tests/run.py b/tests/gem5/cpu_tests/run.py index 06790c7ea1..2feddb0a51 100644 --- a/tests/gem5/cpu_tests/run.py +++ b/tests/gem5/cpu_tests/run.py @@ -24,8 +24,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os import argparse +import os import m5 from m5.objects import * diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index 94596f4f5c..f1fcc38dcc 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -36,25 +36,34 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os -import tempfile -import shutil -import sys -import socket -import threading import gzip - +import os +import shutil +import socket +import sys +import tempfile +import threading import urllib.error import urllib.request +from typing import ( + List, + Optional, +) -from testlib.fixture import Fixture -from testlib.configuration import config, constants -from testlib.helper import log_call, cacheresult, joinpath, absdirpath import testlib.log as log +from testlib.configuration import ( + config, + constants, +) +from testlib.fixture import Fixture +from testlib.helper import ( + absdirpath, + cacheresult, + joinpath, + log_call, +) from testlib.state import Result -from typing import Optional, List - class VariableFixture(Fixture): def __init__(self, value=None, name=None): @@ -342,7 +351,9 @@ class DownloadedProgram(UniqueFixture): urllib.request.urlretrieve(self.url, self.filename) def _getremotetime(self): - import datetime, time + import datetime + import time + import _strptime # Needed for python threading bug u = urllib.request.urlopen(self.url, timeout=10) diff --git a/tests/gem5/fs/linux/arm/configs/arm_generic.py b/tests/gem5/fs/linux/arm/configs/arm_generic.py index ad2ea58597..d5c9b8c501 100644 --- a/tests/gem5/fs/linux/arm/configs/arm_generic.py +++ b/tests/gem5/fs/linux/arm/configs/arm_generic.py @@ -33,19 +33,24 @@ # (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 ABCMeta, abstractmethod +from abc import ( + ABCMeta, + abstractmethod, +) + import m5 from m5.objects import * from m5.proxy import * m5.util.addToPath("../configs/") -from common import FSConfig from base_caches import * from base_config import * -from common.cores.arm.O3_ARM_v7a import * +from common import ( + FSConfig, + SysPaths, +) from common.Benchmarks import SysConfig - -from common import SysPaths +from common.cores.arm.O3_ARM_v7a import * class ArmSESystemUniprocessor(BaseSESystemUniprocessor): diff --git a/tests/gem5/fs/linux/arm/configs/base_config.py b/tests/gem5/fs/linux/arm/configs/base_config.py index 4bf374b01c..8f7cffb255 100644 --- a/tests/gem5/fs/linux/arm/configs/base_config.py +++ b/tests/gem5/fs/linux/arm/configs/base_config.py @@ -33,15 +33,22 @@ # (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 ABCMeta, abstractmethod import argparse +from abc import ( + ABCMeta, + abstractmethod, +) + +from base_caches import * +from common import ( + FSConfig, + Options, +) +from ruby import Ruby + import m5 from m5.objects import * from m5.proxy import * -from common import FSConfig -from common import Options -from base_caches import * -from ruby import Ruby _have_kvm_support = "BaseKvmCPU" in globals() diff --git a/tests/gem5/fs/linux/arm/configs/checkpoint.py b/tests/gem5/fs/linux/arm/configs/checkpoint.py index f1b8a1bf72..6f57e3dc91 100644 --- a/tests/gem5/fs/linux/arm/configs/checkpoint.py +++ b/tests/gem5/fs/linux/arm/configs/checkpoint.py @@ -33,9 +33,9 @@ # (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 multiprocessing import Process -import sys import os +import sys +from multiprocessing import Process import m5 diff --git a/tests/gem5/fs/linux/arm/configs/realview-minor-dual.py b/tests/gem5/fs/linux/arm/configs/realview-minor-dual.py index c6b4e45e9d..08f2be87dc 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-minor-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview-minor-dual.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-minor.py b/tests/gem5/fs/linux/arm/configs/realview-minor.py index a6351628fd..108b5ac500 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-minor.py +++ b/tests/gem5/fs/linux/arm/configs/realview-minor.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-o3-checker.py b/tests/gem5/fs/linux/arm/configs/realview-o3-checker.py index 89e5c66fd3..5f0ab44f9f 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-o3-checker.py +++ b/tests/gem5/fs/linux/arm/configs/realview-o3-checker.py @@ -33,10 +33,11 @@ # (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 * from arm_generic import * from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-o3-dual.py b/tests/gem5/fs/linux/arm/configs/realview-o3-dual.py index f4326dbda1..cebd29e998 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-o3-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview-o3-dual.py @@ -33,10 +33,11 @@ # (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 * from arm_generic import * from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 +from m5.objects import * + root = LinuxArmFSSystem( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-o3.py b/tests/gem5/fs/linux/arm/configs/realview-o3.py index 6a1b757300..9b6494e04a 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-o3.py +++ b/tests/gem5/fs/linux/arm/configs/realview-o3.py @@ -33,10 +33,11 @@ # (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 * from arm_generic import * from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-checkpoint.py b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-checkpoint.py index a60fd96b27..b437ba21cc 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-checkpoint.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-checkpoint.py @@ -35,9 +35,10 @@ import functools -from m5.objects import * -from arm_generic import * import checkpoint +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-dual.py b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-dual.py index c02f8727ea..0f588bb003 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic-dual.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-atomic.py b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic.py index 9c782ad97a..1e079e3c56 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-atomic.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-atomic.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual-ruby.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual-ruby.py index 741ededdff..8afbc1a63d 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual-ruby.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual-ruby.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual.py index aaea9deb83..c3a76ebe8e 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-dual.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-timing-ruby.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-ruby.py index fcca94361e..a99cec184b 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-timing-ruby.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-timing-ruby.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-simple-timing.py b/tests/gem5/fs/linux/arm/configs/realview-simple-timing.py index 2afbdd0a0e..9f40606292 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-simple-timing.py +++ b/tests/gem5/fs/linux/arm/configs/realview-simple-timing.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( aarch64_kernel=False, machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-atomic.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-atomic.py index d2f2100f52..c7b8044246 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-atomic.py +++ b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-atomic.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( mem_class=SimpleMemory, diff --git a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-full.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-full.py index 6ed99a3772..2a468e63b6 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-full.py +++ b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-full.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-noncaching-timing.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-noncaching-timing.py index cc77f440ab..8afda7b49a 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-noncaching-timing.py +++ b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-noncaching-timing.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( cpu_classes=(ArmNonCachingSimpleCPU, ArmTimingSimpleCPU) diff --git a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-o3.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-o3.py index 4fca57ea1e..e0b1a30c43 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-o3.py +++ b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-o3.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( aarch64_kernel=False, diff --git a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-timing.py b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-timing.py index 5157da6dac..a160e809a1 100644 --- a/tests/gem5/fs/linux/arm/configs/realview-switcheroo-timing.py +++ b/tests/gem5/fs/linux/arm/configs/realview-switcheroo-timing.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-kvm-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-kvm-dual.py index e64ba2fbf5..91c0ebb0a2 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-kvm-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-kvm-dual.py @@ -33,9 +33,13 @@ # (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 * from arm_generic import * -from m5.ticks import fixGlobalFrequency, fromSeconds + +from m5.objects import * +from m5.ticks import ( + fixGlobalFrequency, + fromSeconds, +) root = LinuxArmFSSystem( mem_mode="atomic_noncaching", diff --git a/tests/gem5/fs/linux/arm/configs/realview64-kvm.py b/tests/gem5/fs/linux/arm/configs/realview64-kvm.py index 8fa6997da8..ac7f7134fa 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-kvm.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-kvm.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="atomic_noncaching", machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview64-minor-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-minor-dual.py index aed5d83c71..772ad986cf 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-minor-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-minor-dual.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( mem_mode="timing", mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-minor.py b/tests/gem5/fs/linux/arm/configs/realview64-minor.py index 7bad3c52ed..630a94bab0 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-minor.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-minor.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=ArmMinorCPU ).create_root() diff --git a/tests/gem5/fs/linux/arm/configs/realview64-o3-checker.py b/tests/gem5/fs/linux/arm/configs/realview64-o3-checker.py index 00d9a5773a..0c32aa6915 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-o3-checker.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-o3-checker.py @@ -33,10 +33,11 @@ # (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 * from arm_generic import * from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="timing", machine_type="VExpress_GEM5_V1", diff --git a/tests/gem5/fs/linux/arm/configs/realview64-o3-dual-ruby.py b/tests/gem5/fs/linux/arm/configs/realview64-o3-dual-ruby.py index a4bffe902e..db8edf3c4f 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-o3-dual-ruby.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-o3-dual-ruby.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( mem_mode="timing", mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-o3-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-o3-dual.py index 75fe10e316..1263035764 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-o3-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-o3-dual.py @@ -33,10 +33,11 @@ # (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 * from arm_generic import * from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 +from m5.objects import * + root = LinuxArmFSSystem( mem_mode="timing", mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-o3.py b/tests/gem5/fs/linux/arm/configs/realview64-o3.py index c8ae8ec5af..1c7c3b09fc 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-o3.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-o3.py @@ -33,10 +33,11 @@ # (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 * from arm_generic import * from common.cores.arm.O3_ARM_v7a import O3_ARM_v7a_3 +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=O3_ARM_v7a_3 ).create_root() diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-checkpoint.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-checkpoint.py index fa73a0ee6e..ebf9ad7879 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-checkpoint.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-checkpoint.py @@ -35,9 +35,10 @@ import functools -from m5.objects import * -from arm_generic import * import checkpoint +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSystemUniprocessor( mem_mode="atomic", mem_class=SimpleMemory, cpu_class=ArmAtomicSimpleCPU diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-dual.py index 19cf751603..c208816dea 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic-dual.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( mem_mode="atomic", mem_class=SimpleMemory, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic.py index 299dd7b0a7..2595e88311 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-atomic.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="atomic", mem_class=SimpleMemory, cpu_class=ArmAtomicSimpleCPU ).create_root() diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual-ruby.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual-ruby.py index 96ad96355c..8b37b1a2a2 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual-ruby.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual-ruby.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( mem_mode="timing", mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual.py index 8b62cd3414..e6f1043b84 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-dual.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystem( mem_mode="timing", mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-ruby.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-ruby.py index f6024537a2..aa8fe14b4c 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-ruby.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing-ruby.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="timing", mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing.py b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing.py index 6897f3b1ad..7b0e7ce137 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-simple-timing.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-simple-timing.py @@ -33,9 +33,10 @@ # (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 * from arm_generic import * +from m5.objects import * + root = LinuxArmFSSystemUniprocessor( mem_mode="timing", mem_class=DDR3_1600_8x8, cpu_class=ArmTimingSimpleCPU ).create_root() diff --git a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-atomic.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-atomic.py index c2f67f0553..37c8d1e77d 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-atomic.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-atomic.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( mem_class=SimpleMemory, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-full.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-full.py index 020957875d..0cb96586dc 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-full.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-full.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-o3.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-o3.py index f899337a8f..6da3b59eda 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-o3.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-o3.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( mem_class=DDR3_1600_8x8, cpu_classes=(ArmO3CPU, ArmO3CPU) diff --git a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-timing.py b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-timing.py index 4ccce5d953..8ac0a78335 100644 --- a/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-timing.py +++ b/tests/gem5/fs/linux/arm/configs/realview64-switcheroo-timing.py @@ -33,9 +33,10 @@ # (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 * -from arm_generic import * import switcheroo +from arm_generic import * + +from m5.objects import * root = LinuxArmFSSwitcheroo( mem_class=DDR3_1600_8x8, diff --git a/tests/gem5/fs/linux/arm/configs/switcheroo.py b/tests/gem5/fs/linux/arm/configs/switcheroo.py index 3c39fbf96a..87ab6f4b2b 100644 --- a/tests/gem5/fs/linux/arm/configs/switcheroo.py +++ b/tests/gem5/fs/linux/arm/configs/switcheroo.py @@ -34,9 +34,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 -import _m5 from m5.objects import * +import _m5 + m5.util.addToPath("../configs/") from base_caches import * diff --git a/tests/gem5/fs/linux/arm/run.py b/tests/gem5/fs/linux/arm/run.py index e677297cad..90349b33cd 100644 --- a/tests/gem5/fs/linux/arm/run.py +++ b/tests/gem5/fs/linux/arm/run.py @@ -36,9 +36,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import sys import os import os.path +import sys from os.path import join as joinpath import m5 diff --git a/tests/gem5/fs/linux/arm/test.py b/tests/gem5/fs/linux/arm/test.py index f503f7ae02..aa5961bcb4 100644 --- a/tests/gem5/fs/linux/arm/test.py +++ b/tests/gem5/fs/linux/arm/test.py @@ -37,12 +37,11 @@ Arm FS simulation tests """ +import re from os.path import join as joinpath from testlib import * -import re - arm_fs_kvm_tests = ["realview64-kvm", "realview64-kvm-dual"] arm_fs_quick_tests = [ diff --git a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py index 512e2c7cc2..5ffb62873d 100644 --- a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py +++ b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py @@ -28,10 +28,11 @@ This runs simple tests to ensure the examples in `configs/example/gem5_library` still function. They simply check the simulation completed. """ +import os +import re + from testlib import * from testlib.log import * -import re -import os if config.bin_path: resource_path = config.bin_path diff --git a/tests/gem5/gem5_resources/configs/download_check.py b/tests/gem5/gem5_resources/configs/download_check.py index 4d5f9ac69c..f051638000 100644 --- a/tests/gem5/gem5_resources/configs/download_check.py +++ b/tests/gem5/gem5_resources/configs/download_check.py @@ -24,20 +24,18 @@ # (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.resources.downloader import ( - list_resources, - get_resource, -) - -from gem5.resources.client import get_resource_json_obj - -from gem5.resources.md5_utils import md5 - +import argparse import os import shutil -import argparse from pathlib import Path +from gem5.resources.client import get_resource_json_obj +from gem5.resources.downloader import ( + get_resource, + list_resources, +) +from gem5.resources.md5_utils import md5 + parser = argparse.ArgumentParser( description="A script that will checks that input resource IDs will " "download a resource and that resources md5 value is correct. " diff --git a/tests/gem5/insttest_se/configs/simple_binary_run.py b/tests/gem5/insttest_se/configs/simple_binary_run.py index 1a0f819a8f..d48fdfc7ea 100644 --- a/tests/gem5/insttest_se/configs/simple_binary_run.py +++ b/tests/gem5/insttest_se/configs/simple_binary_run.py @@ -31,27 +31,31 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import Resource -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.base_cpu_core import BaseCPUCore -from gem5.components.processors.base_cpu_processor import BaseCPUProcessor -from gem5.components.processors.simple_core import SimpleCore -from gem5.components.boards.mem_mode import MemMode -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set, ISA +import argparse +import importlib from m5.util import fatal -import argparse -import importlib +from gem5.components.boards.mem_mode import MemMode +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.cpu_types import ( + CPUTypes, + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.resources.resource import Resource +from gem5.simulate.simulator import Simulator cpu_types_string_map = { CPUTypes.ATOMIC: "AtomicSimpleCPU", diff --git a/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py b/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py index cb6d1b44e1..3dc6119454 100644 --- a/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py +++ b/tests/gem5/kvm_fork_tests/configs/boot_kvm_fork_run.py @@ -43,18 +43,18 @@ from textwrap import dedent import m5 from m5.objects import Root -from gem5.components.boards.x86_board import X86Board from gem5.coherence_protocol import CoherenceProtocol -from gem5.isas import ISA +from gem5.components.boards.x86_board import X86Board from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import ( CPUTypes, - get_cpu_types_str_set, get_cpu_type_from_str, + get_cpu_types_str_set, ) from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) +from gem5.isas import ISA from gem5.resources.resource import obtain_resource from gem5.runtime import get_runtime_coherence_protocol from gem5.utils.requires import requires diff --git a/tests/gem5/kvm_switch_tests/configs/boot_kvm_switch_exit.py b/tests/gem5/kvm_switch_tests/configs/boot_kvm_switch_exit.py index 2d21261161..c5b59b7f4e 100644 --- a/tests/gem5/kvm_switch_tests/configs/boot_kvm_switch_exit.py +++ b/tests/gem5/kvm_switch_tests/configs/boot_kvm_switch_exit.py @@ -33,22 +33,22 @@ import argparse import m5 from m5.objects import Root -from gem5.isas import ISA -from gem5.components.boards.x86_board import X86Board from gem5.coherence_protocol import CoherenceProtocol +from gem5.components.boards.x86_board import X86Board from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import ( CPUTypes, - get_cpu_types_str_set, get_cpu_type_from_str, + get_cpu_types_str_set, ) from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) +from gem5.isas import ISA from gem5.resources.resource import obtain_resource from gem5.runtime import get_runtime_coherence_protocol -from gem5.simulate.simulator import Simulator from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator from gem5.utils.requires import requires parser = argparse.ArgumentParser( diff --git a/tests/gem5/m5_util/configs/simple_binary_run.py b/tests/gem5/m5_util/configs/simple_binary_run.py index ab12156ae2..b6f52bcd34 100644 --- a/tests/gem5/m5_util/configs/simple_binary_run.py +++ b/tests/gem5/m5_util/configs/simple_binary_run.py @@ -31,28 +31,31 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import Resource -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.base_cpu_core import BaseCPUCore -from gem5.components.processors.base_cpu_processor import BaseCPUProcessor -from gem5.components.processors.simple_core import SimpleCore -from gem5.components.boards.mem_mode import MemMode -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set, ISA - -from m5.util import fatal - import argparse import importlib +from m5.util import fatal + +from gem5.components.boards.mem_mode import MemMode +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.cpu_types import ( + CPUTypes, + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.resources.resource import Resource +from gem5.simulate.simulator import Simulator parser = argparse.ArgumentParser( description="A gem5 script for running simple binaries in SE mode." diff --git a/tests/gem5/m5_util/test_exit.py b/tests/gem5/m5_util/test_exit.py index 214a20ada9..9bb4238a57 100644 --- a/tests/gem5/m5_util/test_exit.py +++ b/tests/gem5/m5_util/test_exit.py @@ -40,6 +40,7 @@ Test file for the util m5 exit assembly instruction. """ import re + from testlib import * m5_exit_regex = re.compile( diff --git a/tests/gem5/m5threads_test_atomic/atomic_system.py b/tests/gem5/m5threads_test_atomic/atomic_system.py index b7bd67db10..62a698a025 100644 --- a/tests/gem5/m5threads_test_atomic/atomic_system.py +++ b/tests/gem5/m5threads_test_atomic/atomic_system.py @@ -24,11 +24,13 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse +import sys + +from caches import * + import m5 from m5.objects import * -from caches import * -import sys -import argparse parser = argparse.ArgumentParser(description="m5threads atomic tester") parser.add_argument("--cpu-type", default="DerivO3CPU") diff --git a/tests/gem5/m5threads_test_atomic/caches.py b/tests/gem5/m5threads_test_atomic/caches.py index 29de48b065..e9f112013b 100755 --- a/tests/gem5/m5threads_test_atomic/caches.py +++ b/tests/gem5/m5threads_test_atomic/caches.py @@ -31,8 +31,17 @@ gem5 configuration script. """ import m5 -from m5.objects import Cache, L2XBar, StridePrefetcher, SubSystem -from m5.params import AddrRange, AllMemory, MemorySize +from m5.objects import ( + Cache, + L2XBar, + StridePrefetcher, + SubSystem, +) +from m5.params import ( + AddrRange, + AllMemory, + MemorySize, +) from m5.util.convert import toMemorySize # Some specific options for caches diff --git a/tests/gem5/memory/simple-run.py b/tests/gem5/memory/simple-run.py index ec5b2d3385..910b632b11 100644 --- a/tests/gem5/memory/simple-run.py +++ b/tests/gem5/memory/simple-run.py @@ -33,11 +33,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import argparse + import m5 from m5.objects import * -import argparse - parser = argparse.ArgumentParser(description="Simple memory tester") parser.add_argument("--bandwidth", default=None) parser.add_argument("--latency", default=None) diff --git a/tests/gem5/multi_isa/configs/runtime_isa_check.py b/tests/gem5/multi_isa/configs/runtime_isa_check.py index 1076e99335..ffc50ee927 100644 --- a/tests/gem5/multi_isa/configs/runtime_isa_check.py +++ b/tests/gem5/multi_isa/configs/runtime_isa_check.py @@ -29,11 +29,15 @@ This is a very simple script to test the output given by `gem5.runtime.get_runtime_isa` """ -from gem5.runtime import get_runtime_isa -from gem5.isas import ISA, get_isas_str_set, get_isa_from_str - import argparse +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.runtime import get_runtime_isa + parser = argparse.ArgumentParser( description="A simple script used to check the output of " "`gem5.runtime.get_runtime_isa`" diff --git a/tests/gem5/multi_isa/configs/supported_isa_check.py b/tests/gem5/multi_isa/configs/supported_isa_check.py index 5f535e76a7..5b6dfc7c8a 100644 --- a/tests/gem5/multi_isa/configs/supported_isa_check.py +++ b/tests/gem5/multi_isa/configs/supported_isa_check.py @@ -29,11 +29,14 @@ This is a very simple script to test the output given by `gem5.runtime.get_supported_isas` """ -from gem5.runtime import get_supported_isas -from gem5.isas import get_isas_str_set, get_isa_from_str - -import os import argparse +import os + +from gem5.isas import ( + get_isa_from_str, + get_isas_str_set, +) +from gem5.runtime import get_supported_isas parser = argparse.ArgumentParser( description="A simple script used to check the output of " diff --git a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py index 341548729b..92786bb001 100644 --- a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py +++ b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py @@ -35,27 +35,30 @@ Notes * This will only function for the X86 ISA. """ +import argparse +import time + import m5.stats -from gem5.resources.resource import obtain_resource from gem5.components.boards.x86_board import X86Board from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import ( + get_cpu_type_from_str, + get_cpu_types_str_set, +) from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) from gem5.isas import ISA -from gem5.runtime import get_runtime_isa, get_runtime_coherence_protocol -from gem5.simulate.simulator import Simulator +from gem5.resources.resource import obtain_resource +from gem5.runtime import ( + get_runtime_coherence_protocol, + get_runtime_isa, +) from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator from gem5.utils.requires import requires -import time -import argparse - requires(isa_required=ISA.X86) diff --git a/tests/gem5/replacement_policies/configs/cache_hierarchies.py b/tests/gem5/replacement_policies/configs/cache_hierarchies.py index 6177dd4ac9..e6eab320a3 100644 --- a/tests/gem5/replacement_policies/configs/cache_hierarchies.py +++ b/tests/gem5/replacement_policies/configs/cache_hierarchies.py @@ -27,12 +27,13 @@ from typing import Type -from gem5.utils.override import overrides +from m5.objects.ReplacementPolicies import BaseReplacementPolicy + +from gem5.components.boards.abstract_board import AbstractBoard from gem5.components.cachehierarchies.ruby.mi_example_cache_hierarchy import ( MIExampleCacheHierarchy, ) -from gem5.components.boards.abstract_board import AbstractBoard -from m5.objects.ReplacementPolicies import BaseReplacementPolicy +from gem5.utils.override import overrides class ModMIExampleCacheHierarchy(MIExampleCacheHierarchy): diff --git a/tests/gem5/replacement_policies/configs/run_replacement_policy.py b/tests/gem5/replacement_policies/configs/run_replacement_policy.py index ec38bf382f..8f52a061f6 100644 --- a/tests/gem5/replacement_policies/configs/run_replacement_policy.py +++ b/tests/gem5/replacement_policies/configs/run_replacement_policy.py @@ -30,9 +30,9 @@ from importlib.machinery import SourceFileLoader from cache_hierarchies import ModMIExampleCacheHierarchy import m5 - from m5.debug import flags from m5.objects import Root + from gem5.components.boards.test_board import TestBoard from gem5.components.memory.simple import SingleChannelSimpleMemory from gem5.components.processors.complex_generator import ComplexGenerator diff --git a/tests/gem5/replacement_policies/run_replacement_policy.py b/tests/gem5/replacement_policies/run_replacement_policy.py index ec38bf382f..8f52a061f6 100644 --- a/tests/gem5/replacement_policies/run_replacement_policy.py +++ b/tests/gem5/replacement_policies/run_replacement_policy.py @@ -30,9 +30,9 @@ from importlib.machinery import SourceFileLoader from cache_hierarchies import ModMIExampleCacheHierarchy import m5 - from m5.debug import flags from m5.objects import Root + from gem5.components.boards.test_board import TestBoard from gem5.components.memory.simple import SingleChannelSimpleMemory from gem5.components.processors.complex_generator import ComplexGenerator 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 3726d7de46..0192d3dbff 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 @@ -33,18 +33,20 @@ Characteristics * Runs exclusively on the RISC-V ISA with the classic caches """ -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.resources.resource import Resource -from gem5.components.processors.cpu_types import CPUTypes -from gem5.components.boards.riscv_board import RiscvBoard -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator -from gem5.resources.resource import obtain_resource - import argparse import importlib +from gem5.components.boards.riscv_board import RiscvBoard +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import ( + Resource, + obtain_resource, +) +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires + parser = argparse.ArgumentParser( description="A script to run the RISCV boot exit tests." ) diff --git a/tests/gem5/riscv_boot_tests/test_linux_boot.py b/tests/gem5/riscv_boot_tests/test_linux_boot.py index 43d1c6d69f..bb2c3a4b04 100644 --- a/tests/gem5/riscv_boot_tests/test_linux_boot.py +++ b/tests/gem5/riscv_boot_tests/test_linux_boot.py @@ -25,7 +25,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import re - from typing import Optional from testlib import * diff --git a/tests/gem5/se_mode/hello_se/configs/simple_binary_run.py b/tests/gem5/se_mode/hello_se/configs/simple_binary_run.py index 19fd0e6b8c..08569f05a0 100644 --- a/tests/gem5/se_mode/hello_se/configs/simple_binary_run.py +++ b/tests/gem5/se_mode/hello_se/configs/simple_binary_run.py @@ -31,27 +31,31 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import obtain_resource -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.base_cpu_core import BaseCPUCore -from gem5.components.processors.base_cpu_processor import BaseCPUProcessor -from gem5.components.processors.simple_core import SimpleCore -from gem5.components.boards.mem_mode import MemMode -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set, ISA +import argparse +import importlib from m5.util import fatal -import argparse -import importlib +from gem5.components.boards.mem_mode import MemMode +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.cpu_types import ( + CPUTypes, + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator cpu_types_string_map = { CPUTypes.ATOMIC: "AtomicSimpleCPU", diff --git a/tests/gem5/se_mode/hello_se/test_hello_se.py b/tests/gem5/se_mode/hello_se/test_hello_se.py index ebcef719a8..3520f3c7cf 100644 --- a/tests/gem5/se_mode/hello_se/test_hello_se.py +++ b/tests/gem5/se_mode/hello_se/test_hello_se.py @@ -43,10 +43,10 @@ Tests which run simple binaries in gem5's SE mode. The stdlib's SimpleBoard is used to run these tests. """ -from testlib import * - import re +from testlib import * + isa_str_map = { constants.gcn3_x86_tag: "x86", constants.arm_tag: "arm", diff --git a/tests/gem5/stats/configs/simple_binary_run.py b/tests/gem5/stats/configs/simple_binary_run.py index b4d9d76d8d..4729202ae2 100644 --- a/tests/gem5/stats/configs/simple_binary_run.py +++ b/tests/gem5/stats/configs/simple_binary_run.py @@ -31,27 +31,31 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import Resource -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.base_cpu_core import BaseCPUCore -from gem5.components.processors.base_cpu_processor import BaseCPUProcessor -from gem5.components.processors.simple_core import SimpleCore -from gem5.components.boards.mem_mode import MemMode -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set, ISA +import argparse +import importlib from m5.util import fatal -import argparse -import importlib +from gem5.components.boards.mem_mode import MemMode +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.cpu_types import ( + CPUTypes, + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.resources.resource import Resource +from gem5.simulate.simulator import Simulator parser = argparse.ArgumentParser( description="A gem5 script for running simple binaries in SE mode." diff --git a/tests/gem5/stats/test_hdf5.py b/tests/gem5/stats/test_hdf5.py index c226d717de..a92c43e1b8 100644 --- a/tests/gem5/stats/test_hdf5.py +++ b/tests/gem5/stats/test_hdf5.py @@ -46,8 +46,9 @@ It will not run if the build/ARM/gem5.opt has not been built. As this is not built prior to this test being processed during the Weekly run, this test is not run. """ -import re import os +import re + from testlib import * if config.bin_path: diff --git a/tests/gem5/stdlib/configs/requires_check.py b/tests/gem5/stdlib/configs/requires_check.py index eb29f32aa3..76845174eb 100644 --- a/tests/gem5/stdlib/configs/requires_check.py +++ b/tests/gem5/stdlib/configs/requires_check.py @@ -28,12 +28,15 @@ This is a very simple script to test the behavior of 'gem5.utils.requires'` """ -from gem5.utils.requires import requires -from gem5.isas import ISA, get_isas_str_set, get_isa_from_str - - import argparse +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.utils.requires import requires + parser = argparse.ArgumentParser( description="A simple script used to check the behavior of " "`gem5.utils.requires`." diff --git a/tests/gem5/stdlib/configs/simple_binary_run.py b/tests/gem5/stdlib/configs/simple_binary_run.py index a0e4c7f62a..d02fac4533 100644 --- a/tests/gem5/stdlib/configs/simple_binary_run.py +++ b/tests/gem5/stdlib/configs/simple_binary_run.py @@ -31,27 +31,31 @@ The system has no cache heirarchy and is as "bare-bones" as you can get in gem5 while still being functinal. """ -from gem5.resources.resource import Resource -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.base_cpu_core import BaseCPUCore -from gem5.components.processors.base_cpu_processor import BaseCPUProcessor -from gem5.components.processors.simple_core import SimpleCore -from gem5.components.boards.mem_mode import MemMode -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator -from gem5.isas import get_isa_from_str, get_isas_str_set, ISA +import argparse +import importlib from m5.util import fatal -import argparse -import importlib +from gem5.components.boards.mem_mode import MemMode +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.base_cpu_core import BaseCPUCore +from gem5.components.processors.base_cpu_processor import BaseCPUProcessor +from gem5.components.processors.cpu_types import ( + CPUTypes, + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_core import SimpleCore +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ( + ISA, + get_isa_from_str, + get_isas_str_set, +) +from gem5.resources.resource import Resource +from gem5.simulate.simulator import Simulator cpu_types_string_map = { CPUTypes.ATOMIC: "AtomicSimpleCPU", diff --git a/tests/gem5/stdlib/configs/simulator_exit_event_run.py b/tests/gem5/stdlib/configs/simulator_exit_event_run.py index 56c99359f2..6b5e06890f 100644 --- a/tests/gem5/stdlib/configs/simulator_exit_event_run.py +++ b/tests/gem5/stdlib/configs/simulator_exit_event_run.py @@ -46,18 +46,17 @@ functions or a lone function can also be passed. This can be specified by the `--exit-event-type` parameter. """ -from gem5.resources.resource import obtain_resource -from gem5.components.memory import SingleChannelDDR3_1600 +import argparse + from gem5.components.boards.simple_board import SimpleBoard from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.boards.simple_board import SimpleBoard -from gem5.simulate.simulator import Simulator -from gem5.simulate.exit_event import ExitEvent from gem5.isas import ISA - -import argparse +from gem5.resources.resource import obtain_resource +from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator parser = argparse.ArgumentParser( description="A gem5 script for running simple binaries in SE mode." diff --git a/tests/gem5/suite.py b/tests/gem5/suite.py index 939ecdd8fa..7b01366c23 100644 --- a/tests/gem5/suite.py +++ b/tests/gem5/suite.py @@ -36,18 +36,25 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os import copy +import os import subprocess import sys -from testlib.test_util import TestFunction -from testlib.suite import TestSuite +from testlib.configuration import ( + config, + constants, +) from testlib.helper import log_call -from testlib.configuration import constants, config -from .fixture import TempdirFixture, Gem5Fixture, VariableFixture +from testlib.suite import TestSuite +from testlib.test_util import TestFunction from . import verifier +from .fixture import ( + Gem5Fixture, + TempdirFixture, + VariableFixture, +) def gem5_verify_config( diff --git a/tests/gem5/to_tick/configs/tick-exit.py b/tests/gem5/to_tick/configs/tick-exit.py index 4f13d723fa..b1da983abd 100644 --- a/tests/gem5/to_tick/configs/tick-exit.py +++ b/tests/gem5/to_tick/configs/tick-exit.py @@ -28,19 +28,19 @@ """ -from gem5.resources.resource import obtain_resource -from gem5.isas import ISA -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator -from gem5.simulate.exit_event import ExitEvent +import argparse import m5 -import argparse +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.exit_event import ExitEvent +from gem5.simulate.simulator import Simulator parser = argparse.ArgumentParser() diff --git a/tests/gem5/to_tick/configs/tick-to-max.py b/tests/gem5/to_tick/configs/tick-to-max.py index 89396915cf..25e0014211 100644 --- a/tests/gem5/to_tick/configs/tick-to-max.py +++ b/tests/gem5/to_tick/configs/tick-to-max.py @@ -33,18 +33,18 @@ run before, at, or after the running of `simulator.run`. time. """ -from gem5.resources.resource import obtain_resource -from gem5.isas import ISA -from gem5.components.memory import SingleChannelDDR3_1600 -from gem5.components.boards.simple_board import SimpleBoard -from gem5.components.cachehierarchies.classic.no_cache import NoCache -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.components.processors.cpu_types import CPUTypes -from gem5.simulate.simulator import Simulator +import argparse import m5 -import argparse +from gem5.components.boards.simple_board import SimpleBoard +from gem5.components.cachehierarchies.classic.no_cache import NoCache +from gem5.components.memory import SingleChannelDDR3_1600 +from gem5.components.processors.cpu_types import CPUTypes +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.simulate.simulator import Simulator parser = argparse.ArgumentParser() diff --git a/tests/gem5/traffic_gen/configs/simple_traffic_run.py b/tests/gem5/traffic_gen/configs/simple_traffic_run.py index 3766d7314f..193b59e2d6 100644 --- a/tests/gem5/traffic_gen/configs/simple_traffic_run.py +++ b/tests/gem5/traffic_gen/configs/simple_traffic_run.py @@ -31,14 +31,17 @@ subsystem. The reported values could be used to compare against a validated set of statistics. """ -import m5 - import argparse import importlib from pathlib import Path -from m5.objects import Root, MemorySize +import m5 +from m5.objects import ( + MemorySize, + Root, +) from m5.stats.gem5stats import get_simstat + from gem5.components.boards.test_board import TestBoard diff --git a/tests/gem5/verifier.py b/tests/gem5/verifier.py index eed9499848..f77c15dded 100644 --- a/tests/gem5/verifier.py +++ b/tests/gem5/verifier.py @@ -40,13 +40,16 @@ """ Built in test cases that verify particular details about a gem5 run. """ -import re -import os import json +import os +import re from testlib import test_util from testlib.configuration import constants -from testlib.helper import joinpath, diff_out_file +from testlib.helper import ( + diff_out_file, + joinpath, +) class Verifier: diff --git a/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py b/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py index 63b6625479..3a91c4d253 100644 --- a/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py +++ b/tests/gem5/x86_boot_tests/configs/x86_boot_exit_run.py @@ -28,24 +28,23 @@ This script will run a simple boot exit test. """ -import m5 - -from gem5.runtime import get_runtime_coherence_protocol -from gem5.isas import ISA -from gem5.utils.requires import requires -from gem5.coherence_protocol import CoherenceProtocol -from gem5.components.boards.x86_board import X86Board -from gem5.components.processors.cpu_types import ( - get_cpu_types_str_set, - get_cpu_type_from_str, -) -from gem5.components.processors.simple_processor import SimpleProcessor -from gem5.simulate.simulator import Simulator -from gem5.resources.resource import obtain_resource - import argparse import importlib +import m5 + +from gem5.coherence_protocol import CoherenceProtocol +from gem5.components.boards.x86_board import X86Board +from gem5.components.processors.cpu_types import ( + get_cpu_type_from_str, + get_cpu_types_str_set, +) +from gem5.components.processors.simple_processor import SimpleProcessor +from gem5.isas import ISA +from gem5.resources.resource import obtain_resource +from gem5.runtime import get_runtime_coherence_protocol +from gem5.simulate.simulator import Simulator +from gem5.utils.requires import requires parser = argparse.ArgumentParser( description="A script to run the gem5 boot test. This test boots the " diff --git a/tests/gem5/x86_boot_tests/test_linux_boot.py b/tests/gem5/x86_boot_tests/test_linux_boot.py index d4b744a0b1..fb16896bf8 100644 --- a/tests/gem5/x86_boot_tests/test_linux_boot.py +++ b/tests/gem5/x86_boot_tests/test_linux_boot.py @@ -24,8 +24,8 @@ # (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 Optional import re +from typing import Optional from testlib import * diff --git a/tests/main.py b/tests/main.py index 77ab73d3c0..063042d43d 100755 --- a/tests/main.py +++ b/tests/main.py @@ -6,8 +6,8 @@ loaders. Discovers and runs all tests from a given root directory. """ -import sys import os +import sys os.environ["PYTHONUNBUFFERED"] = "1" @@ -17,9 +17,9 @@ ext_path = os.path.join(base_dir, os.pardir, "ext") sys.path.insert(0, base_dir) sys.path.insert(0, ext_path) -import testlib.main as testlib import testlib.configuration as config import testlib.helper as helper +import testlib.main as testlib config.basedir = helper.absdirpath(__file__) sys.exit(testlib()) diff --git a/tests/pyunit/pyunit_jsonserializable_check.py b/tests/pyunit/pyunit_jsonserializable_check.py index 9979d3f9d6..3695374b8e 100644 --- a/tests/pyunit/pyunit_jsonserializable_check.py +++ b/tests/pyunit/pyunit_jsonserializable_check.py @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import unittest + from m5.ext.pystats.serializable_stat import SerializableStat diff --git a/tests/pyunit/stdlib/pyunit_looppoint.py b/tests/pyunit/stdlib/pyunit_looppoint.py index f838aa9ff5..398e771df6 100644 --- a/tests/pyunit/stdlib/pyunit_looppoint.py +++ b/tests/pyunit/stdlib/pyunit_looppoint.py @@ -24,22 +24,21 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import os import unittest from m5.params import PcCountPair from gem5.resources.looppoint import ( Looppoint, + LooppointCsvLoader, + LooppointJsonLoader, + LooppointRegion, LooppointRegionPC, LooppointRegionWarmup, LooppointSimulation, - LooppointRegion, - LooppointCsvLoader, - LooppointJsonLoader, ) -import os - class LooppointRegionPCTestSuite(unittest.TestCase): """Tests the resources.looppoint.LooppointRegionPC class.""" diff --git a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py index bc0d00c0f4..f98005e546 100644 --- a/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_client_wrapper_checks.py @@ -24,19 +24,19 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -from gem5.resources.client import get_resource_json_obj -from gem5.resources.client_api.client_wrapper import ClientWrapper -from unittest.mock import patch -import json -from urllib.error import HTTPError -import io import contextlib +import io +import json +import unittest from pathlib import Path +from unittest.mock import patch +from urllib.error import HTTPError +from gem5.resources.client import get_resource_json_obj from gem5.resources.client_api.atlasclient import ( AtlasClientHttpJsonRequestError, ) +from gem5.resources.client_api.client_wrapper import ClientWrapper mock_json_path = Path(__file__).parent / "refs/resources.json" mock_config_json = { diff --git a/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py b/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py index 82fc775975..be2c6d7810 100644 --- a/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_json_client_checks.py @@ -24,11 +24,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -import tempfile -import os -from typing import Dict import json +import os +import tempfile +import unittest +from typing import Dict from gem5.resources.client_api.jsonclient import JSONClient diff --git a/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py b/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py index b1d0ea1bc3..03a7cb95f7 100644 --- a/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_local_file_path_check.py @@ -24,9 +24,10 @@ # (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.resources.downloader import _file_uri_to_path -from pathlib import Path import unittest +from pathlib import Path + +from gem5.resources.downloader import _file_uri_to_path class LocalPathTestSuite(unittest.TestCase): diff --git a/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py b/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py index 7d6e1f42de..4570f74426 100644 --- a/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_md5_utils_check.py @@ -24,13 +24,16 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -import tempfile import os import shutil +import tempfile +import unittest from pathlib import Path -from gem5.resources.md5_utils import md5_file, md5_dir +from gem5.resources.md5_utils import ( + md5_dir, + md5_file, +) class MD5FileTestSuite(unittest.TestCase): diff --git a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py index bab91f2fb7..b4bc5dba94 100644 --- a/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py +++ b/tests/pyunit/stdlib/resources/pyunit_obtain_resources_check.py @@ -24,20 +24,21 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -import os -import io import contextlib +import io +import os +import unittest from pathlib import Path - -from gem5.resources.resource import obtain_resource, BinaryResource - -from gem5.isas import ISA +from unittest.mock import patch from _m5 import core +from gem5.isas import ISA from gem5.resources.client_api.client_wrapper import ClientWrapper -from unittest.mock import patch +from gem5.resources.resource import ( + BinaryResource, + obtain_resource, +) mock_json_path = Path(__file__).parent / "refs/obtain-resource.json" diff --git a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py index 1bf02fd691..2401edbc3e 100644 --- a/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py +++ b/tests/pyunit/stdlib/resources/pyunit_resource_specialization.py @@ -27,18 +27,15 @@ import os import unittest from pathlib import Path +from unittest.mock import patch -from gem5.resources.resource import * - +from gem5.isas import ISA +from gem5.resources.client_api.client_wrapper import ClientWrapper from gem5.resources.looppoint import ( LooppointCsvLoader, LooppointJsonLoader, ) - -from gem5.isas import ISA - -from gem5.resources.client_api.client_wrapper import ClientWrapper -from unittest.mock import patch +from gem5.resources.resource import * mock_json_path = Path(__file__).parent / "refs/resource-specialization.json" diff --git a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py index 419dbaed9f..79944a59fd 100644 --- a/tests/pyunit/stdlib/resources/pyunit_suite_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_suite_checks.py @@ -26,18 +26,19 @@ import contextlib import io -import unittest -import tempfile import os import shutil +import tempfile +import unittest from pathlib import Path +from unittest.mock import patch + +from gem5.resources.client_api.client_wrapper import ClientWrapper from gem5.resources.resource import ( - obtain_resource, SuiteResource, WorkloadResource, + obtain_resource, ) -from gem5.resources.client_api.client_wrapper import ClientWrapper -from unittest.mock import patch mock_config_json = { "sources": { diff --git a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py index c38fc8e3b8..f5917208d5 100644 --- a/tests/pyunit/stdlib/resources/pyunit_workload_checks.py +++ b/tests/pyunit/stdlib/resources/pyunit_workload_checks.py @@ -24,22 +24,23 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest import os +import unittest +from pathlib import Path +from typing import Dict +from unittest.mock import patch -from gem5.resources.workload import Workload, CustomWorkload +from gem5.resources.client_api.client_wrapper import ClientWrapper from gem5.resources.resource import ( BinaryResource, DiskImageResource, - obtain_resource, WorkloadResource, + obtain_resource, +) +from gem5.resources.workload import ( + CustomWorkload, + Workload, ) - -from typing import Dict - -from gem5.resources.client_api.client_wrapper import ClientWrapper -from unittest.mock import patch -from pathlib import Path mock_config_json = { "sources": { diff --git a/tests/pyunit/test_run.py b/tests/pyunit/test_run.py index 76cd5f70cc..fd24f753bb 100644 --- a/tests/pyunit/test_run.py +++ b/tests/pyunit/test_run.py @@ -27,6 +27,7 @@ import os from testlib.configuration import constants + from gem5.suite import * """ diff --git a/tests/run.py b/tests/run.py index f95418523e..cb0d42b996 100644 --- a/tests/run.py +++ b/tests/run.py @@ -37,13 +37,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os -import sys +import os.path import re import string - +import sys from os.path import join as joinpath -import os.path -import os import m5 diff --git a/util/checkpoint-tester.py b/util/checkpoint-tester.py index 9c638dd736..7fffa4bdf5 100755 --- a/util/checkpoint-tester.py +++ b/util/checkpoint-tester.py @@ -64,9 +64,11 @@ # -import os, sys, re -import subprocess import argparse +import os +import re +import subprocess +import sys parser = argparse.ArgumentParser() diff --git a/util/checkpoint_aggregator.py b/util/checkpoint_aggregator.py index 069557a2ef..8621330853 100755 --- a/util/checkpoint_aggregator.py +++ b/util/checkpoint_aggregator.py @@ -26,10 +26,11 @@ # (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 configparser import ConfigParser import gzip - -import sys, re, os +import os +import re +import sys +from configparser import ConfigParser class myCP(ConfigParser): diff --git a/util/cpt_upgrader.py b/util/cpt_upgrader.py index 44928bcd2d..92e104fd25 100755 --- a/util/cpt_upgrader.py +++ b/util/cpt_upgrader.py @@ -70,8 +70,11 @@ import configparser -import glob, types, sys, os +import glob +import os import os.path as osp +import sys +import types verbose_print = False @@ -277,7 +280,10 @@ def process_file(path, **kwargs): if __name__ == "__main__": - from argparse import ArgumentParser, SUPPRESS + from argparse import ( + SUPPRESS, + ArgumentParser, + ) parser = ArgumentParser(usage="%(prog)s [args] ") parser.add_argument( diff --git a/util/decode_inst_dep_trace.py b/util/decode_inst_dep_trace.py index 9cd50a6819..0ae8e9e71b 100755 --- a/util/decode_inst_dep_trace.py +++ b/util/decode_inst_dep_trace.py @@ -86,9 +86,10 @@ # 8,35670,1,STORE,1748748,4,74,0:,6,3:,7 # 9,35670,1,COMP,500::,7 -import protolib import sys +import protolib + # Import the packet proto definitions. If they are not found, attempt # to generate them automatically. This assumes that the script is # executed from the gem5 root. diff --git a/util/decode_inst_trace.py b/util/decode_inst_trace.py index 5e77138689..6aeb5ee3b7 100755 --- a/util/decode_inst_trace.py +++ b/util/decode_inst_trace.py @@ -42,9 +42,10 @@ # protoc --python_out=. inst.proto # The ASCII trace format uses one line per request. -import protolib import sys +import protolib + # Import the packet proto definitions try: import inst_pb2 diff --git a/util/decode_packet_trace.py b/util/decode_packet_trace.py index 5111ea4618..67febce411 100755 --- a/util/decode_packet_trace.py +++ b/util/decode_packet_trace.py @@ -39,10 +39,11 @@ # format. import os -import protolib import subprocess import sys +import protolib + util_dir = os.path.dirname(os.path.realpath(__file__)) # Make sure the proto definitions are up to date. subprocess.check_call(["make", "--quiet", "-C", util_dir, "packet_pb2.py"]) diff --git a/util/encode_inst_dep_trace.py b/util/encode_inst_dep_trace.py index 5ca3cda79b..29aee2b473 100755 --- a/util/encode_inst_dep_trace.py +++ b/util/encode_inst_dep_trace.py @@ -86,9 +86,10 @@ # 8,35670,1,STORE,1748748,4,74,0:,6,3:,7 # 9,35670,1,COMP,500::,7 -import protolib import sys +import protolib + # Import the packet proto definitions. If they are not found, attempt # to generate them automatically. This assumes that the script is # executed from the gem5 root. diff --git a/util/encode_packet_trace.py b/util/encode_packet_trace.py index 5df3b21c7c..48d8b58a40 100755 --- a/util/encode_packet_trace.py +++ b/util/encode_packet_trace.py @@ -51,9 +51,10 @@ # This script can of course also be used as a template to convert # other trace formats into the gem5 protobuf format -import protolib import sys +import protolib + # Import the packet proto definitions. If they are not found, attempt # to generate them automatically. This assumes that the script is # executed from the gem5 root. diff --git a/util/find_copyrights.py b/util/find_copyrights.py index 28e3b4c66b..fa1d47dd45 100644 --- a/util/find_copyrights.py +++ b/util/find_copyrights.py @@ -4,7 +4,10 @@ import os import re import sys -from file_types import lang_type, find_files +from file_types import ( + find_files, + lang_type, +) mode_line = re.compile(r"(-\*- *mode:.* *-\*-)") shell_comment = re.compile(r"^\s*#") diff --git a/util/gem5-resources-manager/api/client.py b/util/gem5-resources-manager/api/client.py index 20a91b50d2..f8d5599e03 100644 --- a/util/gem5-resources-manager/api/client.py +++ b/util/gem5-resources-manager/api/client.py @@ -24,8 +24,14 @@ # (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 ABC, abstractmethod -from typing import Dict, List +from abc import ( + ABC, + abstractmethod, +) +from typing import ( + Dict, + List, +) class Client(ABC): diff --git a/util/gem5-resources-manager/api/create_resources_json.py b/util/gem5-resources-manager/api/create_resources_json.py index 3179142939..02ec96af8d 100644 --- a/util/gem5-resources-manager/api/create_resources_json.py +++ b/util/gem5-resources-manager/api/create_resources_json.py @@ -24,10 +24,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import json -import requests import base64 +import json import os + +import requests from jsonschema import validate diff --git a/util/gem5-resources-manager/api/json_client.py b/util/gem5-resources-manager/api/json_client.py index 24cfaee88c..09c652d748 100644 --- a/util/gem5-resources-manager/api/json_client.py +++ b/util/gem5-resources-manager/api/json_client.py @@ -24,10 +24,14 @@ # (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 pathlib import Path import json +from pathlib import Path +from typing import ( + Dict, + List, +) + from api.client import Client -from typing import Dict, List class JSONClient(Client): diff --git a/util/gem5-resources-manager/api/mongo_client.py b/util/gem5-resources-manager/api/mongo_client.py index 845524b886..6a60549b9a 100644 --- a/util/gem5-resources-manager/api/mongo_client.py +++ b/util/gem5-resources-manager/api/mongo_client.py @@ -25,12 +25,19 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import json -from bson import json_util -from api.client import Client -from pymongo.errors import ConnectionFailure, ConfigurationError -from pymongo import MongoClient -from typing import Dict, List +from typing import ( + Dict, + List, +) + import pymongo +from api.client import Client +from bson import json_util +from pymongo import MongoClient +from pymongo.errors import ( + ConfigurationError, + ConnectionFailure, +) class DatabaseConnectionError(Exception): diff --git a/util/gem5-resources-manager/gem5_resource_cli.py b/util/gem5-resources-manager/gem5_resource_cli.py index 28528bec92..27f10aebe1 100644 --- a/util/gem5-resources-manager/gem5_resource_cli.py +++ b/util/gem5-resources-manager/gem5_resource_cli.py @@ -25,17 +25,18 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import json -from pymongo import MongoClient -from api.create_resources_json import ResourceJsonCreator -import os -from dotenv import load_dotenv import argparse +import json +import os from itertools import cycle from shutil import get_terminal_size from threading import Thread from time import sleep +from api.create_resources_json import ResourceJsonCreator +from dotenv import load_dotenv +from pymongo import MongoClient + load_dotenv() # read MONGO_URI from environment variable diff --git a/util/gem5-resources-manager/server.py b/util/gem5-resources-manager/server.py index ec298d6c70..f0357a4a27 100644 --- a/util/gem5-resources-manager/server.py +++ b/util/gem5-resources-manager/server.py @@ -24,28 +24,32 @@ # (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 flask import ( - render_template, - Flask, - request, - redirect, - url_for, - make_response, -) -from bson import json_util -import json -import jsonschema -import requests -import markdown import base64 +import json import secrets from pathlib import Path -from werkzeug.utils import secure_filename -from cryptography.fernet import Fernet, InvalidToken -from cryptography.hazmat.primitives.kdf.scrypt import Scrypt -from cryptography.exceptions import InvalidSignature + +import jsonschema +import markdown +import requests from api.json_client import JSONClient from api.mongo_client import MongoDBClient +from bson import json_util +from cryptography.exceptions import InvalidSignature +from cryptography.fernet import ( + Fernet, + InvalidToken, +) +from cryptography.hazmat.primitives.kdf.scrypt import Scrypt +from flask import ( + Flask, + make_response, + redirect, + render_template, + request, + url_for, +) +from werkzeug.utils import secure_filename databases = {} diff --git a/util/gem5-resources-manager/test/api_test.py b/util/gem5-resources-manager/test/api_test.py index 0ff439cd2e..e6918831ea 100644 --- a/util/gem5-resources-manager/test/api_test.py +++ b/util/gem5-resources-manager/test/api_test.py @@ -24,17 +24,18 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import flask import contextlib -import unittest -from server import app -import server import json -from bson import json_util +import unittest from unittest.mock import patch + +import flask import mongomock -from api.mongo_client import MongoDBClient import requests +import server +from api.mongo_client import MongoDBClient +from bson import json_util +from server import app @contextlib.contextmanager diff --git a/util/gem5-resources-manager/test/comprehensive_test.py b/util/gem5-resources-manager/test/comprehensive_test.py index 4c32087324..f878b0c347 100644 --- a/util/gem5-resources-manager/test/comprehensive_test.py +++ b/util/gem5-resources-manager/test/comprehensive_test.py @@ -24,14 +24,15 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -from server import app -import json -from bson import json_util import copy -import mongomock +import json +import unittest from unittest.mock import patch + +import mongomock from api.mongo_client import MongoDBClient +from bson import json_util +from server import app class TestComprehensive(unittest.TestCase): diff --git a/util/gem5-resources-manager/test/json_client_test.py b/util/gem5-resources-manager/test/json_client_test.py index 0168d475ac..963743c4ac 100644 --- a/util/gem5-resources-manager/test/json_client_test.py +++ b/util/gem5-resources-manager/test/json_client_test.py @@ -24,14 +24,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -from api.json_client import JSONClient -from server import app import json -from bson import json_util -from unittest.mock import patch +import unittest from pathlib import Path +from unittest.mock import patch + from api.json_client import JSONClient +from bson import json_util +from server import app def get_json(): diff --git a/util/gem5-resources-manager/test/mongo_client_test.py b/util/gem5-resources-manager/test/mongo_client_test.py index 761475ead8..8322fe7507 100644 --- a/util/gem5-resources-manager/test/mongo_client_test.py +++ b/util/gem5-resources-manager/test/mongo_client_test.py @@ -24,13 +24,17 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest -from server import app, databases import json -from bson import json_util -import mongomock +import unittest from unittest.mock import patch + +import mongomock from api.mongo_client import MongoDBClient +from bson import json_util +from server import ( + app, + databases, +) class TestApi(unittest.TestCase): diff --git a/util/gem5-stubgen.py b/util/gem5-stubgen.py index d003e2212e..70d7c3ac64 100644 --- a/util/gem5-stubgen.py +++ b/util/gem5-stubgen.py @@ -24,7 +24,10 @@ # (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 mypy.stubgen import generate_stubs, parse_options +from mypy.stubgen import ( + generate_stubs, + parse_options, +) """ This allows us to generate stubs for the modules in gem5. The output will be diff --git a/util/gem5art/artifact/gem5art/artifact/__init__.py b/util/gem5art/artifact/gem5art/artifact/__init__.py index 7e026d5761..c15c4008e8 100644 --- a/util/gem5art/artifact/gem5art/artifact/__init__.py +++ b/util/gem5art/artifact/gem5art/artifact/__init__.py @@ -26,14 +26,14 @@ """This is the gem5 artifact package""" +from ._artifactdb import getDBConnection from .artifact import Artifact from .common_queries import ( getByName, getDiskImages, - getLinuxBinaries, getgem5Binaries, + getLinuxBinaries, ) -from ._artifactdb import getDBConnection __all__ = [ "Artifact", diff --git a/util/gem5art/artifact/gem5art/artifact/_artifactdb.py b/util/gem5art/artifact/gem5art/artifact/_artifactdb.py index a18f47d7d0..428936075c 100644 --- a/util/gem5art/artifact/gem5art/artifact/_artifactdb.py +++ b/util/gem5art/artifact/gem5art/artifact/_artifactdb.py @@ -34,14 +34,24 @@ artifacts stored in the database. Some common queries can be found in common_queries.py """ -from abc import ABC, abstractmethod - import copy import json import os -from pathlib import Path import shutil -from typing import Any, Dict, Iterable, Union, Type, List, Tuple +from abc import ( + ABC, + abstractmethod, +) +from pathlib import Path +from typing import ( + Any, + Dict, + Iterable, + List, + Tuple, + Type, + Union, +) from urllib.parse import urlparse from uuid import UUID diff --git a/util/gem5art/artifact/gem5art/artifact/artifact.py b/util/gem5art/artifact/gem5art/artifact/artifact.py index d178b218dd..177842f591 100644 --- a/util/gem5art/artifact/gem5art/artifact/artifact.py +++ b/util/gem5art/artifact/gem5art/artifact/artifact.py @@ -28,14 +28,22 @@ """ import hashlib -from inspect import cleandoc import json -from pathlib import Path import subprocess import time -from typing import Any, Dict, List, Union, Optional -from uuid import UUID, uuid4 -import json +from inspect import cleandoc +from pathlib import Path +from typing import ( + Any, + Dict, + List, + Optional, + Union, +) +from uuid import ( + UUID, + uuid4, +) from ._artifactdb import getDBConnection diff --git a/util/gem5art/artifact/setup.py b/util/gem5art/artifact/setup.py index 78247eb16d..7c1a1d8851 100755 --- a/util/gem5art/artifact/setup.py +++ b/util/gem5art/artifact/setup.py @@ -28,8 +28,11 @@ from os.path import join from pathlib import Path -from setuptools import setup, find_namespace_packages +from setuptools import ( + find_namespace_packages, + setup, +) with open(Path(__file__).parent / "README.md", encoding="utf-8") as f: long_description = f.read() diff --git a/util/gem5art/artifact/tests/test_artifact.py b/util/gem5art/artifact/tests/test_artifact.py index a12cc8f028..c1578bda68 100644 --- a/util/gem5art/artifact/tests/test_artifact.py +++ b/util/gem5art/artifact/tests/test_artifact.py @@ -27,14 +27,20 @@ """Tests for the Artifact object and associated functions""" import hashlib -from pathlib import Path -import unittest -from uuid import uuid4, UUID -import sys import io +import sys +import unittest +from pathlib import Path +from uuid import ( + UUID, + uuid4, +) from gem5art import artifact -from gem5art.artifact._artifactdb import ArtifactDB, getDBConnection +from gem5art.artifact._artifactdb import ( + ArtifactDB, + getDBConnection, +) class MockDB(ArtifactDB): diff --git a/util/gem5art/artifact/tests/test_filedb.py b/util/gem5art/artifact/tests/test_filedb.py index b7144ffcf3..bd87e59dbd 100644 --- a/util/gem5art/artifact/tests/test_filedb.py +++ b/util/gem5art/artifact/tests/test_filedb.py @@ -29,8 +29,8 @@ import json import os -from pathlib import Path import unittest +from pathlib import Path from uuid import UUID from gem5art.artifact import Artifact diff --git a/util/gem5art/run/bin/gem5art-getruns b/util/gem5art/run/bin/gem5art-getruns index da8d2f0835..fe6046c1c0 100755 --- a/util/gem5art/run/bin/gem5art-getruns +++ b/util/gem5art/run/bin/gem5art-getruns @@ -35,7 +35,10 @@ from json import dump import gem5art.artifact from gem5art.artifact import getDBConnection -from gem5art.run import getRunsByNameLike, getRuns +from gem5art.run import ( + getRuns, + getRunsByNameLike, +) def parseArgs(): diff --git a/util/gem5art/run/gem5art/run.py b/util/gem5art/run/gem5art/run.py index 7b7b823200..4918fa870c 100644 --- a/util/gem5art/run/gem5art/run.py +++ b/util/gem5art/run/gem5art/run.py @@ -35,13 +35,25 @@ experiment is reproducible and the output is saved to the database. import hashlib import json import os -from pathlib import Path import signal import subprocess import time -from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union -from uuid import UUID, uuid4 import zipfile +from pathlib import Path +from typing import ( + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Tuple, + Union, +) +from uuid import ( + UUID, + uuid4, +) from gem5art import artifact from gem5art.artifact import Artifact diff --git a/util/gem5art/run/setup.py b/util/gem5art/run/setup.py index 1ab51b5c2d..70d62117d2 100755 --- a/util/gem5art/run/setup.py +++ b/util/gem5art/run/setup.py @@ -28,8 +28,11 @@ from os.path import join from pathlib import Path -from setuptools import setup, find_namespace_packages +from setuptools import ( + find_namespace_packages, + setup, +) with open(Path(__file__).parent / "README.md", encoding="utf-8") as f: long_description = f.read() diff --git a/util/gem5art/run/tests/test_run.py b/util/gem5art/run/tests/test_run.py index 0bdd561220..58fe8571b5 100644 --- a/util/gem5art/run/tests/test_run.py +++ b/util/gem5art/run/tests/test_run.py @@ -27,9 +27,9 @@ """Tests for gem5Run object""" import hashlib -from pathlib import Path import os import unittest +from pathlib import Path from uuid import uuid4 from gem5art.artifact import artifact diff --git a/util/gem5art/tasks/gem5art/tasks/tasks.py b/util/gem5art/tasks/gem5art/tasks/tasks.py index 3d92956341..6e1a6030f7 100755 --- a/util/gem5art/tasks/gem5art/tasks/tasks.py +++ b/util/gem5art/tasks/gem5art/tasks/tasks.py @@ -24,10 +24,11 @@ # (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 .celery import gem5app import multiprocessing as mp import time +from .celery import gem5app + @gem5app.task(bind=True, serializer="pickle") def run_gem5_instance(self, gem5_run, cwd="."): diff --git a/util/gem5art/tasks/setup.py b/util/gem5art/tasks/setup.py index 290c68a17a..1cfe4c770d 100755 --- a/util/gem5art/tasks/setup.py +++ b/util/gem5art/tasks/setup.py @@ -28,8 +28,11 @@ from os.path import join from pathlib import Path -from setuptools import setup, find_namespace_packages +from setuptools import ( + find_namespace_packages, + setup, +) with open(Path(__file__).parent / "README.md", encoding="utf-8") as f: long_description = f.read() diff --git a/util/gem5img.py b/util/gem5img.py index dcb66e0bc9..4a8c0916fe 100755 --- a/util/gem5img.py +++ b/util/gem5img.py @@ -42,13 +42,21 @@ # Script for managing a gem5 disk image. # -from argparse import ArgumentParser import os -from os import environ as env -import string -from subprocess import CalledProcessError, Popen, PIPE, STDOUT -from sys import exit, argv import re +import string +from argparse import ArgumentParser +from os import environ as env +from subprocess import ( + PIPE, + STDOUT, + CalledProcessError, + Popen, +) +from sys import ( + argv, + exit, +) # Some constants. MaxLBACylinders = 16383 diff --git a/util/gen_arm_fs_files.py b/util/gen_arm_fs_files.py index 6446d79bfb..3a6605be6f 100755 --- a/util/gen_arm_fs_files.py +++ b/util/gen_arm_fs_files.py @@ -38,14 +38,16 @@ # (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 argparse import ArgumentParser, ArgumentDefaultsHelpFormatter -from subprocess import call -from platform import machine +import os +import sys +from argparse import ( + ArgumentDefaultsHelpFormatter, + ArgumentParser, +) from distutils import spawn from glob import glob - -import sys -import os +from platform import machine +from subprocess import call def run_cmd(explanation, working_dir, cmd, stdout=None): diff --git a/util/gerrit-bot/bot.py b/util/gerrit-bot/bot.py index 5ef4151a48..5f6afdaf99 100755 --- a/util/gerrit-bot/bot.py +++ b/util/gerrit-bot/bot.py @@ -26,14 +26,17 @@ # (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 gerrit import GerritResponseParser as Parser -from gerrit import GerritRestAPI -from util import add_maintainers_to_change, convert_time_in_seconds - import json +import sys import time -import sys +from gerrit import GerritResponseParser as Parser +from gerrit import GerritRestAPI + +from util import ( + add_maintainers_to_change, + convert_time_in_seconds, +) sys.path.append("..") import maint.lib.maintainers diff --git a/util/gerrit-bot/gerrit.py b/util/gerrit-bot/gerrit.py index 2e68a70645..b75434b4b3 100644 --- a/util/gerrit-bot/gerrit.py +++ b/util/gerrit-bot/gerrit.py @@ -26,10 +26,11 @@ import copy import json -import requests from types import SimpleNamespace from urllib.parse import urljoin +import requests + class GerritResponseParser: @staticmethod diff --git a/util/git-commit-msg.py b/util/git-commit-msg.py index f0a60110c7..d40aa68e1c 100755 --- a/util/git-commit-msg.py +++ b/util/git-commit-msg.py @@ -32,8 +32,8 @@ import os import re import sys -from maint.lib import maintainers +from maint.lib import maintainers from style.repo import GitRepo diff --git a/util/git-pre-commit.py b/util/git-pre-commit.py index c6f3b3c033..0a51ba0478 100755 --- a/util/git-pre-commit.py +++ b/util/git-pre-commit.py @@ -36,16 +36,21 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from tempfile import TemporaryFile +import argparse import os import subprocess import sys +from tempfile import TemporaryFile from style.repo import GitRepo -from style.verifiers import all_verifiers, all_regions -from style.style import StdioUI, check_ignores - -import argparse +from style.style import ( + StdioUI, + check_ignores, +) +from style.verifiers import ( + all_regions, + all_verifiers, +) parser = argparse.ArgumentParser(description="gem5 git style checker hook") diff --git a/util/maint/list_changes.py b/util/maint/list_changes.py index 1dcb70def2..805d7676b6 100755 --- a/util/maint/list_changes.py +++ b/util/maint/list_changes.py @@ -36,8 +36,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import subprocess import re +import subprocess from functools import wraps diff --git a/util/maint/show_changes_by_file.py b/util/maint/show_changes_by_file.py index 8da3ee64bd..600f1e8f1a 100755 --- a/util/maint/show_changes_by_file.py +++ b/util/maint/show_changes_by_file.py @@ -33,7 +33,10 @@ import subprocess -from collections import OrderedDict, defaultdict +from collections import ( + OrderedDict, + defaultdict, +) class OrderedDefaultDict(OrderedDict, defaultdict): diff --git a/util/md5.py b/util/md5.py index 333f714109..0c55f92e0d 100644 --- a/util/md5.py +++ b/util/md5.py @@ -26,7 +26,11 @@ import argparse from pathlib import Path -from gem5.resources.md5_utils import md5_file, md5_dir + +from gem5.resources.md5_utils import ( + md5_dir, + md5_file, +) parser = argparse.ArgumentParser( description="A utility to determine the md5 hash of files and " diff --git a/util/minorview.py b/util/minorview.py index f7a53b1d26..eb4e0bd617 100755 --- a/util/minorview.py +++ b/util/minorview.py @@ -38,18 +38,23 @@ # minorview.py: Minorview visuliser for MinorCPU model MinorTrace output # -import gtk +import argparse import os import sys -import argparse + +import gtk # Find MinorView modules even if not called from minorview directory minorviewDir = os.path.dirname(os.path.realpath(__file__)) sys.path.append(minorviewDir) from minorview.model import BlobModel -from minorview.view import BlobView, BlobController, BlobWindow from minorview.point import Point +from minorview.view import ( + BlobController, + BlobView, + BlobWindow, +) if __name__ == "__main__": parser = argparse.ArgumentParser(description="Minor visualiser") diff --git a/util/minorview/blobs.py b/util/minorview/blobs.py index 8d379f0cb8..1f6753e76a 100644 --- a/util/minorview/blobs.py +++ b/util/minorview/blobs.py @@ -41,17 +41,23 @@ import pygtk pygtk.require("2.0") -import gtk -import gobject -import cairo -import re import math +import re +import cairo +import gobject +import gtk + +from . import ( + colours, + model, + parse, +) +from .colours import ( + backgroundColour, + black, +) from .point import Point -from . import parse -from . import colours -from .colours import backgroundColour, black -from . import model def centre_size_to_sides(centre, size): diff --git a/util/minorview/model.py b/util/minorview/model.py index cf8c04bc04..91979825c3 100644 --- a/util/minorview/model.py +++ b/util/minorview/model.py @@ -33,14 +33,17 @@ # (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 . import parse -from . import colours +import os +import re +from time import time as wall_time + +from . import ( + blobs, + colours, + parse, +) from .colours import unknownColour from .point import Point -import re -from . import blobs -from time import time as wall_time -import os id_parts = "TSPLFE" diff --git a/util/minorview/view.py b/util/minorview/view.py index 37564996eb..671a80869c 100644 --- a/util/minorview/view.py +++ b/util/minorview/view.py @@ -36,17 +36,25 @@ import pygtk pygtk.require("2.0") -import gtk -import gobject -import cairo import re +import cairo +import gobject +import gtk + +from . import ( + blobs, + colours, + model, + parse, +) +from .model import ( + BlobDataSelect, + BlobModel, + Id, + special_state_chars, +) from .point import Point -from . import parse -from . import colours -from . import model -from .model import Id, BlobModel, BlobDataSelect, special_state_chars -from . import blobs class BlobView: diff --git a/util/o3-pipeview.py b/util/o3-pipeview.py index 3228832446..a821a13b4f 100755 --- a/util/o3-pipeview.py +++ b/util/o3-pipeview.py @@ -38,9 +38,9 @@ # Pipeline activity viewer for the O3 CPU model. import argparse +import copy import os import sys -import copy # Temporary storage for instructions. The queue is filled in out-of-order # until it reaches 'max_threshold' number of instructions. It is then diff --git a/util/obtain-resource.py b/util/obtain-resource.py index de6a7b90e2..b11ee328de 100644 --- a/util/obtain-resource.py +++ b/util/obtain-resource.py @@ -41,9 +41,10 @@ build/ALL/gem5.opt util/obtain-resource.py [-p ] [-q] """ if __name__ == "__m5_main__": - from gem5.resources.resource import obtain_resource import argparse + from gem5.resources.resource import obtain_resource + parser = argparse.ArgumentParser() parser.add_argument( diff --git a/util/on-chip-network-power-area.py b/util/on-chip-network-power-area.py index 563bf6334d..f5e463b3b9 100644 --- a/util/on-chip-network-power-area.py +++ b/util/on-chip-network-power-area.py @@ -25,8 +25,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import os +import string +import subprocess +import sys from configparser import ConfigParser -import string, sys, subprocess, os # Compile DSENT to generate the Python module and then import it. # This script assumes it is executed from the gem5 root. diff --git a/util/oprofile-top.py b/util/oprofile-top.py index 2808ea10fe..a694894473 100755 --- a/util/oprofile-top.py +++ b/util/oprofile-top.py @@ -28,9 +28,10 @@ # Parse sampled function profile output (quick hack). -import sys -import re import getopt +import re +import sys + from categories import * diff --git a/util/plot_dram/PlotPowerStates.py b/util/plot_dram/PlotPowerStates.py index 31e831f8b0..d22249aa25 100755 --- a/util/plot_dram/PlotPowerStates.py +++ b/util/plot_dram/PlotPowerStates.py @@ -36,11 +36,12 @@ import matplotlib matplotlib.use("Agg") -import matplotlib.pyplot as plt -from matplotlib.font_manager import FontProperties -import numpy as np import os +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.font_manager import FontProperties + # global results dict results = {} idleResults = {} diff --git a/util/plot_dram/dram_lat_mem_rd_plot.py b/util/plot_dram/dram_lat_mem_rd_plot.py index 798148f714..a8ef288028 100755 --- a/util/plot_dram/dram_lat_mem_rd_plot.py +++ b/util/plot_dram/dram_lat_mem_rd_plot.py @@ -36,15 +36,15 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. try: - import matplotlib.pyplot as plt import matplotlib as mpl + import matplotlib.pyplot as plt import numpy as np except ImportError: print("Failed to import matplotlib and numpy") exit(-1) -import sys import re +import sys # This script is intended to post process and plot the output from diff --git a/util/plot_dram/dram_sweep_plot.py b/util/plot_dram/dram_sweep_plot.py index 8fbeaf511c..c789ab32a4 100755 --- a/util/plot_dram/dram_sweep_plot.py +++ b/util/plot_dram/dram_sweep_plot.py @@ -36,16 +36,16 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. try: - from mpl_toolkits.mplot3d import Axes3D - from matplotlib import cm import matplotlib.pyplot as plt import numpy as np + from matplotlib import cm + from mpl_toolkits.mplot3d import Axes3D except ImportError: print("Failed to import matplotlib and numpy") exit(-1) -import sys import re +import sys # Determine the parameters of the sweep from the simout output, and diff --git a/util/plot_dram/lowp_dram_sweep_plot.py b/util/plot_dram/lowp_dram_sweep_plot.py index 0f53a3319b..89b69b5116 100755 --- a/util/plot_dram/lowp_dram_sweep_plot.py +++ b/util/plot_dram/lowp_dram_sweep_plot.py @@ -35,11 +35,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import PlotPowerStates as plotter import argparse import os from subprocess import call +import PlotPowerStates as plotter + parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter ) diff --git a/util/slicc b/util/slicc index d660510b58..14f4c09c54 100755 --- a/util/slicc +++ b/util/slicc @@ -27,7 +27,10 @@ if __name__ == "__main__": import sys - from os.path import dirname, join + from os.path import ( + dirname, + join, + ) base = dirname(__file__) sys.path.insert(1, join(base, "../src/mem")) diff --git a/util/streamline/m5stats2streamline.py b/util/streamline/m5stats2streamline.py index e350806e87..ec2dc0e834 100755 --- a/util/streamline/m5stats2streamline.py +++ b/util/streamline/m5stats2streamline.py @@ -58,15 +58,16 @@ # APC project generation based on Gator v17 (DS-5 v5.17) # Subsequent versions should be backward compatible -import re, sys, os -from configparser import ConfigParser -import gzip -import xml.etree.ElementTree as ET -import xml.dom.minidom as minidom -import shutil -import zlib - import argparse +import gzip +import os +import re +import shutil +import sys +import xml.dom.minidom as minidom +import xml.etree.ElementTree as ET +import zlib +from configparser import ConfigParser parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, diff --git a/util/style.py b/util/style.py index 1b3ebe1602..fd1882a4d5 100755 --- a/util/style.py +++ b/util/style.py @@ -38,12 +38,11 @@ import os import sys -from style.file_types import lang_type import style.verifiers -from style.region import all_regions - -from style.style import StdioUI from style import repo +from style.file_types import lang_type +from style.region import all_regions +from style.style import StdioUI verifier_names = {c.__name__: c for c in style.verifiers.all_verifiers} diff --git a/util/style/repo.py b/util/style/repo.py index 04db36d15d..758aaa1180 100644 --- a/util/style/repo.py +++ b/util/style/repo.py @@ -35,9 +35,9 @@ # (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 * import os import subprocess +from abc import * from .region import * from .style import modified_regions diff --git a/util/style/style.py b/util/style/style.py index a40671fb47..add8069bdf 100644 --- a/util/style/style.py +++ b/util/style/style.py @@ -39,10 +39,13 @@ # (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 ABCMeta, abstractmethod import difflib import re import sys +from abc import ( + ABCMeta, + abstractmethod, +) from .region import * diff --git a/util/style/verifiers.py b/util/style/verifiers.py index 4860cc461e..654ce7a720 100644 --- a/util/style/verifiers.py +++ b/util/style/verifiers.py @@ -40,17 +40,22 @@ # (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 ABCMeta, abstractmethod -from difflib import SequenceMatcher import inspect import os import re import sys +from abc import ( + ABCMeta, + abstractmethod, +) +from difflib import SequenceMatcher -from . import style -from . import sort_includes -from .region import * +from . import ( + sort_includes, + style, +) from .file_types import lang_type +from .region import * def safefix(fix_func): diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py index d23b6764c7..1e8269c92a 100644 --- a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py +++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/SystemC_Example.py @@ -23,13 +23,11 @@ # (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.params import * -from m5.SimObject import SimObject -from m5.params import * -from m5.proxy import * - from m5.objects.SystemC import SystemC_ScModule from m5.objects.Tlm import TlmTargetSocket +from m5.params import * +from m5.proxy import * +from m5.SimObject import SimObject # This class is a subclass of sc_module, and all the special magic which makes diff --git a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py index 71529ba879..36686bf89b 100755 --- a/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py +++ b/util/systemc/systemc_within_gem5/systemc_gem5_tlm/config.py @@ -28,8 +28,8 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os -import m5 +import m5 from m5.objects import * # Create a config to be used by the traffic generator diff --git a/util/systemc/systemc_within_gem5/systemc_sc_main/config.py b/util/systemc/systemc_within_gem5/systemc_sc_main/config.py index 454c3b5813..81c9e15f56 100755 --- a/util/systemc/systemc_within_gem5/systemc_sc_main/config.py +++ b/util/systemc/systemc_within_gem5/systemc_sc_main/config.py @@ -24,10 +24,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse -import m5 import sys -from m5.objects import SystemC_Kernel, Root +import m5 +from m5.objects import ( + Root, + SystemC_Kernel, +) # pylint:disable=unused-variable diff --git a/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py b/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py index e4535d2c12..7832328c0d 100644 --- a/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py +++ b/util/systemc/systemc_within_gem5/systemc_simple_object/SystemC_Example.py @@ -23,11 +23,10 @@ # (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.SystemC import SystemC_ScModule from m5.params import * from m5.SimObject import SimObject -from m5.objects.SystemC import SystemC_ScModule - # This class is a subclass of sc_module, and all the special magic which makes # that work is handled in the base classes. diff --git a/util/systemc/systemc_within_gem5/systemc_simple_object/config.py b/util/systemc/systemc_within_gem5/systemc_simple_object/config.py index 8a86e1fb01..c71c5ac3db 100755 --- a/util/systemc/systemc_within_gem5/systemc_simple_object/config.py +++ b/util/systemc/systemc_within_gem5/systemc_simple_object/config.py @@ -25,10 +25,15 @@ import argparse -import m5 import sys -from m5.objects import SystemC_Kernel, Root, SystemC_Printer, Gem5_Feeder +import m5 +from m5.objects import ( + Gem5_Feeder, + Root, + SystemC_Kernel, + SystemC_Printer, +) # pylint:disable=unused-variable diff --git a/util/systemc/systemc_within_gem5/systemc_tlm/config.py b/util/systemc/systemc_within_gem5/systemc_tlm/config.py index 454c3b5813..81c9e15f56 100755 --- a/util/systemc/systemc_within_gem5/systemc_tlm/config.py +++ b/util/systemc/systemc_within_gem5/systemc_tlm/config.py @@ -24,10 +24,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse -import m5 import sys -from m5.objects import SystemC_Kernel, Root +import m5 +from m5.objects import ( + Root, + SystemC_Kernel, +) # pylint:disable=unused-variable diff --git a/util/tlm/conf/tlm_elastic_slave.py b/util/tlm/conf/tlm_elastic_slave.py index 1007c5244b..8614eae26b 100644 --- a/util/tlm/conf/tlm_elastic_slave.py +++ b/util/tlm/conf/tlm_elastic_slave.py @@ -29,9 +29,11 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 - from m5.objects import * -from m5.util import addToPath, fatal +from m5.util import ( + addToPath, + fatal, +) addToPath("../../../configs/common/") diff --git a/util/tlm/conf/tlm_master.py b/util/tlm/conf/tlm_master.py index a3782a72cc..a7e5d8b99e 100644 --- a/util/tlm/conf/tlm_master.py +++ b/util/tlm/conf/tlm_master.py @@ -29,11 +29,11 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import os + import m5 from m5.objects import * -import os - # Base System Architecture: # +-----+ ^ # | TLM | | TLM World diff --git a/util/tlm/examples/tlm_elastic_slave_with_l2.py b/util/tlm/examples/tlm_elastic_slave_with_l2.py index 6b3f7b43fb..5bb15b520d 100644 --- a/util/tlm/examples/tlm_elastic_slave_with_l2.py +++ b/util/tlm/examples/tlm_elastic_slave_with_l2.py @@ -29,9 +29,11 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import m5 - from m5.objects import * -from m5.util import addToPath, fatal +from m5.util import ( + addToPath, + fatal, +) addToPath("../../../configs/common/") diff --git a/util/update-copyright.py b/util/update-copyright.py index 1c3fd611ac..3ad0c92466 100755 --- a/util/update-copyright.py +++ b/util/update-copyright.py @@ -41,7 +41,6 @@ import subprocess import sys import git_filter_repo - import update_copyright parser = argparse.ArgumentParser( From 9afe9932bc8814e3027242740ac2f69f31032e09 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Thu, 30 Nov 2023 07:27:52 -0800 Subject: [PATCH 637/693] sim,python: Restore sigint handler in python (#531) Currently, if you try to use ctrl-c while python code is running nothing happens. This is not ideal. This change enables users to use ctrl-c while python is running (e.g., when a large disk image is downloading). To do this, we moved the `initSignals` function in gem5 from `main` to the simulate loop. Thus, every time the simulate loop starts (i.e., is called from python) gem5 will install its signal handlers. Also, when the control is returned to python, we put python's default SIGINT handler back. Change-Id: I14490e48d931eb316e8c641217bf8d8ddaa340ed Signed-off-by: Jason Lowe-Power --- src/sim/init_signals.cc | 23 ++++++++++++++++++----- src/sim/init_signals.hh | 4 ++++ src/sim/simulate.cc | 8 ++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/sim/init_signals.cc b/src/sim/init_signals.cc index b9aa6f6e4d..b574f12ea1 100644 --- a/src/sim/init_signals.cc +++ b/src/sim/init_signals.cc @@ -84,7 +84,8 @@ setupAltStack() static void installSignalHandler(int signal, void (*handler)(int sigtype), - int flags = SA_RESTART) + int flags = SA_RESTART, + struct sigaction *old_sa = NULL) { struct sigaction sa; @@ -93,7 +94,7 @@ installSignalHandler(int signal, void (*handler)(int sigtype), sa.sa_handler = handler; sa.sa_flags = flags; - if (sigaction(signal, &sa, NULL) == -1) + if (sigaction(signal, &sa, old_sa) == -1) panic("Failed to setup handler for signal %i\n", signal); } @@ -196,9 +197,6 @@ initSignals() // Dump intermediate stats and reset them installSignalHandler(SIGUSR2, dumprstStatsHandler); - // Exit cleanly on Interrupt (Ctrl-C) - installSignalHandler(SIGINT, exitNowHandler); - // Print the current cycle number and a backtrace on abort. Make // sure the signal is unmasked and the handler reset when a signal // is delivered to be able to invoke the default handler. @@ -218,4 +216,19 @@ initSignals() installSignalHandler(SIGIO, ioHandler); } +struct sigaction old_int_sa; + +void initSigInt() +{ + // Exit cleanly on Interrupt (Ctrl-C) + installSignalHandler(SIGINT, exitNowHandler, SA_RESTART, &old_int_sa); +} + +void restoreSigInt() +{ + // Restore the old SIGINT handler + sigaction(SIGINT, &old_int_sa, NULL); +} + + } // namespace gem5 diff --git a/src/sim/init_signals.hh b/src/sim/init_signals.hh index ea9f3d5229..2da3aae877 100644 --- a/src/sim/init_signals.hh +++ b/src/sim/init_signals.hh @@ -38,6 +38,10 @@ void exitNowHandler(int sigtype); void abortHandler(int sigtype); void initSignals(); +// separate out sigint handler so that we can restore the python one +void initSigInt(); +void restoreSigInt(); + } // namespace gem5 #endif // __SIM_INIT_SIGNALS_HH__ diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index abd2b1d391..6505f57904 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -50,6 +50,7 @@ #include "base/types.hh" #include "sim/async.hh" #include "sim/eventq.hh" +#include "sim/init_signals.hh" #include "sim/sim_events.hh" #include "sim/sim_exit.hh" #include "sim/stat_control.hh" @@ -187,6 +188,10 @@ GlobalSimLoopExitEvent *global_exit_event= nullptr; GlobalSimLoopExitEvent * simulate(Tick num_cycles) { + // install the sigint handler to catch ctrl-c and exit the sim loop cleanly + // Note: This should be done before initializing the threads + initSigInt(); + if (global_exit_event)//cleaning last global exit event global_exit_event->clean(); std::unique_ptr quantum_event; @@ -229,6 +234,9 @@ simulate(Tick num_cycles) Event *local_event = doSimLoop(mainEventQueue[0]); assert(local_event); + // Restore normal ctrl-c operation as soon as the event queue is done + restoreSigInt(); + inParallelMode = false; // locate the global exit event and return it to Python From a16fd8a592104528bfd89d6b54e6219d8024399b Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Thu, 30 Nov 2023 23:36:26 +0800 Subject: [PATCH 638/693] scons: Limit adding fastmodel files and libpath (#629) The change will only add include and library path if the fastmodel is required to build. The change will benefit for most of gem5 build. Change-Id: I98c20bd1470b7227940036199e02bc001e307eac --- src/arch/arm/fastmodel/CortexA76/SConscript | 3 +++ src/arch/arm/fastmodel/CortexR52/SConscript | 3 +++ src/arch/arm/fastmodel/GIC/SConscript | 3 +++ src/arch/arm/fastmodel/PL330_DMAC/SConscript | 3 +++ src/arch/arm/fastmodel/SConscript | 2 ++ src/arch/arm/fastmodel/iris/SConscript | 3 +++ src/arch/arm/fastmodel/reset_controller/SConscript | 3 +++ 7 files changed, 20 insertions(+) diff --git a/src/arch/arm/fastmodel/CortexA76/SConscript b/src/arch/arm/fastmodel/CortexA76/SConscript index f3c66063de..8ed2cce634 100644 --- a/src/arch/arm/fastmodel/CortexA76/SConscript +++ b/src/arch/arm/fastmodel/CortexA76/SConscript @@ -25,6 +25,9 @@ Import('*') +if not env['CONF']['USE_ARM_FASTMODEL']: + Return() + protocol_dir = Dir('..').Dir('protocol') for name in ('x1', 'x2', 'x3', 'x4'): diff --git a/src/arch/arm/fastmodel/CortexR52/SConscript b/src/arch/arm/fastmodel/CortexR52/SConscript index bf3df74483..1ecaad86da 100644 --- a/src/arch/arm/fastmodel/CortexR52/SConscript +++ b/src/arch/arm/fastmodel/CortexR52/SConscript @@ -25,6 +25,9 @@ Import('*') +if not env['CONF']['USE_ARM_FASTMODEL']: + Return() + protocol_dir = Dir('..').Dir('protocol') for name in ('x1', 'x2', 'x3', 'x4'): diff --git a/src/arch/arm/fastmodel/GIC/SConscript b/src/arch/arm/fastmodel/GIC/SConscript index c56ddd537f..db16c96da0 100644 --- a/src/arch/arm/fastmodel/GIC/SConscript +++ b/src/arch/arm/fastmodel/GIC/SConscript @@ -25,6 +25,9 @@ Import('*') +if not env['CONF']['USE_ARM_FASTMODEL']: + Return() + protocol_dir = Dir('..').Dir('protocol') ArmFastModelComponent(File('GIC.sgproj'), File('GIC.lisa'), diff --git a/src/arch/arm/fastmodel/PL330_DMAC/SConscript b/src/arch/arm/fastmodel/PL330_DMAC/SConscript index e93b45c1ff..3a68af21a3 100644 --- a/src/arch/arm/fastmodel/PL330_DMAC/SConscript +++ b/src/arch/arm/fastmodel/PL330_DMAC/SConscript @@ -25,6 +25,9 @@ Import('*') +if not env['CONF']['USE_ARM_FASTMODEL']: + Return() + protocol_dir = Dir('..').Dir('protocol') ArmFastModelComponent(File('PL330.sgproj'), File('PL330.lisa'), diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript index 16b2b02e3f..925520a01c 100644 --- a/src/arch/arm/fastmodel/SConscript +++ b/src/arch/arm/fastmodel/SConscript @@ -49,6 +49,8 @@ import os.path if env['CONF']['USE_ARM_FASTMODEL']: env.TagImplies('arm fastmodel', 'arm isa') +else: + Return() def extract_var(name): val = env['CONF'].get(name, None) diff --git a/src/arch/arm/fastmodel/iris/SConscript b/src/arch/arm/fastmodel/iris/SConscript index 33877195d9..f4d54faeb4 100644 --- a/src/arch/arm/fastmodel/iris/SConscript +++ b/src/arch/arm/fastmodel/iris/SConscript @@ -25,6 +25,9 @@ Import('*') +if not env['CONF']['USE_ARM_FASTMODEL']: + Return() + SimObject('Iris.py', sim_objects=[ 'IrisTLB', 'IrisMMU', 'IrisInterrupts', 'IrisISA', 'IrisBaseCPU'], tags='arm fastmodel') diff --git a/src/arch/arm/fastmodel/reset_controller/SConscript b/src/arch/arm/fastmodel/reset_controller/SConscript index 8e5de8ee8b..70ca576865 100644 --- a/src/arch/arm/fastmodel/reset_controller/SConscript +++ b/src/arch/arm/fastmodel/reset_controller/SConscript @@ -25,6 +25,9 @@ Import('*') +if not env['CONF']['USE_ARM_FASTMODEL']: + Return() + SimObject('FastModelResetControllerExample.py', sim_objects=[ 'FastModelResetControllerExample'], tags='arm fastmodel') From 62a2b6eed29e4120ffe6152c5e3161e5ac40aee4 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Thu, 30 Nov 2023 15:09:28 -0800 Subject: [PATCH 639/693] ext: Update readme for DRAMSys Specify the cmake version Change-Id: I8bbdb128667df37724c38caef5572d8fb1641ef5 --- ext/dramsys/README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/dramsys/README b/ext/dramsys/README index 1af3903b12..f7cac523b0 100644 --- a/ext/dramsys/README +++ b/ext/dramsys/README @@ -11,3 +11,6 @@ This is done by setting the value of the "StoreMode" key to "Store" in the base Those configuration file can be found in 'DRAMSys/library/resources/configs/simulator'. Currently, DRAMSys is only supported in conjunction with a cache. Running DRAMSys in Release mode without caches will silently fail! + +Note: DRAMSys requires cmake version >= 3.24. This is not available via apt on Ubuntu 20.04 or 22.04. +See `util/dockerfiles/ubuntu-20.04_all-dependencies/Dockerfile` for an example of how to install cmake 3.24. From 743b2aada6c0aa1868a756a85d7002f52e2d9947 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 29 Nov 2023 18:02:07 -0800 Subject: [PATCH 640/693] stdlib: Move resource download to `get_local_path` This change decouple's the downloading of a resource from it's data. With this change the `obtain_resource` function returns the `AbstractResource` implementation which contains the data. The resource itself (e.g., the actual disk image, binary, file, etc.) is only downloaded to the host system, if not already present, upon the `get_local_path` call. `get_local_path` is the function used by gem5 to ultimately load the resource into a simulation, therefore this change ensures we only download resources when they are loaded into a simulation. This change is not ideal and comes with the following caveats: 1. The `downloader` function is created in `obtain_workload` and passed to the `AbstractResource` implementation for later use. This function comes with the following requirements: * The function will download the resource to `local_path`. * The function will not re-download the resources if already present as this function is called _everytime_ `get_local_path` is called. 2. The directories needed to store `local_path` are created in `obtain_workload` regardless. Ergo even if the resource is not used and `get_local_path` is never called these directories are still created. Change-Id: I3f0e9a0099cba946630d719c3d17b7da0bccf74a --- src/python/gem5/resources/resource.py | 101 +++++++++++++++++++++----- 1 file changed, 81 insertions(+), 20 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index b5ece9dbb0..6966c8a7c6 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -27,6 +27,7 @@ import json import os from abc import ABCMeta +from functools import partial from pathlib import Path from typing import ( Any, @@ -94,6 +95,7 @@ class AbstractResource: local_path: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, ): """ :param local_path: The path on the host system where this resource is @@ -104,18 +106,17 @@ class AbstractResource: string should navigate users to where the source for this resource may be found. Not a required parameter. By default is None. :param resource_version: Version of the resource itself. + :param downloader: A partial function which is used to download the + resource. If set, this is called if the resource is not present at the + specified `local_path`. """ - if local_path and not os.path.exists(local_path): - raise Exception( - f"Local path specified for resource, '{local_path}', does not " - "exist." - ) self._id = id self._local_path = local_path self._description = description self._source = source self._version = resource_version + self._downloader = downloader def get_category_name(cls) -> str: raise NotImplementedError @@ -134,7 +135,19 @@ class AbstractResource: return self._version def get_local_path(self) -> Optional[str]: - """Returns the local path of the resource.""" + """Returns the local path of the resource. + + If specified the `downloader` partial function is called to download + the resource if it is not present or up-to-date at the specified + `local_path`. + """ + if self._downloader: + self._downloader() + if self._local_path and not os.path.exists(self._local_path): + raise Exception( + f"Local path specified for resource, '{self._local_path}', " + "does not exist." + ) return self._local_path def get_description(self) -> Optional[str]: @@ -158,24 +171,34 @@ class FileResource(AbstractResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): - if not os.path.isfile(local_path): - raise Exception( - f"FileResource path specified, '{local_path}', is not a file." - ) - super().__init__( local_path=local_path, id=id, description=description, source=source, resource_version=resource_version, + downloader=downloader, ) def get_category_name(cls) -> str: return "FileResource" + def get_local_path(self) -> Optional[str]: + # Here we override get_local_path to ensure the file exists. + file_path = super().get_local_path() + + if not file_path: + raise Exception("FileResource path not specified.") + + if not os.path.isfile(file_path): + raise Exception( + f"FileResource path specified, '{file_path}', is not a file." + ) + return file_path + class DirectoryResource(AbstractResource): """A resource consisting of a directory.""" @@ -187,25 +210,35 @@ class DirectoryResource(AbstractResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): - if not os.path.isdir(local_path): - raise Exception( - f"DirectoryResource path specified, {local_path}, is not a " - "directory." - ) - super().__init__( local_path=local_path, id=id, description=description, source=source, resource_version=resource_version, + downloader=downloader, ) def get_category_name(cls) -> str: return "DirectoryResource" + def get_local_path(self) -> Optional[str]: + # Here we override get_local_path to ensure the directory exists. + dir_path = super().get_local_path() + + if not dir_path: + raise Exception("DirectoryResource path not specified.") + + if not os.path.isdir(dir_path): + raise Exception( + f"DirectoryResource path specified, {dir_path}, is not a " + "directory." + ) + return dir_path + class DiskImageResource(FileResource): """A Disk Image resource.""" @@ -217,6 +250,7 @@ class DiskImageResource(FileResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, root_partition: Optional[str] = None, **kwargs, ): @@ -226,6 +260,7 @@ class DiskImageResource(FileResource): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) self._root_partition = root_partition @@ -247,6 +282,7 @@ class BinaryResource(FileResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, architecture: Optional[Union[ISA, str]] = None, **kwargs, ): @@ -256,6 +292,7 @@ class BinaryResource(FileResource): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) self._architecture = None @@ -283,6 +320,7 @@ class BootloaderResource(BinaryResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, architecture: Optional[Union[ISA, str]] = None, **kwargs, ): @@ -293,6 +331,7 @@ class BootloaderResource(BinaryResource): architecture=architecture, source=source, resource_version=resource_version, + downloader=downloader, ) def get_category_name(cls) -> str: @@ -309,6 +348,7 @@ class GitResource(DirectoryResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): super().__init__( @@ -317,6 +357,7 @@ class GitResource(DirectoryResource): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) def get_category_name(cls) -> str: @@ -333,6 +374,7 @@ class KernelResource(BinaryResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, architecture: Optional[Union[ISA, str]] = None, **kwargs, ): @@ -343,6 +385,7 @@ class KernelResource(BinaryResource): source=source, architecture=architecture, resource_version=resource_version, + downloader=downloader, ) def get_category_name(cls) -> str: @@ -364,6 +407,7 @@ class CheckpointResource(DirectoryResource): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): super().__init__( @@ -372,6 +416,7 @@ class CheckpointResource(DirectoryResource): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) def get_category_name(cls) -> str: @@ -396,6 +441,7 @@ class SimpointResource(AbstractResource): workload_name: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, local_path: Optional[str] = None, **kwargs, ): @@ -417,6 +463,7 @@ class SimpointResource(AbstractResource): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) self._weight_list = weight_list @@ -510,6 +557,7 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): resource_version: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): FileResource.__init__( @@ -519,6 +567,7 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) LooppointCsvLoader.__init__(self, pinpoints_file=Path(local_path)) @@ -535,6 +584,7 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): region_id: Optional[Union[str, int]] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): FileResource.__init__( @@ -544,6 +594,7 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): description=description, source=source, resource_version=resource_version, + downloader=downloader, ) LooppointJsonLoader.__init__( self, looppoint_file=local_path, region_id=region_id @@ -569,6 +620,7 @@ class SimpointDirectoryResource(SimpointResource): workload_name: Optional[str] = None, description: Optional[str] = None, source: Optional[str] = None, + downloader: Optional[partial] = None, **kwargs, ): """ @@ -601,6 +653,7 @@ class SimpointDirectoryResource(SimpointResource): id=id, description=description, source=source, + downloader=downloader, resource_version=resource_version, ) @@ -868,6 +921,10 @@ def obtain_resource( gem5_version=gem5_version, ) + # This is is used to store the partial function which is used to download + # the resource when the `get_local_path` function is called. + downloader: Optional[partial] = None + # If the "url" field is specified, the resoruce must be downloaded. if "url" in resource_json and resource_json["url"]: # If the `to_path` parameter is set, we use that as the path to which @@ -917,7 +974,8 @@ def obtain_resource( ) # Download the resource if it does not already exist. - get_resource( + downloader = partial( + get_resource, resource_name=resource_id, to_path=to_path, download_md5_mismatch=download_md5_mismatch, @@ -941,9 +999,10 @@ def obtain_resource( return DiskImageResource( local_path=to_path, root_partition=root_partition, + downloader=downloader, **resource_json, ) - return CustomResource(local_path=to_path) + return CustomResource(local_path=to_path, downloader=downloader) assert resources_category in _get_resource_json_type_map resource_class = _get_resource_json_type_map[resources_category] @@ -991,7 +1050,9 @@ def obtain_resource( # Once we know what AbstractResource subclass we are using, we create it. # The fields in the JSON object are assumed to map like-for-like to the # subclass contructor, so we can pass the resource_json map directly. - return resource_class(local_path=to_path, **resource_json) + return resource_class( + local_path=to_path, downloader=downloader, **resource_json + ) def _get_default_resource_dir() -> str: From bbe5216d882257cb794f3e33c407a6078556c0f8 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Fri, 1 Dec 2023 01:13:36 +0000 Subject: [PATCH 641/693] arch-riscv: Rename BootloaderKernelWorkload parameters The gem5 standard library hardcoded some parameters of the workload. E.g., the kernel filename must be `object_file`. Change-Id: I5eeb7359be399138693eaba0738eaf524c59408f Signed-off-by: Hoa Nguyen --- src/arch/riscv/RiscvFsWorkload.py | 6 ++---- src/arch/riscv/linux/fs_workload.cc | 8 ++++---- src/arch/riscv/linux/fs_workload.hh | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/arch/riscv/RiscvFsWorkload.py b/src/arch/riscv/RiscvFsWorkload.py index 36580a5498..467d7ec26a 100644 --- a/src/arch/riscv/RiscvFsWorkload.py +++ b/src/arch/riscv/RiscvFsWorkload.py @@ -67,9 +67,7 @@ class RiscvBootloaderKernelWorkload(Workload): bootloader_addr = Param.Addr( 0x0, "Where to place the bootloader in memory." ) - kernel_filename = Param.String( - "", "vmlinux file. Don't use kernel if empty." - ) + object_file = Param.String("", "vmlinux file. Don't use kernel if empty.") kernel_addr = Param.Addr( 0x80200000, "Where to place the kernel in memory. Typically, after the first " @@ -85,6 +83,6 @@ class RiscvBootloaderKernelWorkload(Workload): dtb_addr = Param.Addr(0x87E00000, "Where to place the DTB in memory.") # booting parameters - boot_args = Param.String( + command_line = Param.String( "", "Booting arguments, to be passed to the kernel" ) diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index 2946d6c324..2b36f0aaa5 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -97,8 +97,8 @@ BootloaderKernelWorkload::loadBootloaderSymbolTable() void BootloaderKernelWorkload::loadKernelSymbolTable() { - if (params().kernel_filename != "") { - kernel = loader::createObjectFile(params().kernel_filename); + if (params().object_file != "") { + kernel = loader::createObjectFile(params().object_file); kernelSymbolTable = kernel->symtab(); auto renamedKernelSymbolTable = \ kernelSymbolTable.functionSymbols()->rename( @@ -131,7 +131,7 @@ BootloaderKernelWorkload::loadBootloader() void BootloaderKernelWorkload::loadKernel() { - if (params().kernel_filename != "") { + if (params().object_file != "") { Addr kernel_paddr_offset = params().kernel_addr; kernel->buildImage().offset(kernel_paddr_offset).write( system->physProxy @@ -139,7 +139,7 @@ BootloaderKernelWorkload::loadKernel() delete kernel; inform("Loaded kernel \'%s\' at 0x%llx\n", - params().kernel_filename, + params().object_file, kernel_paddr_offset); } else { inform("Kernel is not specified.\n"); diff --git a/src/arch/riscv/linux/fs_workload.hh b/src/arch/riscv/linux/fs_workload.hh index a0366a27c4..95269e6f93 100644 --- a/src/arch/riscv/linux/fs_workload.hh +++ b/src/arch/riscv/linux/fs_workload.hh @@ -81,7 +81,7 @@ class BootloaderKernelWorkload: public Workload public: PARAMS(RiscvBootloaderKernelWorkload); BootloaderKernelWorkload(const Params &p) - : Workload(p), entryPoint(p.entry_point), bootArgs(p.boot_args) + : Workload(p), entryPoint(p.entry_point), bootArgs(p.command_line) { loadBootloaderSymbolTable(); loadKernelSymbolTable(); From be3163a07208fecdd7791f26ed6de2dec11b62e1 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Fri, 1 Dec 2023 01:16:24 +0000 Subject: [PATCH 642/693] stdlib: Integrate BootloaderKernelWorkload Change-Id: Ifeaa98059d5667c3335eaccd57a5295f44f88e43 Signed-off-by: Hoa Nguyen --- .../components/boards/kernel_disk_workload.py | 3 ++- src/python/gem5/components/boards/riscv_board.py | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 16c196208b..db86133fd8 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -201,8 +201,9 @@ class KernelDiskWorkload: # implementation of the ArmBoard class expects a boot loader file to be # provided along with the kernel and the disk image. + self._bootloader = [] if bootloader is not None: - self._bootloader = [bootloader.get_local_path()] + self._bootloader.append(bootloader.get_local_path()) # Set the readfile. if readfile: diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 0ce9d0192b..3675708879 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -42,7 +42,7 @@ from m5.objects import ( PMAChecker, Port, RawDiskImage, - RiscvLinux, + RiscvBootloaderKernelWorkload, RiscvMmioVirtIO, RiscvRTC, VirtIOBlock, @@ -97,7 +97,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): @overrides(AbstractSystemBoard) def _setup_board(self) -> None: - self.workload = RiscvLinux() + self.workload = RiscvBootloaderKernelWorkload() # Contains a CLINT, PLIC, UART, and some functions for the dtb, etc. self.platform = HiFive() @@ -488,6 +488,18 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): def get_disk_device(self): return "/dev/vda" + @overrides(AbstractSystemBoard) + def _pre_instantiate(self): + if len(self._bootloader) > 0: + self.workload.bootloader_addr = 0x0 + self.workload.bootloader_filename = self._bootloader[0] + self.workload.kernel_addr = 0x80200000 + self.workload.entry_point = 0x80000000 # Bootloader starting point + else: + self.workload.kernel_addr = 0x0 + self.workload.entry_point = 0x80000000 + self._connect_things() + @overrides(KernelDiskWorkload) def _add_disk_to_board(self, disk_image: AbstractResource): image = CowDiskImage( From 0a2f9d4b1830a4d286986cf29a23ca9a97bec99b Mon Sep 17 00:00:00 2001 From: Matt Sinclair Date: Fri, 1 Dec 2023 12:15:47 -0600 Subject: [PATCH 643/693] mem-ruby: update CacheMemory RubyCache debug prints Update the RubyCache debug flag prints in CacheMemory to be more descriptive and make clearer what is happening in a given function. This makes it easier to determine what is happening when looking at the RubyCache debug flags prints. Change-Id: Ieee172b6df0d100f4b1e8fe4bba872fc9cf65854 --- src/mem/ruby/structures/CacheMemory.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/mem/ruby/structures/CacheMemory.cc b/src/mem/ruby/structures/CacheMemory.cc index 3b97d34d18..90d67fb29b 100644 --- a/src/mem/ruby/structures/CacheMemory.cc +++ b/src/mem/ruby/structures/CacheMemory.cc @@ -188,7 +188,7 @@ bool CacheMemory::tryCacheAccess(Addr address, RubyRequestType type, DataBlock*& data_ptr) { - DPRINTF(RubyCache, "address: %#x\n", address); + DPRINTF(RubyCache, "trying to access address: %#x\n", address); AbstractCacheEntry* entry = lookup(address); if (entry != nullptr) { // Do we even have a tag match? @@ -197,14 +197,20 @@ CacheMemory::tryCacheAccess(Addr address, RubyRequestType type, data_ptr = &(entry->getDataBlk()); if (entry->m_Permission == AccessPermission_Read_Write) { + DPRINTF(RubyCache, "Have permission to access address: %#x\n", + address); return true; } if ((entry->m_Permission == AccessPermission_Read_Only) && (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) { + DPRINTF(RubyCache, "Have permission to access address: %#x\n", + address); return true; } // The line must not be accessible } + DPRINTF(RubyCache, "Do not have permission to access address: %#x\n", + address); data_ptr = NULL; return false; } @@ -213,7 +219,7 @@ bool CacheMemory::testCacheAccess(Addr address, RubyRequestType type, DataBlock*& data_ptr) { - DPRINTF(RubyCache, "address: %#x\n", address); + DPRINTF(RubyCache, "testing address: %#x\n", address); AbstractCacheEntry* entry = lookup(address); if (entry != nullptr) { // Do we even have a tag match? @@ -221,9 +227,14 @@ CacheMemory::testCacheAccess(Addr address, RubyRequestType type, entry->setLastAccess(curTick()); data_ptr = &(entry->getDataBlk()); + DPRINTF(RubyCache, "have permission for address %#x?: %d\n", + address, + entry->m_Permission != AccessPermission_NotPresent); return entry->m_Permission != AccessPermission_NotPresent; } + DPRINTF(RubyCache, "do not have permission for address %#x\n", + address); data_ptr = NULL; return false; } @@ -273,7 +284,7 @@ CacheMemory::allocate(Addr address, AbstractCacheEntry *entry) assert(address == makeLineAddress(address)); assert(!isTagPresent(address)); assert(cacheAvail(address)); - DPRINTF(RubyCache, "address: %#x\n", address); + DPRINTF(RubyCache, "allocating address: %#x\n", address); // Find the first open slot int64_t cacheSet = addressToCacheSet(address); @@ -311,7 +322,7 @@ CacheMemory::allocate(Addr address, AbstractCacheEntry *entry) void CacheMemory::deallocate(Addr address) { - DPRINTF(RubyCache, "address: %#x\n", address); + DPRINTF(RubyCache, "deallocating address: %#x\n", address); AbstractCacheEntry* entry = lookup(address); assert(entry != nullptr); m_replacementPolicy_ptr->invalidate(entry->replacementData); From d96b6cdae7e956d6ed248a2b9285953b8116d7bd Mon Sep 17 00:00:00 2001 From: Ivana Mitrovic Date: Fri, 1 Dec 2023 11:43:49 -0800 Subject: [PATCH 644/693] misc, stdlib: Update documentation to adhere to RST formatting. (#631) This PR updates files in `src/python` to adhere to reStructuredText formatting. --- .../gem5/components/boards/abstract_board.py | 84 ++++--- .../boards/abstract_system_board.py | 4 +- .../gem5/components/boards/arm_board.py | 19 +- .../boards/experimental/lupv_board.py | 12 +- .../components/boards/kernel_disk_workload.py | 74 +++--- src/python/gem5/components/boards/mem_mode.py | 4 +- .../gem5/components/boards/riscv_board.py | 12 +- .../components/boards/se_binary_workload.py | 42 ++-- .../gem5/components/boards/simple_board.py | 4 +- .../gem5/components/boards/test_board.py | 2 +- .../gem5/components/boards/x86_board.py | 10 +- .../abstract_cache_hierarchy.py | 8 +- .../abstract_two_level_cache_hierarchy.py | 12 - .../chi/nodes/memory_controller.py | 3 +- .../chi/private_l1_cache_hierarchy.py | 2 +- .../classic/caches/l1dcache.py | 4 +- .../classic/caches/l1icache.py | 2 +- .../classic/caches/mmu_cache.py | 2 +- .../cachehierarchies/classic/no_cache.py | 31 +-- .../classic/private_l1_cache_hierarchy.py | 4 +- .../private_l1_private_l2_cache_hierarchy.py | 13 +- .../private_l1_shared_l2_cache_hierarchy.py | 4 +- .../memory/abstract_memory_system.py | 10 +- .../components/memory/dram_interfaces/ddr3.py | 2 +- .../components/memory/dram_interfaces/ddr4.py | 16 +- .../components/memory/dram_interfaces/gddr.py | 4 +- .../components/memory/dram_interfaces/hbm.py | 26 +- .../components/memory/dram_interfaces/hmc.py | 15 +- .../memory/dram_interfaces/lpddr2.py | 2 +- .../memory/dram_interfaces/lpddr3.py | 2 +- .../memory/dram_interfaces/lpddr5.py | 42 ++-- .../memory/dram_interfaces/wideio.py | 2 +- .../gem5/components/memory/dramsim_3.py | 4 +- src/python/gem5/components/memory/hbm.py | 15 +- src/python/gem5/components/memory/memory.py | 15 +- .../gem5/components/memory/multi_channel.py | 6 +- .../gem5/components/memory/single_channel.py | 12 +- .../components/processors/abstract_core.py | 38 +-- .../processors/abstract_generator.py | 7 +- .../processors/abstract_generator_core.py | 3 +- .../processors/abstract_processor.py | 5 +- .../processors/base_cpu_processor.py | 1 - .../processors/complex_generator.py | 28 ++- .../processors/complex_generator_core.py | 76 +++--- .../gem5/components/processors/cpu_types.py | 2 +- .../components/processors/gups_generator.py | 10 +- .../processors/gups_generator_ep.py | 10 +- .../processors/gups_generator_par.py | 10 +- .../components/processors/linear_generator.py | 13 +- .../processors/linear_generator_core.py | 13 +- .../components/processors/random_generator.py | 13 +- .../processors/random_generator_core.py | 13 +- .../gem5/components/processors/simple_core.py | 4 +- .../components/processors/simple_processor.py | 9 +- .../processors/simple_switchable_processor.py | 14 +- .../processors/switchable_processor.py | 2 +- .../processors/traffic_generator.py | 4 +- .../processors/traffic_generator_core.py | 4 +- src/python/gem5/isas.py | 9 +- .../gem5/prebuilt/demo/x86_demo_board.py | 10 +- .../riscvmatched/riscvmatched_board.py | 14 +- .../riscvmatched/riscvmatched_cache.py | 5 +- .../riscvmatched/riscvmatched_core.py | 9 +- src/python/gem5/resources/client.py | 28 ++- .../resources/client_api/abstract_client.py | 39 +-- .../gem5/resources/client_api/atlasclient.py | 1 + .../resources/client_api/client_wrapper.py | 61 +++-- .../gem5/resources/client_api/jsonclient.py | 1 + src/python/gem5/resources/downloader.py | 66 ++--- src/python/gem5/resources/elfie.py | 5 +- src/python/gem5/resources/looppoint.py | 92 +++---- src/python/gem5/resources/md5_utils.py | 12 +- src/python/gem5/resources/resource.py | 194 ++++++++------- src/python/gem5/resources/workload.py | 18 +- src/python/gem5/runtime.py | 8 +- src/python/gem5/simulate/exit_event.py | 7 +- .../gem5/simulate/exit_event_generators.py | 29 ++- src/python/gem5/simulate/simulator.py | 227 ++++++++++-------- src/python/gem5/utils/filelock.py | 11 +- .../utils/multiprocessing/_command_line.py | 2 +- src/python/gem5/utils/override.py | 1 + src/python/gem5/utils/progress_bar.py | 2 +- src/python/gem5/utils/requires.py | 6 +- src/python/gem5/utils/simpoint.py | 48 ++-- src/python/m5/SimObject.py | 1 - src/python/m5/ext/pystats/abstract_stat.py | 34 +-- src/python/m5/ext/pystats/jsonloader.py | 26 +- .../m5/ext/pystats/serializable_stat.py | 79 +++--- src/python/m5/ext/pystats/statistic.py | 12 +- src/python/m5/simulate.py | 26 +- src/python/m5/stats/gem5stats.py | 70 ++---- src/python/m5/util/attrdict.py | 2 +- 92 files changed, 1039 insertions(+), 920 deletions(-) diff --git a/src/python/gem5/components/boards/abstract_board.py b/src/python/gem5/components/boards/abstract_board.py index 7d251e8296..d3c01e21f8 100644 --- a/src/python/gem5/components/boards/abstract_board.py +++ b/src/python/gem5/components/boards/abstract_board.py @@ -59,7 +59,7 @@ class AbstractBoard: Boards are used as the object which can connect together all other components. This abstract class defines the external interface that other boards must provide. Boards can be specialized for different ISAs or system - designs (e.g., core counts, cache types, memory channels, I/O devices, etc) + designs (e.g., core counts, cache types, memory channels, I/O devices, etc). In addition to providing the place that system components are connected, the board also exposes an interface for the caches, processor, and memory @@ -68,7 +68,7 @@ class AbstractBoard: The board also exposes an interface to set up I/O devices which needs to be specialized for each ISA and/or platform. - Board inherits from System and can therefore be used as a System simobject + Board inherits from System and can therefore be used as a System SimObject when required. """ @@ -87,7 +87,7 @@ class AbstractBoard: :param memory: The memory for this board. :param cache_hierarchy: The Cache Hierarchy for this board. In some boards caches can be optional. If so, - that board must override `_connect_things`. + that board must override ``_connect_things``. """ if not isinstance(self, System): @@ -143,8 +143,10 @@ class AbstractBoard: def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]: """Get the memory ports exposed on this board - Note: The ports should be returned such that the address ranges are - in ascending order. + .. note:: + + The ports should be returned such that the address ranges are + in ascending order. """ return self.get_memory().get_mem_ports() @@ -175,6 +177,7 @@ class AbstractBoard: def get_clock_domain(self) -> ClockDomain: """Get the clock domain. + :returns: The clock domain. """ return self.clk_domain @@ -192,7 +195,7 @@ class AbstractBoard: def is_fullsystem(self) -> bool: """ - Returns True if the board is to be run in FS mode. Otherwise the board + Returns ``True`` if the board is to be run in FS mode. Otherwise the board is to be run in Se mode. An exception will be thrown if this has not been set. @@ -213,10 +216,10 @@ class AbstractBoard: Set the workload for this board to run. This function will take the workload specified and run the correct - workload function (e.g., `set_kernel_disk_workload`) with the correct + workload function (e.g., ``set_kernel_disk_workload``) with the correct parameters - :params workload: The workload to be set to this board. + :param workload: The workload to be set to this board. """ try: @@ -244,7 +247,7 @@ class AbstractBoard: """ This function is called in the AbstractBoard constructor, before the memory, processor, and cache hierarchy components are incorporated via - `_connect_thing()`, but after the `_setup_memory_ranges()` function. + ``_connect_thing()``, but after the ``_setup_memory_ranges()`` function. This function should be overridden by boards to specify components, connections unique to that board. """ @@ -257,7 +260,7 @@ class AbstractBoard: def has_dma_ports(self) -> bool: """Determine whether the board has DMA ports or not. - :returns: True if the board has DMA ports, otherwise False. + :returns: ``True`` if the board has DMA ports, otherwise ``False``. """ raise NotImplementedError @@ -276,13 +279,14 @@ class AbstractBoard: def has_io_bus(self) -> bool: """Determine whether the board has an IO bus or not. - :returns: True if the board has an IO bus, otherwise False. + :returns: ``True`` if the board has an IO bus, otherwise ``False``. """ raise NotImplementedError @abstractmethod def get_io_bus(self) -> IOXBar: """Get the board's IO Bus. + This abstract method must be implemented within the subclasses if they support DMA and/or full system simulation. @@ -299,14 +303,15 @@ class AbstractBoard: def has_coherent_io(self) -> bool: """Determine whether the board needs coherent I/O - :returns: True if the board needs coherent I/O, false otherwise + :returns: ``True`` if the board needs coherent I/O, ``False`` otherwise. """ raise NotImplementedError @abstractmethod def get_mem_side_coherent_io_port(self): """Get the memory-side coherent I/O port. - This abstract method must be implemented if has_coherent_io is true. + + This abstract method must be implemented if ``has_coherent_io`` is ``True``. This returns a *port* (not a bus) that should be connected to a CPU-side port for which coherent I/O (DMA) is issued. @@ -318,8 +323,8 @@ class AbstractBoard: """ Set the memory ranges for this board and memory system. - This is called in the constructor, prior to `_setup_board` and - `_connect_things`. It should query the board's memory to determine the + This is called in the constructor, prior to ``_setup_board`` and + ``_connect_things``. It should query the board's memory to determine the size and the set the memory ranges on the memory system and on the board. @@ -327,11 +332,11 @@ class AbstractBoard: of memory and memory system's range to be the same as the board. Full system implementations will likely need something more complicated. - Notes - ----- - * This *must* be called prior to the incorporation of the cache - hierarchy (via `_connect_things`) as cache hierarchies depend upon - knowing the memory system's ranges. + .. note:: + + This *must* be called prior to the incorporation of the cache + hierarchy (via ``_connect_things``) as cache hierarchies depend upon + knowing the memory system's ranges. """ raise NotImplementedError @@ -346,14 +351,13 @@ class AbstractBoard: Developers may build upon this assumption when creating components. - Notes - ----- + .. note:: - * The processor is incorporated after the cache hierarchy due to a bug - noted here: https://gem5.atlassian.net/browse/GEM5-1113. Until this - bug is fixed, this ordering must be maintained. - * Once this function is called `_connect_things_called` *must* be set - to `True`. + * The processor is incorporated after the cache hierarchy due to a bug + noted here: https://gem5.atlassian.net/browse/GEM5-1113. Until this + bug is fixed, this ordering must be maintained. + * Once this function is called ``_connect_things_called`` *must* be set + to ``True``. """ if self._connect_things_called: @@ -374,15 +378,15 @@ class AbstractBoard: self._connect_things_called = True def _post_instantiate(self): - """Called to set up anything needed after m5.instantiate""" + """Called to set up anything needed after ``m5.instantiate``.""" self.get_processor()._post_instantiate() if self.get_cache_hierarchy(): self.get_cache_hierarchy()._post_instantiate() self.get_memory()._post_instantiate() def _pre_instantiate(self): - """To be called immediately before m5.instantiate. This is where - `_connect_things` is executed by default.""" + """To be called immediately before ``m5.instantiate``. This is where + ``_connect_things`` is executed by default.""" # Connect the memory, processor, and cache hierarchy. self._connect_things() @@ -392,28 +396,28 @@ class AbstractBoard: Here we check that connect things has been called and throw an Exception if it has not. - Since v22.1 `_connect_things` function has + Since v22.1 ``_connect_things`` function has been moved from the AbstractBoard constructor to the - `_pre_instantation` function. Users who have used the gem5 stdlib + ``_pre_instantation`` function. Users who have used the gem5 stdlib components (i.e., boards which inherit from AbstractBoard) and the Simulator module should notice no change. Those who do not use the - Simulator module and instead called `m5.instantiate` directly must - call `AbstractBoard._pre_instantation` prior so `_connect_things` is + Simulator module and instead called ``m5.instantiate`` directly must + call ``AbstractBoard._pre_instantation`` prior to ``_connect_things`` is called. In order to avoid confusion, this check has been incorporated and the Exception thrown explains the fix needed to convert old scripts - to function with v22.1. + to function with `v22.1`. - This function is called in `AbstractSystemBoard.createCCObject` and - ArmBoard.createCCObject`. Both these functions override - `SimObject.createCCObject`. We can not do that here as AbstractBoard + This function is called in ``AbstractSystemBoard.createCCObject`` and + ``ArmBoard.createCCObject``. Both these functions override + ``SimObject.createCCObject``. We can not do that here as AbstractBoard does not inherit form System. """ if not self._connect_things_called: raise Exception( """ -AbstractBoard's `_connect_things` function has not been called. This is likely +AbstractBoard's ``_connect_things`` function has not been called. This is likely due to not running a board outside of the gem5 Standard Library Simulator module. If this is the case, this can be resolved by calling -`._pre_instantiate()` prior to `m5.instantiate()`. +``._pre_instantiate()`` prior to ``m5.instantiate()``. """ ) diff --git a/src/python/gem5/components/boards/abstract_system_board.py b/src/python/gem5/components/boards/abstract_system_board.py index 471a9458cd..8fe48920b5 100644 --- a/src/python/gem5/components/boards/abstract_system_board.py +++ b/src/python/gem5/components/boards/abstract_system_board.py @@ -61,8 +61,8 @@ class AbstractSystemBoard(System, AbstractBoard): @overrides(SimObject) def createCCObject(self): - """We override this function as it is called in `m5.instantiate`. This - means we can insert a check to ensure the `_connect_things` function + """We override this function as it is called in ``m5.instantiate``. This + means we can insert a check to ensure the ``_connect_things`` function has been run. """ super()._connect_things_check() diff --git a/src/python/gem5/components/boards/arm_board.py b/src/python/gem5/components/boards/arm_board.py index e976d71836..c60761c16d 100644 --- a/src/python/gem5/components/boards/arm_board.py +++ b/src/python/gem5/components/boards/arm_board.py @@ -194,7 +194,7 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): def _setup_io_devices(self) -> None: """ - This method first sets up the platform. ARM uses `realview` platform. + This method first sets up the platform. ARM uses ``realview`` platform. Most of the on-chip and off-chip devices are setup by the realview platform. Once realview is setup, we connect the I/O devices to the I/O bus. @@ -334,16 +334,19 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): self.generateDtb(self._get_dtb_filename()) def _get_dtb_filename(self) -> str: - """Returns the dtb file location. + """Returns the ``dtb`` file location. - **Note**: This may be the _expected_ file location when generated. A - file may not exist at this location when this function is called.""" + .. note:: + + This may be the ``_expected_`` file location when generated. A + file may not exist at this location when this function is called. + """ return os.path.join(m5.options.outdir, "device.dtb") def _add_pci_device(self, pci_device: PciVirtIO) -> None: """Attaches the PCI Device to the board. All devices will be added to - `self.pci_device` as a pre-instantiation setup. + ``self.pci_device`` as a pre-instantiation setup. :param pci_device: The PCI Device to add. """ @@ -374,7 +377,7 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): def _setup_memory_ranges(self) -> None: """ The ArmBoard's memory can only be setup after realview is setup. We set - this up in the `_setup_board` function. + this up in the ``_setup_board`` function. """ pass @@ -393,8 +396,8 @@ class ArmBoard(ArmSystem, AbstractBoard, KernelDiskWorkload): @overrides(SimObject) def createCCObject(self): - """We override this function as it is called in `m5.instantiate`. This - means we can insert a check to ensure the `_connect_things` function + """We override this function as it is called in ``m5.instantiate``. This + means we can insert a check to ensure the ``_connect_things`` function has been run. """ super()._connect_things_check() diff --git a/src/python/gem5/components/boards/experimental/lupv_board.py b/src/python/gem5/components/boards/experimental/lupv_board.py index a27d57e902..2448ede45e 100644 --- a/src/python/gem5/components/boards/experimental/lupv_board.py +++ b/src/python/gem5/components/boards/experimental/lupv_board.py @@ -216,7 +216,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): ] def _setup_io_devices(self) -> None: - """Connect the I/O devices to the I/O bus""" + """Connect the I/O devices to the I/O bus.""" for device in self._off_chip_devices: device.pio = self.iobus.mem_side_ports self.lupio_blk.dma = self.iobus.cpu_side_ports @@ -234,7 +234,7 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): ] def _setup_pma(self) -> None: - """Set the PMA devices on each core""" + """Set the PMA devices on each core.""" uncacheable_range = [ AddrRange(dev.pio_addr, size=dev.pio_size) for dev in self._on_chip_devices + self._off_chip_devices @@ -278,9 +278,11 @@ class LupvBoard(AbstractSystemBoard, KernelDiskWorkload): memory.set_memory_range(self.mem_ranges) def _generate_device_tree(self, outdir: str) -> None: - """Creates the dtb and dts files. - Creates two files in the outdir: 'device.dtb' and 'device.dts' - :param outdir: Directory to output the files + """Creates the ``dtb`` and ``dts`` files. + + Creates two files in the outdir: ``device.dtb`` and ``device.dts``. + + :param outdir: Directory to output the files. """ state = FdtState(addr_cells=2, size_cells=2, cpu_cells=1) root = FdtNode("/") diff --git a/src/python/gem5/components/boards/kernel_disk_workload.py b/src/python/gem5/components/boards/kernel_disk_workload.py index 16c196208b..f0b0b0ff1a 100644 --- a/src/python/gem5/components/boards/kernel_disk_workload.py +++ b/src/python/gem5/components/boards/kernel_disk_workload.py @@ -53,25 +53,25 @@ class KernelDiskWorkload: added as a superclass to a board and the abstract methods implemented. E.g.: - ``` - class X86Board(AbstractBoard, KernelDiskWorkload): - ... - @overrides(KernelDiskWorkload) - def get_default_kernel_args(self) -> List[str]: - return [ - "earlyprintk=ttyS0", - "console=ttyS0", - "lpj=7999923", - "root={root_value}", - ] - ... - ``` + .. code-block:: python - Notes - ----- + class X86Board(AbstractBoard, KernelDiskWorkload): + ... + @overrides(KernelDiskWorkload) + def get_default_kernel_args(self) -> List[str]: + return [ + "earlyprintk=ttyS0", + "console=ttyS0", + "lpj=7999923", + "root={root_value}", + ] + ... - * This assumes only one disk is set. - * This assumes the Linux kernel is used. + + .. note:: + + * This assumes only one disk is set. + * This assumes the Linux kernel is used. """ @abstractmethod @@ -79,9 +79,9 @@ class KernelDiskWorkload: """ Returns a default list of arguments for the workload kernel. We assume the following strings may be used as placeholders, to be replaced when - `set_kernel_disk_workload` is executed: + ``set_kernel_disk_workload`` is executed: - * `{root_value}` : set to `get_default_kernel_root_val()`. + * `{root_value}` : set to ``get_default_kernel_root_val()``. :returns: A default list of arguments for the workload kernel. """ @@ -101,8 +101,10 @@ class KernelDiskWorkload: """ Sets the configuration needed to add the disk image to the board. - **Note:** This will be executed at the end of the - `set_kernel_disk_workload` function. + .. note:: + + This will be executed at the end of the + ``set_kernel_disk_workload`` function. :param disk_image: The disk image to add to the system. """ @@ -124,14 +126,14 @@ class KernelDiskWorkload: ) -> str: """ Get the default kernel root value to be passed to the kernel. This is - determined by the value implemented in the `get_disk_device()` + determined by the value implemented in the ``get_disk_device()`` function, and the disk image partition, obtained from - `get_disk_root_partition()` - + ``get_disk_root_partition()`` :param disk_image: The disk image to be added to the system. - :returns: The default value for the 'root' argument to be passed to the - kernel. + + :returns: The default value for the ``root`` argument to be passed to the + kernel. """ return self.get_disk_device() + ( self.get_disk_root_partition(disk_image) or "" @@ -156,19 +158,23 @@ class KernelDiskWorkload: :param kernel: The kernel to boot. :param disk_image: The disk image to mount. :param bootloader: The current implementation of the ARM board requires - three resources to operate -- kernel, disk image, and, a bootloader. + three resources to operate -- kernel, disk image, + and, a bootloader. :param readfile: An optional parameter stating the file to be read by - by `m5 readfile`. + by ``m5 readfile``. :param readfile_contents: An optional parameter stating the contents of - the readfile file. If set with `readfile`, the contents of `readfile` - will be overwritten with `readfile_contents`, otherwise a new file will - be created with the value of `readfile_contents`. + the readfile file. If set with ``readfile``, + the contents of `readfile` will be overwritten + with ``readfile_contents``, otherwise a new file + will be created with the value of + ``readfile_contents``. :param kernel_args: An optional parameter for setting arguments to be - passed to the kernel. By default set to `get_default_kernel_args()`. + passed to the kernel. By default set to + ``get_default_kernel_args()``. :param exit_on_work_items: Whether the simulation should exit on work - items. True by default. + items. ``True`` by default. :param checkpoint: The checkpoint directory. Used to restore the - simulation to that checkpoint. + simulation to that checkpoint. """ # We assume this this is in a multiple-inheritance setup with an diff --git a/src/python/gem5/components/boards/mem_mode.py b/src/python/gem5/components/boards/mem_mode.py index c1e1baca8a..c794b01673 100644 --- a/src/python/gem5/components/boards/mem_mode.py +++ b/src/python/gem5/components/boards/mem_mode.py @@ -38,10 +38,10 @@ class MemMode(Enum): def mem_mode_to_string(mem_mode: MemMode) -> str: """ - Returns the string form of the mem_mode, compatible with the gem5 + Returns the string form of the ``mem_mode``, compatible with the gem5 simulator. - :returns: The string form of the mem_mode + :returns: The string form of the ``mem_mode``. """ if mem_mode == MemMode.TIMING: return "timing" diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index 0ce9d0192b..f032388571 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -69,7 +69,7 @@ from .kernel_disk_workload import KernelDiskWorkload class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): """ - A board capable of full system simulation for RISC-V + A board capable of full system simulation for RISC-V. At a high-level, this is based on the HiFive Unmatched board from SiFive. @@ -138,7 +138,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): self._off_chip_devices = [self.platform.uart, self.disk, self.rng] def _setup_io_devices(self) -> None: - """Connect the I/O devices to the I/O bus""" + """Connect the I/O devices to the I/O bus.""" # Add PCI self.platform.pci_host.pio = self.iobus.mem_side_ports @@ -177,7 +177,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): self.bridge.ranges.append(AddrRange(0x40000000, size="512MB")) def _setup_pma(self) -> None: - """Set the PMA devices on each core""" + """Set the PMA devices on each core.""" uncacheable_range = [ AddrRange(dev.pio_addr, size=dev.pio_size) @@ -230,11 +230,11 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): memory.set_memory_range(self.mem_ranges) def generate_device_tree(self, outdir: str) -> None: - """Creates the dtb and dts files. + """Creates the ``dtb`` and ``dts`` files. - Creates two files in the outdir: 'device.dtb' and 'device.dts' + Creates two files in the outdir: ``device.dtb`` and ``device.dts``. - :param outdir: Directory to output the files + :param outdir: Directory to output the files. """ state = FdtState(addr_cells=2, size_cells=2, cpu_cells=1) diff --git a/src/python/gem5/components/boards/se_binary_workload.py b/src/python/gem5/components/boards/se_binary_workload.py index 0c13ffedd1..4db4e008ba 100644 --- a/src/python/gem5/components/boards/se_binary_workload.py +++ b/src/python/gem5/components/boards/se_binary_workload.py @@ -57,13 +57,15 @@ class SEBinaryWorkload: This class is used to enable simple Syscall-Execution (SE) mode execution of a binary. - For this to function correctly the SEBinaryWorkload class should be added + For this to function correctly the `SEBinaryWorkload` class should be added as a superclass to a board (i.e., something that inherits from - AbstractBoard). + `AbstractBoard`). - **Important Notes:** At present this implementation is limited. A single - process is added to all cores as the workload. Therefore, despite allowing - for multi-core setups, multi-program workloads are not presently supported. + .. note:: + + At present this implementation is limited. A single + process is added to all cores as the workload. Therefore, despite allowing + for multi-core setups, multi-program workloads are not presently supported. """ def set_se_binary_workload( @@ -85,14 +87,14 @@ class SEBinaryWorkload: :param binary: The resource encapsulating the binary to be run. :param exit_on_work_items: Whether the simulation should exit on work - items. True by default. + items. ``True`` by default. :param stdin_file: The input file for the binary :param stdout_file: The output file for the binary :param stderr_file: The error output file for the binary :param env_list: The environment variables defined for the binary :param arguments: The input arguments for the binary :param checkpoint: The checkpoint directory. Used to restore the - simulation to that checkpoint. + simulation to that checkpoint. """ # We assume this this is in a multiple-inheritance setup with an @@ -166,15 +168,17 @@ class SEBinaryWorkload: * Dynamically linked executables are partially supported when the host ISA and the simulated ISA are the same. - **Warning:** Simpoints only works with one core + .. warning:: + + SimPoints only works with one core :param binary: The resource encapsulating the binary to be run. - :param arguments: The input arguments for the binary + :param arguments: The input arguments for the binary. :param simpoint: The SimpointResource that contains the list of - SimPoints starting instructions, the list of weights, and the SimPoints - interval + SimPoints starting instructions, the list of + weights, and the SimPoints interval. :param checkpoint: The checkpoint directory. Used to restore the - simulation to that checkpoint. + simulation to that checkpoint. """ self._simpoint_resource = simpoint @@ -218,11 +222,11 @@ class SEBinaryWorkload: :param binary: The resource encapsulating the binary to be run. :param looppoint: The LoopPoint object that contain all the information - gather from the LoopPoint files and a LoopPointManager that will raise - exit events for LoopPoints - :param arguments: The input arguments for the binary + gather from the LoopPoint files and a LoopPointManager + that will raise exit events for LoopPoints. + :param arguments: The input arguments for the binary. :param region_id: If set, will only load the Looppoint region - corresponding to that ID. + corresponding to that ID. """ assert isinstance(looppoint, Looppoint) @@ -251,10 +255,10 @@ class SEBinaryWorkload: * Dynamically linked executables are partially supported when the host ISA and the simulated ISA are the same. - :param elfie: The resource encapsulating the binary elfie to be run. + :param elfie: The resource encapsulating the binary ELFie to be run. :param elfie_info: The ELFieInfo object that contain all the - information for the ELFie - :param arguments: The input arguments for the binary + information for the ELFie. + :param arguments: The input arguments for the binary. """ assert isinstance(elfie_info, ELFieInfo) diff --git a/src/python/gem5/components/boards/simple_board.py b/src/python/gem5/components/boards/simple_board.py index 1891dfd345..85f36b94b0 100644 --- a/src/python/gem5/components/boards/simple_board.py +++ b/src/python/gem5/components/boards/simple_board.py @@ -48,7 +48,7 @@ class SimpleBoard(AbstractSystemBoard, SEBinaryWorkload): **Limitations** * Only supports SE mode - You can run a binary executable via the `set_se_binary_workload` function. + You can run a binary executable via the ``set_se_binary_workload`` function. """ def __init__( @@ -98,7 +98,7 @@ class SimpleBoard(AbstractSystemBoard, SEBinaryWorkload): @overrides(AbstractSystemBoard) def get_mem_side_coherent_io_port(self) -> Port: raise NotImplementedError( - "SimpleBoard does not have any I/O ports. Use has_coherent_io to " + "SimpleBoard does not have any I/O ports. Use `has_coherent_io` to " "check this." ) diff --git a/src/python/gem5/components/boards/test_board.py b/src/python/gem5/components/boards/test_board.py index 0c0407f888..2599c6853d 100644 --- a/src/python/gem5/components/boards/test_board.py +++ b/src/python/gem5/components/boards/test_board.py @@ -50,7 +50,7 @@ class TestBoard(AbstractSystemBoard): To work as a traffic generator board, pass a generator as a processor. - This board does not require a cache hierarchy (it can be none) in which + This board does not require a cache hierarchy (it can be ``none``) in which case the processor (generator) will be directly connected to the memory. The clock frequency is only used if there is a cache hierarchy or when using the GUPS generators. diff --git a/src/python/gem5/components/boards/x86_board.py b/src/python/gem5/components/boards/x86_board.py index 764688da60..a0ba325475 100644 --- a/src/python/gem5/components/boards/x86_board.py +++ b/src/python/gem5/components/boards/x86_board.py @@ -67,8 +67,8 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): A board capable of full system simulation for X86. **Limitations** - * Currently, this board's memory is hardcoded to 3GB - * Much of the I/O subsystem is hard coded + * Currently, this board's memory is hardcoded to 3GB. + * Much of the I/O subsystem is hard coded. """ def __init__( @@ -108,8 +108,10 @@ class X86Board(AbstractSystemBoard, KernelDiskWorkload): def _setup_io_devices(self): """Sets up the x86 IO devices. - Note: This is mostly copy-paste from prior X86 FS setups. Some of it - may not be documented and there may be bugs. + .. note:: + + This is mostly copy-paste from prior X86 FS setups. Some of it + may not be documented and there may be bugs. """ # Constants similar to x86_traits.hh diff --git a/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py index d8722a1df7..930c6e7cff 100644 --- a/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/abstract_cache_hierarchy.py @@ -57,9 +57,7 @@ class AbstractCacheHierarchy(SubSystem): unique for each setup. :param board: The board in which the cache heirarchy is to be - incorporated. - - :type board: AbstractBoard + incorporated. """ raise NotImplementedError @@ -70,10 +68,10 @@ class AbstractCacheHierarchy(SubSystem): Specifies whether this cache hierarchy is using the Ruby memory system or not. - :returns: True if the cache hierarchy is ruby. Otherwise False. + :returns: ``True`` if the cache hierarchy is ruby. Otherwise ``False``. """ raise NotImplementedError def _post_instantiate(self): - """Called to set up anything needed after m5.instantiate""" + """Called to set up anything needed after ``m5.instantiate``.""" pass diff --git a/src/python/gem5/components/cachehierarchies/abstract_two_level_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/abstract_two_level_cache_hierarchy.py index d6a035f2cb..593f9c7c1e 100644 --- a/src/python/gem5/components/cachehierarchies/abstract_two_level_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/abstract_two_level_cache_hierarchy.py @@ -43,27 +43,15 @@ class AbstractTwoLevelCacheHierarchy: """ :param l1i_size: The size of the L1 Instruction cache (e.g. "32kB"). - :type l1i_size: str - :param l1i_assoc: - :type l1i_assoc: int - :param l1d_size: The size of the L1 Data cache (e.g. "32kB"). - :type l1d_size: str - :param l1d_assoc: - :type l1d_assoc: int - :param l2_size: The size of the L2 cache (e.g., "256kB"). - :type l2_size: str - :param l2_assoc: - - :type l2_assoc: int """ self._l1i_size = l1i_size self._l1i_assoc = l1i_assoc diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py b/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py index e7cbafefb2..54bab22a64 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/memory_controller.py @@ -40,6 +40,7 @@ from .abstract_node import TriggerMessageBuffer class MemCtrlMessageBuffer(MessageBuffer): """ MessageBuffer exchanging messages with the memory + These buffers should also not be affected by the Ruby tester randomization. """ @@ -48,7 +49,7 @@ class MemCtrlMessageBuffer(MessageBuffer): class MemoryController(Memory_Controller): - """A controller that connects to memory""" + """A controller that connects to memory.""" _version = 0 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 index 92b240da26..f3b7036e66 100644 --- a/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/chi/private_l1_cache_hierarchy.py @@ -143,7 +143,7 @@ class PrivateL1CacheHierarchy(AbstractRubyCacheHierarchy): 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 + for the core with a split I/D cache. """ cluster = SubSystem() cluster.dcache = PrivateL1MOESICache( diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py b/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py index 6165870129..5fc9a79a1b 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/l1dcache.py @@ -39,8 +39,8 @@ class L1DCache(Cache): """ A simple L1 data cache with default values. - If the cache has a mostly exclusive downstream cache, writeback_clean - should be set to True. + If the cache has a mostly exclusive downstream cache, ``writeback_clean`` + should be set to ``True``. """ def __init__( diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py b/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py index d5130b2b28..2a2d6d41d5 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/l1icache.py @@ -40,7 +40,7 @@ class L1ICache(Cache): A simple L1 instruction cache with default values. If the cache does not have a downstream cache or the downstream cache - is mostly inclusive as usual, writeback_clean should be set to False. + is mostly inclusive as usual, ``writeback_clean`` should be set to ``False``. """ def __init__( diff --git a/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py b/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py index 2da494aa6c..badb242ccf 100644 --- a/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py +++ b/src/python/gem5/components/cachehierarchies/classic/caches/mmu_cache.py @@ -38,7 +38,7 @@ class MMUCache(Cache): A simple Memory Management Unit (MMU) cache with default values. If the cache does not have a downstream cache or the downstream cache - is mostly inclusive as usual, writeback_clean should be set to False. + is mostly inclusive as usual, ``writeback_clean`` should be set to ``False``. """ def __init__( diff --git a/src/python/gem5/components/cachehierarchies/classic/no_cache.py b/src/python/gem5/components/cachehierarchies/classic/no_cache.py index b43e6f69cb..3fb37bb43c 100644 --- a/src/python/gem5/components/cachehierarchies/classic/no_cache.py +++ b/src/python/gem5/components/cachehierarchies/classic/no_cache.py @@ -46,20 +46,22 @@ class NoCache(AbstractClassicCacheHierarchy): By default a SystemXBar of width 64bit is used, though this can be configured via the constructor. - NOTE: At present this does not work with FS. The following error is - received: + .. note:: + + At present this does not work with FS. The following error is + received: + + .. code-block:: + ... + build/X86/mem/snoop_filter.cc:277: panic: panic condition + (sf_item.requested & req_mask).none() occurred: SF value + 0000000000000000000000000000000000000000000000000000000000000000 ... + missing the original request + Memory Usage: 3554472 KBytes + Program aborted at tick 1668400099164 + --- BEGIN LIBC BACKTRACE --- + ... - ``` - ... - build/X86/mem/snoop_filter.cc:277: panic: panic condition - (sf_item.requested & req_mask).none() occurred: SF value - 0000000000000000000000000000000000000000000000000000000000000000 ... - missing the original request - Memory Usage: 3554472 KBytes - Program aborted at tick 1668400099164 - --- BEGIN LIBC BACKTRACE --- - ... - ``` """ @staticmethod @@ -85,7 +87,8 @@ class NoCache(AbstractClassicCacheHierarchy): ) -> None: """ :param membus: The memory bus for this setup. This parameter is - optional and will default toa 64 bit width SystemXBar is not specified. + optional and will default toa 64 bit width SystemXBar + is not specified. :type membus: BaseXBar """ diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py index b5be4905df..97348fdbe5 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py @@ -54,7 +54,7 @@ class PrivateL1CacheHierarchy(AbstractClassicCacheHierarchy): the PrivateL1CacheHierarchy. :returns: The default memory bus for the PrivateL1PrivateL2 - CacheHierarchy. + CacheHierarchy. """ membus = SystemXBar(width=64) membus.badaddr_responder = BadAddr() @@ -73,7 +73,7 @@ class PrivateL1CacheHierarchy(AbstractClassicCacheHierarchy): :param l1i_size: The size of the L1 Instruction Cache (e.g., "32kB"). :param membus: The memory bus. This parameter is optional parameter and - will default to a 64 bit width SystemXBar is not specified. + will default to a 64 bit width SystemXBar is not specified. """ AbstractClassicCacheHierarchy.__init__(self=self) 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 748f7e1f5c..d1d43ec0c8 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 @@ -60,9 +60,8 @@ class PrivateL1PrivateL2CacheHierarchy( the PrivateL1PrivateL2 CacheHierarchy. :returns: The default memory bus for the PrivateL1PrivateL2 - CacheHierarchy. + CacheHierarchy. - :rtype: SystemXBar """ membus = SystemXBar(width=64) membus.badaddr_responder = BadAddr() @@ -79,20 +78,12 @@ class PrivateL1PrivateL2CacheHierarchy( """ :param l1d_size: The size of the L1 Data Cache (e.g., "32kB"). - :type l1d_size: str - :param l1i_size: The size of the L1 Instruction Cache (e.g., "32kB"). - :type l1i_size: str - :param l2_size: The size of the L2 Cache (e.g., "256kB"). - :type l2_size: str - :param membus: The memory bus. This parameter is optional parameter and - will default to a 64 bit width SystemXBar is not specified. - - :type membus: BaseXBar + will default to a 64 bit width SystemXBar is not specified. """ AbstractClassicCacheHierarchy.__init__(self=self) diff --git a/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py b/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py index 68671738c8..4e2c622d62 100644 --- a/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py +++ b/src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py @@ -61,7 +61,7 @@ class PrivateL1SharedL2CacheHierarchy( the PrivateL1SharedL2 CacheHierarchy. :returns: The default memory bus for the PrivateL1SharedL2 - CacheHierarchy. + CacheHierarchy. :rtype: SystemXBar """ @@ -88,7 +88,7 @@ class PrivateL1SharedL2CacheHierarchy( :param l1i_assoc: The associativity of the L1 Instruction Cache. :param l2_assoc: The associativity of the L2 Cache. :param membus: The memory bus. This parameter is optional parameter and - will default to a 64 bit width SystemXBar is not specified. + will default to a 64 bit width SystemXBar is not specified. """ AbstractClassicCacheHierarchy.__init__(self=self) diff --git a/src/python/gem5/components/memory/abstract_memory_system.py b/src/python/gem5/components/memory/abstract_memory_system.py index e985cf1d9b..e214602732 100644 --- a/src/python/gem5/components/memory/abstract_memory_system.py +++ b/src/python/gem5/components/memory/abstract_memory_system.py @@ -58,22 +58,22 @@ class AbstractMemorySystem(SubSystem): @abstractmethod def get_mem_ports(self) -> Sequence[Tuple[AddrRange, Port]]: - """Get the ports to connect this memory system to the cache""" + """Get the ports to connect this memory system to the cache.""" raise NotImplementedError @abstractmethod def get_memory_controllers(self) -> List[MemCtrl]: - """Get all of the memory controllers in this memory system""" + """Get all of the memory controllers in this memory system.""" raise NotImplementedError @abstractmethod def get_size(self) -> int: - """Returns the total size of the memory system""" + """Returns the total size of the memory system.""" raise NotImplementedError @abstractmethod def set_memory_range(self, ranges: List[AddrRange]) -> None: - """Set the total range for this memory system + """Set the total range for this memory system. May pass multiple non-overlapping ranges. The total size of the ranges should match the size of the memory. @@ -84,5 +84,5 @@ class AbstractMemorySystem(SubSystem): raise NotImplementedError def _post_instantiate(self) -> None: - """Called to set up anything needed after m5.instantiate""" + """Called to set up anything needed after ``m5.instantiate``.""" pass diff --git a/src/python/gem5/components/memory/dram_interfaces/ddr3.py b/src/python/gem5/components/memory/dram_interfaces/ddr3.py index ec8f0392cc..7b75354de0 100644 --- a/src/python/gem5/components/memory/dram_interfaces/ddr3.py +++ b/src/python/gem5/components/memory/dram_interfaces/ddr3.py @@ -43,7 +43,7 @@ These memory "interfaces" contain the timing, energy, etc. parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ diff --git a/src/python/gem5/components/memory/dram_interfaces/ddr4.py b/src/python/gem5/components/memory/dram_interfaces/ddr4.py index 62017e4493..b35c7ac399 100644 --- a/src/python/gem5/components/memory/dram_interfaces/ddr4.py +++ b/src/python/gem5/components/memory/dram_interfaces/ddr4.py @@ -40,10 +40,10 @@ """Interfaces for DDR4 memories -These memory "interfaces" contain the timing,energy,etc parameters for each +These memory "interfaces" contain the timing, energy, etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ @@ -55,7 +55,9 @@ class DDR4_2400_16x4(DRAMInterface): A single DDR4-2400 x64 channel (one command and address bus), with timings based on a DDR4-2400 8 Gbit datasheet (Micron MT40A2G4) in an 16x4 configuration. - Total channel capacity is 32GiB + + Total channel capacity is 32GiB. + 16 devices/rank * 2 ranks/channel * 1GiB/device = 32GiB/channel """ @@ -170,7 +172,9 @@ class DDR4_2400_8x8(DDR4_2400_16x4): A single DDR4-2400 x64 channel (one command and address bus), with timings based on a DDR4-2400 8 Gbit datasheet (Micron MT40A1G8) in an 8x8 configuration. - Total channel capacity is 16GiB + + Total channel capacity is 16GiB. + 8 devices/rank * 2 ranks/channel * 1GiB/device = 16GiB/channel """ @@ -201,7 +205,9 @@ class DDR4_2400_4x16(DDR4_2400_16x4): A single DDR4-2400 x64 channel (one command and address bus), with timings based on a DDR4-2400 8 Gbit datasheet (Micron MT40A512M16) in an 4x16 configuration. - Total channel capacity is 4GiB + + Total channel capacity is 4GiB. + 4 devices/rank * 1 ranks/channel * 1GiB/device = 4GiB/channel """ diff --git a/src/python/gem5/components/memory/dram_interfaces/gddr.py b/src/python/gem5/components/memory/dram_interfaces/gddr.py index 4c5e3c5bf4..fc28316e29 100644 --- a/src/python/gem5/components/memory/dram_interfaces/gddr.py +++ b/src/python/gem5/components/memory/dram_interfaces/gddr.py @@ -40,10 +40,10 @@ """Interfaces for GDDR memory devices -These memory "interfaces" contain the timing,energy,etc parameters for each +These memory "interfaces" contain the timing, energy, etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ diff --git a/src/python/gem5/components/memory/dram_interfaces/hbm.py b/src/python/gem5/components/memory/dram_interfaces/hbm.py index 50578a04c8..50af4a9325 100644 --- a/src/python/gem5/components/memory/dram_interfaces/hbm.py +++ b/src/python/gem5/components/memory/dram_interfaces/hbm.py @@ -40,10 +40,10 @@ """Interfaces for HBM memory devices -These memory "interfaces" contain the timing,energy,etc parameters for each +These memory "interfaces" contain the timing, energy, etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ @@ -56,15 +56,18 @@ class HBM_1000_4H_1x128(DRAMInterface): default timings based on data publically released ("HBM: Memory Solution for High Performance Processors", MemCon, 2014), IDD measurement values, and by extrapolating data from other classes. - Architecture values based on published HBM spec + + Architecture values based on published HBM spec. + A 4H stack is defined, 2Gb per die for a total of 1GiB of memory. **IMPORTANT** HBM gen1 supports up to 8 128-bit physical channels Configuration defines a single channel, with the capacity - set to (full_ stack_capacity / 8) based on 2Gb dies - To use all 8 channels, set 'channels' parameter to 8 in - system configuration + set to (full_ stack_capacity / 8) based on 2Gb dies. + + To use all 8 channels, set ``channels`` parameter to 8 in + system configuration. """ # 128-bit interface legacy mode @@ -149,16 +152,17 @@ class HBM_1000_4H_1x64(HBM_1000_4H_1x128): default timings based on HBM gen1 and data publically released A 4H stack is defined, 8Gb per die for a total of 4GiB of memory. Note: This defines a pseudo-channel with a unique controller - instantiated per pseudo-channel + instantiated per pseudo-channel. + Stay at same IO rate (1Gbps) to maintain timing relationship with - HBM gen1 class (HBM_1000_4H_x128) where possible + HBM gen1 class (HBM_1000_4H_x128) where possible. **IMPORTANT** For HBM gen2 with pseudo-channel mode, configure 2X channels. Configuration defines a single pseudo channel, with the capacity - set to (full_ stack_capacity / 16) based on 8Gb dies - To use all 16 pseudo channels, set 'channels' parameter to 16 in - system configuration + set to (full_ stack_capacity / 16) based on 8Gb dies. + To use all 16 pseudo channels, set ``channels`` parameter to 16 in + system configuration. """ # 64-bit pseudo-channel interface diff --git a/src/python/gem5/components/memory/dram_interfaces/hmc.py b/src/python/gem5/components/memory/dram_interfaces/hmc.py index 2c445ef57f..1371b78c18 100644 --- a/src/python/gem5/components/memory/dram_interfaces/hmc.py +++ b/src/python/gem5/components/memory/dram_interfaces/hmc.py @@ -40,10 +40,10 @@ """Interfaces for HMC memory devices -These memory "interfaces" contain the timing,energy,etc parameters for each +These memory "interfaces" contain the timing, energy, etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. Note that HMC is configured differently than some other DRAM interfaces. @@ -58,22 +58,29 @@ class HMC_2500_1x32(DDR3_1600_8x8): uses RC (resistance-capacitance) and CV (capacitance-voltage) models to estimate the DRAM bank latency and power numbers. [2] High performance AXI-4.0 based interconnect for extensible smart memory - cubes (E. Azarkhish et. al) + cubes (E. Azarkhish et. al). Assumed for the HMC model is a 30 nm technology node. The modelled HMC consists of 4 Gbit layers which sum up to 2GiB of memory (4 layers). Each layer has 16 vaults and each vault consists of 2 banks per layer. In order to be able to use the same controller used for 2D DRAM generations for HMC, the following analogy is done: + Channel (DDR) => Vault (HMC) + device_size (DDR) => size of a single layer in a vault + ranks per channel (DDR) => number of layers + banks per rank (DDR) => banks per layer + devices per rank (DDR) => devices per layer ( 1 for HMC). + The parameters for which no input is available are inherited from the DDR3 configuration. + This configuration includes the latencies from the DRAM to the logic layer - of the HMC + of the HMC. """ # size of device diff --git a/src/python/gem5/components/memory/dram_interfaces/lpddr2.py b/src/python/gem5/components/memory/dram_interfaces/lpddr2.py index 53725a2266..b5209e3a12 100644 --- a/src/python/gem5/components/memory/dram_interfaces/lpddr2.py +++ b/src/python/gem5/components/memory/dram_interfaces/lpddr2.py @@ -43,7 +43,7 @@ These memory "interfaces" contain the timing,energy,etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ diff --git a/src/python/gem5/components/memory/dram_interfaces/lpddr3.py b/src/python/gem5/components/memory/dram_interfaces/lpddr3.py index d08e8fbdda..6b483e9d3f 100644 --- a/src/python/gem5/components/memory/dram_interfaces/lpddr3.py +++ b/src/python/gem5/components/memory/dram_interfaces/lpddr3.py @@ -43,7 +43,7 @@ These memory "interfaces" contain the timing,energy,etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ diff --git a/src/python/gem5/components/memory/dram_interfaces/lpddr5.py b/src/python/gem5/components/memory/dram_interfaces/lpddr5.py index f35bef15ae..574f5c242b 100644 --- a/src/python/gem5/components/memory/dram_interfaces/lpddr5.py +++ b/src/python/gem5/components/memory/dram_interfaces/lpddr5.py @@ -43,7 +43,7 @@ These memory "interfaces" contain the timing,energy,etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ @@ -54,10 +54,12 @@ class LPDDR5_5500_1x16_BG_BL32(DRAMInterface): """ A single LPDDR5 x16 interface (one command/address bus) for a single x16 channel with default timings based on - initial JEDEC specification - Starting with 5.5Gbps data rates and 8Gbit die + initial JEDEC specification. + + Starting with 5.5Gbps data rates and 8Gbit die. + Configuring for 16-bank mode with bank-group architecture - burst of 32, which means bursts can be interleaved + burst of 32, which means bursts can be interleaved. """ # Increase buffer size to account for more bank resources @@ -208,9 +210,11 @@ class LPDDR5_5500_1x16_8B_BL32(LPDDR5_5500_1x16_BG_BL32): """ A single LPDDR5 x16 interface (one command/address bus) for a single x16 channel with default timings based on - initial JEDEC specification - Starting with 5.5Gbps data rates and 8Gbit die - Configuring for 8-bank mode, burst of 32 + initial JEDEC specification. + + Starting with 5.5Gbps data rates and 8Gbit die. + + Configuring for 8-bank mode, burst of 32. """ # 4KiB page with 8B mode @@ -249,10 +253,12 @@ class LPDDR5_6400_1x16_BG_BL32(LPDDR5_5500_1x16_BG_BL32): """ A single LPDDR5 x16 interface (one command/address bus) for a single x16 channel with default timings based on - initial JEDEC specification - 6.4Gbps data rates and 8Gbit die + initial JEDEC specification. + + 6.4Gbps data rates and 8Gbit die. + Configuring for 16-bank mode with bank-group architecture - burst of 32, which means bursts can be interleaved + burst of 32, which means bursts can be interleaved. """ # 5.5Gb/s DDR with 4:1 WCK:CK ratio for 687.5 MHz CK @@ -297,9 +303,11 @@ class LPDDR5_6400_1x16_BG_BL16(LPDDR5_6400_1x16_BG_BL32): """ A single LPDDR5 x16 interface (one command/address bus) for a single x16 channel with default timings based on initial - JEDEC specifcation - 6.4Gbps data rates and 8Gbit die - Configuring for 16-bank mode with bank-group architecture, burst of 16 + JEDEC specifcation. + + 6.4Gbps data rates and 8Gbit die. + + Configuring for 16-bank mode with bank-group architecture, burst of 16. """ # LPDDR5 is a BL16 or BL32 device @@ -321,9 +329,11 @@ class LPDDR5_6400_1x16_8B_BL32(LPDDR5_6400_1x16_BG_BL32): """ A single LPDDR5 x16 interface (one command/address bus) for a single x16 channel with default timings based on - initial JEDEC specification - 6.4Gbps data rates and 8Gbit die - Configuring for 8-bank mode, burst of 32 + initial JEDEC specification. + + 6.4Gbps data rates and 8Gbit die. + + Configuring for 8-bank mode, burst of 32. """ # 4KiB page with 8B mode diff --git a/src/python/gem5/components/memory/dram_interfaces/wideio.py b/src/python/gem5/components/memory/dram_interfaces/wideio.py index 1e00865071..82a9f8b440 100644 --- a/src/python/gem5/components/memory/dram_interfaces/wideio.py +++ b/src/python/gem5/components/memory/dram_interfaces/wideio.py @@ -43,7 +43,7 @@ These memory "interfaces" contain the timing,energy,etc parameters for each memory type and are usually based on datasheets for the memory devices. -You can use these interfaces in the MemCtrl object as the `dram` timing +You can use these interfaces in the MemCtrl object as the ``dram`` timing interface. """ diff --git a/src/python/gem5/components/memory/dramsim_3.py b/src/python/gem5/components/memory/dramsim_3.py index fd99df9dbd..62167e0b49 100644 --- a/src/python/gem5/components/memory/dramsim_3.py +++ b/src/python/gem5/components/memory/dramsim_3.py @@ -24,10 +24,12 @@ from .abstract_memory_system import AbstractMemorySystem def config_ds3(mem_type: str, num_chnls: int) -> Tuple[str, str]: """ This function creates a config file that will be used to create a memory - controller of type DRAMSim3. It stores the config file in /tmp/ directory. + controller of type DRAMSim3. It stores the config file in ``/tmp/`` directory. :param mem_type: The name for the type of the memory to be configured. + :param num_chnls: The number of channels to configure for the memory + :returns: A tuple containing the output file and the output directory. """ config = configparser.ConfigParser() diff --git a/src/python/gem5/components/memory/hbm.py b/src/python/gem5/components/memory/hbm.py index 7d59caa478..1e1c83e2bd 100644 --- a/src/python/gem5/components/memory/hbm.py +++ b/src/python/gem5/components/memory/hbm.py @@ -70,17 +70,18 @@ class HighBandwidthMemory(ChanneledMemory): ) -> None: """ :param dram_interface_class: The DRAM interface type to create with - this memory controller + this memory controller. :param num_channels: The number of channels that needs to be - simulated + simulated. :param size: Optionally specify the size of the DRAM controller's - address space. By default, it starts at 0 and ends at the size of - the DRAM device specified + address space. By default, it starts at 0 and ends at + the size of the DRAM device specified. :param addr_mapping: Defines the address mapping scheme to be used. - If None, it is defaulted to addr_mapping from dram_interface_class. + If ``None``, it is defaulted to ``addr_mapping`` + from ``dram_interface_class``. :param interleaving_size: Defines the interleaving size of the multi- - channel memory system. By default, it is equivalent to the atom - size, i.e., 64. + channel memory system. By default, it is + equivalent to the atom size, i.e., 64. """ super().__init__( dram_interface_class, diff --git a/src/python/gem5/components/memory/memory.py b/src/python/gem5/components/memory/memory.py index 6742da2c3f..6f17a9f7b3 100644 --- a/src/python/gem5/components/memory/memory.py +++ b/src/python/gem5/components/memory/memory.py @@ -82,17 +82,18 @@ class ChanneledMemory(AbstractMemorySystem): ) -> None: """ :param dram_interface_class: The DRAM interface type to create with - this memory controller + this memory controller. :param num_channels: The number of channels that needs to be - simulated + simulated. :param size: Optionally specify the size of the DRAM controller's - address space. By default, it starts at 0 and ends at the size of - the DRAM device specified + address space. By default, it starts at 0 and ends at + the size of the DRAM device specified. :param addr_mapping: Defines the address mapping scheme to be used. - If None, it is defaulted to addr_mapping from dram_interface_class. + If ``None``, it is defaulted to ``addr_mapping`` from + ``dram_interface_class``. :param interleaving_size: Defines the interleaving size of the multi- - channel memory system. By default, it is equivalent to the atom - size, i.e., 64. + channel memory system. By default, it is + equivalent to the atom size, i.e., 64. """ num_channels = _try_convert(num_channels, int) interleaving_size = _try_convert(interleaving_size, int) diff --git a/src/python/gem5/components/memory/multi_channel.py b/src/python/gem5/components/memory/multi_channel.py index 59d06fba1f..0e26a1a795 100644 --- a/src/python/gem5/components/memory/multi_channel.py +++ b/src/python/gem5/components/memory/multi_channel.py @@ -41,7 +41,7 @@ def DualChannelDDR3_1600( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A dual channel memory system using DDR3_1600_8x8 based DIMM + A dual channel memory system using DDR3_1600_8x8 based DIMM. """ return ChanneledMemory(DDR3_1600_8x8, 2, 64, size=size) @@ -50,7 +50,7 @@ def DualChannelDDR3_2133( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A dual channel memory system using DDR3_2133_8x8 based DIMM + A dual channel memory system using DDR3_2133_8x8 based DIMM. """ return ChanneledMemory(DDR3_2133_8x8, 2, 64, size=size) @@ -59,7 +59,7 @@ def DualChannelDDR4_2400( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A dual channel memory system using DDR4_2400_8x8 based DIMM + A dual channel memory system using DDR4_2400_8x8 based DIMM. """ return ChanneledMemory(DDR4_2400_8x8, 2, 64, size=size) diff --git a/src/python/gem5/components/memory/single_channel.py b/src/python/gem5/components/memory/single_channel.py index 0efb2979a5..246dfa8b6e 100644 --- a/src/python/gem5/components/memory/single_channel.py +++ b/src/python/gem5/components/memory/single_channel.py @@ -46,7 +46,7 @@ def SingleChannelDDR3_1600( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A single channel memory system using DDR3_1600_8x8 based DIMM + A single channel memory system using DDR3_1600_8x8 based DIMM. """ return ChanneledMemory(DDR3_1600_8x8, 1, 64, size=size) @@ -55,7 +55,7 @@ def SingleChannelDDR3_2133( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A single channel memory system using DDR3_2133_8x8 based DIMM + A single channel memory system using DDR3_2133_8x8 based DIMM. """ return ChanneledMemory(DDR3_2133_8x8, 1, 64, size=size) @@ -64,7 +64,7 @@ def SingleChannelDDR4_2400( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A single channel memory system using DDR4_2400_8x8 based DIMM + A single channel memory system using DDR4_2400_8x8 based DIMM. """ return ChanneledMemory(DDR4_2400_8x8, 1, 64, size=size) @@ -87,7 +87,7 @@ def DIMM_DDR5_4400( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A single DIMM of DDR5 has two channels + A single DIMM of DDR5 has two channels. """ return ChanneledMemory(DDR5_4400_4x8, 2, 64, size=size) @@ -96,7 +96,7 @@ def DIMM_DDR5_6400( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A single DIMM of DDR5 has two channels + A single DIMM of DDR5 has two channels. """ return ChanneledMemory(DDR5_6400_4x8, 2, 64, size=size) @@ -105,6 +105,6 @@ def DIMM_DDR5_8400( size: Optional[str] = None, ) -> AbstractMemorySystem: """ - A single DIMM of DDR5 has two channels + A single DIMM of DDR5 has two channels. """ return ChanneledMemory(DDR5_8400_4x8, 2, 64, size=size) diff --git a/src/python/gem5/components/processors/abstract_core.py b/src/python/gem5/components/processors/abstract_core.py index dcde782ce1..ce0181187b 100644 --- a/src/python/gem5/components/processors/abstract_core.py +++ b/src/python/gem5/components/processors/abstract_core.py @@ -58,9 +58,9 @@ class AbstractCore(SubSystem): def requires_send_evicts(self) -> bool: """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 + 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. """ return False @@ -96,11 +96,11 @@ class AbstractCore(SubSystem): @abstractmethod def connect_walker_ports(self, port1: Port, port2: Port) -> None: """ - Connect the response port from itb and dtb to their respective request + Connect the response port from ``itb`` and ``dtb`` to their respective request ports in the core. - :param port1: The response port from itb walker to connect to. - :param port2: The response port from dtb walker to connect to. + :param port1: The response port from ``itb`` walker to connect to. + :param port2: The response port from ``dtb`` walker to connect to. """ raise NotImplementedError @@ -139,15 +139,16 @@ class AbstractCore(SubSystem): ) -> None: """Schedule simpoint exit events for the core. - This is used to raise SIMPOINT_BEGIN exit events in the gem5 standard - library. This is called through the set_workload functions and should - not be called directly. Duplicate instruction counts in the inst_starts list will not - be scheduled. + This is used to raise ``SIMPOINT_BEGIN`` exit events in the gem5 standard + library. This is called through the ``set_workload`` functions and should + not be called directly. Duplicate instruction counts in the ``inst_starts`` + list will not be scheduled. - :param inst_starts: a list of SimPoints starting instructions - :param board_initialized: True if the board has already been - initialized, otherwise False. This parameter is necessary as simpoints - are setup differently dependent on this. + :param inst_starts: A list of SimPoints starting instructions. + :param board_initialized: ``True`` if the board has already been + initialized, otherwise ``False``. This parameter is + necessary as SimPoints are setup differently + dependent on this. """ raise NotImplementedError("This core type does not support simpoints") @@ -159,12 +160,13 @@ class AbstractCore(SubSystem): given number of instructions. This is called through the simulator module and should not be called directly. - This is used to raise MAX_INSTS exit event in the gem5 standard library + This is used to raise ``MAX_INSTS`` exit event in the gem5 standard library. :param inst: a number of instructions - :param board_initialized: True if the board has already been - initialized, otherwise False. This parameter is necessary as the - instruction stop is setup differently dependent on this. + :param board_initialized: ``True`` if the board has already been + initialized, otherwise ``False``. This parameter is + necessary as the instruction stop is setup + differently dependent on this. """ raise NotImplementedError("This core type does not support MAX_INSTS") diff --git a/src/python/gem5/components/processors/abstract_generator.py b/src/python/gem5/components/processors/abstract_generator.py index 0f9acc48ac..d1f4a51833 100644 --- a/src/python/gem5/components/processors/abstract_generator.py +++ b/src/python/gem5/components/processors/abstract_generator.py @@ -60,11 +60,12 @@ class AbstractGenerator(AbstractProcessor): Create a list of AbstractGeneratorCore (which is an AbstractCore), to pass to the constructor of the AbstractProcessor. Due to the different prototypes for the constructor of different generator types - inputs are noted as *args. This way the abstract method _create_cores + inputs are noted as *args. This way the abstract ``method _create_cores`` could be called without AbstractGenerator having to know what the prototype for the constructor of the inheriting class is. It also - limits the _create_cores function to only using positional arguments. - keyword (optional arguments) are still allowable in the constructor of + limits the ``_create_cores`` function to only using positional arguments. + + Keyword (optional arguments) are still allowable in the constructor of the inheriting classes. """ super().__init__(cores=cores) diff --git a/src/python/gem5/components/processors/abstract_generator_core.py b/src/python/gem5/components/processors/abstract_generator_core.py index ff4285b810..8b411f3fb3 100644 --- a/src/python/gem5/components/processors/abstract_generator_core.py +++ b/src/python/gem5/components/processors/abstract_generator_core.py @@ -68,7 +68,7 @@ class AbstractGeneratorCore(AbstractCore): def connect_icache(self, port: Port) -> None: """ Generator cores only have one request port which we will connect to - the data cache not the icache. Just connect the icache to the + the data cache not the ``icache``. Just connect the ``icache`` to the PortTerminator here. """ self.port_end.req_ports = port @@ -109,6 +109,7 @@ class AbstractGeneratorCore(AbstractCore): def start_traffic(self): """ External interface to start generating the trace of addresses. + Depending on what SimObject is wrapped by this component this method might need be implemented. """ diff --git a/src/python/gem5/components/processors/abstract_processor.py b/src/python/gem5/components/processors/abstract_processor.py index b34da25906..79dba438a2 100644 --- a/src/python/gem5/components/processors/abstract_processor.py +++ b/src/python/gem5/components/processors/abstract_processor.py @@ -50,8 +50,9 @@ class AbstractProcessor(SubSystem): isa: ISA = ISA.NULL, ) -> None: """Set the cores on the processor + Cores are optional for some processor types. If a processor does not - set the cores here, it must override `get_num_cores` and `get_cores` + set the cores here, it must override ``get_num_cores`` and ``get_cores``. """ super().__init__() @@ -80,5 +81,5 @@ class AbstractProcessor(SubSystem): raise NotImplementedError def _post_instantiate(self) -> None: - """Called to set up anything needed after m5.instantiate""" + """Called to set up anything needed after ``m5.instantiate``.""" pass diff --git a/src/python/gem5/components/processors/base_cpu_processor.py b/src/python/gem5/components/processors/base_cpu_processor.py index 23e37cd262..b1a63ea8ce 100644 --- a/src/python/gem5/components/processors/base_cpu_processor.py +++ b/src/python/gem5/components/processors/base_cpu_processor.py @@ -55,7 +55,6 @@ class BaseCPUProcessor(AbstractProcessor): Disclaimer ---------- - Multiple cores comprising of different BaseCPU types has not been tested and is not officially supported. """ diff --git a/src/python/gem5/components/processors/complex_generator.py b/src/python/gem5/components/processors/complex_generator.py index 9d4c1b33b7..ca3422b83c 100644 --- a/src/python/gem5/components/processors/complex_generator.py +++ b/src/python/gem5/components/processors/complex_generator.py @@ -70,18 +70,19 @@ class ComplexGenerator(AbstractGenerator): generator with the params specified. :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ ranges = partition_range(min_addr, max_addr, len(self.cores)) for i, core in enumerate(self.cores): @@ -110,18 +111,19 @@ class ComplexGenerator(AbstractGenerator): generator with the params specified. :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ for core in self.cores: core.add_random( @@ -141,7 +143,7 @@ class ComplexGenerator(AbstractGenerator): Sets the traffic pattern defined by generator argument. :param generator: A python generator object that creates traffic - patterns through calls to methods of PyTrafficGen. + patterns through calls to methods of PyTrafficGen. """ for core in self.cores: core.set_traffic_from_python_generator(generator) diff --git a/src/python/gem5/components/processors/complex_generator_core.py b/src/python/gem5/components/processors/complex_generator_core.py index 058f009df8..076bdd9662 100644 --- a/src/python/gem5/components/processors/complex_generator_core.py +++ b/src/python/gem5/components/processors/complex_generator_core.py @@ -47,7 +47,8 @@ from .abstract_generator_core import AbstractGeneratorCore class TrafficModes(Enum): """The traffic mode class - This class is an enum to store traffic mode in a more meaningful way + + This class is an enum to store traffic mode in a more meaningful way. """ linear = 0 @@ -67,9 +68,10 @@ class ComplexTrafficParams: data_limit: int, ): """The complex traffic params class + This class is a container for parameters to create either a linear or random traffic. The complex generator core stores a list of complex - traffic params for resolution after m5.instantiate is called. + traffic params for resolution after ``m5.instantiate`` is called. """ self._mode = mode self._duration = duration @@ -86,7 +88,7 @@ class ComplexGeneratorCore(AbstractGeneratorCore): """The complex generator core interface. This class defines the interface for a generator core that will create - a series of different types of traffic. This core uses PyTrafficGen to + a series of different types of traffic. This core uses `PyTrafficGen` to create and inject the synthetic traffic. This generator could be used to create more complex traffics that consist of linear and random traffic in different phases. @@ -114,22 +116,23 @@ class ComplexGeneratorCore(AbstractGeneratorCore): """ This function will add the params for a linear traffic to the list of traffic params in this generator core. These params will be later - resolved by the start_traffic call. This core uses a PyTrafficGen to + resolved by the ``start_traffic`` call. This core uses a `PyTrafficGen` to create the traffic based on the specified params below. :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ param = ComplexTrafficParams( TrafficModes.linear, @@ -157,22 +160,23 @@ class ComplexGeneratorCore(AbstractGeneratorCore): """ This function will add the params for a random traffic to the list of traffic params in this generator core. These params will be later - resolved by the start_traffic call. This core uses a PyTrafficGen to + resolved by the ``start_traffic`` call. This core uses a PyTrafficGen to create the traffic based on the specified params below. :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ param = ComplexTrafficParams( TrafficModes.random, @@ -192,13 +196,13 @@ class ComplexGeneratorCore(AbstractGeneratorCore): """ This function first checks if there are any pending traffics that require creation, if so it will create the pending traffics based on - traffic_params list and adds them to the traffic list, then it starts + ``traffic_params`` list and adds them to the traffic list, then it starts generating the traffic at the top of the traffic list. It also pops the first element in the list so that every time this function is called a new traffic is generated, each instance of a call to this function - should happen before each instance of the call to m5.simulate(). All + should happen before each instance of the call to ``m5.simulate()``. All the instances of calls to this function should happen after - m5.instantiate() + ``m5.instantiate()``. """ if not self._traffic_set: self._set_traffic() @@ -254,15 +258,15 @@ class ComplexGeneratorCore(AbstractGeneratorCore): ) -> None: """ Function to set the traffic from a user defined python generator. - The generator should only only assume one input argument (positional) + The generator should only assume one input argument (positional) for the actual PyTrafficGen object to create the traffic. This is possible either through using a generator with hardcoded parameters in the function calls to PyTrafficGen methods or by compiling a flexible python generator into a generator object with only one - input argument (positional) using functools.partial. + input argument (positional) using ``functools.partial``. :param generator: A python generator object that creates traffic - patterns through calls to methods of PyTrafficGen. + patterns through calls to methods of PyTrafficGen. """ if not self._traffic_set: self._set_traffic() @@ -284,18 +288,19 @@ class ComplexGeneratorCore(AbstractGeneratorCore): used to exit the simulation). :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ duration = fromSeconds(toLatency(duration)) rate = toMemoryBandwidth(rate) @@ -330,18 +335,19 @@ class ComplexGeneratorCore(AbstractGeneratorCore): used to exit the simulation). :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ duration = fromSeconds(toLatency(duration)) rate = toMemoryBandwidth(rate) diff --git a/src/python/gem5/components/processors/cpu_types.py b/src/python/gem5/components/processors/cpu_types.py index aa3f822300..20f0356c3e 100644 --- a/src/python/gem5/components/processors/cpu_types.py +++ b/src/python/gem5/components/processors/cpu_types.py @@ -52,7 +52,7 @@ def get_cpu_type_from_str(input: str) -> CPUTypes: the enum's value. E.g., "kvm" will return ISA.KVM. Throws an exception if the input string is invalid. - `get_cpu_types_str_set()` can be used to determine the valid strings. + ``get_cpu_types_str_set()`` can be used to determine the valid strings. This is for parsing text inputs that specify CPU Type targets. diff --git a/src/python/gem5/components/processors/gups_generator.py b/src/python/gem5/components/processors/gups_generator.py index beccd339a7..b90be0ec1c 100644 --- a/src/python/gem5/components/processors/gups_generator.py +++ b/src/python/gem5/components/processors/gups_generator.py @@ -43,6 +43,7 @@ class GUPSGenerator(AbstractGenerator): clk_freq: Optional[str] = None, ): """The GUPSGenerator class + This class defines the interface for a single core GUPSGenerator, this generator could be used in place of a processor. For multicore versions of this generator look at GUPSGeneraorEP (EP stands for embarrassingly @@ -51,10 +52,11 @@ class GUPSGenerator(AbstractGenerator): :param start_addr: The start address for allocating the update table. :param mem_size: The size of memory to allocate for the update table. - Should be a power of 2. + Should be a power of 2. :param update_limit: The number of updates to do before terminating - simulation. Pass zero to run the benchmark to completion (The amount of - time it takes to simulate depends on ) + simulation. Pass zero to run the benchmark to + completion (The amount of time it takes to simulate + depends on it). """ super().__init__( cores=[ @@ -70,7 +72,7 @@ class GUPSGenerator(AbstractGenerator): @overrides(AbstractGenerator) def start_traffic(self): """ - Since GUPSGeneratorCore does not need a call to start_traffic to + Since GUPSGeneratorCore does not need a call to ``start_traffic`` to start generation. This function is just pass. """ pass diff --git a/src/python/gem5/components/processors/gups_generator_ep.py b/src/python/gem5/components/processors/gups_generator_ep.py index bd6adde3e5..8c62f01e02 100644 --- a/src/python/gem5/components/processors/gups_generator_ep.py +++ b/src/python/gem5/components/processors/gups_generator_ep.py @@ -45,6 +45,7 @@ class GUPSGeneratorEP(AbstractGenerator): clk_freq: Optional[str] = None, ): """The GUPSGeneratorEP class + This class defines the interface for multi core GUPSGenerator, this generator could be used in place of a processor. In terms of benchmarking this generator implements the embarrassigly parallel @@ -52,10 +53,11 @@ class GUPSGeneratorEP(AbstractGenerator): :param start_addr: The start address for allocating the update table. :param mem_size: The size of memory to allocate for the update table. - Should be a power of 2. + Should be a power of 2. :param update_limit: The number of updates to do before terminating - simulation. Pass zero to run the benchmark to completion (The amount of - time it takes to simulate depends on ) + simulation. Pass zero to run the benchmark to + completion (The amount of time it takes to simulate + depends on it). """ super().__init__( cores=self._create_cores( @@ -94,7 +96,7 @@ class GUPSGeneratorEP(AbstractGenerator): @overrides(AbstractGenerator) def start_traffic(self): """ - Since GUPSGeneratorCore does not need a call to start_traffic to + Since GUPSGeneratorCore does not need a call to ``start_traffic`` to start generation. This function is just pass. """ pass diff --git a/src/python/gem5/components/processors/gups_generator_par.py b/src/python/gem5/components/processors/gups_generator_par.py index 5db0459dbc..c80a8ca62c 100644 --- a/src/python/gem5/components/processors/gups_generator_par.py +++ b/src/python/gem5/components/processors/gups_generator_par.py @@ -46,6 +46,7 @@ class GUPSGeneratorPAR(AbstractGenerator): clk_freq: Optional[str] = None, ): """The GUPSGeneratorPAR class + This class defines the interface for multi core GUPSGenerator, this generator could be used in place of a processor. In terms of benchmarking this generator implements the parallel (3rd) @@ -53,10 +54,11 @@ class GUPSGeneratorPAR(AbstractGenerator): :param start_addr: The start address for allocating the update table. :param mem_size: The size of memory to allocate for the update table. - Should be a power of 2. + Should be a power of 2. :param update_limit: The number of updates to do before terminating - simulation. Pass zero to run the benchmark to completion (The amount of - time it takes to simulate depends on ) + simulation. Pass zero to run the benchmark to + completion (The amount of time it takes to simulate + depends on it). """ super().__init__( cores=self._create_cores( @@ -89,7 +91,7 @@ class GUPSGeneratorPAR(AbstractGenerator): @overrides(AbstractGenerator) def start_traffic(self): """ - Since GUPSGeneratorCore does not need a call to start_traffic to + Since GUPSGeneratorCore does not need a call to ``start_traffic`` to start generation. This function is just pass. """ pass diff --git a/src/python/gem5/components/processors/linear_generator.py b/src/python/gem5/components/processors/linear_generator.py index 13779a0f6d..0e847614c7 100644 --- a/src/python/gem5/components/processors/linear_generator.py +++ b/src/python/gem5/components/processors/linear_generator.py @@ -65,18 +65,19 @@ class LinearGenerator(AbstractGenerator): :param num_cores: The number of linear generator cores to create. :param duration: The number of ticks for the generator to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ def _create_cores( diff --git a/src/python/gem5/components/processors/linear_generator_core.py b/src/python/gem5/components/processors/linear_generator_core.py index 11fdde3a15..449d90a98a 100644 --- a/src/python/gem5/components/processors/linear_generator_core.py +++ b/src/python/gem5/components/processors/linear_generator_core.py @@ -61,18 +61,19 @@ class LinearGeneratorCore(AbstractGeneratorCore): uses PyTrafficGen to create and inject the synthetic traffic. :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ self.generator = PyTrafficGen() self._duration = duration diff --git a/src/python/gem5/components/processors/random_generator.py b/src/python/gem5/components/processors/random_generator.py index 496aaf8606..affe37cf80 100644 --- a/src/python/gem5/components/processors/random_generator.py +++ b/src/python/gem5/components/processors/random_generator.py @@ -64,18 +64,19 @@ class RandomGenerator(AbstractGenerator): :param num_cores: The number of linear generator cores to create. :param duration: The number of ticks for the generator to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ def _create_cores( diff --git a/src/python/gem5/components/processors/random_generator_core.py b/src/python/gem5/components/processors/random_generator_core.py index aa440ce2d7..67f3f5e4ac 100644 --- a/src/python/gem5/components/processors/random_generator_core.py +++ b/src/python/gem5/components/processors/random_generator_core.py @@ -61,18 +61,19 @@ class RandomGeneratorCore(AbstractGeneratorCore): PyTrafficGen to create and inject the synthetic traffic. :param duration: The number of ticks for the generator core to generate - traffic. + traffic. :param rate: The rate at which the synthetic data is read/written. :param block_size: The number of bytes to be read/written with each - request. + request. :param min_addr: The lower bound of the address range the generator - will read/write from/to. + will read/write from/to. :param max_addr: The upper bound of the address range the generator - will read/write from/to. + will read/write from/to. :param rd_perc: The percentage of read requests among all the generated - requests. The write percentage would be equal to 100 - rd_perc. + requests. The write percentage would be equal to + ``100 - rd_perc``. :param data_limit: The amount of data in bytes to read/write by the - generator before stopping generation. + generator before stopping generation. """ self.generator = PyTrafficGen() self._duration = duration diff --git a/src/python/gem5/components/processors/simple_core.py b/src/python/gem5/components/processors/simple_core.py index a79cf5c165..36b99481bc 100644 --- a/src/python/gem5/components/processors/simple_core.py +++ b/src/python/gem5/components/processors/simple_core.py @@ -37,8 +37,8 @@ from .cpu_types import CPUTypes class SimpleCore(BaseCPUCore): """ - A SimpleCore instantiates a core based on the CPUType enum pass. The - SimpleCore creates a single SimObject of that type. + A `SimpleCore` instantiates a core based on the CPUType enum pass. The + `SimpleCore` creates a single `SimObject` of that type. """ def __init__( diff --git a/src/python/gem5/components/processors/simple_processor.py b/src/python/gem5/components/processors/simple_processor.py index 4b569b1f77..da645e8d74 100644 --- a/src/python/gem5/components/processors/simple_processor.py +++ b/src/python/gem5/components/processors/simple_processor.py @@ -46,13 +46,14 @@ class SimpleProcessor(BaseCPUProcessor): ) -> None: """ :param cpu_type: The CPU type for each type in the processor. + :param num_cores: The number of CPU cores in the processor. :param isa: The ISA of the processor. This argument is optional. If not - set the `runtime.get_runtime_isa` is used to determine the ISA at - runtime. **WARNING**: This functionality is deprecated. It is - recommended you explicitly set your ISA via SimpleProcessor - construction. + set the ``runtime.get_runtime_isa`` is used to determine the + ISA at runtime. **WARNING**: This functionality is deprecated. + It is recommended you explicitly set your ISA via SimpleProcessor + construction. """ if not isa: warn( diff --git a/src/python/gem5/components/processors/simple_switchable_processor.py b/src/python/gem5/components/processors/simple_switchable_processor.py index 62fc83c4fe..6516455480 100644 --- a/src/python/gem5/components/processors/simple_switchable_processor.py +++ b/src/python/gem5/components/processors/simple_switchable_processor.py @@ -57,16 +57,16 @@ class SimpleSwitchableProcessor(SwitchableProcessor): ) -> None: """ :param starting_core_type: The CPU type for each type in the processor - to start with (i.e., when the simulation has just started). + to start with (i.e., when the simulation has + just started). - :param switch_core_types: The CPU type for each core, to be switched - to.. + :param switch_core_types: The CPU type for each core, to be switched to. :param isa: The ISA of the processor. This argument is optional. If not - set the `runtime.get_runtime_isa` is used to determine the ISA at - runtime. **WARNING**: This functionality is deprecated. It is - recommended you explicitly set your ISA via SimpleSwitchableProcessor - construction. + set the ``runtime.get_runtime_isa`` is used to determine the + ISA at runtime. **WARNING**: This functionality is deprecated. + It is recommended you explicitly set your ISA via + SimpleSwitchableProcessor construction. """ if not isa: diff --git a/src/python/gem5/components/processors/switchable_processor.py b/src/python/gem5/components/processors/switchable_processor.py index e226702999..2436c9e81f 100644 --- a/src/python/gem5/components/processors/switchable_processor.py +++ b/src/python/gem5/components/processors/switchable_processor.py @@ -46,7 +46,7 @@ class SwitchableProcessor(AbstractProcessor): system using SimpleCores. Though this class can be used directly, it is best inherited from. See - "SimpleSwitchableCPU" for an example of this. + SimpleSwitchableCPU for an example of this. """ def __init__( diff --git a/src/python/gem5/components/processors/traffic_generator.py b/src/python/gem5/components/processors/traffic_generator.py index c38a053bb0..6364e0b9b7 100644 --- a/src/python/gem5/components/processors/traffic_generator.py +++ b/src/python/gem5/components/processors/traffic_generator.py @@ -45,8 +45,8 @@ class TrafficGenerator(AbstractGenerator): generator cores that could replace the processing cores in a board. :param config_file_list: A list containing the path to configuration - file each describing the traffic pattern that should be created by - each core of the generator. + file each describing the traffic pattern that + should be created by each core of the generator. """ def _create_cores( diff --git a/src/python/gem5/components/processors/traffic_generator_core.py b/src/python/gem5/components/processors/traffic_generator_core.py index 0260d9e72a..9e17fe8860 100644 --- a/src/python/gem5/components/processors/traffic_generator_core.py +++ b/src/python/gem5/components/processors/traffic_generator_core.py @@ -42,8 +42,8 @@ class TrafficGeneratorCore(AbstractGeneratorCore): a compound traffic specified by the parameters below. It uses TrafficGen to create the traffic. - :param config_file: path to the configuration file specifying the - pattern of traffic. + :param config_file: Path to the configuration file specifying the + pattern of traffic. """ def __init__(self, config_file: str): diff --git a/src/python/gem5/isas.py b/src/python/gem5/isas.py index ad156d6f2e..2f54c33916 100644 --- a/src/python/gem5/isas.py +++ b/src/python/gem5/isas.py @@ -42,10 +42,11 @@ class ISA(Enum): E.g., to check if the X86 ISA is compiled: - ``` - if buildEnv[f"USE_{ISA.X86.value}_ISA"]: + .. code-block:: + + if buildEnv[f"USE_{ISA.X86.value}_ISA"]: ... - ``` + """ X86 = "x86" @@ -70,7 +71,7 @@ def get_isa_from_str(input: str) -> ISA: the enum's value. E.g., "x86" will return ISA.X86. Throws an exception if the input string is invalid. - `get_isas_str_set()` can be used to determine the valid strings. + ``get_isas_str_set()`` can be used to determine the valid strings. This is for parsing text inputs that specify ISA targets. diff --git a/src/python/gem5/prebuilt/demo/x86_demo_board.py b/src/python/gem5/prebuilt/demo/x86_demo_board.py index 084f1eeffe..cb68a2dbb4 100644 --- a/src/python/gem5/prebuilt/demo/x86_demo_board.py +++ b/src/python/gem5/prebuilt/demo/x86_demo_board.py @@ -54,14 +54,14 @@ class X86DemoBoard(X86Board): ------- An example of using the X86DemoBoard can be found in - `configs/example/gem5_library/x86-ubuntu-run.py`. + ``configs/example/gem5_library/x86-ubuntu-run.py``. To run: - ``` - scons build/X86/gem5.opt -j`nproc` - ./build/X86/gem5.opt configs/example/gem5_library/x86-ubuntu-run.py - ``` + .. code-block:: + + scons build/X86/gem5.opt -j`nproc` + ./build/X86/gem5.opt configs/example/gem5_library/x86-ubuntu-run.py """ diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index 55efe2dabc..c735313a6a 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -76,11 +76,14 @@ from .riscvmatched_processor import U74Processor def U74Memory(): """ Memory for the U74 board. + DDR4 Subsystem with 16GB of memory. + Starts at 0x80000000. + Details at: Section 23, page 195 of the datasheet. - return: ChanneledMemory + :return: ChanneledMemory """ memory = SingleChannelDDR4_2400("16GB") memory.set_memory_range( @@ -96,14 +99,15 @@ class RISCVMatchedBoard( A board capable of full system simulation for RISC-V At a high-level, this is based on the HiFive Unmatched board from SiFive. - Based on : src/python/gem5/components/boards/riscv_board.py + Based on : ``src/python/gem5/components/boards/riscv_board.py`` This board assumes that you will be booting Linux for fullsystem emulation. The frequency of the RTC for the system is set to 1MHz. Details can be found on page 77, section 7.1 of the datasheet. - Datasheet for inbuilt params can be found here: https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf + Datasheet for inbuilt params can be found here: + https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf """ def __init__( @@ -307,9 +311,9 @@ class RISCVMatchedBoard( memory.set_memory_range(self.mem_ranges) def generate_device_tree(self, outdir: str) -> None: - """Creates the dtb and dts files. + """Creates the ``dtb`` and ``dts`` files. - Creates two files in the outdir: 'device.dtb' and 'device.dts' + Creates two files in the outdir: ``device.dtb`` and ``device.dts`` :param outdir: Directory to output the files """ diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py index 213b4e7b1e..abec836a37 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_cache.py @@ -60,7 +60,9 @@ class RISCVMatchedCacheHierarchy( A cache setup where each core has a private L1 Data and Instruction Cache, and a shared L2 cache. + The HiFive board has a partially inclusive cache hierarchy, hence this hierarchy is chosen. + The details of the cache hierarchy are in Table 7, page 36 of the datasheet. - L1 Instruction Cache: @@ -78,7 +80,6 @@ class RISCVMatchedCacheHierarchy( ) -> None: """ :param l2_size: The size of the L2 Cache (e.g., "256kB"). - :type l2_size: str """ AbstractClassicCacheHierarchy.__init__(self=self) AbstractTwoLevelCacheHierarchy.__init__( @@ -165,7 +166,7 @@ class RISCVMatchedCacheHierarchy( self.membus.cpu_side_ports = self.l2cache.mem_side def _setup_io_cache(self, board: AbstractBoard) -> None: - """Create a cache for coherent I/O connections""" + """Create a cache for coherent I/O connections.""" self.iocache = Cache( assoc=8, tag_latency=50, diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py index 1c7ea38ac1..179e466e7a 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_core.py @@ -113,7 +113,7 @@ class U74CPU(RiscvMinorCPU): """ The fetch, decode, and execute stage parameters from the ARM HPI CPU This information about the CPU can be found on page 15 of - gem5_rsk_gem5-21.2.pdf at https://github.com/arm-university/arm-gem5-rsk + `gem5_rsk_gem5-21.2.pdf` at https://github.com/arm-university/arm-gem5-rsk The parameters that are changed are: - threadPolicy: @@ -206,8 +206,11 @@ class U74Core(BaseCPUCore): - globalCtrBits: 4 - choiceCtrBits: 4 - localHistoryTableSize: 4096 B - NOTE: The TournamentBP deviates from the actual BP. - This configuration performs the best in relation to the hardware. + + .. note:: + + The TournamentBP deviates from the actual BP. + This configuration performs the best in relation to the hardware. """ def __init__( diff --git a/src/python/gem5/resources/client.py b/src/python/gem5/resources/client.py index 3428b037e0..1fecbb9c08 100644 --- a/src/python/gem5/resources/client.py +++ b/src/python/gem5/resources/client.py @@ -47,9 +47,11 @@ from .client_api.client_wrapper import ClientWrapper def getFileContent(file_path: Path) -> Dict: """ - Get the content of the file at the given path - :param file_path: The path of the file - :return: The content of the file + Get the content of the file at the given path. + + :param file_path: The path of the file. + + :return: The content of the file. """ if file_path.exists(): with open(file_path) as file: @@ -136,10 +138,10 @@ def list_resources( :param clients: The list of clients to query :param gem5_version: The gem5 version of the resource to get. By default, - it is the gem5 version of the current build. If set to none, it will return - all gem5 versions of the resource. + it is the gem5 version of the current build. If set to + ``None``, it will return all gem5 versions of the resource. :return: A Python Dict where the key is the resource id and the value is - a list of all the supported resource versions. + a list of all the supported resource versions. """ return _get_clientwrapper().list_resources(clients, gem5_version) @@ -151,13 +153,15 @@ def get_resource_json_obj( gem5_version: Optional[str] = core.gem5Version, ) -> Dict: """ - Get the resource json object from the clients wrapper - :param resource_id: The resource id - :param resource_version: The resource version - :param clients: The list of clients to query + Get the resource json object from the clients wrapper. + + :param resource_id: The resource id. + :param resource_version: The resource version. + :param clients: The list of clients to query. :param gem5_version: The gem5 versions to filter the resources based on - compatibility. By default, it is the gem5 version of the current build. - If None, filtering based on compatibility is not performed. + compatibility. By default, it is the gem5 version of the + current build. If ``None``, filtering based on compatibility + is not performed. """ return _get_clientwrapper().get_resource_json_obj_from_client( diff --git a/src/python/gem5/resources/client_api/abstract_client.py b/src/python/gem5/resources/client_api/abstract_client.py index b58ac1efe2..2ec4a3cdb8 100644 --- a/src/python/gem5/resources/client_api/abstract_client.py +++ b/src/python/gem5/resources/client_api/abstract_client.py @@ -41,8 +41,10 @@ class AbstractClient(ABC): def _url_validator(self, url: str) -> bool: """ Validates the provided URL. + :param url: The URL to be validated. - :return: True if the URL is valid, False otherwise. + + :return: ``True`` if the URL is valid, ``False`` otherwise. """ try: result = urllib.parse.urlparse(url) @@ -59,12 +61,13 @@ class AbstractClient(ABC): ) -> List[Dict[str, Any]]: """ :param resource_id: The ID of the Resource. Optional, if not set, all - resources will be returned. - :param resource_version: The version of the Resource. Optional, if - not set, all resource versions will be returned. Note: If `resource_id` - is not set, this parameter will be ignored. + resources will be returned. + :param resource_version: The version of the `Resource`. Optional, if + not set, all resource versions will be returned. + Note: If ``resource_id`` is not set, this + parameter will be ignored. :param gem5_version: The version of gem5. Optional, if not set, all - versions will be returned. + versions will be returned. :return: A list of all the Resources with the given ID. """ raise NotImplementedError @@ -74,15 +77,19 @@ class AbstractClient(ABC): resources_to_filter: List[Dict[str, Any]], gem5_version: Optional[str] = None, ) -> List[Dict[str, Any]]: - """Returns a filtered list resources based on gem5 version + """ + Returns a filtered list resources based on gem5 version compatibility. - Note: This function assumes if the minor component of - a resource's gem5_version is not specified, the resource is compatible - with all minor versions of the same major version. - Likewise, if no hot-fix component is specified, it is assumed that - the resource is compatible with all hot-fix versions of the same - minor version. + .. note:: + + This function assumes if the minor component of a resource's + gem5_version is not specified, the resource is compatible with all + minor versions of the same major version. + + Likewise, if no hot-fix component is specified, it is assumed that + the resource is compatible with all hot-fix versions of the same + minor version. * '20.1' would be compatible with gem5 '20.1.1.0' and '20.1.2.0'. * '21.5.2' would be compatible with gem5 '21.5.2.0' and '21.5.2.0'. @@ -90,8 +97,9 @@ class AbstractClient(ABC): :param resources_to_filter: The list of resources to filter. :param gem5_version: The gem5 version in which the filtered resources - should be compatible. If None, no filtering will be done. - : + should be compatible. If ``None``, no filtering will + be done. + """ if not gem5_version: return resources_to_filter @@ -106,6 +114,7 @@ class AbstractClient(ABC): def get_resources_by_id(self, resource_id: str) -> List[Dict[str, Any]]: """ :param resource_id: The ID of the Resource. + :return: A list of all the Resources with the given ID. """ return self.get_resources(resource_id=resource_id) diff --git a/src/python/gem5/resources/client_api/atlasclient.py b/src/python/gem5/resources/client_api/atlasclient.py index 75adcf764d..1a4f9737c9 100644 --- a/src/python/gem5/resources/client_api/atlasclient.py +++ b/src/python/gem5/resources/client_api/atlasclient.py @@ -76,6 +76,7 @@ class AtlasClient(AbstractClient): def __init__(self, config: Dict[str, str]): """ Initializes a connection to a MongoDB Atlas database. + :param uri: The URI for connecting to the MongoDB server. :param db: The name of the database to connect to. :param collection: The name of the collection within the database. diff --git a/src/python/gem5/resources/client_api/client_wrapper.py b/src/python/gem5/resources/client_api/client_wrapper.py index 0777535ca2..4e93fc46b1 100644 --- a/src/python/gem5/resources/client_api/client_wrapper.py +++ b/src/python/gem5/resources/client_api/client_wrapper.py @@ -52,8 +52,10 @@ class ClientWrapper: """ This function creates respective client object for each source in the config file according to the type of source. - Params: config: config file containing the source information - Returns: clients: dictionary of clients for each source + + :param config: config file containing the source information + + :returns: clients: dictionary of clients for each source """ clients = {} for client in config["sources"]: @@ -106,9 +108,10 @@ class ClientWrapper: """ This function returns all the resources with the given id from all the sources. + :param resource_id: The id of the resource to search for. - :param clients: A list of clients to search through. If None, all - clients are searched. + :param clients: A list of clients to search through. If ``None``, all + clients are searched. :return: A list of resources as Python dictionaries. """ resources = [] @@ -147,15 +150,16 @@ class ClientWrapper: """ This function returns the resource object from the client with the given id and version. + :param resource_id: The id of the resource to search for. :param resource_version: The version of the resource to search for. - :param clients: A list of clients to search through. If None, all - clients are searched. + :param clients: A list of clients to search through. If ``None``, all + clients are searched. :param gem5_version: The gem5 version to check compatibility with. If - None, no compatibility check is performed. By default, is the current - version of gem5. + ``None``, no compatibility check is performed. By + default, is the current version of gem5. :return: The resource object as a Python dictionary if found. - If not found, exception is thrown. + If not found, exception is thrown. """ # getting all the resources with the given id from the dictionary resources = self.get_all_resources_by_id(resource_id, clients) @@ -196,10 +200,12 @@ class ClientWrapper: """ Searches for the resource with the given version. If the resource is not found, an exception is thrown. + :param resources: A list of resources to search through. :param resource_version: The version of the resource to search for. + :return: The resource object as a Python dictionary if found. - If not found, None is returned. + If not found, ``None`` is returned. """ return_resource = next( iter( @@ -226,23 +232,29 @@ class ClientWrapper: """ Returns a list of compatible resources with the current gem5 version. - Note: This function assumes if the minor component of - a resource's gem5_version is not specified, it that the - resource is compatible all minor versions of the same major version. - Likewise, if no hot-fix component is specified, it is assumed that - the resource is compatible with all hot-fix versions of the same - minor version. + .. note:: + + This function assumes if the minor component of a resource's + gem5_version is not specified, it that the resource is compatible + all minor versions of the same major version. + + Likewise, if no hot-fix component is specified, it is assumed that + the resource is compatible with all hot-fix versions of the same + minor version. * '20.1' would be compatible with gem5 '20.1.1.0' and '20.1.2.0'. * '21.5.2' would be compatible with gem5 '21.5.2.0' and '21.5.2.0'. * '22.3.2.4' would only be compatible with gem5 '22.3.2.4'. :param resources: A list of resources to filter. + :return: A list of compatible resources as Python dictionaries. - **Note**: This is a big duplication of code. This functionality already - exists in the `AbstractClient` class. This code should be refactored - to avoid this duplication. + .. note:: + + This is a big duplication of code. This functionality already + exists in the `AbstractClient` class. This code should be refactored + to avoid this duplication. """ compatible_resources = [] @@ -255,8 +267,11 @@ class ClientWrapper: def _sort_resources(self, resources: List) -> List: """ Sorts the resources by ID. + If the IDs are the same, the resources are sorted by version. + :param resources: A list of resources to sort. + :return: A list of sorted resources. """ @@ -264,7 +279,7 @@ class ClientWrapper: """This is used for sorting resources by ID and version. First the ID is sorted, then the version. In cases where the version contains periods, it's assumed this is to separate a - "major.minor.hotfix" style versioning system. In which case, the + ``major.minor.hotfix`` style versioning system. In which case, the value separated in the most-significant position is sorted before those less significant. If the value is a digit it is cast as an int, otherwise, it is cast as a string, to lower-case. @@ -288,11 +303,13 @@ class ClientWrapper: ) -> bool: """ Checks if the resource is compatible with the gem5 version. + Prints a warning if the resource is not compatible. + :param resource: The resource to check. :optional param gem5_version: The gem5 version to check - compatibility with. - :return: True if the resource is compatible, False otherwise. + compatibility with. + :return: ``True`` if the resource is compatible, ``False`` otherwise. """ if not resource: return False diff --git a/src/python/gem5/resources/client_api/jsonclient.py b/src/python/gem5/resources/client_api/jsonclient.py index 7ed15ccbe1..f242a788a9 100644 --- a/src/python/gem5/resources/client_api/jsonclient.py +++ b/src/python/gem5/resources/client_api/jsonclient.py @@ -47,6 +47,7 @@ class JSONClient(AbstractClient): def __init__(self, path: str): """ Initializes a JSON client. + :param path: The path to the Resource, either URL or local. """ self.path = path diff --git a/src/python/gem5/resources/downloader.py b/src/python/gem5/resources/downloader.py index 632980ef4d..1d495509ee 100644 --- a/src/python/gem5/resources/downloader.py +++ b/src/python/gem5/resources/downloader.py @@ -73,8 +73,8 @@ def _download(url: str, download_to: str, max_attempts: int = 6) -> None: :param download_to: The location the downloaded file is to be stored. :param max_attempts: The max number of download attempts before stopping. - The default is 6. This translates to roughly 1 minute of retrying before - stopping. + The default is 6. This translates to roughly 1 minute + of retrying before stopping. """ # TODO: This whole setup will only work for single files we can get via @@ -188,16 +188,18 @@ def list_resources( Lists all available resources. Returns a dictionary where the key is the id of the resources and the value is a list of that resource's versions. - :param clients: A list of clients to use when listing resources. If None, - all clients will be used. None by default. + :param clients: A list of clients to use when listing resources. If ``None``, + all clients will be used. ``None`` by default. :param gem5_version: The gem5 version to which all resources should be - compatible with. If None, compatibility of resources is not considered and - all resources will be returned. + compatible with. If ``None``, compatibility of resources + is not considered and all resources will be returned. - **Note**: This function is here for legacy reasons. The `list_resources` - function was originally stored here. In order to remain backwards - compatible, this function will call the `client_list_resources` function + .. note:: + + This function is here for legacy reasons. The ``list_resources`` + function was originally stored here. In order to remain backwards + compatible, this function will call the ``client_list_resources`` function. """ return client_list_resources(clients=clients, gem5_version=gem5_version) @@ -221,36 +223,39 @@ def get_resource( :param resource_name: The resource to be obtained. :param to_path: The location in the file system the resource is to be - stored. The filename should be included. + stored. The filename should be included. - :param unzip: If true, gzipped resources will be unzipped prior to saving - to `to_path`. True by default. + :param unzip: If ``True``, gzipped resources will be unzipped prior to saving + to ``to_path``. ``True`` by default. - :param untar: If true, tar achieve resource will be unpacked prior to - saving to `to_path`. True by default. + :param untar: If ``True``, tar achieve resource will be unpacked prior to + saving to ``to_path``. ``True`` by default. :param download_md5_mismatch: If a resource is present with an incorrect - hash (e.g., an outdated version of the resource is present), `get_resource` - will delete this local resource and re-download it if this parameter is - True. True by default. + hash (e.g., an outdated version of the resource + is present), ``get_resource`` will delete this + local resource and re-download it if this parameter + is ``True``. ``True`` by default. :param resource_version: The version of the resource to be obtained. If - None, the latest version of the resource compatible with the working - directory's gem5 version will be obtained. None by default. + ``None``, the latest version of the resource compatible + with the working directory's gem5 version will be obtained. + ``None`` by default. :param clients: A list of clients to use when obtaining the resource. If - None, all clients will be used. None by default. + ``None``, all clients will be used. ``None`` by default. :param gem5_version: The gem5 version to use when obtaining the resource. - By default, the version of gem5 being used is used. This is used primarily - for testing purposes. + By default, the version of gem5 being used is used. This + is used primarily for testing purposes. - :param quiet: If true, no output will be printed to the console (baring - exceptions). False by default. + :param quiet: If ``True``, no output will be printed to the console (baring + exceptions). ``False`` by default. :raises Exception: An exception is thrown if a file is already present at - `to_path` but it does not have the correct md5 sum. An exception will also - be thrown is a directory is present at `to_path` + ``to_path`` but it does not have the correct md5 sum. An + exception will also be thrown is a directory is present + at ``to_path``. """ # We apply a lock for a specific resource. This is to avoid circumstances @@ -402,11 +407,12 @@ def get_resource( def _file_uri_to_path(uri: str) -> Optional[Path]: """ - If the URI uses the File scheme (e.g, `file://host/path`) then - a Path object for the local path is returned, otherwise None. + If the URI uses the File scheme (e.g, ``file://host/path``) then + a Path object for the local path is returned, otherwise ``None``. - **Note:** Only files from localhost are permitted. An exception - is thrown otherwise. + .. note:: + + Only files from localhost are permitted. An exception is thrown otherwise. :param uri: The file URI to convert. diff --git a/src/python/gem5/resources/elfie.py b/src/python/gem5/resources/elfie.py index 15afd718c1..d90930d3f0 100644 --- a/src/python/gem5/resources/elfie.py +++ b/src/python/gem5/resources/elfie.py @@ -31,9 +31,9 @@ from m5.params import PcCountPair class ELFieInfo: - """Stores information to load/run ELFies + """Stores information to load/run ELFies. - See https://github.com/intel/pinball2elf for more information + See https://github.com/intel/pinball2elf for more information. """ def __init__(self, start: PcCountPair, end: PcCountPair): @@ -50,6 +50,7 @@ class ELFieInfo: A function is used to setup a PC tracker in all the cores and connect all the tracker to the PC tracker manager to perform multithread PC tracking. + :param processor: The processor used in the simulation configuration. """ for core in processor.get_cores(): diff --git a/src/python/gem5/resources/looppoint.py b/src/python/gem5/resources/looppoint.py index 80ae43ce9f..f054498dd9 100644 --- a/src/python/gem5/resources/looppoint.py +++ b/src/python/gem5/resources/looppoint.py @@ -43,9 +43,11 @@ from m5.params import PcCountPair class LooppointRegionPC: """A data structure for storing the Looppoint region's PC information. - **Note**: This is not intended to be a user-facing class. The classes - `LooppointJsonLoader` and `LooppointCSVLoader` can be used to load - and restore Simpoint data. + .. note:: + + This is not intended to be a user-facing class. The classes + LooppointJsonLoader and LooppointCSVLoader can be used to load + and restore Simpoint data. """ def __init__(self, pc: int, globl: int, relative: Optional[int] = None): @@ -97,9 +99,11 @@ class LooppointRegionPC: class LooppointRegionWarmup: """A data structure for storing a Looppoint region's warmup data. - **Note**: This is not intended to be a user-facing class. The classes - `LooppointJsonLoader` and `LooppointCSVLoader` can be used to load - and restore Simpoint data. + .. note:: + + This is not intended to be a user-facing class. The classes + LooppointJsonLoader and LooppointCSVLoader can be used to load + and restore SimPoint data. """ def __init__(self, start: PcCountPair, end: PcCountPair): @@ -140,9 +144,11 @@ class LooppointRegionWarmup: class LooppointSimulation: """A data structure to store the simulation region start and end region. - **Note**: This is not intended to be a user-facing class. The classes - `LooppointJsonLoader` and `LooppointCSVLoader` can be used to load - and restore Simpoint data. + .. note:: + + This is not intended to be a user-facing class. The classes + LooppointJsonLoader and LooppointCSVLoader can be used to load + and restore Simpoint data. """ def __init__(self, start: LooppointRegionPC, end: LooppointRegionPC): @@ -193,9 +199,11 @@ class LooppointSimulation: class LooppointRegion: """A data structure to store Looppoint region information. - **Note**: This is not intended to be a user-facing class. The classes - `LooppointJsonLoader` and `LooppointCSVLoader` can be used to load - and restore Simpoint data. + .. note:: + + This is not intended to be a user-facing class. The classes + LooppointJsonLoader and LooppointCSVLoader can be used to load + and restore SimPoint data. """ def __init__( @@ -205,11 +213,11 @@ class LooppointRegion: warmup: Optional[LooppointRegionWarmup] = None, ): """ - :param simulation: The simulation information for this Looppoint - region. - :param multiplier: The multiplier for this Looppoint region. - :param warmup: The warmup information for this Looppoint region. - Optional. + :param simulation: The simulation information for this LoopPoint + region. + :param multiplier: The multiplier for this LoopPoint region. + :param warmup: The warmup information for this LoopPoint region. + Optional. """ self._simulation = simulation self._multiplier = multiplier @@ -224,24 +232,24 @@ class LooppointRegion: return self._multiplier def get_warmup(self) -> Optional[LooppointRegionWarmup]: - """If set, returns the warmup region information. Otherwise None.""" + """If set, returns the warmup region information. Otherwise ``None``.""" return self._warmup def get_pc_count_pairs(self) -> List[PcCountPair]: - """Returns the PC count pairs for this Looppoint region.""" + """Returns the PC count pairs for this LoopPoint region.""" pc_count_pairs = self.get_simulation().get_pc_count_pairs() if self.get_warmup(): pc_count_pairs.extend(self.get_warmup().get_pc_count_pairs()) return pc_count_pairs def update_relatives_counts(self, manager: PcCountTrackerManager) -> None: - """Updates the relative counds of this Looppoint region.""" + """Updates the relative counds of this LoopPoint region.""" self.get_simulation().update_relatives_counts( manager=manager, include_start=bool(self.get_warmup()) ) def get_start(self) -> PcCountPair: - """Returns the correct starting PcCountPair for this Looppoint + """Returns the correct starting PcCountPair for this LoopPoint region.""" if self.get_warmup(): return self.get_warmup().get_start() @@ -260,19 +268,19 @@ class LooppointRegion: class Looppoint: - """Stores all the Looppoint information for a gem5 workload.""" + """Stores all the LoopPoint information for a gem5 workload.""" def __init__(self, regions: Dict[Union[str, int], LooppointRegion]): """ - :param regions: A dictionary mapping the region_ids with the - LooppointRegions. + :param regions: A dictionary mapping the ``region_ids`` with the + LoopPointRegions. """ self._regions = regions self._manager = PcCountTrackerManager() self._manager.targets = self.get_targets() def set_target_region_id(self, region_id: Union[str, int]) -> None: - """There are use-cases where we want to obtain a looppoint data + """There are use-cases where we want to obtain a LoopPoint data structure containing a single target region via its ID. This function will remove all irrelevant regions.""" @@ -286,7 +294,7 @@ class Looppoint: self._manager.targets = self.get_targets() def get_manager(self) -> PcCountTrackerManager: - """Returns the PcCountTrackerManager for this Looppoint data + """Returns the PcCountTrackerManager for this LoopPoint data structure.""" return self._manager @@ -323,7 +331,7 @@ class Looppoint: def get_current_region(self) -> Optional[Union[str, int]]: """Returns the region id if the current PC Count pair if significant - (e.g. beginning of the checkpoint), otherwise, it returns None to + (e.g. beginning of the checkpoint), otherwise, it returns ``None`` to indicate the current PC Count pair is not significant. """ current_pair = self.get_current_pair() @@ -359,7 +367,7 @@ class Looppoint: def to_json(self) -> Dict[Union[int, str], Dict]: """Returns this data-structure as a dictionary for serialization via - the `output_json_file` function.""" + the ``output_json_file`` function.""" to_return = {} for region_id in self.get_regions(): to_return[region_id] = self.get_regions()[region_id].to_json() @@ -371,18 +379,18 @@ class Looppoint: filepath: str = os.path.join(m5.options.outdir, "looppoint.json"), ) -> Dict[int, Dict]: """ - This function is used to output the _json_file into a json file + This function is used to output the ``_json_file`` into a json file. - :param input_indent: the indent value of the json file - :param filepath: the path of the output json file + :param input_indent: The indent value of the json file. + :param filepath: The path of the output json file. """ with open(filepath, "w") as file: json.dump(self.to_json(), file, indent=input_indent) class LooppointCsvLoader(Looppoint): - """This class will create a Looppoint data structure from data extracted - from a Looppoint pinpoints file.""" + """This class will create a LoopPoint data structure from data extracted + from a LoopPoint pinpoints file.""" def __init__( self, @@ -391,10 +399,10 @@ class LooppointCsvLoader(Looppoint): ): """ :params pinpoints_file: The pinpoints file in which the data is to be - expected. + expected. :params region_id: If set, will only load the specified region data. - Otherwise, all region info is loaded. Is used when restoring to a - particular region. + Otherwise, all region info is loaded. Is used when + restoring to a particular region. """ regions = {} @@ -470,8 +478,8 @@ class LooppointCsvLoader(Looppoint): class LooppointJsonLoader(Looppoint): - """This class will create a generate a Looppoint data structure from data - extracted from a Looppoint json file.""" + """This class will create a generate a LoopPoint data structure from data + extracted from a LoopPoint json file.""" def __init__( self, @@ -479,11 +487,11 @@ class LooppointJsonLoader(Looppoint): region_id: Optional[Union[str, int]] = None, ) -> None: """ - :param looppoint_file: a json file generated by gem5 that has all the - LoopPoint data information + :param looppoint_file: A json file generated by gem5 that has all the + LoopPoint data information. :params region_id: If set, will only load the specified region data. - Otherwise, all region info is loaded. Is used when restoring to a - particular region. + Otherwise, all region info is loaded. Is used when + restoring to a particular region. """ _path = ( diff --git a/src/python/gem5/resources/md5_utils.py b/src/python/gem5/resources/md5_utils.py index a3d4e886f9..fcbdedb967 100644 --- a/src/python/gem5/resources/md5_utils.py +++ b/src/python/gem5/resources/md5_utils.py @@ -70,8 +70,8 @@ def _md5_update_from_dir( def md5(path: Path) -> str: """ - Gets the md5 value of a file or directory. `md5_file` is used if the path - is a file and `md5_dir` is used if the path is a directory. An exception + Gets the md5 value of a file or directory. ``md5_file`` is used if the path + is a file and ``md5_dir`` is used if the path is a directory. An exception is returned if the path is not a valid file or directory. :param path: The path to get the md5 of. @@ -86,7 +86,7 @@ def md5(path: Path) -> str: def md5_file(filename: Path) -> str: """ - Gives the md5 hash of a file + Gives the md5 hash of a file. :filename: The file in which the md5 is to be calculated. """ @@ -99,7 +99,9 @@ def md5_dir(directory: Path) -> str: This is achieved by getting the md5 hash of all files in the directory. - Note: The path of files are also hashed so the md5 of the directory changes - if empty files are included or filenames are changed. + .. note:: + + The path of files are also hashed so the md5 of the directory changes + if empty files are included or filenames are changed. """ return str(_md5_update_from_dir(directory, hashlib.md5()).hexdigest()) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index b5ece9dbb0..88c7617478 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -61,22 +61,24 @@ from .looppoint import ( """ Resources are items needed to run a simulation, such as a disk image, kernel, or binary. The gem5 project provides pre-built resources, with sources, at -. Here we provide the `AbstractResource` class and its +. Here we provide the AbstractResource class and its various implementations which are designed to encapsulate a resource for use in the gem5 Standard Library. These classes may be contructed directly. E.g.: -```python -binary = BinaryResource(local_path="/path/to/binary") -``` +.. code-block:: python -or obtained via the gem5-resources infrastructure with the `obtain_resource` + binary = BinaryResource(local_path="/path/to/binary") + + +or obtained via the gem5-resources infrastructure with the ``obtain_resource`` function: -```python -binary = obtain_resource("resource name here") -``` +.. code-block:: python + + binary = obtain_resource("resource name here") + """ @@ -97,12 +99,13 @@ class AbstractResource: ): """ :param local_path: The path on the host system where this resource is - located. + located. :param description: Description describing this resource. Not a - required parameter. By default is None. + required parameter. By default is ``None``. :param source: The source (as in "source code") for this resource. This - string should navigate users to where the source for this resource - may be found. Not a required parameter. By default is None. + string should navigate users to where the source for this + resource may be found. Not a required parameter. By default + is ``None``. :param resource_version: Version of the resource itself. """ @@ -379,10 +382,10 @@ class CheckpointResource(DirectoryResource): class SimpointResource(AbstractResource): - """A simpoint resource. This resource stores all information required to - perform a Simpoint creation and restore. It contains the Simpoint, the - Simpoint interval, the weight for each Simpoint, the full warmup length, - and the warmup length for each Simpoint. + """A SimPoint resource. This resource stores all information required to + perform a SimPoint creation and restore. It contains the SimPoint, the + SimPoint interval, the weight for each SimPoint, the full warmup length, + and the warmup length for each SimPoint. """ def __init__( @@ -400,15 +403,17 @@ class SimpointResource(AbstractResource): **kwargs, ): """ - :param simpoint_interval: The simpoint interval. - :param simpoint_list: The simpoint list. + :param simpoint_interval: The SimPoint interval. + :param simpoint_list: The SimPoint list. :param weight_list: The weight list. :param warmup_interval: The warmup interval. Default to zero (a value - of zero means effectively not set). - :param workload_name: Simpoints are typically associated with a - particular workload due to their dependency on chosen input parameters. - This field helps backtrack to that resource if required. This should - relate to a workload "name" field in the resource.json file. + of zero means effectively not set). + :param workload_name: SimPoints are typically associated with a + particular workload due to their dependency on + chosen input parameters. + This field helps backtrack to that resource if + required. This should relate to a workload "name" + field in the ``resource.json`` file. """ super().__init__( @@ -435,13 +440,13 @@ class SimpointResource(AbstractResource): self._warmup_list = [0] * len(self.get_simpoint_start_insts) def get_simpoint_list(self) -> List[int]: - """Returns the a list containing all the Simpoints for the workload.""" + """Returns the a list containing all the SimPoints for the workload.""" return self._simpoint_list def get_simpoint_start_insts(self) -> List[int]: - """Returns a lst containing all the Simpoint starting instrunction + """Returns a lst containing all the SimPoint starting instrunction points for the workload. This was calculated by multiplying the - Simpoint with the Simpoint interval when it was generated.""" + SimPoint with the SimPoint interval when it was generated.""" return self._simpoint_start_insts def get_warmup_interval(self) -> int: @@ -449,35 +454,35 @@ class SimpointResource(AbstractResource): return self._warmup_interval def get_weight_list(self) -> List[float]: - """Returns the list that contains the weight for each Simpoint. The + """Returns the list that contains the weight for each SimPoint. The order of the weights matches that of the list returned by - `get_simpoint_list(). I.e. `get_weight_list()[3]` is the weight for - simpoint `get_simpoint_list()[3]`.""" + ``get_simpoint_list()``. I.e. ``get_weight_list()[3]`` is the weight for + SimPoint ``get_simpoint_list()[3]``.""" return self._weight_list def get_simpoint_interval(self) -> int: - """Returns the Simpoint interval value.""" + """Returns the SimPoint interval value.""" return self._simpoint_interval def get_warmup_list(self) -> List[int]: - """Returns the a list containing the warmup length for each Simpoint. - Each warmup length in this list corresponds to the Simpoint at the same - index in `get_simpoint_list()`. I.e., `get_warmup_list()[4]` is the - warmup length for Simpoint `get_simpoint_list()[4]`.""" + """Returns the a list containing the warmup length for each SimPoint. + Each warmup length in this list corresponds to the SimPoint at the same + index in ``get_simpoint_list()``. I.e., ``get_warmup_list()[4]`` is the + warmup length for SimPoint ``get_simpoint_list()[4]``.""" return self._warmup_list def get_workload_name(self) -> Optional[str]: - """Return the workload name this Simpoint is associated with.""" + """Return the workload name this SimPoint is associated with.""" return self._workload_name def _set_warmup_list(self) -> List[int]: """ - This function uses the warmup_interval, fits it into the - simpoint_start_insts, and outputs a list of warmup instruction lengths + This function uses the ``warmup_interval``, fits it into the + ``simpoint_start_insts``, and outputs a list of warmup instruction lengths for each SimPoint. The warmup instruction length is calculated using the starting - instruction of a SimPoint to minus the warmup_interval and the ending + instruction of a SimPoint to minus the ``warmup_interval`` and the ending instruction of the last SimPoint. If it is less than 0, then the warmup instruction length is the gap between the starting instruction of a SimPoint and the ending instruction of the last SimPoint. @@ -500,8 +505,8 @@ class SimpointResource(AbstractResource): class LooppointCsvResource(FileResource, LooppointCsvLoader): - """This Looppoint resource used to create a Looppoint resource from a - pinpoints CSV file""" + """This LoopPoint resource used to create a LoopPoint resource from a + pinpoints CSV file.""" def __init__( self, @@ -554,8 +559,8 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): class SimpointDirectoryResource(SimpointResource): - """A Simpoint diretory resource. This Simpoint Resource assumes the - existance of a directory containing a simpoint file and a weight file.""" + """A SimPoint diretory resource. This SimPoint Resource assumes the + existance of a directory containing a SimPoint file and a weight file.""" def __init__( self, @@ -572,11 +577,11 @@ class SimpointDirectoryResource(SimpointResource): **kwargs, ): """ - :param simpoint_file: The Simpoint file. This file is a list of - Simpoints, each on its own line. It should map 1-to-1 to the weights - file. - :param weight_file: The Simpoint weights file. This file is a list of - weights, each on its own line. + :param simpoint_file: The SimPoint file. This file is a list of + SimPoints, each on its own line. It should map + 1-to-1 to the weights file. + :param weight_file: The SimPoint weights file. This file is a list of + weights, each on its own line. """ self._simpoint_file = simpoint_file self._weight_file = weight_file @@ -605,7 +610,7 @@ class SimpointDirectoryResource(SimpointResource): ) def get_simpoint_file(self) -> Path: - """Return the Simpoint File path.""" + """Return the SimPoint File path.""" return Path(Path(self._local_path) / self._simpoint_file) def get_weight_file(self) -> Path: @@ -615,7 +620,7 @@ class SimpointDirectoryResource(SimpointResource): def _get_weights_and_simpoints_from_file( self, ) -> Tuple[List[int], List[int]]: - """This is a helper function to extract the weights and simpoints from + """This is a helper function to extract the weights and SimPoints from the files. """ simpoint_weight_pair = [] @@ -666,14 +671,15 @@ class SuiteResource(AbstractResource): **kwargs, ) -> None: """ - :param workloads: A list of `WorkloadResource` objects - created from the `_workloads` parameter. + :param workloads: A list of ``WorkloadResource`` objects + created from the ``_workloads`` parameter. :param local_path: The path on the host system where this resource is - located. + located. :param description: Description describing this resource. Not a - required parameter. By default is None. + required parameter. By default is ``None``. :param source: The source (as in "source code") for this resource - on gem5-resources. Not a required parameter. By default is None. + on gem5-resources. Not a required parameter. By default + is ``None``. :param resource_version: Version of the resource itself. """ self._workloads = workloads @@ -709,12 +715,9 @@ class SuiteResource(AbstractResource): def with_input_group(self, input_group: str) -> "SuiteResource": """ - Returns a new SuiteResource object with only the workloads that use the - specified input group. - :param input_group: The input group to filter the workloads by. :returns: A new SuiteResource object with only the workloads that use - the specified input group. + the specified input group. """ if input_group not in self.get_input_groups(): @@ -739,8 +742,6 @@ class SuiteResource(AbstractResource): def get_input_groups(self) -> Set[str]: """ - Returns a set of all input groups used by the workloads in a suite. - :returns: A set of all input groups used by the workloads in a suite. """ return { @@ -792,8 +793,8 @@ class WorkloadResource(AbstractResource): """ Returns the name of the workload function to be run. - This function is called via the AbstractBoard's `set_workload` - function. The parameters from the `get_parameters` function are passed + This function is called via the AbstractBoard's ``set_workload`` + function. The parameters from the ``get_parameters`` function are passed to this function. """ return self._func @@ -803,7 +804,7 @@ class WorkloadResource(AbstractResource): Returns a dictionary mapping the workload parameters to their values. These parameters are passed to the function specified by - `get_function_str` via the AbstractBoard's `set_workload` function. + ``get_function_str`` via the AbstractBoard's ``set_workload`` function. """ return self._params @@ -832,32 +833,36 @@ def obtain_resource( ) -> AbstractResource: """ This function primarily serves as a factory for resources. It will return - the correct `AbstractResource` implementation based on the resource + the correct AbstractResource implementation based on the resource requested. :param resource_name: The name of the gem5 resource as it appears under the - "id" field in the `resource.json` file. + "id" field in the ``resource.json`` file. :param resource_directory: The location of the directory in which the - resource is to be stored. If this parameter is not set, it will set to - the environment variable `GEM5_RESOURCE_DIR`. If the environment is not - set it will default to `~/.cache/gem5` if available, otherwise the CWD. - **Note**: This argument is ignored if the `to_path` parameter is specified. - :param download_md5_mismatch: If the resource is present, but does not - have the correct md5 value, the resoruce will be deleted and - re-downloaded if this value is True. Otherwise an exception will be - thrown. True by default. + resource is to be stored. If this parameter is not + set, it will set to the environment variable + ``GEM5_RESOURCE_DIR``. If the environment is not set + it will default to ``~/.cache/gem5`` if available, + otherwise the CWD. *Note*: This argument is ignored + if the ``to_path`` parameter is specified. + :param download_md5_mismatch: If the resource is present, but does not have + the correct md5 value, the resource will be + deleted and re-downloaded if this value is ``True``. + Otherwise an exception will be thrown. ``True`` by + default. :param resource_version: Version of the resource itself. - Not a required parameter. None by default. + Not a required parameter. ``None`` by default. :param clients: A list of clients to search for the resource. If this - parameter is not set, it will default search all clients. + parameter is not set, it will default search all clients. :param gem5_version: The gem5 version to use to filter incompatible - resource versions. By default set to the current gem5 version. If None, - this filtering is not performed. + resource versions. By default set to the current gem5 + version. If `None`, this filtering is not performed. :param to_path: The path to which the resource is to be downloaded. If - None, the resource will be downloaded to the resource directory with - the file/directory name equal to the ID of the resource. **Note**: Usage - of this parameter will override the `resource_directory` parameter. - :param quiet: If True, suppress output. False by default. + ``None``, the resource will be downloaded to the resource directory + with the file/directory name equal to the ID of the resource. + **Note**: Usage of this parameter will override the + ``resource_directory`` parameter. + :param quiet: If ``True``, suppress output. ``False`` by default. """ # Obtain the resource object entry for this resource @@ -1033,16 +1038,17 @@ class CustomResource(AbstractResource): by a gem5 user as opposed to one available within the gem5 resources repository. - **Warning**: This class is deprecated and will be removed in future - releases of gem5. Please use the correct `AbstractResource` subclass - instead. + .. warning:: + + This class is deprecated and will be removed in future releases of gem5. + Please use the correct AbstractResource subclass instead. """ def __init__(self, local_path: str, metadata: Dict = {}): """ :param local_path: The path of the resource on the host system. :param metadata: Add metadata for the custom resource. **Warning:** - As of v22.1.1, this parameter is not used. + As of v22.1.1, this parameter is not used. """ warn( "The `CustomResource` class is deprecated. Please use an " @@ -1061,9 +1067,11 @@ class CustomDiskImageResource(DiskImageResource): A custom disk image gem5 resource. It can be used to specify a custom, local disk image. - **Warning**: This class is deprecated and will be removed in future - releases of gem5. Please use the `DiskImageResource` class instead. This - class is merely a wrapper for it. + .. warning:: + + This class is deprecated and will be removed in future releases of gem5. + Please use the DiskImageResource class instead. This class is merely + a wrapper for it. """ def __init__( @@ -1077,7 +1085,7 @@ class CustomDiskImageResource(DiskImageResource): :param local_path: The path of the disk image on the host system. :param root_partition: The root disk partition to use. :param metadata: Metadata for the resource. **Warning:** As of " - "v22.1.1, this parameter is not used. + "v22.1.1, this parameter is not used. :param resource_version: Version of the resource itself. """ warn( @@ -1105,12 +1113,12 @@ def Resource( clients: Optional[List[str]] = None, ) -> AbstractResource: """ - This function was created to maintain backwards compability for v21.1.0 + This function was created to maintain backwards compatibility for v21.1.0 and prior releases of gem5 where `Resource` was a class. - In the interests of gem5-resource specialization, the `Resource` class - has been dropped. Instead users are advized to use the `obtain_resource` - function which will return the correct `AbstractResource` implementation. + In the interests of gem5-resource specialization, the ``Resource`` class + has been dropped. Instead users are advised to use the ``obtain_resource`` + function which will return the correct AbstractResource implementation. This function (disguised as a class) wraps this function. """ diff --git a/src/python/gem5/resources/workload.py b/src/python/gem5/resources/workload.py index ef1ffbbb8c..ccc6e4caf7 100644 --- a/src/python/gem5/resources/workload.py +++ b/src/python/gem5/resources/workload.py @@ -47,12 +47,14 @@ def CustomWorkload(function: str, parameters: Dict[str, Any]): A custom workload gem5 resource. It can be used to specify a custom, local workload. - **Warning**: This `CustomWorkload` class is deprecated. It will be removed in a - future release of gem5. Please use the `gem5.resources.resource.WorkloadResource` - class instead. + .. warning:: + + This ``CustomWorkload`` class is deprecated. It will be removed in a + future release of gem5. Please use the + ``gem5.resources.resource.WorkloadResource`` class instead. The class has been stealthily converted to a function which wraps the - `WorkloadResource` class. + ``WorkloadResource`` class. """ warn( "The `CustomWorkload` class is deprecated. Please use " @@ -69,12 +71,14 @@ def Workload( gem5_version: Optional[str] = core.gem5Version, ): """ - **Warning**: The `Workload` class is deprecated. It will be removed in a - future release of gem5. Please use the `gem5.resources.resource.WorkloadResource` + .. warning:: + + The ``Workload`` class is deprecated. It will be removed in a future + release of gem5. Please use the ``gem5.resources.resource.WorkloadResource`` class instead. The class has been stealthily converted to a function which wraps the - `WorkloadResource` class. + ``WorkloadResource`` class. """ warn( "`Workload` has been deprecated. Please use the `obtain_resource` " diff --git a/src/python/gem5/runtime.py b/src/python/gem5/runtime.py index 717e4a8c2b..8756f57748 100644 --- a/src/python/gem5/runtime.py +++ b/src/python/gem5/runtime.py @@ -69,9 +69,10 @@ def get_runtime_isa() -> ISA: one ISA. If neither the "TARGET_ISA" parameter is set and there are multiple ISA targets, an exception is thrown. - **WARNING**: This function is deprecated and may be removed in future - versions of gem5. This function should not be relied upon to run gem5 - simulations. + .. warning:: + + This function is deprecated and may be removed in future versions of + gem5. This function should not be relied upon to run gem5 simulations. :returns: The target ISA. """ @@ -98,6 +99,7 @@ def get_runtime_isa() -> ISA: def get_runtime_coherence_protocol() -> CoherenceProtocol: """Gets the cache coherence protocol. + This can be inferred at runtime. :returns: The cache coherence protocol. diff --git a/src/python/gem5/simulate/exit_event.py b/src/python/gem5/simulate/exit_event.py index cffe864f06..3fd12c371b 100644 --- a/src/python/gem5/simulate/exit_event.py +++ b/src/python/gem5/simulate/exit_event.py @@ -60,10 +60,11 @@ class ExitEvent(Enum): This function will translate common exit strings to their correct ExitEvent categorization. + .. note:: - **Note:** At present, we do not guarantee this list is complete, as - there are no bounds on what string may be returned by the simulator - given an exit event. + At present, we do not guarantee this list is complete, as + there are no bounds on what string may be returned by the simulator + given an exit event. """ if exit_string == "m5_workbegin instruction encountered": diff --git a/src/python/gem5/simulate/exit_event_generators.py b/src/python/gem5/simulate/exit_event_generators.py index a8a5940746..4d18b4cee0 100644 --- a/src/python/gem5/simulate/exit_event_generators.py +++ b/src/python/gem5/simulate/exit_event_generators.py @@ -61,7 +61,7 @@ def warn_default_decorator(gen: Generator, type: str, effect: str): def exit_generator(): """ - A default generator for an exit event. It will return True, indicating that + A default generator for an exit event. It will return ``True``, indicating that the Simulator run loop should exit. """ while True: @@ -86,6 +86,7 @@ def dump_reset_generator(): """ A generator for doing statstic dump and reset. It will reset the simulation statistics and then dump simulation statistics. + The Simulation run loop will continue after executing the behavior of the generator. """ @@ -98,7 +99,8 @@ def dump_reset_generator(): def save_checkpoint_generator(checkpoint_dir: Optional[Path] = None): """ A generator for taking a checkpoint. It will take a checkpoint with the - input path and the current simulation Ticks. + input path and the current simulation ``Ticks``. + The Simulation run loop will continue after executing the behavior of the generator. """ @@ -133,6 +135,7 @@ def dump_stats_generator(): def skip_generator(): """ This generator does nothing when on the exit event. + The simulation will continue after this generator. """ while True: @@ -144,9 +147,9 @@ def simpoints_save_checkpoint_generator( ): """ A generator for taking multiple checkpoints for SimPoints. It will save the - checkpoints in the checkpoint_dir path with the SimPoints' index. + checkpoints in the ``checkpoint_dir`` path with the SimPoints' index. The Simulation run loop will continue after executing the behavior of the - generator until all the SimPoints in the simpoint_list has taken a + generator until all the SimPoints in the ``simpoint_list`` has taken a checkpoint. """ simpoint_list = simpoint.get_simpoint_start_insts() @@ -184,17 +187,19 @@ def looppoint_save_checkpoint_generator( """ A generator for taking a checkpoint for LoopPoint. It will save the checkpoints in the checkpoint_dir path with the Region id. + (i.e. "cpt.Region10) It only takes a checkpoint if the current PC Count pair is a significant PC Count Pair. This is determined in the LoopPoint module. The simulation loop continues after exiting this generator. - :param checkpoint_dir: where to save the checkpoints - :param loopoint: the looppoint object used in the configuration script - :param update_relative: if the generator should update the relative count - information in the output json file, then it should be True. It is default - as True. - :param exit_when_empty: if the generator should exit the simulation loop if - all PC paris have been discovered, then it should be True. It is default as - True. + + :param checkpoint_dir: Where to save the checkpoints. + :param loopoint: The LoopPoint object used in the configuration script + :param update_relative: If the generator should update the relative count + information in the output json file, then it should + be ``True``. It is default as ``True``. + :param exit_when_empty: If the generator should exit the simulation loop if + all PC paris have been discovered, then it should be + ``True``. It is default as ``True``. """ if exit_when_empty: total_pairs = len(looppoint.get_targets()) diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index dcab20ebd4..fcbfb6d57d 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -63,15 +63,17 @@ class Simulator: Example ------- + Examples using the Simulator class can be found under - `configs/example/gem5_library`. + ``configs/example/gem5_library``. The most basic run would be as follows: - ``` - simulator = Simulator(board=board) - simulator.run() - ``` + .. code-block:: + + simulator = Simulator(board=board) + simulator.run() + This will run a simulation and execute default behavior for exit events. """ @@ -106,64 +108,72 @@ class Simulator: """ :param board: The board to be simulated. :param full_system: Whether to run as a full-system simulation or not. - This is optional and used to override default behavior. If not set, - whether or not to run in FS mode will be determined via the board's - `is_fullsystem()` function. + This is optional and used to override default + behavior. If not set, whether or not to run in FS + mode will be determined via the board's + ``is_fullsystem()`` function. :param on_exit_event: An optional map to specify what to execute on - each exit event. There are three possibilities here: a generator, a - list of functions, or a single function.: - 1. Generator: The generator may yield a boolean each time the - associated exit event is encountered. If True the simulator will exit - the simulation loop. - 2. List of functions: Each function must be callable with no mandatory - arguments and return a boolean specifying if the Simulation should exit - the simulation loop. Upon each exit event the list will pop the start - of the list and execute it. If the list is empty the default behavior - for that exit event will be executed. - 3. Single function: The function must be callable with no mandatory - arguments and return a boolean specifying if the Simulation should exit - or not. This function is executed each time the associated exit event - is encountered. - :param checkpoint_path: An optional parameter specifying the directory - of the checkpoint to instantiate from. When the path is None, no - checkpoint will be loaded. By default, the path is None. **This - parameter is deprecated. Please set the checkpoint when setting the - board's workload**. + each exit event. There are three possibilities here: + a generator, a list of functions, or a single function. - `on_exit_event` usage notes + 1. Generator: The generator may yield a boolean each + time the associated exit event is encountered. If + ``True`` the simulator will exit the simulation loop. + + 2. List of functions: Each function must be callable + with no mandatory arguments and return a boolean + specifying if the Simulation should exit the + simulation loop. Upon each exit event the list will + pop the start of the list and execute it. If the list + is empty the default behavior for that exit event will + be executed. + + 3. Single function: The function must be callable with + no mandatory arguments and return a boolean specifying + if the Simulation should exit or not. This function is + executed each time the associated exit event is encountered. + :param checkpoint_path: An optional parameter specifying the directory of + the checkpoint to instantiate from. When the path + is ``None``, no checkpoint will be loaded. By default, + the path is ``None``. **This parameter is deprecated. + Please set the checkpoint when setting the board's + workload**. + + ``on_exit_event`` usage notes --------------------------- With Generators =============== - The `on_exit_event` parameter specifies a Python generator for each + The ``on_exit_event`` parameter specifies a Python generator for each exit event. `next()` is run each time an exit event. The - generator may yield a boolean. If this value of this boolean is True + generator may yield a boolean. If this value of this boolean is ``True`` the Simulator run loop will exit, otherwise the Simulator run loop will continue execution. If the generator has - finished (i.e. a `StopIteration` exception is thrown when - `next()` is executed), then the default behavior for that + finished (i.e. a ``StopIteration`` exception is thrown when + ``next()`` is executed), then the default behavior for that exit event is run. As an example, a user may specify their own exit event setup like so: - ``` - def unique_exit_event(): - processor.switch() - yield False - m5.stats.dump() - yield False - yield True + .. code-block:: - simulator = Simulator( - board=board - on_exit_event = { - ExitEvent.Exit : unique_exit_event(), - }, - ) - ``` + def unique_exit_event(): + processor.switch() + yield False + m5.stats.dump() + yield False + yield True - This will execute `processor.switch()` the first time an exit event is + simulator = Simulator( + board=board + on_exit_event = { + ExitEvent.Exit : unique_exit_event(), + }, + ) + + + This will execute ``processor.switch()`` the first time an exit event is encountered, will dump gem5 statistics the second time an exit event is encountered, and will terminate the Simulator run loop the third time. @@ -176,41 +186,42 @@ class Simulator: An example: - ``` - def stop_simulation() -> bool: - return True + .. code-block:: - def switch_cpus() -> bool: - processor.switch() - return False + def stop_simulation() -> bool: + return True - def print_hello() -> None: - # Here we don't explicitly return a boolean, but the simulator - # treats a None return as False. Ergo the Simulation loop is not - # terminated. - print("Hello") + def switch_cpus() -> bool: + processor.switch() + return False + + def print_hello() -> None: + # Here we don't explicitly return a boolean, but the simulator + # treats a None return as False. Ergo the Simulation loop is not + # terminated. + print("Hello") - simulator = Simulator( - board=board, - on_exit_event = { - ExitEvent.Exit : [ - print_hello, - switch_cpus, - print_hello, - stop_simulation - ], - }, - ) - ``` + simulator = Simulator( + board=board, + on_exit_event = { + ExitEvent.Exit : [ + print_hello, + switch_cpus, + print_hello, + stop_simulation + ], + }, + ) - Upon each `EXIT` type exit event the list will function as a queue, + + Upon each ``EXIT`` type exit event the list will function as a queue, with the top function of the list popped and executed. Therefore, in - this example, the first `EXIT` type exit event will cause `print_hello` - to be executed, and the second `EXIT` type exit event will cause the - `switch_cpus` function to run. The third will execute `print_hello` + this example, the first ``EXIT`` type exit event will cause ``print_hello`` + to be executed, and the second ``EXIT`` type exit event will cause the + ``switch_cpus`` function to run. The third will execute ``print_hello`` again before finally, on the forth exit event will call - `stop_simulation` which will stop the simulation as it returns False. + ``stop_simulation`` which will stop the simulation as it returns ``False``. With a function =============== @@ -219,18 +230,20 @@ class Simulator: accept any mandatory parameters and return a boolean specifying if the simulation loop should end after it is executed. An example: - ``` - def print_hello() -> bool: - print("Hello") - return False - simulator = Simulator( - board=board, - on_exit_event = { - ExitEvent.Exit : print_hello - }, - ) - ``` - The above will print "Hello" on every `Exit` type Exit Event. As the + + .. code-block:: + + def print_hello() -> bool: + print("Hello") + return False + simulator = Simulator( + board=board, + on_exit_event = { + ExitEvent.Exit : print_hello + }, + ) + + The above will print "Hello" on every ``Exit`` type Exit Event. As the function returns False, the simulation loop will not end on these events. @@ -244,7 +257,7 @@ class Simulator: * ExitEvent.EXIT: exit simulation * ExitEvent.CHECKPOINT: take a checkpoint * ExitEvent.FAIL : exit simulation - * ExitEvent.SWITCHCPU: call `switch` on the processor + * ExitEvent.SWITCHCPU: call ``switch`` on the processor * ExitEvent.WORKBEGIN: reset stats * ExitEvent.WORKEND: exit simulation * ExitEvent.USER_INTERRUPT: exit simulation @@ -253,7 +266,7 @@ class Simulator: * ExitEvent.SIMPOINT_BEGIN: reset stats * ExitEvent.MAX_INSTS: exit simulation - These generators can be found in the `exit_event_generator.py` module. + These generators can be found in the ``exit_event_generator.py`` module. """ @@ -346,12 +359,15 @@ class Simulator: def schedule_simpoint(self, simpoint_start_insts: List[int]) -> None: """ - Schedule SIMPOINT_BEGIN exit events + Schedule ``SIMPOINT_BEGIN`` exit events - **Warning:** SimPoints only work with one core + .. warning:: - :param simpoint_start_insts: a list of number of instructions - indicating the starting point of the simpoints + SimPoints only work with one core. + + :param simpoint_start_insts: A list of number of instructions + indicating the starting point of + the SimPoints. """ if self._board.get_processor().get_num_cores() > 1: warn("SimPoints only work with one core") @@ -361,10 +377,10 @@ class Simulator: def schedule_max_insts(self, inst: int) -> None: """ - Schedule a MAX_INSTS exit event when any thread in any core reaches the - given number of instructions. + Schedule a ``MAX_INSTS`` exit event when any thread in any core + reaches the given number of instructions. - :param insts: a number of instructions to run to. + :param insts: A number of instructions to run to. """ for core in self._board.get_processor().get_cores(): core._set_inst_stop_any_thread(inst, self._instantiated) @@ -375,19 +391,19 @@ class Simulator: to a JSON-style schema. :raises Exception: An exception is raised if this function is called - before `run()`. The board must be initialized before obtaining - statistics. + before ``run()``. The board must be initialized + before obtaining statistics. """ return self.get_simstats().to_json() def get_simstats(self) -> SimStat: """ - Obtains the SimStat of the current simulation. + Obtains the `SimStat` of the current simulation. :raises Exception: An exception is raised if this function is called - before `run()`. The board must be initialized before obtaining - statistics. + before ``run()``. The board must be initialized + before obtaining statistics. """ if not self._instantiated: @@ -545,9 +561,10 @@ class Simulator: events accordingly. :param max_ticks: The maximum number of ticks to execute per simulation - run. If this max_ticks value is met, a MAX_TICK exit event is - received, if another simulation exit event is met the tick count is - reset. This is the **maximum number of ticks per simulation run**. + run. If this ``max_ticks`` value is met, a ``MAX_TICK`` + exit event is received, if another simulation exit + event is met the tick count is reset. This is the + **maximum number of ticks per simulation run**. """ # Check to ensure no banned module has been imported. @@ -620,6 +637,6 @@ class Simulator: This function will save the checkpoint to the specified directory. :param checkpoint_dir: The path to the directory where the checkpoint - will be saved. + will be saved. """ m5.checkpoint(str(checkpoint_dir)) diff --git a/src/python/gem5/utils/filelock.py b/src/python/gem5/utils/filelock.py index 215b340ebb..0c53422366 100644 --- a/src/python/gem5/utils/filelock.py +++ b/src/python/gem5/utils/filelock.py @@ -35,7 +35,7 @@ class FileLockException(Exception): class FileLock: """A file locking mechanism that has context-manager support so you can use it in a with statement. This should be relatively cross - compatible as it doesn't rely on msvcrt or fcntl for the locking. + compatible as it doesn't rely on ``msvcrt`` or ``fcntl`` for the locking. """ def __init__(self, file_name, timeout=10, delay=0.05): @@ -54,8 +54,8 @@ class FileLock: def acquire(self): """Acquire the lock, if possible. If the lock is in use, it check again - every `wait` seconds. It does this until it either gets the lock or - exceeds `timeout` number of seconds, in which case it throws + every ``wait`` seconds. It does this until it either gets the lock or + exceeds ``timeout`` number of seconds, in which case it throws an exception. """ start_time = time.time() @@ -91,7 +91,8 @@ class FileLock: def release(self): """Get rid of the lock by deleting the lockfile. - When working in a `with` statement, this gets automatically + + When working in a ``with`` statement, this gets automatically called at the end. """ if self.is_locked: @@ -101,6 +102,7 @@ class FileLock: def __enter__(self): """Activated when used in the with statement. + Should automatically acquire a lock to be used in the with block. """ if not self.is_locked: @@ -109,6 +111,7 @@ class FileLock: def __exit__(self, type, value, traceback): """Activated at the end of the with statement. + It automatically releases the lock if it isn't locked. """ if self.is_locked: diff --git a/src/python/gem5/utils/multiprocessing/_command_line.py b/src/python/gem5/utils/multiprocessing/_command_line.py index 0baf198506..9922447295 100644 --- a/src/python/gem5/utils/multiprocessing/_command_line.py +++ b/src/python/gem5/utils/multiprocessing/_command_line.py @@ -89,7 +89,7 @@ def _gem5_args_for_multiprocessing(name): def get_command_line(name, **kwds): """ - Returns prefix of command line used for spawning a child process + Returns prefix of command line used for spawning a child process. """ if getattr(sys, "frozen", False): return [sys.executable, "--multiprocessing-fork"] + [ diff --git a/src/python/gem5/utils/override.py b/src/python/gem5/utils/override.py index 6c28b18b43..01292a384a 100644 --- a/src/python/gem5/utils/override.py +++ b/src/python/gem5/utils/override.py @@ -30,6 +30,7 @@ def overrides(interface_class): Function override annotation. Corollary to @abc.abstractmethod where the override is not of an abstractmethod. + Modified from answer https://stackoverflow.com/a/8313042/471376 """ diff --git a/src/python/gem5/utils/progress_bar.py b/src/python/gem5/utils/progress_bar.py index 43d3a3dec8..b11d3a17f2 100644 --- a/src/python/gem5/utils/progress_bar.py +++ b/src/python/gem5/utils/progress_bar.py @@ -26,7 +26,7 @@ class FakeTQDM: - """This is a fake wrapper so that the tqdm calls work whether or not it + """This is a fake wrapper so that the ``tqdm`` calls work whether or not it has been installed. """ diff --git a/src/python/gem5/utils/requires.py b/src/python/gem5/utils/requires.py index 461a60ddd8..f1f6053756 100644 --- a/src/python/gem5/utils/requires.py +++ b/src/python/gem5/utils/requires.py @@ -65,11 +65,11 @@ def requires( :param isa_required: The ISA(s) gem5 must be compiled to. :param coherence_protocol_required: The coherence protocol gem5 must be - compiled to. + compiled to. :param kvm_required: The host system must have the Kernel-based Virtual - Machine available. + Machine available. :raises Exception: Raises an exception if the required ISA or coherence - protocol do not match that of the current gem5 binary. + protocol do not match that of the current gem5 binary. """ supported_isas = get_supported_isas() diff --git a/src/python/gem5/utils/simpoint.py b/src/python/gem5/utils/simpoint.py index b8c31d309c..f3b8953bb3 100644 --- a/src/python/gem5/utils/simpoint.py +++ b/src/python/gem5/utils/simpoint.py @@ -41,7 +41,7 @@ from gem5.resources.resource import SimpointResource class SimPoint: """ This SimPoint class is used to manage the information needed for SimPoints - in workload + in workload. """ @@ -56,33 +56,33 @@ class SimPoint: warmup_interval: int = 0, ) -> None: """ - :param simpoint_interval: the length of each SimPoints interval - :param simpoint_file_path: the path to the SimPoints result file - generated by Simpoint3.2 or gem5 - :param weight_file_path: the path to the weight result file generated - by Simpoint3.2 or gem5 + :param simpoint_interval: The length of each SimPoints interval. + :param simpoint_file_path: The path to the SimPoints result file + generated by Simpoint3.2 or gem5. + :param weight_file_path: The path to the weight result file generated + by Simpoint3.2 or gem5. - :param simpoint_list: a list of SimPoints starting instructions - :param weight_list: a list of SimPoints weights - :param warmup_interval: a number of instructions for warming up before - restoring a SimPoints checkpoint + :param simpoint_list: A list of SimPoints starting instructions. + :param weight_list: A list of SimPoints weights. + :param warmup_interval: A number of instructions for warming up before + restoring a SimPoints checkpoint. - usage note - ----------- - Need to pass in the paths or the lists for the SimPoints and their - weights. If the paths are passed in, no actions will be done to the - list. + .. note:: - When passing in simpoint_list and weight_list, passing in sorted lists - (sorted by SimPoints in ascending order) is strongly suggested. - The warmup_list only works correctly with sorted simpoint_list. + Need to pass in the paths or the lists for the SimPoints and their + weights. If the paths are passed in, no actions will be done to the + list. + + When passing in ``simpoint_list`` and ``weight_list``, passing in sorted lists + (sorted by SimPoints in ascending order) is strongly suggested. + The ``warmup_list`` only works correctly with sorted ``simpoint_list``. """ warn( - "This `SimPoint` class has been deprecated in favor of " + "This SimPoint class has been deprecated in favor of " "`SimpointResource` and `SimpointDirectory` resource which may be " "found in `gem5.resources.resource`. Please utilize these. This " - "`SimPoint` class will be removed in future releases of gem5." + "SimPoint class will be removed in future releases of gem5." ) # initalize input if you're passing in a CustomResource @@ -133,7 +133,7 @@ class SimPoint: ) -> Tuple[List[int], List[int]]: """ This function takes in file paths and outputs a list of SimPoints - instruction starts and a list of weights + instruction starts and a list of weights. """ simpoint = [] with open(simpoint_path) as simpoint_file, open( @@ -160,12 +160,12 @@ class SimPoint: def set_warmup_intervals(self, warmup_interval: int) -> List[int]: """ - This function takes the warmup_interval, fits it into the - _simpoint_start_insts, and outputs a list of warmup instruction lengths + This function takes the ``warmup_interval``, fits it into the + ``_simpoint_start_insts``, and outputs a list of warmup instruction lengths for each SimPoint. The warmup instruction length is calculated using the starting - instruction of a SimPoint to minus the warmup_interval and the ending + instruction of a SimPoint to minus the ``warmup_interval`` and the ending instruction of the last SimPoint. If it is less than 0, then the warmup instruction length is the gap between the starting instruction of a SimPoint and the ending instruction of the last SimPoint. diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 3b80a09507..608fc68492 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -1322,7 +1322,6 @@ class SimObject(metaclass=MetaSimObject): The format is the same as that supported by SimObjectCliWrapper. :param simobj_path: Current state to be in. - :type simobj_path: str """ d = self._apply_config_get_dict() return eval(simobj_path, d) diff --git a/src/python/m5/ext/pystats/abstract_stat.py b/src/python/m5/ext/pystats/abstract_stat.py index d5b99b259e..bae327fcf9 100644 --- a/src/python/m5/ext/pystats/abstract_stat.py +++ b/src/python/m5/ext/pystats/abstract_stat.py @@ -50,15 +50,16 @@ class AbstractStat(SerializableStat): ) -> List["AbstractStat"]: """Iterate through all of the children, optionally with a predicate - ``` - >>> system.children(lambda _name: 'cpu' in name) - [cpu0, cpu1, cpu2] - ``` + .. code-block:: - :param: predicate(str) -> bool: Optional. Each child's name is passed - to this function. If it returns true, then the child is - yielded. Otherwise, the child is skipped. - If not provided then all children are returned. + >>> system.children(lambda _name: 'cpu' in name) + [cpu0, cpu1, cpu2] + + + :param predicate: Optional. Each child's name is passed to this function. + If it returns ``True``, then the child is yielded. + Otherwise, the child is skipped. If not provided then + all children are returned. """ to_return = [] @@ -78,15 +79,18 @@ class AbstractStat(SerializableStat): """Find all stats that match the name, recursively through all the SimStats. + .. code-block:: - ``` - >>> system.find('cpu[0-9]') - [cpu0, cpu1, cpu2] - ``` - Note: The above will not match `cpu_other`. + >>> system.find('cpu[0-9]') + [cpu0, cpu1, cpu2] - :param: regex: The regular expression used to search. Can be a - precompiled regex or a string in regex format + + .. note:: + + The above will not match ``cpu_other``. + + :param regex: The regular expression used to search. Can be a + precompiled regex or a string in regex format. """ if isinstance(regex, str): pattern = re.compile(regex) diff --git a/src/python/m5/ext/pystats/jsonloader.py b/src/python/m5/ext/pystats/jsonloader.py index f83c2caa68..260b978174 100644 --- a/src/python/m5/ext/pystats/jsonloader.py +++ b/src/python/m5/ext/pystats/jsonloader.py @@ -46,17 +46,19 @@ from .statistic import ( class JsonLoader(json.JSONDecoder): """ - Subclass of JSONDecoder that overrides 'object_hook'. Converts JSON object + Subclass of JSONDecoder that overrides ``object_hook``. Converts JSON object into a SimStat object. Usage ----- - ``` - from m5.ext.pystats.jsonloader import JsonLoader - with open(path) as f: - simstat_object = json.load(f, cls=JsonLoader) - ``` + .. code-block:: + + from m5.ext.pystats.jsonloader import JsonLoader + + with open(path) as f: + simstat_object = json.load(f, cls=JsonLoader) + """ def __init__(self): @@ -99,12 +101,14 @@ def load(json_file: IO) -> SimStat: Usage ----- - ``` - import m5.ext.pystats as pystats - with open(path) as f: - pystats.jsonloader.load(f) - ``` + .. code-block:: + + import m5.ext.pystats as pystats + + with open(path) as f: + pystats.jsonloader.load(f) + """ simstat_object = json.load(json_file, cls=JsonLoader) diff --git a/src/python/m5/ext/pystats/serializable_stat.py b/src/python/m5/ext/pystats/serializable_stat.py index bb63b2a044..faa70a5022 100644 --- a/src/python/m5/ext/pystats/serializable_stat.py +++ b/src/python/m5/ext/pystats/serializable_stat.py @@ -44,22 +44,21 @@ class SerializableStat: Usage ----- - ``` - import m5.pystats.gem5stats as gem5stats - simstat = gem5stats.get_simstat(root) - print(simstat.dumps()) - ``` + .. code-block:: + + import m5.pystats.gem5stats as gem5stats + + simstat = gem5stats.get_simstat(root) + print(simstat.dumps()) + """ def to_json(self) -> Dict: """ Translates the current object into a JSON dictionary. - Returns - ------- - Dict - The JSON dictionary. + :returns: The JSON dictionary. """ model_dct = {} @@ -75,15 +74,9 @@ class SerializableStat: Translate values into a value which can be handled by the Python stdlib JSON package. - Parameters - ---------- - value: Any - The value to be translated. + :param value: The value to be translated. - Returns - ------- - Union[str,int,float,Dict,List] - A value which can be handled by the Python stdlib JSON package. + :returns: A value which can be handled by the Python stdlib JSON package. """ if isinstance(value, SerializableStat): @@ -102,31 +95,26 @@ class SerializableStat: def dumps(self, **kwargs) -> str: """ This function mirrors the Python stdlib JSON module method - `json.dumps`. It is used to obtain the gem5 statistics output to a + ``json.dumps``. It is used to obtain the gem5 statistics output to a JSON string. - Parameters - ---------- - root: Root - The root of the simulation. + :param root: The root of the simulation. - kwargs: Dict[str, Any] - Additional parameters to be passed to the `json.dumps` method. + :param kwargs: Additional parameters to be passed to the ``json.dumps`` method. - Returns - ------- - str - A string of the gem5 Statistics in a JSON format. + :returns: A string of the gem5 Statistics in a JSON format. Usage Example ------------- - ``` - import m5.pystats.gem5stats as gem5stats - simstat = gem5stats.get_simstat(root) - print(simstat.dumps(indent=6)) - ``` + .. code-block:: + + import m5.pystats.gem5stats as gem5stats + + simstat = gem5stats.get_simstat(root) + print(simstat.dumps(indent=6)) + The above will print the simulation statistic JSON string. The indentation will be 6 (by default the indentation is 4). @@ -141,27 +129,24 @@ class SerializableStat: def dump(self, fp: IO[str], **kwargs) -> None: """ This function mirrors the Python stdlib JSON module method - `json.dump`. The root of the simulation is passed, and the JSON is + ``json.dump``. The root of the simulation is passed, and the JSON is output to the specified. + :param fp: The Text IO stream to output the JSON to. - Parameters - ---------- - fp: IO[str] - The Text IO stream to output the JSON to. - - **kwargs: - Additional parameters to be passed to the ``json.dump`` method. + :param kwargs: Additional parameters to be passed to the ``json.dump`` method. Usage ----- - ``` - import m5.pystats.gem5stats as gem5stats - simstat = gem5stats.get_simstat(root) - with open("test.json") as f: - simstat.dump(fp=f, indent=6) - ``` + .. code-block:: + + import m5.pystats.gem5stats as gem5stats + + simstat = gem5stats.get_simstat(root) + with open("test.json") as f: + simstat.dump(fp=f, indent=6) + The above will dump the json output to the 'test.json' file. The indentation will be of 6 (by default the indentation is 4). diff --git a/src/python/m5/ext/pystats/statistic.py b/src/python/m5/ext/pystats/statistic.py index 019ec8a042..3d4c0c6246 100644 --- a/src/python/m5/ext/pystats/statistic.py +++ b/src/python/m5/ext/pystats/statistic.py @@ -116,10 +116,7 @@ class BaseScalarVector(Statistic): """ Returns the mean of the value vector. - Returns - ------- - float - The mean value across all bins. + :returns: The mean value across all bins. """ assert self.value != None assert isinstance(self.value, List) @@ -132,10 +129,7 @@ class BaseScalarVector(Statistic): """ Returns the count across all the bins. - Returns - ------- - float - The sum of all bin values. + :returns: The sum of all bin values. """ assert self.value != None return sum(self.value) @@ -146,7 +140,7 @@ class Distribution(BaseScalarVector): A statistic type that stores information relating to distributions. Each distribution has a number of bins (>=1) between this range. The values correspond to the value of each bin. - E.g., value[3]` is the value of the 4th bin. + E.g., ``value[3]`` is the value of the 4th bin. It is assumed each bucket is of equal size. """ diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index c2a0eebb22..ebeb74b8bf 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -244,15 +244,15 @@ def scheduleTickExitFromCurrent( ticks: int, exit_string: str = "Tick exit reached" ) -> None: """Schedules a tick exit event from the current tick. I.e., if ticks == 100 - then an exit event will be scheduled at tick `curTick() + 100`. + then an exit event will be scheduled at tick ``curTick() + 100``. - The default `exit_string` value is used by the stdlib Simulator module to - declare this exit event as `ExitEvent.SCHEDULED_TICK`. + The default ``exit_string`` value is used by the stdlib Simulator module to + declare this exit event as ``ExitEvent.SCHEDULED_TICK``. - :param ticks: The simulation ticks, from `curTick()` to schedule the exit - event. + :param ticks: The simulation ticks, from ``curTick()`` to schedule the exit + event. :param exit_string: The exit string to return when the exit event is - triggered. + triggered. """ scheduleTickExitAbsolute(tick=ticks + curTick(), exit_string=exit_string) @@ -263,12 +263,12 @@ def scheduleTickExitAbsolute( """Schedules a tick exit event using absolute ticks. I.e., if tick == 100 then an exit event will be scheduled at tick 100. - The default `exit_string` value is used by the stdlib Simulator module to - declare this exit event as `ExitEvent.SCHEDULED_TICK`. + The default ``exit_string`` value is used by the stdlib Simulator module to + declare this exit event as ``ExitEvent.SCHEDULED_TICK``. :param tick: The absolute simulation tick to schedule the exit event. :param exit_string: The exit string to return when the exit event is - triggered. + triggered. """ if tick <= curTick(): warn("Tick exit scheduled for the past. This will not be triggered.") @@ -351,9 +351,11 @@ def _changeMemoryMode(system, mode): def switchCpus(system, cpuList, verbose=True): """Switch CPUs in a system. - Note: This method may switch the memory mode of the system if that - is required by the CPUs. It may also flush all caches in the - system. + .. note:: + + This method may switch the memory mode of the system if that + is required by the CPUs. It may also flush all caches in the + system. Arguments: system -- Simulated system. diff --git a/src/python/m5/stats/gem5stats.py b/src/python/m5/stats/gem5stats.py index 2d79015627..682149f380 100644 --- a/src/python/m5/stats/gem5stats.py +++ b/src/python/m5/stats/gem5stats.py @@ -48,7 +48,7 @@ import _m5.stats class JsonOutputVistor: """ This is a helper vistor class used to include a JSON output via the stats - API (`src/python/m5/stats/__init__.py`). + API (``src/python/m5/stats/__init__.py``). """ file: str @@ -56,14 +56,9 @@ class JsonOutputVistor: def __init__(self, file: str, **kwargs): """ - Parameters - ---------- + :param file: The output file location in which the JSON will be dumped. - file: str - The output file location in which the JSON will be dumped. - - kwargs: Dict[str, Any] - Additional parameters to be passed to the `json.dumps` method. + :param kwargs: Additional parameters to be passed to the ``json.dumps`` method. """ self.file = file @@ -74,14 +69,13 @@ class JsonOutputVistor: Dumps the stats of a simulation root (or list of roots) to the output JSON file specified in the JsonOutput constructor. - WARNING: This dump assumes the statistics have already been prepared - for the target root. + .. warning:: - Parameters - ---------- + This dump assumes the statistics have already been prepared + for the target root. - roots: Union[List[Root], Root]] - The Root, or List of roots, whose stats are are to be dumped JSON. + + :param roots: The Root, or List of roots, whose stats are are to be dumped JSON. """ with open(self.file, "w") as fp: @@ -93,20 +87,14 @@ def get_stats_group(group: _m5.stats.Group) -> Group: """ Translates a gem5 Group object into a Python stats Group object. A Python statistic Group object is a dictionary of labeled Statistic objects. Any - gem5 object passed to this will have its `getStats()` and `getStatGroups` + gem5 object passed to this will have its ``getStats()`` and ``getStatGroups`` function called, and all the stats translated (inclusive of the stats further down the hierarchy). - Parameters - ---------- - group: _m5.stats.Group - The gem5 _m5.stats.Group object to be translated to be a Python stats - Group object. Typically this will be a gem5 SimObject. + :param group: The gem5 _m5.stats.Group object to be translated to be a Python + stats Group object. Typically this will be a gem5 SimObject. - Returns - ------- - Group - The stats group object translated from the input gem5 object. + :returns: The stats group object translated from the input gem5 object. """ stats_dict = {} @@ -127,16 +115,10 @@ def __get_statistic(statistic: _m5.stats.Info) -> Optional[Statistic]: Translates a _m5.stats.Info object into a Statistic object, to process statistics at the Python level. - Parameters - ---------- - statistic: Info - The Info object to be translated to a Statistic object. + :param statistic: The Info object to be translated to a Statistic object. - Returns - ------- - Optional[Statistic] - The Statistic object of the Info object. Returns None if Info object - cannot be translated. + :returns: The Statistic object of the Info object. Returns ``None`` if + Info object cannot be translated. """ assert isinstance(statistic, _m5.stats.Info) @@ -250,22 +232,16 @@ def get_simstat( SimStat object will contain all the stats for all the SimObjects contained within the "root", inclusive of the "root" SimObject/SimObjects. - Parameters - ---------- - root: Union[SimObject, List[SimObject]] - A SimObject, or list of SimObjects, of the simulation for translation - into a SimStat object. Typically this is the simulation's Root - SimObject as this will obtain the entirety of a run's statistics in a - single SimStat object. + :param root: A SimObject, or list of SimObjects, of the simulation for + translation into a SimStat object. Typically this is the + simulation's Root SimObject as this will obtain the entirety + of a run's statistics in a single SimStat object. - prepare_stats: bool - Dictates whether the stats are to be prepared prior to creating the - SimStat object. By default this is 'True'. + :param prepare_stats: Dictates whether the stats are to be prepared prior + to creating the SimStat object. By default this is + ``True``. - Returns - ------- - SimStat - The SimStat Object of the current simulation. + :Returns: The SimStat Object of the current simulation. """ stats_map = {} diff --git a/src/python/m5/util/attrdict.py b/src/python/m5/util/attrdict.py index 0ff2103277..726f1add94 100644 --- a/src/python/m5/util/attrdict.py +++ b/src/python/m5/util/attrdict.py @@ -69,7 +69,7 @@ class multiattrdict(attrdict): class optiondict(attrdict): - """Modify attrdict so that a missing attribute just returns None""" + """Modify attrdict so that a missing attribute just returns ``None``.""" def __getattr__(self, attr): try: From fc0a043950a828c1f513bfe421f33eeb70a6aa83 Mon Sep 17 00:00:00 2001 From: anoop Date: Fri, 1 Dec 2023 22:01:19 +0100 Subject: [PATCH 645/693] mem-ruby: Unused L3CacheCntrl freed (#598) Seems like the MOESI_AMD_Base-L3Cache.sm file is unused in the VIPER protocol. It's confusing to have it in the GPU_VIPER.slicc file. --- configs/ruby/GPU_VIPER.py | 1 + src/mem/ruby/protocol/GPU_VIPER.slicc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index d853c2ef54..96d86f38d3 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -345,6 +345,7 @@ class L3Cache(RubyCache): self.replacement_policy = TreePLRURP() +# unused in GPU_VIPER; see git blame for discussion class L3Cntrl(L3Cache_Controller, CntrlBase): def create(self, options, ruby_system, system): self.version = self.versionCount() diff --git a/src/mem/ruby/protocol/GPU_VIPER.slicc b/src/mem/ruby/protocol/GPU_VIPER.slicc index 196058b0d8..8a09fb0580 100644 --- a/src/mem/ruby/protocol/GPU_VIPER.slicc +++ b/src/mem/ruby/protocol/GPU_VIPER.slicc @@ -8,4 +8,4 @@ include "GPU_VIPER-msg.sm"; include "GPU_VIPER-TCP.sm"; include "GPU_VIPER-SQC.sm"; include "GPU_VIPER-TCC.sm"; -include "MOESI_AMD_Base-L3cache.sm"; +include "MOESI_AMD_Base-L3cache.sm"; // unused in GPU_VIPER; see git blame for discussion From 88601d3ac5b81da1c3b787bb625fe5fccd1b1b72 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Fri, 1 Dec 2023 00:24:49 -0800 Subject: [PATCH 646/693] stdlib: Add `ShadowResource` The purpose of a `ShadowResource` is a resource which only contains the ID and Version information, not any additional information about the resource thus avoiding the `obtain_resource` call. When attributes of the `ShadowResource` are accessed which can only be obtained via `obtain_resource` the `ShowResource` calls the function and returns what is required. This is useful for `Suite` resources which contain several workloads and resources which may not all be needed when the `Suite` object is first instantiated. Change-Id: Icc56261b2c4d74e4079ee66486ddae677bb35cfa --- src/python/gem5/resources/resource.py | 53 ++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 6966c8a7c6..ee86d96cda 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -118,6 +118,10 @@ class AbstractResource: self._version = resource_version self._downloader = downloader + def get_id(self) -> str: + """Returns the ID of the resource.""" + return self._id + def get_category_name(cls) -> str: raise NotImplementedError @@ -803,6 +807,40 @@ class SuiteResource(AbstractResource): } +class ShadowResource(AbstractResource): + """A special resource class which delays the `obtain_resource` call. It is, + in a sense, half constructed. Only when a function or attribute is called + which is is neither `get_id` or `get_resource_version` does this class + fully construct itself by calling the `obtain_resource_call` partial + function. + """ + + def __init__( + self, + id: str, + resource_version: str, + obtain_resource_call: partial, + ): + super().__init__( + id=id, + resource_version=resource_version, + ) + self._workload: Optional[AbstractResource] = None + self._obtain_resource_call = obtain_resource_call + + def __getattr__(self, attr): + """if getting the id or resource version, we keep the object in the + "shdow state" where the `obtain_resource` function has not been called. + When more information is needed by calling another attribute, we call + the `obtain_resource` function and store the result in the `_workload`. + """ + if attr in {"get_id", "get_resource_version"}: + return getattr(super(), attr) + if not self._workload: + self._workload = self._obtain_resource_call() + return getattr(self._workload, attr) + + class WorkloadResource(AbstractResource): """A workload resource. This resource is used to specify a workload to run on a board. It contains the function to call and the parameters to pass to @@ -1012,12 +1050,17 @@ def obtain_resource( workloads_obj = {} for workload in workloads: workloads_obj[ - obtain_resource( - workload["id"], + ShadowResource( + id=workload["id"], resource_version=workload["resource_version"], - resource_directory=resource_directory, - clients=clients, - gem5_version=gem5_version, + obtain_resource_call=partial( + obtain_resource, + workload["id"], + resource_version=workload["resource_version"], + resource_directory=resource_directory, + clients=clients, + gem5_version=gem5_version, + ), ) ] = set(workload["input_group"]) resource_json["workloads"] = workloads_obj From 2fbbdad618a83f49597eea33f70be7c5b51ba5dd Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Thu, 30 Nov 2023 09:52:53 +0000 Subject: [PATCH 647/693] base: Add encapsulation to the loader::Symbol class This commit converts `gem5::loader::Symbol` to a full class with private members, enforcing encapsulation. Until now client code has been able to (and does) access members directly. This change will enable class invariants to be enforced via accessor methods. Change-Id: Ia0b5b080d4f656637a211808e13dce1ddca74541 Reviewed-by: Andreas Sandberg --- src/arch/arm/insts/static_inst.cc | 10 +-- src/arch/generic/linux/threadinfo.hh | 2 +- src/arch/mips/isa/formats/branch.isa | 4 +- src/arch/power/insts/branch.cc | 4 +- src/arch/power/process.cc | 4 +- src/arch/riscv/linux/fs_workload.cc | 8 +-- src/arch/sparc/insts/branch.cc | 6 +- src/base/loader/elf_object.cc | 33 +++++---- src/base/loader/symtab.cc | 29 +++++--- src/base/loader/symtab.hh | 77 ++++++++++++++++---- src/base/loader/symtab.test.cc | 104 ++++++++++++++------------- src/cpu/base.cc | 6 +- src/cpu/exetrace.cc | 6 +- src/cpu/profile.cc | 4 +- src/kern/linux/helpers.cc | 30 ++++---- src/sim/kernel_workload.cc | 4 +- src/sim/workload.hh | 2 +- 17 files changed, 201 insertions(+), 132 deletions(-) diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 54045f2fb1..a645b39270 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -401,8 +401,8 @@ ArmStaticInst::printTarget(std::ostream &os, Addr target, if (symtab) { auto it = symtab->findNearest(target); if (it != symtab->end()) { - ccprintf(os, "<%s", it->name); - Addr delta = target - it->address; + ccprintf(os, "<%s", it->name()); + Addr delta = target - it->address(); if (delta) ccprintf(os, "+%d>", delta); else @@ -486,9 +486,9 @@ ArmStaticInst::printMemSymbol(std::ostream &os, if (symtab) { auto it = symtab->findNearest(addr); if (it != symtab->end()) { - ccprintf(os, "%s%s", prefix, it->name); - if (it->address != addr) - ccprintf(os, "+%d", addr - it->address); + ccprintf(os, "%s%s", prefix, it->name()); + if (it->address() != addr) + ccprintf(os, "+%d", addr - it->address()); ccprintf(os, suffix); } } diff --git a/src/arch/generic/linux/threadinfo.hh b/src/arch/generic/linux/threadinfo.hh index 70511c47fa..8af6d6f1de 100644 --- a/src/arch/generic/linux/threadinfo.hh +++ b/src/arch/generic/linux/threadinfo.hh @@ -60,7 +60,7 @@ class ThreadInfo return false; } - data = TranslatingPortProxy(tc).read(it->address, byteOrder); + data = TranslatingPortProxy(tc).read(it->address(), byteOrder); return true; } diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index 1b7c1057b6..0da32eb7ca 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -194,7 +194,7 @@ output decoder {{ loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) - ss << it->name; + ss << it->name(); else ccprintf(ss, "%#x", target); @@ -214,7 +214,7 @@ output decoder {{ } else if (_numSrcRegs == 0) { loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(disp)) != symtab->end()) - ss << it->name; + ss << it->name(); else ccprintf(ss, "0x%x", disp); } else if (_numSrcRegs == 1) { diff --git a/src/arch/power/insts/branch.cc b/src/arch/power/insts/branch.cc index b68f89bf9b..c422c5d535 100644 --- a/src/arch/power/insts/branch.cc +++ b/src/arch/power/insts/branch.cc @@ -97,7 +97,7 @@ BranchOp::generateDisassembly( loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) - ss << it->name; + ss << it->name(); else ccprintf(ss, "%#x", target); @@ -149,7 +149,7 @@ BranchDispCondOp::generateDisassembly( loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) - ss << it->name; + ss << it->name(); else ccprintf(ss, "%#x", target); diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index d31aca2faf..88b462d7a2 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -122,8 +122,8 @@ PowerProcess::initState() loader::Symbol symbol = sym; // Try to read entry point from function descriptor - if (initVirtMem->tryReadBlob(sym.address, &entry, sizeof(Addr))) - symbol.address = gtoh(entry, byteOrder); + if (initVirtMem->tryReadBlob(sym.address(), &entry, sizeof(Addr))) + symbol.relocate(gtoh(entry, byteOrder)); symbolTable->insert(symbol); } diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index 2946d6c324..78572e647b 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -86,8 +86,8 @@ BootloaderKernelWorkload::loadBootloaderSymbolTable() bootloaderSymbolTable.offset( bootloader_paddr_offset )->functionSymbols()->rename( - [](std::string &name) { - name = "bootloader." + name; + [](const std::string &name) { + return "bootloader." + name; } ); loader::debugSymbolTable.insert(*renamedBootloaderSymbolTable); @@ -102,8 +102,8 @@ BootloaderKernelWorkload::loadKernelSymbolTable() kernelSymbolTable = kernel->symtab(); auto renamedKernelSymbolTable = \ kernelSymbolTable.functionSymbols()->rename( - [](std::string &name) { - name = "kernel." + name; + [](const std::string &name) { + return "kernel." + name; } ); loader::debugSymbolTable.insert(*renamedKernelSymbolTable); diff --git a/src/arch/sparc/insts/branch.cc b/src/arch/sparc/insts/branch.cc index 84861cc2c3..7109f9a95d 100644 --- a/src/arch/sparc/insts/branch.cc +++ b/src/arch/sparc/insts/branch.cc @@ -88,9 +88,9 @@ BranchDisp::generateDisassembly( loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->findNearest(target)) != symtab->end()) { - ccprintf(response, " <%s", it->name); - if (it->address != target) - ccprintf(response, "+%d>", target - it->address); + ccprintf(response, " <%s", it->name()); + if (it->address() != target) + ccprintf(response, "+%d>", target - it->address()); else ccprintf(response, ">"); } diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 5eef4cb44c..5b2cda6894 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013, 2019 ARM Limited + * Copyright (c) 2011-2013, 2019, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -178,48 +178,51 @@ ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd) if (!sym_name || sym_name[0] == '$') continue; - loader::Symbol symbol; - symbol.address = sym.st_value; - symbol.name = sym_name; - + loader::Symbol::Binding binding = + loader::Symbol::Binding::Global; switch (GELF_ST_BIND(sym.st_info)) { case STB_GLOBAL: - symbol.binding = loader::Symbol::Binding::Global; + binding = loader::Symbol::Binding::Global; break; case STB_LOCAL: - symbol.binding = loader::Symbol::Binding::Local; + binding = loader::Symbol::Binding::Local; break; case STB_WEAK: - symbol.binding = loader::Symbol::Binding::Weak; + binding = loader::Symbol::Binding::Weak; break; default: continue; } + loader::Symbol::SymbolType symbol_type = + loader::Symbol::SymbolType::NoType; switch (GELF_ST_TYPE(sym.st_info)) { case STT_NOTYPE: - symbol.type = loader::Symbol::SymbolType::NoType; + symbol_type = loader::Symbol::SymbolType::NoType; break; case STT_OBJECT: - symbol.type = loader::Symbol::SymbolType::Object; + symbol_type = loader::Symbol::SymbolType::Object; break; case STT_FUNC: - symbol.type = loader::Symbol::SymbolType::Function; + symbol_type = loader::Symbol::SymbolType::Function; break; case STT_SECTION: - symbol.type = loader::Symbol::SymbolType::Section; + symbol_type = loader::Symbol::SymbolType::Section; break; case STT_FILE: - symbol.type = loader::Symbol::SymbolType::File; + symbol_type = loader::Symbol::SymbolType::File; break; default: - symbol.type = loader::Symbol::SymbolType::Other; + symbol_type = loader::Symbol::SymbolType::Other; break; } + loader::Symbol symbol( + binding, symbol_type, sym_name, sym.st_value); + if (_symtab.insert(symbol)) { DPRINTF(Loader, "Symbol: %-40s value %#x.\n", - symbol.name, symbol.address); + symbol.name(), symbol.address()); } } } diff --git a/src/base/loader/symtab.cc b/src/base/loader/symtab.cc index cd7bec3d56..eb63ccbff6 100644 --- a/src/base/loader/symtab.cc +++ b/src/base/loader/symtab.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 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) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -53,17 +65,17 @@ SymbolTable::clear() bool SymbolTable::insert(const Symbol &symbol) { - if (symbol.name.empty()) + if (symbol.name().empty()) return false; int idx = symbols.size(); - if (!nameMap.insert({ symbol.name, idx }).second) + if (!nameMap.insert({ symbol.name(), idx }).second) return false; // There can be multiple symbols for the same address, so always // update the addrTable multimap when we see a new symbol name. - addrMap.insert({ symbol.address, idx }); + addrMap.insert({ symbol.address(), idx }); symbols.emplace_back(symbol); @@ -98,10 +110,11 @@ SymbolTable::serialize(const std::string &base, CheckpointOut &cp) const int i = 0; for (auto &symbol: symbols) { - paramOut(cp, csprintf("%s.addr_%d", base, i), symbol.address); - paramOut(cp, csprintf("%s.symbol_%d", base, i), symbol.name); - paramOut(cp, csprintf("%s.binding_%d", base, i), (int)symbol.binding); - paramOut(cp, csprintf("%s.type_%d", base, i), (int)symbol.type); + paramOut(cp, csprintf("%s.addr_%d", base, i), symbol.address()); + paramOut(cp, csprintf("%s.symbol_%d", base, i), symbol.name()); + paramOut(cp, csprintf("%s.binding_%d", base, i), + (int)symbol.binding()); + paramOut(cp, csprintf("%s.type_%d", base, i), (int)symbol.type()); i++; } } @@ -125,7 +138,7 @@ SymbolTable::unserialize(const std::string &base, CheckpointIn &cp, binding = default_binding; if (!optParamIn(cp, csprintf("%s.type_%d", base, i), type)) type = Symbol::SymbolType::Other; - insert({binding, type, name, address}); + insert(Symbol(binding, type, name, address)); } } diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 654064c9db..953ca39889 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 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 Daniel R. Carvalho * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. @@ -47,8 +59,9 @@ namespace gem5 namespace loader { -struct Symbol +class Symbol { + public: enum class Binding { Global, @@ -67,12 +80,46 @@ struct Symbol Other }; - Binding binding; - SymbolType type; - std::string name; - Addr address; + Symbol(const Binding binding, const SymbolType type, + const std::string & name, const Addr addr) + : _binding(binding), _type(type), _name(name), _address(addr) + {} + + Symbol(const Symbol & other) = default; + Symbol & operator=(const Symbol & other) = default; + + Binding binding() const { + return _binding; + } + + SymbolType type() const { + return _type; + } + + std::string name() const { + return _name; + } + + void rename(const std::string & new_name) { + _name = new_name; + } + + Addr address() const { + return _address; + } + + void relocate(const Addr new_addr) { + _address = new_addr; + } + + private: + Binding _binding; + SymbolType _type; + std::string _name; + Addr _address; }; + class SymbolTable { public: @@ -171,7 +218,7 @@ class SymbolTable filterByBinding(Symbol::Binding binding) const { auto filt = [binding](const Symbol &symbol) { - return symbol.binding == binding; + return symbol.binding() == binding; }; return filter(filt); } @@ -187,7 +234,7 @@ class SymbolTable filterBySymbolType(const Symbol::SymbolType& symbol_type) const { auto filt = [symbol_type](const Symbol &symbol) { - return symbol.type == symbol_type; + return symbol.type() == symbol_type; }; return filter(filt); } @@ -242,9 +289,9 @@ class SymbolTable { SymTabOp op = [addr_offset](SymbolTable &symtab, const Symbol &symbol) { - Symbol sym = symbol; - sym.address += addr_offset; - symtab.insert(sym); + symtab.insert( + Symbol(symbol.binding(), symbol.type(), symbol.name(), + symbol.address() + addr_offset)); }; return operate(op); } @@ -260,9 +307,9 @@ class SymbolTable mask(Addr m) const { SymTabOp op = [m](SymbolTable &symtab, const Symbol &symbol) { - Symbol sym = symbol; - sym.address &= m; - symtab.insert(sym); + symtab.insert( + Symbol(symbol.binding(), symbol.type(), symbol.name(), + symbol.address() & m)); }; return operate(op); } @@ -275,11 +322,11 @@ class SymbolTable * @retval SymbolTablePtr A pointer to the modified SymbolTable copy. */ SymbolTablePtr - rename(std::function func) const + rename(std::function func) const { SymTabOp op = [func](SymbolTable &symtab, const Symbol &symbol) { Symbol sym = symbol; - func(sym.name); + sym.rename(func(sym.name())); symtab.insert(sym); }; return operate(op); diff --git a/src/base/loader/symtab.test.cc b/src/base/loader/symtab.test.cc index 1705a4165c..9a7b8c86b9 100644 --- a/src/base/loader/symtab.test.cc +++ b/src/base/loader/symtab.test.cc @@ -52,26 +52,26 @@ getSymbolError(const loader::Symbol& symbol, const loader::Symbol& expected) { std::stringstream ss; - if (symbol.binding != expected.binding) { + if (symbol.binding() != expected.binding()) { ss << " symbols' bindings do not match: seen `" << - (int)symbol.binding << "`, expected `" << - (int)expected.binding << "`.\n"; + (int)symbol.binding() << "`, expected `" << + (int)expected.binding() << "`.\n"; } - if (symbol.type != expected.type) { + if (symbol.type() != expected.type()) { ss << " symbols' types do not match: seen `" << - (int)symbol.type << "`, expected `" << - (int)expected.type << "`.\n"; + (int)symbol.type() << "`, expected `" << + (int)expected.type() << "`.\n"; } - if (symbol.name != expected.name) { - ss << " symbols' names do not match: seen `" << symbol.name << - "`, expected `" << expected.name << "`.\n"; + if (symbol.name() != expected.name()) { + ss << " symbols' names do not match: seen `" << symbol.name() << + "`, expected `" << expected.name() << "`.\n"; } - if (symbol.address != expected.address) { + if (symbol.address() != expected.address()) { ss << " symbols' addresses do not match: seen `" << - symbol.address << "`, expected `" << expected.address << "`.\n"; + symbol.address() << "`, expected `" << expected.address() << "`.\n"; } // No error, symbols match @@ -273,12 +273,12 @@ TEST(LoaderSymtabTest, Offset) // Check that the new table is offset loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].type, symbols[0].name, - symbols[0].address + offset}, - {symbols[1].binding, symbols[1].type, symbols[1].name, - symbols[1].address + offset}, - {symbols[2].binding, symbols[2].type, symbols[2].name, - symbols[2].address + offset}, + {symbols[0].binding(), symbols[0].type(), symbols[0].name(), + symbols[0].address() + offset}, + {symbols[1].binding(), symbols[1].type(), symbols[1].name(), + symbols[1].address() + offset}, + {symbols[2].binding(), symbols[2].type(), symbols[2].name(), + symbols[2].address() + offset}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2]})); @@ -316,14 +316,14 @@ TEST(LoaderSymtabTest, Mask) // Check that the new table is masked loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].type, symbols[0].name, - symbols[0].address & mask}, - {symbols[1].binding, symbols[1].type, symbols[1].name, - symbols[1].address & mask}, - {symbols[2].binding, symbols[2].type, symbols[2].name, - symbols[2].address & mask}, - {symbols[3].binding, symbols[3].type, symbols[3].name, - symbols[3].address & mask}, + {symbols[0].binding(), symbols[0].type(), symbols[0].name(), + symbols[0].address() & mask}, + {symbols[1].binding(), symbols[1].type(), symbols[1].name(), + symbols[1].address() & mask}, + {symbols[2].binding(), symbols[2].type(), symbols[2].name(), + symbols[2].address() & mask}, + {symbols[3].binding(), symbols[3].type(), symbols[3].name(), + symbols[3].address() & mask}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2], expected_symbols[3]})); @@ -353,7 +353,7 @@ TEST(LoaderSymtabTest, Rename) EXPECT_TRUE(symtab.insert(symbols[3])); const auto symtab_new = - symtab.rename([](std::string &name) { name = name + "_suffix"; }); + symtab.rename([](const std::string &name) { return name + "_suffix"; }); // Check that the original table is not modified ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2], @@ -361,14 +361,14 @@ TEST(LoaderSymtabTest, Rename) // Check that the new table's symbols have been renamed loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].type, symbols[0].name + "_suffix", - symbols[0].address}, - {symbols[1].binding, symbols[1].type, symbols[1].name + "_suffix", - symbols[1].address}, - {symbols[2].binding, symbols[2].type, symbols[2].name + "_suffix", - symbols[2].address}, - {symbols[3].binding, symbols[3].type, symbols[3].name + "_suffix", - symbols[3].address}, + {symbols[0].binding(), symbols[0].type(), symbols[0].name() + "_suffix", + symbols[0].address()}, + {symbols[1].binding(), symbols[1].type(), symbols[1].name() + "_suffix", + symbols[1].address()}, + {symbols[2].binding(), symbols[2].type(), symbols[2].name() + "_suffix", + symbols[2].address()}, + {symbols[3].binding(), symbols[3].type(), symbols[3].name() + "_suffix", + symbols[3].address()}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2], expected_symbols[3]})); @@ -398,10 +398,12 @@ TEST(LoaderSymtabTest, RenameNonUnique) EXPECT_TRUE(symtab.insert(symbols[3])); int i = 0; - const auto symtab_new = symtab.rename([&i](std::string &name) + const auto symtab_new = symtab.rename([&i](const std::string &name) { if ((i++ % 2) == 0) { - name = "NonUniqueName"; + return std::string("NonUniqueName"); + } else { + return name; } }); @@ -412,12 +414,12 @@ TEST(LoaderSymtabTest, RenameNonUnique) // Check that the new table's symbols have been renamed, yet it does not // contain the symbols with duplicated names loader::Symbol expected_symbols[] = { - {symbols[0].binding, symbols[0].type, "NonUniqueName", - symbols[0].address}, - {symbols[1].binding, symbols[1].type, symbols[1].name, - symbols[1].address}, - {symbols[3].binding, symbols[3].type, symbols[3].name, - symbols[3].address}, + {symbols[0].binding(), symbols[0].type(), "NonUniqueName", + symbols[0].address()}, + {symbols[1].binding(), symbols[1].type(), symbols[1].name(), + symbols[1].address()}, + {symbols[3].binding(), symbols[3].type(), symbols[3].name(), + symbols[3].address()}, }; ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0], expected_symbols[1], expected_symbols[2]})); @@ -597,7 +599,7 @@ TEST(LoaderSymtabTest, FindUniqueAddress) EXPECT_TRUE(symtab.insert(symbols[1])); EXPECT_TRUE(symtab.insert(symbols[2])); - const auto it = symtab.find(symbols[2].address); + const auto it = symtab.find(symbols[2].address()); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[2]); } @@ -622,7 +624,7 @@ TEST(LoaderSymtabTest, FindNonUniqueAddress) EXPECT_TRUE(symtab.insert(symbols[1])); EXPECT_TRUE(symtab.insert(symbols[2])); - const auto it = symtab.find(symbols[1].address); + const auto it = symtab.find(symbols[1].address()); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[1]); } @@ -658,7 +660,7 @@ TEST(LoaderSymtabTest, FindExistingName) EXPECT_TRUE(symtab.insert(symbols[1])); EXPECT_TRUE(symtab.insert(symbols[2])); - const auto it = symtab.find(symbols[1].name); + const auto it = symtab.find(symbols[1].name()); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[1]); } @@ -677,7 +679,7 @@ TEST(LoaderSymtabTest, FindNearestExact) EXPECT_TRUE(symtab.insert(symbols[0])); EXPECT_TRUE(symtab.insert(symbols[1])); - const auto it = symtab.findNearest(symbols[1].address); + const auto it = symtab.findNearest(symbols[1].address()); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[1]); } @@ -695,7 +697,7 @@ TEST(LoaderSymtabTest, FindNearestRound) "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); - const auto it = symtab.findNearest(symbol.address + 0x1); + const auto it = symtab.findNearest(symbol.address() + 0x1); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbol); } @@ -719,10 +721,10 @@ TEST(LoaderSymtabTest, FindNearestRoundWithNext) EXPECT_TRUE(symtab.insert(symbols[1])); Addr next_addr; - const auto it = symtab.findNearest(symbols[0].address + 0x1, next_addr); + const auto it = symtab.findNearest(symbols[0].address() + 0x1, next_addr); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[0]); - ASSERT_EQ(next_addr, symbols[1].address); + ASSERT_EQ(next_addr, symbols[1].address()); } /** @@ -740,7 +742,7 @@ TEST(LoaderSymtabTest, FindNearestRoundWithNextNonExistent) EXPECT_TRUE(symtab.insert(symbol)); Addr next_addr; - const auto it = symtab.findNearest(symbol.address + 0x1, next_addr); + const auto it = symtab.findNearest(symbol.address() + 0x1, next_addr); ASSERT_NE(it, symtab.end()); ASSERT_PRED_FORMAT2(checkSymbol, *it, symbol); ASSERT_EQ(next_addr, 0); @@ -759,7 +761,7 @@ TEST(LoaderSymtabTest, FindNearestNonExistent) "symbol", 0x10}; EXPECT_TRUE(symtab.insert(symbol)); - const auto it = symtab.findNearest(symbol.address - 0x1); + const auto it = symtab.findNearest(symbol.address() - 0x1); ASSERT_EQ(it, symtab.end()); } diff --git a/src/cpu/base.cc b/src/cpu/base.cc index bea21a1928..9e015f8c16 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012,2016-2017, 2019-2020 ARM Limited + * Copyright (c) 2011-2012,2016-2017, 2019-2020 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -795,8 +795,8 @@ BaseCPU::traceFunctionsInternal(Addr pc) currentFunctionStart = pc; currentFunctionEnd = pc + 1; } else { - sym_str = it->name; - currentFunctionStart = it->address; + sym_str = it->name(); + currentFunctionStart = it->address(); } ccprintf(*functionTraceStream, " (%d)\n%d: %s", diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 6cd5269fa7..2be3557d4b 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -81,11 +81,11 @@ ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran) if (debug::ExecSymbol && (!FullSystem || !in_user_mode) && (it = loader::debugSymbolTable.findNearest(cur_pc)) != loader::debugSymbolTable.end()) { - Addr delta = cur_pc - it->address; + Addr delta = cur_pc - it->address(); if (delta) - ccprintf(outs, " @%s+%d", it->name, delta); + ccprintf(outs, " @%s+%d", it->name(), delta); else - ccprintf(outs, " @%s", it->name); + ccprintf(outs, " @%s", it->name()); } if (inst->isMicroop()) { diff --git a/src/cpu/profile.cc b/src/cpu/profile.cc index 25d739c381..06c8d46bc2 100644 --- a/src/cpu/profile.cc +++ b/src/cpu/profile.cc @@ -63,7 +63,7 @@ BaseStackTrace::tryGetSymbol(std::string &symbol, Addr addr, const auto it = symtab->find(addr); if (it == symtab->end()) return false; - symbol = it->name; + symbol = it->name(); return true; } @@ -151,7 +151,7 @@ FunctionProfile::sample(ProfileNode *node, Addr pc) auto it = symtab.findNearest(pc); if (it != symtab.end()) { - pc_count[it->address]++; + pc_count[it->address()]++; } else { // record PC even if we don't have a symbol to avoid // silently biasing the histogram diff --git a/src/kern/linux/helpers.cc b/src/kern/linux/helpers.cc index b024226985..4d1bb19542 100644 --- a/src/kern/linux/helpers.cc +++ b/src/kern/linux/helpers.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022 Arm Limited + * Copyright (c) 2016, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -125,9 +125,9 @@ dumpDmesg(ThreadContext *tc, std::ostream &os) return; } - uint32_t log_buf_len = proxy.read(lb_len->address, bo); - uint32_t log_first_idx = proxy.read(first->address, bo); - uint32_t log_next_idx = proxy.read(next->address, bo); + uint32_t log_buf_len = proxy.read(lb_len->address(), bo); + uint32_t log_first_idx = proxy.read(first->address(), bo); + uint32_t log_next_idx = proxy.read(next->address(), bo); if (log_first_idx >= log_buf_len || log_next_idx >= log_buf_len) { warn("dmesg pointers/length corrupted\n"); @@ -143,7 +143,7 @@ dumpDmesg(ThreadContext *tc, std::ostream &os) warn("Unexpected dmesg buffer length\n"); return; } - proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length); + proxy.readBlob(lb->address() + log_first_idx, log_buf.data(), length); } else { const int length_2 = log_buf_len - log_first_idx; if (length_2 < 0 || length_2 + log_next_idx > log_buf.size()) { @@ -151,8 +151,10 @@ dumpDmesg(ThreadContext *tc, std::ostream &os) return; } length = log_buf_len; - proxy.readBlob(lb->address + log_first_idx, log_buf.data(), length_2); - proxy.readBlob(lb->address, log_buf.data() + length_2, log_next_idx); + proxy.readBlob( + lb->address() + log_first_idx, log_buf.data(), length_2); + proxy.readBlob( + lb->address(), log_buf.data() + length_2, log_next_idx); } // Print dmesg buffer content @@ -498,7 +500,8 @@ dumpDmesgImpl(ThreadContext *tc, std::ostream &os) ringbuffer_t dynamic_rb; auto dynamic_rb_symbol = symtab.find("printk_rb_dynamic"); if (dynamic_rb_symbol != symtab_end_it) { - dynamic_rb = ringbuffer_t::read(proxy, dynamic_rb_symbol->address, bo); + dynamic_rb = + ringbuffer_t::read(proxy, dynamic_rb_symbol->address(), bo); } else { warn("Failed to find required dmesg symbols.\n"); return; @@ -508,7 +511,7 @@ dumpDmesgImpl(ThreadContext *tc, std::ostream &os) ringbuffer_t static_rb; auto static_rb_symbol = symtab.find("printk_rb_static"); if (static_rb_symbol != symtab_end_it) { - static_rb = ringbuffer_t::read(proxy, static_rb_symbol->address, bo); + static_rb = ringbuffer_t::read(proxy, static_rb_symbol->address(), bo); } else { warn("Failed to find required dmesg symbols.\n"); return; @@ -521,21 +524,22 @@ dumpDmesgImpl(ThreadContext *tc, std::ostream &os) auto active_ringbuffer_ptr_symbol = symtab.find("prb"); if (active_ringbuffer_ptr_symbol != symtab_end_it) { active_ringbuffer_ptr = - proxy.read(active_ringbuffer_ptr_symbol->address, bo); + proxy.read(active_ringbuffer_ptr_symbol->address(), + bo); } else { warn("Failed to find required dmesg symbols.\n"); return; } if (active_ringbuffer_ptr == 0 || - (active_ringbuffer_ptr != dynamic_rb_symbol->address && - active_ringbuffer_ptr != static_rb_symbol->address)) { + (active_ringbuffer_ptr != dynamic_rb_symbol->address() && + active_ringbuffer_ptr != static_rb_symbol->address())) { warn("Kernel Dmesg ringbuffer appears to be invalid.\n"); return; } ringbuffer_t & rb = - (active_ringbuffer_ptr == dynamic_rb_symbol->address) + (active_ringbuffer_ptr == dynamic_rb_symbol->address()) ? dynamic_rb : static_rb; atomic_var_t head_offset = rb.data.head_offset; diff --git a/src/sim/kernel_workload.cc b/src/sim/kernel_workload.cc index c338b23b16..27e27137a9 100644 --- a/src/sim/kernel_workload.cc +++ b/src/sim/kernel_workload.cc @@ -66,8 +66,8 @@ KernelWorkload::KernelWorkload(const Params &p) : Workload(p), kernelSymtab = kernelObj->symtab(); auto initKernelSymtab = kernelSymtab.mask(_loadAddrMask) ->offset(_loadAddrOffset) - ->rename([](std::string &name) { - name = "kernel_init." + name; + ->rename([](const std::string &name) { + return "kernel_init." + name; }); loader::debugSymbolTable.insert(*initKernelSymtab); diff --git a/src/sim/workload.hh b/src/sim/workload.hh index 10129379e0..727a283fd4 100644 --- a/src/sim/workload.hh +++ b/src/sim/workload.hh @@ -141,7 +141,7 @@ class Workload : public SimObject if (it == symtab.end()) return nullptr; - return new T(system, desc, fixFuncEventAddr(it->address), + return new T(system, desc, fixFuncEventAddr(it->address()), std::forward(args)...); } From 7ecff99c25d3e07cbcb764e466fdff4d69733e11 Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Thu, 30 Nov 2023 12:11:28 +0000 Subject: [PATCH 648/693] base: Add a size field to the Symbol object Add a size field to the Symbol objects in the Symbol Table. This allows client code to read the data associated with a symbol in cases where the data type/size is not known beforehand (e.g. if an object's size might be different between different versions of a workload/kernel). Access is mediated via the `sizeOrDefault()` method, which requires client code to specify a fallback size. Since correct size data may not be available (for example in legacy checkpoints), this forces the client code to consider the 'missing size data' case. Change-Id: If1a47463790b25beadf94f84382e3b7392ab2f04 Reviewed-by: Andreas Sandberg --- src/base/loader/elf_object.cc | 3 ++- src/base/loader/symtab.cc | 15 ++++++++++++++- src/base/loader/symtab.hh | 30 +++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 5b2cda6894..26fb443c79 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -218,7 +218,8 @@ ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd) } loader::Symbol symbol( - binding, symbol_type, sym_name, sym.st_value); + binding, symbol_type, sym_name, sym.st_value, + sym.st_size); if (_symtab.insert(symbol)) { DPRINTF(Loader, "Symbol: %-40s value %#x.\n", diff --git a/src/base/loader/symtab.cc b/src/base/loader/symtab.cc index eb63ccbff6..cea79c4cae 100644 --- a/src/base/loader/symtab.cc +++ b/src/base/loader/symtab.cc @@ -111,6 +111,10 @@ SymbolTable::serialize(const std::string &base, CheckpointOut &cp) const int i = 0; for (auto &symbol: symbols) { paramOut(cp, csprintf("%s.addr_%d", base, i), symbol.address()); + if (symbol.sizeIsValid()) { + paramOut(cp, csprintf("%s.size_%d", base, i), + symbol.sizeOrDefault(0x0)); + } paramOut(cp, csprintf("%s.symbol_%d", base, i), symbol.name()); paramOut(cp, csprintf("%s.binding_%d", base, i), (int)symbol.binding()); @@ -128,17 +132,26 @@ SymbolTable::unserialize(const std::string &base, CheckpointIn &cp, paramIn(cp, base + ".size", size); for (int i = 0; i < size; ++i) { Addr address; + size_t size; std::string name; Symbol::Binding binding = default_binding; Symbol::SymbolType type = Symbol::SymbolType::Other; paramIn(cp, csprintf("%s.addr_%d", base, i), address); + bool size_present = optParamIn( + cp, csprintf("%s.size_%d", base, i), size, false); paramIn(cp, csprintf("%s.symbol_%d", base, i), name); if (!optParamIn(cp, csprintf("%s.binding_%d", base, i), binding)) binding = default_binding; if (!optParamIn(cp, csprintf("%s.type_%d", base, i), type)) type = Symbol::SymbolType::Other; - insert(Symbol(binding, type, name, address)); + if (size_present) { + insert(Symbol(binding, type, name, address, size)); + } else { + warn_once( + "warning: one or more Symbols does not have a valid size."); + insert(Symbol(binding, type, name, address)); + } } } diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 953ca39889..d33ed85f63 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -80,9 +80,16 @@ class Symbol Other }; + Symbol(const Binding binding, const SymbolType type, + const std::string & name, const Addr addr, const size_t size) + : _binding(binding), _type(type), _name(name), _address(addr), + _size(size), _sizeIsValid(true) + {} + Symbol(const Binding binding, const SymbolType type, const std::string & name, const Addr addr) - : _binding(binding), _type(type), _name(name), _address(addr) + : _binding(binding), _type(type), _name(name), _address(addr), + _size(0x0), _sizeIsValid(false) {} Symbol(const Symbol & other) = default; @@ -112,11 +119,32 @@ class Symbol _address = new_addr; } + /** + * Return the Symbol size if it is valid, otherwise return the + * default value supplied. + * + * This method forces the client code to consider the possibility + * that the `SymbolTable` may contain `Symbol`s that do not have + * valid sizes. + */ + size_t sizeOrDefault(const size_t default_size) const { + return _sizeIsValid ? _size : default_size; + } + + /** + * Return whether the Symbol size is valid or not. + */ + bool sizeIsValid() const { + return _sizeIsValid; + } + private: Binding _binding; SymbolType _type; std::string _name; Addr _address; + size_t _size; + bool _sizeIsValid; }; From f21df19fd7204f5b8a12d96adfef89fd9d8738e7 Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Wed, 22 Nov 2023 08:50:11 +0000 Subject: [PATCH 649/693] misc: Add function to extract the Linux Kernel Version This function, `extract_kernel_version`, attempts to find the Kernel version by searching the `uts_namespace` struct at the exported symbol `init_uts_ns`. This structure contains the Kernel version as a string, and is referenced by `procfs` to return the Kernel version in a running system. Different versions of the Kernel use different layouts for this structure, and the top level structure is marked as `__randomize_layout`, so the exact layout in memory cannot be relied on. Because of this, `extract_kernel_version` takes the approach of searching the memory holding the structure for printable strings, and parsing the version from those strings. Change-Id: If8b2e81a041af891fd6e56a87346a341df3c9728 Reviewed-by: Andreas Sandberg --- src/kern/linux/helpers.cc | 100 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/kern/linux/helpers.cc b/src/kern/linux/helpers.cc index 4d1bb19542..d153a75504 100644 --- a/src/kern/linux/helpers.cc +++ b/src/kern/linux/helpers.cc @@ -37,7 +37,10 @@ #include "kern/linux/helpers.hh" +#include +#include #include +#include #include "base/compiler.hh" #include "base/loader/object_file.hh" @@ -585,6 +588,103 @@ dumpDmesgImpl(ThreadContext *tc, std::ostream &os) } } +/** Extract all null-terminated printable strings from a buffer and + * return them as a vector. + * + */ +std::vector +extract_printable_strings(const std::vector buffer) +{ + std::vector results; + std::string result; + bool reading_printable = false; + for (const uint8_t byte: buffer) { + if (std::isprint(byte)) { + result += static_cast(byte); + reading_printable = true; + } else if (reading_printable) { + if (byte == '\0') { + results.push_back(result); + } + result.clear(); + reading_printable = false; + } + } + return results; +} + +/** Try to extract the Linux Kernel Version. + * + * This function attempts to find the Kernel version by searching the + * `uts_namespace` struct at the exported symbol `init_uts_ns`. This + * structure contains the Kernel version as a string, and is + * referenced by `procfs` to return the Kernel version in a running + * system. + * + * Different versions of the Kernel use different layouts for this + * structure, and the top level structure is marked as + * `__randomize_layout`, so the exact layout in memory cannot be + * relied on. Because of this, `extract_kernel_version` takes the + * approach of searching the memory holding the structure for + * printable strings, and parsing the version from those strings. + * + * If a likely match is found, the version is packed into a uint32_t + * in the standard format used by the Linux kernel (which allows + * numerical comparison of version numbers) and returned. + * + * If no likely match is found, 0x0 is returned to indicate an error. + * + */ +[[maybe_unused]] +uint32_t +extract_kernel_version(ThreadContext* tc) { + System *system = tc->getSystemPtr(); + const auto &symtab = system->workload->symtab(tc); + auto symtab_end_it = symtab.end(); + + auto symbol = symtab.find("init_uts_ns"); + if (symbol == symtab_end_it) { + return 0x0; + } + + // Use size of `init_uts_ns` in Linux v5.18.0 as a default. + // (e.g. for upgraded checkpoints.) + const size_t INIT_UTS_NS_SIZE_DEFAULT = 432; + const size_t BUFFER_SIZE = + symbol->sizeOrDefault(INIT_UTS_NS_SIZE_DEFAULT); + + TranslatingPortProxy proxy(tc); + std::vector buffer(BUFFER_SIZE); + proxy.readBlob( + symbol->address(), buffer.data(), buffer.size() * sizeof(uint8_t)); + auto strings = extract_printable_strings(buffer); + + const std::regex version_re {"^(\\d+)\\.(\\d+)\\.(\\d)+$"}; + std::smatch match; + for (const auto& string: strings) { + if (std::regex_search(string, match, version_re)) { + try { + int major = std::stoi(match[1]); + int minor = std::stoi(match[2]); + int point = std::stoi(match[3]); + return ( + (major & 0xFF) << 16 + | (minor & 0xFF) << 8 + | std::min(point, 255)); + } + catch (const std::invalid_argument &) { + // This shouldn't be possible if the regex matched. + continue; + } + catch (const std::out_of_range &) { + continue; + } + } + } + + return 0x0; +} + /** Dump the kernel Dmesg ringbuffer for Linux versions post-v5.10. * * Delegates to an architecture specific template funtion instance. From ccb8b3096711bc9b371af371d399da7f47e4fe50 Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Wed, 22 Nov 2023 08:59:01 +0000 Subject: [PATCH 650/693] misc: Update Dmesg dump for changes to printk in Linux v5.18+. Linux v5.18+ changed the format of one of the data structures used to implement the printk ring buffer. This caused the gem5 feature to dump the printk messages on Kernel panic to fail for Kernels 5.18.0 and later. This patch updates the printk messages dump feature to support the new printk ring buffer format when Kernels 5.18 and later are detected. This patch addresses gem5 Issue #550: https://github.com/gem5/gem5/issues/550 Change-Id: I533d539eafb83c44eeb4b9fbbcdd9c172fd398e6 Reported-by: Hoa Nguyen Reviewed-by: Andreas Sandberg --- src/kern/linux/helpers.cc | 83 +++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/src/kern/linux/helpers.cc b/src/kern/linux/helpers.cc index d153a75504..97b363c864 100644 --- a/src/kern/linux/helpers.cc +++ b/src/kern/linux/helpers.cc @@ -266,6 +266,41 @@ struct GEM5_PACKED DmesgInfoRecord } }; +/** Metadata struct for Linux pre-v5.18.0 + * + */ +template +struct Metadata_Pre_v5_18_0 +{ + using atomic_var_t = AtomicVarType; + using guest_ptr_t = + typename std::make_unsigned_t; + unsigned int mask_bits; + guest_ptr_t metadata_ring_ptr; + guest_ptr_t info_ring_ptr; + atomic_var_t unused1; + atomic_var_t unused2; +}; + + +/** Metadata struct for Linux post-v5.18.0 + * + */ +template +struct Metadata_Post_v5_18_0 +{ + using atomic_var_t = AtomicVarType; + using guest_ptr_t = + typename std::make_unsigned_t; + unsigned int mask_bits; + guest_ptr_t metadata_ring_ptr; + guest_ptr_t info_ring_ptr; + atomic_var_t unused1; + atomic_var_t unused2; + atomic_var_t unused3; +}; + + /** Top-level ringbuffer record for the Linux dmesg ringbuffer, post-v5.10. * * Struct data members are compatible with the equivalent Linux data @@ -276,7 +311,7 @@ struct GEM5_PACKED DmesgInfoRecord * the gem5 world, and reading/generating appropriate masks. * */ -template +template struct GEM5_PACKED DmesgRingbuffer { static_assert( @@ -291,14 +326,9 @@ struct GEM5_PACKED DmesgRingbuffer using metadata_record_t = DmesgMetadataRecord; // Struct data members - struct - { - unsigned int mask_bits; - guest_ptr_t metadata_ring_ptr; - guest_ptr_t info_ring_ptr; - atomic_var_t unused1; - atomic_var_t unused2; - } metadata; + + // Metadata struct size depends on the Linux Kernel Version + MetadataStructType metadata; struct { unsigned int mask_bits; @@ -391,9 +421,16 @@ struct GEM5_PACKED DmesgRingbuffer } }; -// Aliases for the two types of Ringbuffer that could be used. -using Linux64_Ringbuffer = DmesgRingbuffer; -using Linux32_Ringbuffer = DmesgRingbuffer; +// Aliases for the types of Ringbuffer that could be used. +using Linux64_Ringbuffer_Pre_v5_18_0 = + DmesgRingbuffer>; +using Linux32_Ringbuffer_Pre_v5_18_0 = + DmesgRingbuffer>; + +using Linux64_Ringbuffer_Post_v5_18_0 = + DmesgRingbuffer>; +using Linux32_Ringbuffer_Post_v5_18_0 = + DmesgRingbuffer>; /** Print the record at the specified offset into the data ringbuffer, * and return the offset of the next entry in the data ringbuffer, @@ -635,7 +672,6 @@ extract_printable_strings(const std::vector buffer) * If no likely match is found, 0x0 is returned to indicate an error. * */ -[[maybe_unused]] uint32_t extract_kernel_version(ThreadContext* tc) { System *system = tc->getSystemPtr(); @@ -695,11 +731,26 @@ dumpDmesg(ThreadContext *tc, std::ostream &os) { System *system = tc->getSystemPtr(); const bool os_is_64_bit = loader::archIs64Bit(system->workload->getArch()); + const uint32_t kernel_version = extract_kernel_version(tc); + const uint32_t KERNEL_5_18_0 = 0x00051200; - if (os_is_64_bit) { - dumpDmesgImpl(tc, os); + if (kernel_version == 0x0) { + warn("Could not determine Linux Kernel version. " + "Assuming post-v5.18.0\n"); + } + + if (kernel_version == 0x0 || kernel_version >= KERNEL_5_18_0) { + if (os_is_64_bit) { + dumpDmesgImpl(tc, os); + } else { + dumpDmesgImpl(tc, os); + } } else { - dumpDmesgImpl(tc, os); + if (os_is_64_bit) { + dumpDmesgImpl(tc, os); + } else { + dumpDmesgImpl(tc, os); + } } } From 39fd61d7ddea49e5ab0cdcada5c734a6826f3636 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Fri, 1 Dec 2023 14:03:59 -0800 Subject: [PATCH 651/693] misc: Fix precommit install (#634) Previously, the `subprocess` module was used to execute shell command installing precommit hook. However, after #431 [1], the import of the `subprocess` module was overriden by `asyncio.subprocess`, which has a different API to execute the shell command. This change removes the `asyncio.subprocess` import. [1] https://github.com/gem5/gem5/pull/431 Change-Id: I9a7d51f85518089d258ab57c5d849a36dcf128e9 Signed-off-by: Hoa Nguyen --- site_scons/site_tools/git.py | 1 - 1 file changed, 1 deletion(-) diff --git a/site_scons/site_tools/git.py b/site_scons/site_tools/git.py index 40e5d6267e..dea6d8e152 100644 --- a/site_scons/site_tools/git.py +++ b/site_scons/site_tools/git.py @@ -41,7 +41,6 @@ import os import subprocess import sys -from asyncio import subprocess import gem5_scons.util import SCons.Script From 9d108826b07386ceaa875d6668786c4551440cf8 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Fri, 1 Dec 2023 15:19:17 -0800 Subject: [PATCH 652/693] tests: fix artifact reference in HACC tests (#638) Change-Id: I181f17a598885b59c186ff7e810d5b8b3b304e05 --- .github/workflows/gpu-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gpu-tests.yaml b/.github/workflows/gpu-tests.yaml index 8e26873159..a60218e6e7 100644 --- a/.github/workflows/gpu-tests.yaml +++ b/.github/workflows/gpu-tests.yaml @@ -76,7 +76,7 @@ jobs: ref: develop - uses: actions/download-artifact@v3 with: - name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-gcn3 + name: weekly-test-${{ github.run_number }}-attempt-${{ github.run_attempt }}-gem5-build-vega path: build/VEGA_X86 - run: chmod u+x build/VEGA_X86/gem5.opt - name: make hip directory From 84efeb976a23d27fcb737d01cd3fe419143711ff Mon Sep 17 00:00:00 2001 From: Robert Hauser <85344819+robhau@users.noreply.github.com> Date: Sat, 2 Dec 2023 01:18:51 +0100 Subject: [PATCH 653/693] systemc: Bugfix in TlmToGem5Bridge (#615) In handleBeginReq, a timing request is sent. If the receiver rejects the request, the bridge will save the pointers of the original transaction object and the generated gem5 packet. After a recvReqRetry-signal and a successful timing request, the variable for transaction object pointer, but not for the gem5 packet, is set to nullptr. When a new transaction with the phase BEGIN_REQ arrives, the assertion in handleBeginReq that there is no pending gem5 packet fails. Therefore, the variable pendingPacket has to be set to nullptr in recvReqRetry after a successful timing request too. Change-Id: I876f8f88e1893e8fdfa3441ed2ae5ddc39cef2ce Co-authored-by: Robert Hauser --- src/systemc/tlm_bridge/tlm_to_gem5.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/systemc/tlm_bridge/tlm_to_gem5.cc b/src/systemc/tlm_bridge/tlm_to_gem5.cc index c02efe7437..036ca738ca 100644 --- a/src/systemc/tlm_bridge/tlm_to_gem5.cc +++ b/src/systemc/tlm_bridge/tlm_to_gem5.cc @@ -540,6 +540,7 @@ TlmToGem5Bridge::recvReqRetry() trans.release(); pendingRequest = nullptr; + pendingPacket = nullptr; } } From ecb72b74f831d2a8495944be2f4f874d63ad1dbe Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Fri, 1 Dec 2023 17:05:41 -0800 Subject: [PATCH 654/693] misc: Add gem5_build/ to .gitignore (#642) The website's documentation on building gem5 now references /gem5_build in addition to /build. So, we should ignore files in that directory as well as the build directory. Change-Id: Ie226545e04b885ce81b3c17e18b5052ed64af328 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8aaf08f076..d1904756d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build +gem5_build parser.out parsetab.py cscope.files From d9c870f6417c7c344e898c5e9d69912f79aa3033 Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Sat, 2 Dec 2023 01:33:59 +0000 Subject: [PATCH 655/693] sim: Rework the Linux Kernel exit events (#639) This patch reworks the Linux Kernel panic and oops events. The code has been re-factored to provide re-usable events that can be applied to all ISAs from the base `KernelWorkload` `SimObject`. At the moment they are installed for the Arm workloads. This update also provides more configuration options that can be specified using the new `KernelPanicOopsBehaviour` enum. The options are applied to the Kernel Workload parameters `on_panic` and `on_oops` which are available to all subclasses of `KernelWorkload`. The main rationale for this reworking is to add the option to cleanly exit the simulation after dumping the Dmesg buffer. Without this option, the simulation would continue running after a Kernel panic. If system components (e.g. a system timer) keep the event queue alive, this causes the simulation to run slowly to the maximum allowed tick. --- src/arch/arm/linux/fs_workload.cc | 29 +++++++++++----------- src/kern/linux/events.cc | 30 +++++++++++----------- src/kern/linux/events.hh | 41 +++++++++---------------------- src/sim/SConscript | 16 ++++++++++-- src/sim/Workload.py | 34 +++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 61 deletions(-) diff --git a/src/arch/arm/linux/fs_workload.cc b/src/arch/arm/linux/fs_workload.cc index 26146ef001..81bc5ae1ca 100644 --- a/src/arch/arm/linux/fs_workload.cc +++ b/src/arch/arm/linux/fs_workload.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013, 2016, 2020 ARM Limited + * Copyright (c) 2010-2013, 2016, 2020, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -228,21 +228,22 @@ FsLinux::startup() } } - const std::string dmesg_output = name() + ".dmesg"; - if (params().panic_on_panic) { - kernelPanic = addKernelFuncEventOrPanic( - "panic", "Kernel panic in simulated kernel", dmesg_output); - } else { - kernelPanic = addKernelFuncEventOrPanic( - "panic", "Kernel panic in simulated kernel", dmesg_output); + const std::string dmesg_output_fname = name() + ".dmesg"; + + kernelPanic = addKernelFuncEvent( + "panic", "Kernel panic in simulated kernel", + dmesg_output_fname, params().on_panic); + if (kernelPanic == nullptr) { + warn("Could not add Kernel Panic event handler. " + "`panic` symbol not found."); } - if (params().panic_on_oops) { - kernelOops = addKernelFuncEventOrPanic( - "oops_exit", "Kernel oops in guest", dmesg_output); - } else { - kernelOops = addKernelFuncEventOrPanic( - "oops_exit", "Kernel oops in guest", dmesg_output); + kernelOops = addKernelFuncEvent( + "oops_exit", "Kernel oops in guest", + dmesg_output_fname, params().on_oops); + if (kernelOops == nullptr) { + warn("Could not add Kernel Oops event handler. " + "`oops_exit` symbol not found."); } // With ARM udelay() is #defined to __udelay diff --git a/src/kern/linux/events.cc b/src/kern/linux/events.cc index 35767596af..721bac8a45 100644 --- a/src/kern/linux/events.cc +++ b/src/kern/linux/events.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016 ARM Limited + * Copyright (c) 2011, 2016, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -49,6 +49,7 @@ #include "kern/linux/helpers.hh" #include "kern/system_events.hh" #include "sim/core.hh" +#include "sim/sim_exit.hh" #include "sim/system.hh" namespace gem5 @@ -58,25 +59,22 @@ namespace linux { void -DmesgDump::process(ThreadContext *tc) +PanicOrOopsEvent::process(ThreadContext *tc) { - inform("Dumping kernel dmesg buffer to %s...\n", fname); - OutputStream *os = simout.create(fname); - dumpDmesg(tc, *os->stream()); - simout.close(os); - warn(descr()); -} -void -KernelPanic::process(ThreadContext *tc) -{ - inform("Dumping kernel dmesg buffer to %s...\n", fname); - OutputStream *os = simout.create(fname); - dumpDmesg(tc, *os->stream()); - simout.close(os); + if (behaviour != KernelPanicOopsBehaviour::Continue) { + inform("Dumping kernel dmesg buffer to %s...\n", fname); + OutputStream *os = simout.create(fname); + dumpDmesg(tc, *os->stream()); + simout.close(os); + } - panic(descr()); + if (behaviour == KernelPanicOopsBehaviour::DumpDmesgAndExit) { + exitSimLoop(descr(), static_cast(1), curTick(), false); + } else if (behaviour == KernelPanicOopsBehaviour::DumpDmesgAndPanic) { + panic(descr()); + } } void diff --git a/src/kern/linux/events.hh b/src/kern/linux/events.hh index 966c1ba075..2f1e60cd28 100644 --- a/src/kern/linux/events.hh +++ b/src/kern/linux/events.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited + * Copyright (c) 2016, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -47,6 +47,7 @@ #include "base/compiler.hh" #include "base/trace.hh" #include "debug/DebugPrintf.hh" +#include "enums/KernelPanicOopsBehaviour.hh" #include "kern/linux/printk.hh" #include "kern/system_events.hh" #include "mem/se_translating_port_proxy.hh" @@ -83,43 +84,25 @@ class DebugPrintk : public Base }; /** - * Dump the guest kernel's dmesg buffer to a file in gem5's output - * directory and print a warning. + * Specify what to do on a Linux Kernel Panic or Oops. * - * @warn This event uses linux::dumpDmesg() and comes with the same + * @warn This event may use linux::dumpDmesg() and comes with the same * limitations. Most importantly, the kernel's address mappings must * be available to the translating proxy. */ -class DmesgDump : public PCEvent +class PanicOrOopsEvent : public PCEvent { protected: std::string fname; + KernelPanicOopsBehaviour behaviour; public: - DmesgDump(PCEventScope *s, const std::string &desc, Addr addr, - const std::string &_fname) : - PCEvent(s, desc, addr), fname(_fname) - {} - void process(ThreadContext *tc) override; -}; - -/** - * Dump the guest kernel's dmesg buffer to a file in gem5's output - * directory and panic. - * - * @warn This event uses linux::dumpDmesg() and comes with the same - * limitations. Most importantly, the kernel's address mappings must - * be available to the translating proxy. - */ -class KernelPanic : public PCEvent -{ - protected: - std::string fname; - - public: - KernelPanic(PCEventScope *s, const std::string &desc, Addr addr, - const std::string &_fname) : - PCEvent(s, desc, addr), fname(_fname) + PanicOrOopsEvent(PCEventScope *s, const std::string &desc, Addr addr, + const std::string &_fname, + const KernelPanicOopsBehaviour _behaviour) + : PCEvent(s, desc, addr) + , fname(_fname) + , behaviour(_behaviour) {} void process(ThreadContext *tc) override; }; diff --git a/src/sim/SConscript b/src/sim/SConscript index 78b06c5b1d..a9216de824 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -1,5 +1,16 @@ # -*- mode:python -*- - +# Copyright (c) 2023 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) 2006 The Regents of The University of Michigan # All rights reserved. # @@ -31,7 +42,8 @@ Import('*') SimObject('ClockedObject.py', sim_objects=['ClockedObject']) SimObject('TickedObject.py', sim_objects=['TickedObject']) SimObject('Workload.py', sim_objects=[ - 'Workload', 'StubWorkload', 'KernelWorkload', 'SEWorkload']) + 'Workload', 'StubWorkload', 'KernelWorkload', 'SEWorkload'], + enums=['KernelPanicOopsBehaviour']) SimObject('Root.py', sim_objects=['Root']) SimObject('ClockDomain.py', sim_objects=[ 'ClockDomain', 'SrcClockDomain', 'DerivedClockDomain']) diff --git a/src/sim/Workload.py b/src/sim/Workload.py index 998c6c13d6..50625e8085 100644 --- a/src/sim/Workload.py +++ b/src/sim/Workload.py @@ -1,3 +1,15 @@ +# Copyright (c) 2023 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 2019 Google Inc. # # Redistribution and use in source and binary forms, with or without @@ -62,6 +74,16 @@ class StubWorkload(Workload): ) +class KernelPanicOopsBehaviour(ScopedEnum): + "Define what gem5 should do after a Kernel Panic or Oops." + vals = [ + "Continue", + "DumpDmesgAndContinue", + "DumpDmesgAndExit", + "DumpDmesgAndPanic", + ] + + class KernelWorkload(Workload): type = "KernelWorkload" cxx_header = "sim/kernel_workload.hh" @@ -86,6 +108,18 @@ class KernelWorkload(Workload): command_line = Param.String("a", "boot flags to pass to the kernel") + on_panic = Param.KernelPanicOopsBehaviour( + "DumpDmesgAndExit", + "Define how gem5 should behave after a Linux Kernel Panic. " + "Handler might not be implemented for all architectures.", + ) + + on_oops = Param.KernelPanicOopsBehaviour( + "DumpDmesgAndExit", + "Define how gem5 should behave after a Linux Kernel Oops. " + "Handler might not be implemented for all architectures.", + ) + class SEWorkloadMeta(type(Workload)): all_se_workload_classes = [] From 88c57e22de5e51352647c9af37f83b28548d802e Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Sun, 3 Dec 2023 13:21:37 -0800 Subject: [PATCH 656/693] misc: update gapbs example to use suites (#607) --- .../gem5_library/x86-gapbs-benchmarks.py | 73 ++----------------- 1 file changed, 5 insertions(+), 68 deletions(-) diff --git a/configs/example/gem5_library/x86-gapbs-benchmarks.py b/configs/example/gem5_library/x86-gapbs-benchmarks.py index d425d797a6..4ef6f52b9c 100644 --- a/configs/example/gem5_library/x86-gapbs-benchmarks.py +++ b/configs/example/gem5_library/x86-gapbs-benchmarks.py @@ -73,36 +73,12 @@ requires( kvm_required=True, ) -# Following are the list of benchmark programs for gapbs - -benchmark_choices = ["cc", "bc", "tc", "pr", "bfs"] - -synthetic_choices = ["0", "1"] - -size_choices = [ - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", - "15", - "16", - "USA-road-d.NY.gr", -] - parser = argparse.ArgumentParser( description="An example configuration script to run the gapbs benchmarks." ) +gapbs_suite = obtain_resource("gapbs-benchmark-suite") + # The only positional argument accepted is the benchmark name in this script. parser.add_argument( @@ -110,28 +86,12 @@ parser.add_argument( type=str, required=True, help="Input the benchmark program to execute.", - choices=benchmark_choices, -) - -parser.add_argument( - "--synthetic", - type=str, - required=True, - help="Synthetic Graph:: 1: synthetic graph is True; 0: real graph", - choices=synthetic_choices, -) - -parser.add_argument( - "--size", - type=str, - required=True, - help="Graph Size:: If synthetic is True, then specify a size [1 .. 15]. \ - Otherwise, specify a graph name [USA-road-d.NY.gr]", - choices=size_choices, + choices=[workload.get_id() for workload in gapbs_suite], ) args = parser.parse_args() + # Setting up all the fixed system parameters here # Caches: MESI Two Level Cache Hierarchy @@ -185,30 +145,7 @@ board = X86Board( # committed instructions till ROI ends (marked by `workend`). We then finish # executing the rest of the benchmark. -# GAPBS benchmarks can be run using a synthetic graph - -if args.synthetic == "1": - if args.size == "USA-road-d.NY.gr": - print( - "fatal: cannot use a real graph with --synthetic 1", - file=sys.stderr, - ) - exit(-1) - - command = f"./{args.benchmark} -g {args.size}\n" -else: - command = f"./{args.benchmark} -sf ../{args.size}" - -board.set_kernel_disk_workload( - # The x86 linux kernel will be automatically downloaded to the - # `~/.cache/gem5` directory if not already present. - # gapbs benchamarks was tested with kernel version 4.19.83 - kernel=obtain_resource("x86-linux-kernel-4.19.83"), - # The x86-gapbs image will be automatically downloaded to the - # `~/.cache/gem5` directory if not already present. - disk_image=obtain_resource("x86-gapbs"), - readfile_contents=command, -) +board.set_workload(obtain_resource(args.benchmark)) def handle_workbegin(): From 7a5052b3a0e1bfb54f3f1c3dd3eba633526829b0 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 3 Dec 2023 13:22:11 -0800 Subject: [PATCH 657/693] arch-arm: Only build ArmCapstoneDisassembler when ISA is arm (#553) Currently, if the Capstone header file is found in the host system, scons will try to build the ArmCapstoneDisassembler regardless of the gem5 target ISA. This is causing problem when the host has Capstone, but the gem5 target ISA is not arm. Compiling gem5 in this case will cause errors, e.g., ArmISA and ArmSystem is not found. This change aims to prevent building the ArmCapstoneDisassembler when the gem5 target ISA is not arm. Ref: [1] The Arm Capstone PR https://github.com/gem5/gem5/pull/494 Change-Id: I1e714d34aec8fe2a2af8cd351536951053a4d8a5 --- src/arch/arm/tracers/SConscript | 6 +++--- src/cpu/Kconfig | 6 ++++++ src/cpu/SConscript | 8 +++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/arch/arm/tracers/SConscript b/src/arch/arm/tracers/SConscript index ca012c5c2e..7b729ad065 100644 --- a/src/arch/arm/tracers/SConscript +++ b/src/arch/arm/tracers/SConscript @@ -43,7 +43,7 @@ Source('tarmac_tracer.cc', tags='arm isa') Source('tarmac_record.cc', tags='arm isa') Source('tarmac_record_v8.cc', tags='arm isa') -if env['CONF']['HAVE_CAPSTONE']: +if env['CONF']['USE_CAPSTONE']: SimObject('ArmCapstone.py', sim_objects=['ArmCapstoneDisassembler'], - tags=['capstone', 'arm isa']) - Source('capstone.cc', tags=['capstone', 'arm isa']) + tags=['arm isa']) + Source('capstone.cc', tags=['arm isa']) diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index 33a00e9c45..e1f96678c8 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -27,3 +27,9 @@ config HAVE_CAPSTONE def_bool $(HAVE_CAPSTONE) rsource "kvm/Kconfig" + +config USE_CAPSTONE + depends on HAVE_CAPSTONE + depends on USE_ARM_ISA + bool "Use CapstoneDisassembler" + default y diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 03ba7b924d..64c64903bd 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -115,9 +115,11 @@ Source('simple_thread.cc') Source('thread_context.cc') Source('thread_state.cc') Source('timing_expr.cc') -SourceLib('capstone', tags='capstone') -Source('capstone.cc', tags='capstone') -SimObject('Capstone.py', sim_objects=['CapstoneDisassembler'], tags='capstone') + +if env['CONF']['USE_CAPSTONE']: + SourceLib('capstone') + Source('capstone.cc') + SimObject('Capstone.py', sim_objects=['CapstoneDisassembler']) SimObject('DummyChecker.py', sim_objects=['DummyChecker']) Source('checker/cpu.cc') From 5eba3941f498a266b44970811bb8aa849d533735 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Sun, 3 Dec 2023 13:22:46 -0800 Subject: [PATCH 658/693] arch-riscv: fix o3 cpu stuck in spinlock bug (#641) --- src/arch/riscv/isa/decoder.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 4a6eed2e89..be4b621a37 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -4657,7 +4657,7 @@ decode QUADRANT default Unknown::unknown() { tc->quiesce(); } }}, IsNonSpeculative, IsQuiesce, - IsSerializeAfter, No_OpClass); + IsSerializeAfter, No_OpClass, IsSquashAfter); } 0x9: sfence_vma({{ MISA misa = xc->readMiscReg(MISCREG_ISA); From bad569a3f83e5870f1274d62e0980a360853c321 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Sun, 3 Dec 2023 13:23:46 -0800 Subject: [PATCH 659/693] misc: update x86-npb-benchmarks.py to use suites (#587) - updated the x86-npb-benchmarks.py to use npb workloads and suites. The suites and workloads are not in the database are also waiting feedback. I am attaching the JSON file here. [npb_workloads_suite.json](https://github.com/gem5/gem5/files/13431116/npb_workloads_suite.json) To run the x86-npb-benchmarks.py script use the GEM5_RESOURCE_JSON_APPEND env variable. The full command is: ``` GEM5_RESOURCE_JSON_APPEND=[path to npb_workloads_suite.json] ./build/X86/gem5.opt configs/example/gem5_library/x86-npb-benchmarks.py --benchmark [benchmark] ``` Change-Id: I248e6452ea4122e9260e34e4368847660edae577 --- .../gem5_library/x86-npb-benchmarks.py | 40 ++++--------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/configs/example/gem5_library/x86-npb-benchmarks.py b/configs/example/gem5_library/x86-npb-benchmarks.py index c78c6102aa..6e6d501c37 100644 --- a/configs/example/gem5_library/x86-npb-benchmarks.py +++ b/configs/example/gem5_library/x86-npb-benchmarks.py @@ -76,8 +76,6 @@ requires( # Following are the list of benchmark programs for npb. -benchmark_choices = ["bt", "cg", "ep", "ft", "is", "lu", "mg", "sp"] - # We are restricting classes of NPB to A, B and C as the other classes (D and # F) require main memory size of more than 3 GB. The X86Board is currently # limited to 3 GB of memory. This limitation is explained later in line 136. @@ -86,12 +84,11 @@ benchmark_choices = ["bt", "cg", "ep", "ft", "is", "lu", "mg", "sp"] # works with class D in the current configuration. More information on the # memory footprint for NPB is available at https://arxiv.org/abs/2010.13216 -size_choices = ["A", "B", "C"] - parser = argparse.ArgumentParser( description="An example configuration script to run the npb benchmarks." ) +npb_suite = obtain_resource("npb-benchmark-suite") # The only positional argument accepted is the benchmark name in this script. parser.add_argument( @@ -99,15 +96,7 @@ parser.add_argument( type=str, required=True, help="Input the benchmark program to execute.", - choices=benchmark_choices, -) - -parser.add_argument( - "--size", - type=str, - required=True, - help="Input the class of the program to simulate.", - choices=size_choices, + choices=[workload.get_id() for workload in npb_suite], ) parser.add_argument( @@ -119,11 +108,12 @@ parser.add_argument( args = parser.parse_args() + # The simulation may fail in the case of `mg` with class C as it uses 3.3 GB -# of memory (more information is availabe at https://arxiv.org/abs/2010.13216). +# of memory (more information is available at https://arxiv.org/abs/2010.13216). # We warn the user here. -if args.benchmark == "mg" and args.size == "C": +if args.benchmark == "npb-mg-c": warn( "mg.C uses 3.3 GB of memory. Currently we are simulating 3 GB\ of main memory in the system." @@ -131,7 +121,7 @@ if args.benchmark == "mg" and args.size == "C": # The simulation will fail in the case of `ft` with class C. We warn the user # here. -elif args.benchmark == "ft" and args.size == "C": +elif args.benchmark == "npb-ft-c": warn( "There is not enough memory for ft.C. Currently we are\ simulating 3 GB of main memory in the system." @@ -194,23 +184,7 @@ board = X86Board( # Also, we sleep the system for some time so that the output is printed # properly. - -command = ( - f"/home/gem5/NPB3.3-OMP/bin/{args.benchmark}.{args.size}.x;" - + "sleep 5;" - + "m5 exit;" -) - -board.set_kernel_disk_workload( - # The x86 linux kernel will be automatically downloaded to the - # `~/.cache/gem5` directory if not already present. - # npb benchamarks was tested with kernel version 4.19.83 - kernel=obtain_resource("x86-linux-kernel-4.19.83"), - # The x86-npb image will be automatically downloaded to the - # `~/.cache/gem5` directory if not already present. - disk_image=obtain_resource("x86-npb"), - readfile_contents=command, -) +board.set_workload(obtain_resource(args.benchmark)) # The first exit_event ends with a `workbegin` cause. This means that the From c718e94753e78cbe5b87578ef60d8e949ef23338 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Sun, 3 Dec 2023 13:38:59 -0800 Subject: [PATCH 660/693] stdlib: Add comment to ShadowResource (#645) This comment explains that this solution is a hack the solution created by https://github.com/gem5/gem5/issues/644 should eventually replace it. --- src/python/gem5/resources/resource.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index ea830b2a2a..08d046fc01 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -814,6 +814,12 @@ class ShadowResource(AbstractResource): which is is neither `get_id` or `get_resource_version` does this class fully construct itself by calling the `obtain_resource_call` partial function. + + **Note:** This class is a hack. The ideal solution to this would be to + enable the bundled obtaining of resources in the gem5 Standard Library. + Use of the class is discouraged and should not be depended on. Issue + https://github.com/gem5/gem5/issues/644 is tracking the implementation of + an alternative. """ def __init__( From 895944fa27c2e84a27705f814e4782357df7514b Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Sun, 3 Dec 2023 13:39:26 -0800 Subject: [PATCH 661/693] mem-ruby: Fix compile error in chi-dvm-funcs (#646) clang correctly found that the functions `inCache`, `hasBeenPrefetched` and `inMissQueue` had the wrong signatures in the DVM funcs files. These functions are unused, so this change just updates their signatures. Change-Id: Id669ff661e1c6c46eaf04ea1f17cd9866a9e49ed --- src/mem/ruby/protocol/chi/CHI-dvm-misc-node-funcs.sm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mem/ruby/protocol/chi/CHI-dvm-misc-node-funcs.sm b/src/mem/ruby/protocol/chi/CHI-dvm-misc-node-funcs.sm index ce87d02cf9..5d07862d25 100644 --- a/src/mem/ruby/protocol/chi/CHI-dvm-misc-node-funcs.sm +++ b/src/mem/ruby/protocol/chi/CHI-dvm-misc-node-funcs.sm @@ -137,15 +137,19 @@ Cycles dataLatency() { return intToCycles(0); } -bool inCache(Addr txnId) { +bool inCache(Addr txnId, bool is_secure) { return false; } -bool hasBeenPrefetched(Addr txnId) { +bool hasBeenPrefetched(Addr txnId, bool is_secure, RequestorID requestor) { return false; } -bool inMissQueue(Addr txnId) { +bool hasBeenPrefetched(Addr txnId, bool is_secure) { + return false; +} + +bool inMissQueue(Addr txnId, bool is_secure) { return false; } From 7b986419533083dc48d961dcc502701f673a9af2 Mon Sep 17 00:00:00 2001 From: Nitish Arya <42148385+aryanitish@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:02:50 +0100 Subject: [PATCH 662/693] arch-riscv: correctly pass arguments to kernel with new bootloader+kernel (#635) The [PR](https://github.com/gem5/gem5/pull/390) adds support for new bootloader and linux kernel. However after applying the changes the arguments are not passed correctly to the kernel resulting in kernel panic during simulations. This commit fixes the issue. --- src/python/gem5/components/boards/riscv_board.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gem5/components/boards/riscv_board.py b/src/python/gem5/components/boards/riscv_board.py index a3685f2991..dcb6fab7c5 100644 --- a/src/python/gem5/components/boards/riscv_board.py +++ b/src/python/gem5/components/boards/riscv_board.py @@ -256,7 +256,7 @@ class RiscvBoard(AbstractSystemBoard, KernelDiskWorkload): root.append(node) node = FdtNode(f"chosen") - bootargs = " ".join(self.get_default_kernel_args()) + bootargs = self.workload.command_line node.append(FdtPropertyStrings("bootargs", [bootargs])) node.append(FdtPropertyStrings("stdout-path", ["/uart@10000000"])) root.append(node) From 569e21f798f61c22a91e8f6bad083a82fdf43034 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 4 Dec 2023 09:53:35 -0800 Subject: [PATCH 663/693] configs,stdlib,tests: Remove get_runtime_isa() (#241) `get_runtime_isa()` has been deprecated for some time. It is a leftover piece of code from when gem5 was compiled to a single ISA and that ISA used to configure the simulated system to use that ISA. Since multi-ISA compilations are possible, `get_runtime_isa()` should not be used. Unless the gem5 binary is compiled to a single ISA, a failure will occur. The new proceedure for specify which ISA to use is by the setting of the correct `BaseCPU` implementation. E.g., `X86SimpleTimingCPU` of `ArmO3CPU`. This patch removes the remaining `get_runtime_isa()` instances and removes the function itself. The `SimpleCore` class has been updated to allow for it's CPU factory to return a class, needed by scripts in "configs/common". The deprecated functionality in the standard library, which allowed for the specifying of an ISA when setting up a processor and/or core has also been removed. Setting an ISA is now manditory. Fixes #216. --- configs/common/CacheConfig.py | 22 ++++++----- configs/common/Caches.py | 19 --------- configs/common/ObjectList.py | 33 ++++++++++++++++ configs/common/Options.py | 4 +- configs/common/Simulation.py | 5 ++- configs/deprecated/example/fs.py | 7 ++-- configs/deprecated/example/se.py | 7 ++-- configs/example/apu_se.py | 6 +-- configs/example/hmc_hello.py | 25 ++++++++---- configs/learning_gem5/part1/two_level.py | 2 - configs/network/Network.py | 4 +- configs/ruby/Ruby.py | 13 +++---- .../components/processors/base_cpu_core.py | 15 +++---- .../gem5/components/processors/simple_core.py | 39 +++++++++++-------- .../components/processors/simple_processor.py | 18 +-------- .../processors/simple_switchable_processor.py | 21 ++-------- src/python/gem5/runtime.py | 37 ------------------ tests/gem5/multi_isa/README.md | 2 +- tests/gem5/multi_isa/test_multi_isa.py | 20 ---------- .../configs/parsec_disk_run.py | 4 -- 20 files changed, 125 insertions(+), 178 deletions(-) diff --git a/configs/common/CacheConfig.py b/configs/common/CacheConfig.py index 723978f05c..cfc8f95fa5 100644 --- a/configs/common/CacheConfig.py +++ b/configs/common/CacheConfig.py @@ -47,7 +47,6 @@ import m5 from m5.objects import * from gem5.isas import ISA -from gem5.runtime import get_runtime_isa def _get_hwp(hwp_option): @@ -118,9 +117,6 @@ def config_cache(options, system): None, ) - if get_runtime_isa() in [ISA.X86, ISA.RISCV]: - walk_cache_class = PageTableWalkerCache - # Set the cache line size of the system system.cache_line_size = options.cacheline_size @@ -151,11 +147,13 @@ def config_cache(options, system): icache = icache_class(**_get_cache_opts("l1i", options)) dcache = dcache_class(**_get_cache_opts("l1d", options)) - # If we have a walker cache specified, instantiate two - # instances here - if walk_cache_class: - iwalkcache = walk_cache_class() - dwalkcache = walk_cache_class() + # If we are using ISA.X86 or ISA.RISCV, we set walker caches. + if ObjectList.CPUList().get_isa(options.cpu_type) in [ + ISA.RiscvCPU, + ISA.X86CPU, + ]: + iwalkcache = PageTableWalkerCache() + dwalkcache = PageTableWalkerCache() else: iwalkcache = None dwalkcache = None @@ -193,7 +191,11 @@ def config_cache(options, system): # on these names. For simplicity, we would advise configuring # it to use this naming scheme; if this isn't possible, change # the names below. - if get_runtime_isa() in [ISA.X86, ISA.ARM, ISA.RISCV]: + if ObjectList.CPUList().get_isa(options.cpu_type) in [ + ISA.X86, + ISA.ARM, + ISA.RISCV, + ]: system.cpu[i].addPrivateSplitL1Caches( ExternalCache("cpu%d.icache" % i), ExternalCache("cpu%d.dcache" % i), diff --git a/configs/common/Caches.py b/configs/common/Caches.py index ac8dc17f7d..682b937d8b 100644 --- a/configs/common/Caches.py +++ b/configs/common/Caches.py @@ -41,7 +41,6 @@ from m5.defines import buildEnv from m5.objects import * from gem5.isas import ISA -from gem5.runtime import get_runtime_isa # Base implementations of L1, L2, IO and TLB-walker caches. There are # used in the regressions and also as base components in the @@ -87,21 +86,3 @@ class IOCache(Cache): mshrs = 20 size = "1kB" tgts_per_mshr = 12 - - -class PageTableWalkerCache(Cache): - assoc = 2 - tag_latency = 2 - data_latency = 2 - response_latency = 2 - mshrs = 10 - size = "1kB" - tgts_per_mshr = 12 - - # the x86 table walker actually writes to the table-walker cache - if get_runtime_isa() in [ISA.X86, ISA.RISCV]: - is_read_only = False - else: - is_read_only = True - # Writeback clean lines as well - writeback_clean = True diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index 4a893e4d14..940403467f 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -41,6 +41,7 @@ from textwrap import TextWrapper import m5.internal.params import m5.objects +from gem5.isas import ISA from gem5.runtime import get_supported_isas @@ -159,6 +160,38 @@ class CPUList(ObjectList): ): self._sub_classes[name] = cls + def get_isa(self, name: str) -> ISA: + """For a given CPU (string representation) determine the ISA of the + CPU.""" + + cls = self.get(name) + + def class_exist(className: str) -> bool: + """Check if a class exists.""" + import types + + result = False + try: + result = eval("type(" + className + ")") == types.ClassType + except NameError: + pass + return result + + if class_exist(m5.objects.X86CPU) and issubclass( + cls, m5.objects.X86CPU + ): + return ISA.X86 + elif class_exist(m5.objects.ArmCPU) and issubclass( + cls, m5.objects.ArmCPU + ): + return ISA.ARM + elif class_exist(m5.objects.RiscvCPU) and issubclass( + cls, m5.objects.RiscvCPU + ): + return ISA.RISCV + else: + raise ValueError("Unable to determine CPU ISA.") + class EnumList(ObjectList): """Creates a list of possible values for a given enum class.""" diff --git a/configs/common/Options.py b/configs/common/Options.py index cd658e33c1..91e42e6b37 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -45,6 +45,8 @@ import m5 from m5.defines import buildEnv from m5.objects import * +from gem5.runtime import get_supported_isas + vio_9p_help = """\ Enable the Virtio 9P device and set the path to share. The default 9p path is m5ou5/9p/share, and it can be changed by setting VirtIO9p.root with --param. A @@ -250,7 +252,7 @@ def addCommonOptions(parser): ) parser.add_argument( "--cpu-type", - default="AtomicSimpleCPU", + default=list(get_supported_isas())[0].name + "AtomicSimpleCPU", choices=ObjectList.cpu_list.get_names(), help="type of cpu to run with", ) diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 34825fb415..f33a006d45 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -81,7 +81,10 @@ def setCPUClass(options): TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu) elif options.fast_forward: CPUClass = TmpClass - TmpClass = AtomicSimpleCPU + TmpClass = getCPUClass( + ObjectList.CPUList().get_isa(options.cpu_type).name + + "AtomicSimpleCPU" + ) test_mem_mode = "atomic" # Ruby only supports atomic accesses in noncaching mode diff --git a/configs/deprecated/example/fs.py b/configs/deprecated/example/fs.py index 52354dc3a2..7fabf7b1bd 100644 --- a/configs/deprecated/example/fs.py +++ b/configs/deprecated/example/fs.py @@ -53,7 +53,6 @@ from m5.util import ( from m5.util.fdthelper import * from gem5.isas import ISA -from gem5.runtime import get_runtime_isa addToPath("../../") @@ -86,9 +85,8 @@ def cmd_line_template(): return None -def build_test_system(np): +def build_test_system(np, isa: ISA): cmdline = cmd_line_template() - isa = get_runtime_isa() if isa == ISA.MIPS: test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0], cmdline=cmdline) elif isa == ISA.SPARC: @@ -384,7 +382,8 @@ else: np = args.num_cpus -test_sys = build_test_system(np) +isa = ObjectList.CPUList.get_isa(args.cpu_type) +test_sys = build_test_system(np, isa) if len(bm) == 2: drive_sys = build_drive_system(np) diff --git a/configs/deprecated/example/se.py b/configs/deprecated/example/se.py index ad610b05d3..16ea1fddb0 100644 --- a/configs/deprecated/example/se.py +++ b/configs/deprecated/example/se.py @@ -55,7 +55,6 @@ from m5.util import ( ) from gem5.isas import ISA -from gem5.runtime import get_runtime_isa addToPath("../../") @@ -119,7 +118,7 @@ def get_processes(args): idx += 1 if args.smt: - assert args.cpu_type == "DerivO3CPU" + assert isinstance(args.cpu_type, DerivO3CPU) return multiprocesses, idx else: return multiprocesses, 1 @@ -150,7 +149,7 @@ if args.bench: for app in apps: try: - if get_runtime_isa() == ISA.ARM: + if ObjectList.CPUList().get_isa(args.cpu_type) == ISA.ARM: exec( "workload = %s('arm_%s', 'linux', '%s')" % (app, args.arm_iset, args.spec_input) @@ -165,7 +164,7 @@ if args.bench: multiprocesses.append(workload.makeProcess()) except: print( - f"Unable to find workload for {get_runtime_isa().name()}: {app}", + f"Unable to find workload for ISA: {app}", file=sys.stderr, ) sys.exit(1) diff --git a/configs/example/apu_se.py b/configs/example/apu_se.py index 219f8f9f29..b375bbef7b 100644 --- a/configs/example/apu_se.py +++ b/configs/example/apu_se.py @@ -40,7 +40,7 @@ from m5.objects import * from m5.util import addToPath from gem5.isas import ISA -from gem5.runtime import get_runtime_isa +from gem5.runtime import get_supported_isas addToPath("../") @@ -786,7 +786,7 @@ system.clk_domain = SrcClockDomain( if fast_forward: have_kvm_support = "BaseKvmCPU" in globals() - if have_kvm_support and get_runtime_isa() == ISA.X86: + if have_kvm_support and get_supported_isas().contains(ISA.X86): system.vm = KvmVM() system.m5ops_base = 0xFFFF0000 for i in range(len(host_cpu.workload)): @@ -825,7 +825,7 @@ for i in range(args.num_cpus): system.cpu[i].dcache_port = ruby_port.in_ports ruby_port.mem_request_port = system.piobus.cpu_side_ports - if get_runtime_isa() == ISA.X86: + if get_supported_isas().contains(ISA.X86): system.cpu[i].interrupts[0].pio = system.piobus.mem_side_ports system.cpu[i].interrupts[ 0 diff --git a/configs/example/hmc_hello.py b/configs/example/hmc_hello.py index b2e9af1f60..83bf8be640 100644 --- a/configs/example/hmc_hello.py +++ b/configs/example/hmc_hello.py @@ -37,17 +37,23 @@ import m5 from m5.objects import * from m5.util import * -from gem5.runtime import get_runtime_isa - addToPath("../") from common import ( HMC, MemConfig, + ObjectList, ) pd = "Simple 'hello world' example using HMC as main memory" parser = argparse.ArgumentParser(description=pd) +parser.add_argument( + "--cpu-type", + type=str, + default="X86TimingSimpleCPU", + choices=ObjectList.CPUList().get_names(), + help="CPU model to use", +) HMC.add_options(parser) options = parser.parse_args() # create the system we are going to simulate @@ -58,8 +64,8 @@ system.mem_mode = "timing" clk = "1GHz" vd = VoltageDomain(voltage="1V") system.clk_domain = SrcClockDomain(clock=clk, voltage_domain=vd) -# create a simple CPU -system.cpu = TimingSimpleCPU() +# create a CPU +system.cpu = ObjectList().get(options.cpu_type)() # config memory system MemConfig.config_mem(options, system) # hook the CPU ports up to the membus @@ -70,10 +76,15 @@ system.cpu.createInterruptController() # connect special port in the system to the membus. This port is a # functional-only port to allow the system to read and write memory. system.system_port = system.membus.cpu_side_ports -# get ISA for the binary to run. -isa = get_runtime_isa() # run 'hello' and use the compiled ISA to find the binary -binary = "tests/test-progs/hello/bin/" + isa.name.lower() + "/linux/hello" + + +binary = ( + "tests/test-progs/hello/bin/" + + ObjectList.CPUList().get_isa(options.cpu_type).name.lower() + + "/linux/hello" +) + # create a process for a simple "Hello World" application process = Process() # cmd is a list which begins with the executable (like argv) diff --git a/configs/learning_gem5/part1/two_level.py b/configs/learning_gem5/part1/two_level.py index a105faeca3..ab3111c799 100644 --- a/configs/learning_gem5/part1/two_level.py +++ b/configs/learning_gem5/part1/two_level.py @@ -43,8 +43,6 @@ import m5 # import all of the SimObjects from m5.objects import * -from gem5.runtime import get_runtime_isa - # Add the common scripts to our path m5.util.addToPath("../../") diff --git a/configs/network/Network.py b/configs/network/Network.py index 0973809c33..2b4b6af244 100644 --- a/configs/network/Network.py +++ b/configs/network/Network.py @@ -37,8 +37,8 @@ from m5.util import ( def define_options(parser): - # By default, ruby uses the simple timing cpu - parser.set_defaults(cpu_type="TimingSimpleCPU") + # By default, ruby uses the simple timing cpu and the X86 ISA + parser.set_defaults(cpu_type="X86TimingSimpleCPU") parser.add_argument( "--topology", diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index ae30d55077..83c5edea6f 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -48,7 +48,6 @@ from m5.util import ( ) from gem5.isas import ISA -from gem5.runtime import get_runtime_isa addToPath("../") @@ -62,8 +61,8 @@ from topologies import * def define_options(parser): - # By default, ruby uses the simple timing cpu - parser.set_defaults(cpu_type="TimingSimpleCPU") + # By default, ruby uses the simple timing cpu and the X86 ISA + parser.set_defaults(cpu_type="X86TimingSimpleCPU") parser.add_argument( "--ruby-clock", @@ -331,9 +330,9 @@ def send_evicts(options): # 1. The O3 model must keep the LSQ coherent with the caches # 2. The x86 mwait instruction is built on top of coherence invalidations # 3. The local exclusive monitor in ARM systems - if options.cpu_type == "DerivO3CPU" or get_runtime_isa() in ( - ISA.X86, - ISA.ARM, - ): + + if isinstance( + options.cpu_type, DerivO3CPU + ) or ObjectList.CPUList().get_isa(options.cpu_type) in [ISA.X86, ISA.ARM]: return True return False diff --git a/src/python/gem5/components/processors/base_cpu_core.py b/src/python/gem5/components/processors/base_cpu_core.py index 710a91f1b8..19f5c85af2 100644 --- a/src/python/gem5/components/processors/base_cpu_core.py +++ b/src/python/gem5/components/processors/base_cpu_core.py @@ -40,7 +40,6 @@ from m5.objects import ( from m5.params import PcCountPair from ...isas import ISA -from ...runtime import get_runtime_isa from ...utils.override import overrides from ...utils.requires import requires from .abstract_core import AbstractCore @@ -51,17 +50,19 @@ class BaseCPUCore(AbstractCore): An stdlib AbstractCore subclass which wraps a BaseCPU SimObject type. """ - def __init__(self, core: BaseCPU, isa: Optional[ISA] = None): + def __init__(self, core: BaseCPU, isa: ISA): super().__init__() # There is some annoying redundancy here. The BaseCPU type already # defines the ISA, so here we are defining it twice. However, there # currently isn't a good way to get the ISA from the BaseCPU Type. - if isa: - requires(isa_required=isa) - self._isa = isa - else: - self._isa = get_runtime_isa() + # + # TODO: Have some helper function to get the ISA from a BaseCPU type. + # This may just be a cause of using `instanceof`: + # e.g., `if instanceof(cpu, X86Cpu): return ISA.X86`. + # + requires(isa_required=isa) + self._isa = isa self.core = core self.core.createThreads() diff --git a/src/python/gem5/components/processors/simple_core.py b/src/python/gem5/components/processors/simple_core.py index 36b99481bc..0d05b34e2d 100644 --- a/src/python/gem5/components/processors/simple_core.py +++ b/src/python/gem5/components/processors/simple_core.py @@ -29,7 +29,6 @@ import platform from typing import Optional from ...isas import ISA -from ...runtime import get_runtime_isa from ...utils.requires import requires from .base_cpu_core import BaseCPUCore from .cpu_types import CPUTypes @@ -41,17 +40,8 @@ class SimpleCore(BaseCPUCore): `SimpleCore` creates a single `SimObject` of that type. """ - def __init__( - self, cpu_type: CPUTypes, core_id: int, isa: Optional[ISA] = None - ): - # If the ISA is not specified, we infer it via the `get_runtime_isa` - # function. - if isa: - requires(isa_required=isa) - isa = isa - else: - isa = get_runtime_isa() - + def __init__(self, cpu_type: CPUTypes, core_id: int, isa: ISA): + requires(isa_required=isa) super().__init__( core=SimpleCore.cpu_simobject_factory( isa=isa, cpu_type=cpu_type, core_id=core_id @@ -65,15 +55,14 @@ class SimpleCore(BaseCPUCore): return self._cpu_type @classmethod - def cpu_simobject_factory(cls, cpu_type: CPUTypes, isa: ISA, core_id: int): + def cpu_class_factory(cls, cpu_type: CPUTypes, isa: ISA) -> type: """ - A factory used to return the SimObject core object given the cpu type, + A factory used to return the SimObject type given the cpu type, and ISA target. An exception will be thrown if there is an incompatibility. :param cpu_type: The target CPU type. :param isa: The target ISA. - :param core_id: The id of the core to be returned. """ assert isa is not None @@ -145,4 +134,22 @@ class SimpleCore(BaseCPUCore): "gem5." ) - return to_return_cls(cpu_id=core_id) + return to_return_cls + + @classmethod + def cpu_simobject_factory( + cls, cpu_type: CPUTypes, isa: ISA, core_id: int + ) -> BaseCPUCore: + """ + A factory used to return the SimObject core object given the cpu type, + and ISA target. An exception will be thrown if there is an + incompatibility. + + :param cpu_type: The target CPU type. + :param isa: The target ISA. + :param core_id: The id of the core to be returned. + """ + + return cls.cpu_class_factory(cpu_type=cpu_type, isa=isa)( + cpu_id=core_id + ) diff --git a/src/python/gem5/components/processors/simple_processor.py b/src/python/gem5/components/processors/simple_processor.py index da645e8d74..d47e3794b2 100644 --- a/src/python/gem5/components/processors/simple_processor.py +++ b/src/python/gem5/components/processors/simple_processor.py @@ -41,28 +41,14 @@ class SimpleProcessor(BaseCPUProcessor): same CPUType. """ - def __init__( - self, cpu_type: CPUTypes, num_cores: int, isa: Optional[ISA] = None - ) -> None: + def __init__(self, cpu_type: CPUTypes, num_cores: int, isa: ISA) -> None: """ :param cpu_type: The CPU type for each type in the processor. :param num_cores: The number of CPU cores in the processor. - :param isa: The ISA of the processor. This argument is optional. If not - set the ``runtime.get_runtime_isa`` is used to determine the - ISA at runtime. **WARNING**: This functionality is deprecated. - It is recommended you explicitly set your ISA via SimpleProcessor - construction. + :param isa: The ISA of the processor. """ - if not isa: - warn( - "An ISA for the SimpleProcessor was not set. This will " - "result in usage of `runtime.get_runtime_isa` to obtain the " - "ISA. This function is deprecated and will be removed in " - "future releases of gem5. Please explicitly state the ISA " - "via the processor constructor." - ) super().__init__( cores=[ SimpleCore(cpu_type=cpu_type, core_id=i, isa=isa) diff --git a/src/python/gem5/components/processors/simple_switchable_processor.py b/src/python/gem5/components/processors/simple_switchable_processor.py index 6516455480..2be422afe6 100644 --- a/src/python/gem5/components/processors/simple_switchable_processor.py +++ b/src/python/gem5/components/processors/simple_switchable_processor.py @@ -53,31 +53,18 @@ class SimpleSwitchableProcessor(SwitchableProcessor): starting_core_type: CPUTypes, switch_core_type: CPUTypes, num_cores: int, - isa: Optional[ISA] = None, + isa: ISA = None, ) -> None: """ :param starting_core_type: The CPU type for each type in the processor to start with (i.e., when the simulation has just started). + :param switch_core_types: The CPU type for each core, to be switched + to. - :param switch_core_types: The CPU type for each core, to be switched to. - - :param isa: The ISA of the processor. This argument is optional. If not - set the ``runtime.get_runtime_isa`` is used to determine the - ISA at runtime. **WARNING**: This functionality is deprecated. - It is recommended you explicitly set your ISA via - SimpleSwitchableProcessor construction. + :param isa: The ISA of the processor. """ - if not isa: - warn( - "An ISA for the SimpleSwitchableProcessor was not set. This " - "will result in usage of `runtime.get_runtime_isa` to obtain " - "the ISA. This function is deprecated and will be removed in " - "future releases of gem5. Please explicitly state the ISA " - "via the processor constructor." - ) - if num_cores <= 0: raise AssertionError("Number of cores must be a positive integer!") diff --git a/src/python/gem5/runtime.py b/src/python/gem5/runtime.py index 8756f57748..a7a284f7ae 100644 --- a/src/python/gem5/runtime.py +++ b/src/python/gem5/runtime.py @@ -60,43 +60,6 @@ def get_supported_isas() -> Set[ISA]: return supported_isas -def get_runtime_isa() -> ISA: - """ - Returns a single target ISA at runtime. - - This determined via the "TARGET_ISA" parameter, which is set at - compilation. If not set, but only one ISA is compiled, we assume it's the - one ISA. If neither the "TARGET_ISA" parameter is set and there are - multiple ISA targets, an exception is thrown. - - .. warning:: - - This function is deprecated and may be removed in future versions of - gem5. This function should not be relied upon to run gem5 simulations. - - :returns: The target ISA. - """ - - warn( - "The `get_runtime_isa` function is deprecated. Please migrate away " - "from using this function." - ) - - if "TARGET_ISA" in buildEnv.keys(): - return get_isa_from_str(buildEnv["TARGET_ISA"]) - - supported_isas = get_supported_isas() - - if len(supported_isas) == 1: - return next(iter(supported_isas)) - - raise Exception( - "Cannot determine the the runtime ISA. Either the " - "'TARGET_ISA' parameter must be set or the binary only " - "compiled to one ISA." - ) - - def get_runtime_coherence_protocol() -> CoherenceProtocol: """Gets the cache coherence protocol. diff --git a/tests/gem5/multi_isa/README.md b/tests/gem5/multi_isa/README.md index 94d8c1a3e1..1721ad59ec 100644 --- a/tests/gem5/multi_isa/README.md +++ b/tests/gem5/multi_isa/README.md @@ -1,6 +1,6 @@ # Multi ISA -These tests check that all our ISAs are both currrently supported within gem5, as well as checking that get_runtime_isa() works as expected. +These tests check that all our ISAs are both currrently supported within gem5. To run these tests by themselves, you can run the following command in the tests directory: diff --git a/tests/gem5/multi_isa/test_multi_isa.py b/tests/gem5/multi_isa/test_multi_isa.py index c9726174c0..2727fe43de 100644 --- a/tests/gem5/multi_isa/test_multi_isa.py +++ b/tests/gem5/multi_isa/test_multi_isa.py @@ -39,26 +39,6 @@ isa_map = { for isa in isa_map.keys(): if isa in ("x86", "arm", "riscv"): - # We only do these checks for X86, ARM, and RISCV to save compiling - # other ISAs. - gem5_verify_config( - name=f"runtime-isa-check_{isa}-compiled-alone", - verifiers=(), - fixtures=(), - config=joinpath( - config.base_dir, - "tests", - "gem5", - "multi_isa", - "configs", - "runtime_isa_check.py", - ), - config_args=["-e", isa], - valid_isas=(isa_map[isa],), - valid_hosts=constants.supported_hosts, - length=constants.long_tag, - ) - gem5_verify_config( name=f"supported-isas-check_{isa}-compiled-alone", verifiers=(), diff --git a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py index 92786bb001..606205f103 100644 --- a/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py +++ b/tests/gem5/parsec_benchmarks/configs/parsec_disk_run.py @@ -51,10 +51,6 @@ from gem5.components.processors.simple_switchable_processor import ( ) from gem5.isas import ISA from gem5.resources.resource import obtain_resource -from gem5.runtime import ( - get_runtime_coherence_protocol, - get_runtime_isa, -) from gem5.simulate.exit_event import ExitEvent from gem5.simulate.simulator import Simulator from gem5.utils.requires import requires From cf087d4d11155a9d0a7bb33e397678087a6885a8 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sun, 12 Nov 2023 10:36:03 +0000 Subject: [PATCH 664/693] arch-riscv: Add PCEvent for RISCV FS Workload kernel panic/oops Inspired by a similar feature in ARM's full system workload, this change adds an option to halt gem5 simulation if the guest system encounter kernel panic or kernel oops. On RiscvISA::BootloaderKernelWorkload, by default, the simulation will exit upon kernel panic, while kernel oops will not induce simulation halt. This is because the system will essentially do nop after a kernel panic, while the system might be still functional after a kernel oops. Dumping kernel's dmesg is useful for diagonizing the cause of kernel panic, so ideally, we want to dump the guest's dmesg to the host. However, due to a bug described in [1], kernel v5.18+ dmesg might not be dumped properly. Hence, the dmesg will not be dumped to the host. On RiscvISA::FsLinux, this feature is turned off by default as the symbols from the official RISC-V kernel resource are stripped from the binary. However, if this feature is enable, the dmesg will be dumped to the host system. [1] https://github.com/gem5/gem5/issues/550 Change-Id: I8f52257727a3a789ebf99fdd4dffe5b3d89f1ebf Signed-off-by: Hoa Nguyen Co-authored-by: Jason Lowe-Power --- src/arch/riscv/RiscvFsWorkload.py | 35 +++++++++++++- src/arch/riscv/linux/fs_workload.cc | 72 +++++++++++++++++++++++++++++ src/arch/riscv/linux/fs_workload.hh | 39 ++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/src/arch/riscv/RiscvFsWorkload.py b/src/arch/riscv/RiscvFsWorkload.py index 467d7ec26a..24dff58828 100644 --- a/src/arch/riscv/RiscvFsWorkload.py +++ b/src/arch/riscv/RiscvFsWorkload.py @@ -55,6 +55,16 @@ class RiscvLinux(KernelWorkload): ) dtb_addr = Param.Addr(0x87E00000, "DTB address") + # gem5 event upon guest's kernel panic + # Default to false because when the kernel is compiled into the bootloader + # it will not have symbols + exit_on_kernel_panic = Param.Bool( + False, "Generate gem5 panic upon the guest's kernel panic." + ) + exit_on_kernel_oops = Param.Bool( + False, "Generate gem5 panic upon the guest's kernel oops." + ) + class RiscvBootloaderKernelWorkload(Workload): type = "RiscvBootloaderKernelWorkload" @@ -84,5 +94,28 @@ class RiscvBootloaderKernelWorkload(Workload): # booting parameters command_line = Param.String( - "", "Booting arguments, to be passed to the kernel" + "", "Booting arguments, to be passed to the kernel." + ) + + # gem5 event upon guest's kernel panic + # Note that if the kernel doesn't have symbols there will be a warning and + # gem5 will not exit + exit_on_kernel_panic = Param.Bool( + True, "Generate gem5 exit upon the guest's kernel panic." + ) + exit_on_kernel_oops = Param.Bool( + False, "Generate gem5 exit upon the guest's kernel oops." + ) + + # Note: Duplicated from KernelWorkload for now + on_panic = Param.KernelPanicOopsBehaviour( + "DumpDmesgAndExit", + "Define how gem5 should behave after a Linux Kernel Panic. " + "Handler might not be implemented for all architectures.", + ) + + on_oops = Param.KernelPanicOopsBehaviour( + "DumpDmesgAndExit", + "Define how gem5 should behave after a Linux Kernel Oops. " + "Handler might not be implemented for all architectures.", ) diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index da1af8d59b..309d324bcb 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -32,7 +32,10 @@ #include "base/loader/dtb_file.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" +#include "cpu/pc_event.hh" +#include "kern/linux/events.hh" #include "sim/kernel_workload.hh" +#include "sim/sim_exit.hh" #include "sim/system.hh" namespace gem5 @@ -75,6 +78,42 @@ FsLinux::initState() } } +void +FsLinux::startup() +{ + KernelWorkload::startup(); + + addExitOnKernelPanicEvent(); + addExitOnKernelOopsEvent(); +} + +void +FsLinux::addExitOnKernelPanicEvent() +{ + const std::string dmesg_output = name() + ".dmesg"; + if (params().exit_on_kernel_panic) { + kernelPanicPcEvent = addKernelFuncEvent( + "panic", "Kernel panic in simulated system.", + dmesg_output, params().on_panic + ); + warn_if(!kernelPanicPcEvent, "Failed to find kernel symbol 'panic'"); + } +} + +void +FsLinux::addExitOnKernelOopsEvent() +{ + const std::string dmesg_output = name() + ".dmesg"; + if (params().exit_on_kernel_oops) { + kernelOopsPcEvent = addKernelFuncEvent( + "oops_exit", "Kernel oops in simulated system.", + dmesg_output, params().on_oops + ); + warn_if(!kernelOopsPcEvent, + "Failed to find kernel symbol 'oops_exit'"); + } +} + void BootloaderKernelWorkload::loadBootloaderSymbolTable() { @@ -169,6 +208,30 @@ BootloaderKernelWorkload::loadDtb() } } +void +BootloaderKernelWorkload::addExitOnKernelPanicEvent() +{ + const std::string dmesg_output = name() + ".dmesg"; + if (params().exit_on_kernel_panic) { + kernelPanicPcEvent = addFuncEvent( + kernelSymbolTable, "panic", "Kernel panic in simulated system.", + dmesg_output, params().on_panic + ); + } +} + +void +BootloaderKernelWorkload::addExitOnKernelOopsEvent() +{ + const std::string dmesg_output = name() + ".dmesg"; + if (params().exit_on_kernel_oops) { + kernelOopsPcEvent = addFuncEvent( + kernelSymbolTable, "oops_exit", "Kernel oops in simulated system.", + dmesg_output, params().on_oops + ); + } +} + void BootloaderKernelWorkload::initState() { @@ -182,6 +245,15 @@ BootloaderKernelWorkload::initState() } } +void +BootloaderKernelWorkload::startup() +{ + Workload::startup(); + + addExitOnKernelPanicEvent(); + addExitOnKernelOopsEvent(); +} + void BootloaderKernelWorkload::serialize(CheckpointOut &checkpoint) const { diff --git a/src/arch/riscv/linux/fs_workload.hh b/src/arch/riscv/linux/fs_workload.hh index 95269e6f93..c5fcd70eb0 100644 --- a/src/arch/riscv/linux/fs_workload.hh +++ b/src/arch/riscv/linux/fs_workload.hh @@ -44,11 +44,30 @@ namespace RiscvISA class FsLinux : public KernelWorkload { + private: + /** + * Event to halt the simulator if the kernel calls panic() or + * oops_exit() + **/ + PCEvent *kernelPanicPcEvent = nullptr; + PCEvent *kernelOopsPcEvent = nullptr; + void addExitOnKernelPanicEvent(); + void addExitOnKernelOopsEvent(); public: PARAMS(RiscvLinux); FsLinux(const Params &p) : KernelWorkload(p) {} + ~FsLinux() + { + if (kernelPanicPcEvent != nullptr) { + delete kernelPanicPcEvent; + } + if (kernelOopsPcEvent != nullptr) { + delete kernelOopsPcEvent; + } + } void initState() override; + void startup() override; void setSystem(System *sys) override @@ -71,12 +90,21 @@ class BootloaderKernelWorkload: public Workload loader::SymbolTable bootloaderSymbolTable; const std::string bootArgs; + /** + * Event to halt the simulator if the kernel calls panic() or + * oops_exit() + **/ + PCEvent *kernelPanicPcEvent = nullptr; + PCEvent *kernelOopsPcEvent = nullptr; + private: void loadBootloaderSymbolTable(); void loadKernelSymbolTable(); void loadBootloader(); void loadKernel(); void loadDtb(); + void addExitOnKernelPanicEvent(); + void addExitOnKernelOopsEvent(); public: PARAMS(RiscvBootloaderKernelWorkload); @@ -87,7 +115,18 @@ class BootloaderKernelWorkload: public Workload loadKernelSymbolTable(); } + ~BootloaderKernelWorkload() + { + if (kernelPanicPcEvent != nullptr) { + delete kernelPanicPcEvent; + } + if (kernelOopsPcEvent != nullptr) { + delete kernelOopsPcEvent; + } + } + void initState() override; + void startup() override; void setSystem(System *sys) override From 4a77d532b0191f4db54ea40f4184e7c6a5e0f8f9 Mon Sep 17 00:00:00 2001 From: Hoa Nguyen Date: Sat, 25 Nov 2023 22:36:05 +0000 Subject: [PATCH 665/693] stdlib: Add Kernel Panic/Oops exit event to stdlib RISCV full system workloads have the capability of exit the simulation loop upon the guest's kernel panic/oops. This change adds more stdlib exit event types to accommodate the corresponding gem5 exits upon the guest's kernel panic and kernel oops. Change-Id: I3a4f313711793a473c6f138ff831b948034d0bb6 Signed-off-by: Hoa Nguyen --- src/python/gem5/simulate/exit_event.py | 6 ++++++ src/python/gem5/simulate/simulator.py | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/python/gem5/simulate/exit_event.py b/src/python/gem5/simulate/exit_event.py index 3fd12c371b..b902643a3f 100644 --- a/src/python/gem5/simulate/exit_event.py +++ b/src/python/gem5/simulate/exit_event.py @@ -53,6 +53,8 @@ class ExitEvent(Enum): PERF_COUNTER_DISABLE = "performance counter disabled" PERF_COUNTER_RESET = "performance counter reset" PERF_COUNTER_INTERRUPT = "performance counter interrupt" + KERNEL_PANIC = "kernel panic in simulated system" + KERNEL_OOPS = "kernel oops in simulated system" @classmethod def translate_exit_status(cls, exit_string: str) -> "ExitEvent": @@ -103,6 +105,10 @@ class ExitEvent(Enum): return ExitEvent.PERF_COUNTER_RESET elif exit_string == "performance counter interrupt": return ExitEvent.PERF_COUNTER_INTERRUPT + elif exit_string == "Kernel panic in simulated system.": + return ExitEvent.KERNEL_PANIC + elif exit_string == "Kernel oops in simulated system.": + return ExitEvent.KERNEL_OOPS elif exit_string.endswith("will terminate the simulation.\n"): # This is for the traffic generator exit event return ExitEvent.EXIT diff --git a/src/python/gem5/simulate/simulator.py b/src/python/gem5/simulate/simulator.py index fcbfb6d57d..708a484ead 100644 --- a/src/python/gem5/simulate/simulator.py +++ b/src/python/gem5/simulate/simulator.py @@ -308,6 +308,8 @@ class Simulator: "max instructions", "exiting the simulation", )(), + ExitEvent.KERNEL_PANIC: exit_generator(), + ExitEvent.KERNEL_OOPS: exit_generator(), } if on_exit_event: From f00d7f70a4c88ff6b3ee703cb09ff33cc617f74f Mon Sep 17 00:00:00 2001 From: Matthew Poremba Date: Mon, 4 Dec 2023 19:14:46 -0800 Subject: [PATCH 666/693] configs: Fix apu_se.py CPU type checks (#651) The current checks do not work. Correct the CPU type names Change-Id: I81778873df0567c4a8dabbbe659c4c7a39326f98 --- configs/example/apu_se.py | 27 ++++++++++++--------------- configs/ruby/GPU_VIPER.py | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/configs/example/apu_se.py b/configs/example/apu_se.py index b375bbef7b..f9daf8a88b 100644 --- a/configs/example/apu_se.py +++ b/configs/example/apu_se.py @@ -398,8 +398,8 @@ if buildEnv["PROTOCOL"] == "None": fatal("GPU model requires ruby") # Currently the gpu model requires only timing or detailed CPU -if not (args.cpu_type == "TimingSimpleCPU" or args.cpu_type == "DerivO3CPU"): - fatal("GPU model requires TimingSimpleCPU or DerivO3CPU") +if not (args.cpu_type == "X86TimingSimpleCPU" or args.cpu_type == "X86O3CPU"): + fatal("GPU model requires X86TimingSimpleCPU or X86O3CPU.") # This file can support multiple compute units assert args.num_compute_units >= 1 @@ -571,7 +571,7 @@ cp_list = [] cpu_list = [] CpuClass, mem_mode = Simulation.getCPUClass(args.cpu_type) -if CpuClass == AtomicSimpleCPU: +if CpuClass == X86AtomicSimpleCPU or CpuClass == AtomicSimpleCPU: fatal("AtomicSimpleCPU is not supported") if mem_mode != "timing": fatal("Only the timing memory mode is supported") @@ -825,18 +825,15 @@ for i in range(args.num_cpus): system.cpu[i].dcache_port = ruby_port.in_ports ruby_port.mem_request_port = system.piobus.cpu_side_ports - if get_supported_isas().contains(ISA.X86): - system.cpu[i].interrupts[0].pio = system.piobus.mem_side_ports - system.cpu[i].interrupts[ - 0 - ].int_requestor = system.piobus.cpu_side_ports - system.cpu[i].interrupts[ - 0 - ].int_responder = system.piobus.mem_side_ports - if fast_forward: - system.cpu[i].mmu.connectWalkerPorts( - ruby_port.in_ports, ruby_port.in_ports - ) + + # X86 ISA is implied from cpu type check above + system.cpu[i].interrupts[0].pio = system.piobus.mem_side_ports + system.cpu[i].interrupts[0].int_requestor = system.piobus.cpu_side_ports + system.cpu[i].interrupts[0].int_responder = system.piobus.mem_side_ports + if fast_forward: + system.cpu[i].mmu.connectWalkerPorts( + ruby_port.in_ports, ruby_port.in_ports + ) # attach CU ports to Ruby # Because of the peculiarities of the CP core, you may have 1 CPU but 2 diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index 96d86f38d3..0818b7f0eb 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -129,7 +129,7 @@ class CPCntrl(CorePair_Controller, CntrlBase): self.sequencer1.is_cpu_sequencer = True self.issue_latency = options.cpu_to_dir_latency - self.send_evictions = send_evicts(options) + self.send_evictions = True if options.cpu_type == "X86O3CPU" else False self.ruby_system = ruby_system From 9bd61f217fcbf0d787d96550307108f7ba614f55 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Thu, 7 Dec 2023 02:57:18 +0800 Subject: [PATCH 667/693] configs: Fix issues after get_runtime_isa() #241 removed (#652) 1. Fix the wrong ISA detect of get_isa function 2. Fix the typo ObjectLIst.cpu_list 3. Fix missing PageTableWalkerCache 4. Fix the invalid default cpu_type paramter Change-Id: I217ea8da8a6d8e712743a5b32c4c0669216ce6c4 --- configs/common/CacheConfig.py | 8 ++++---- configs/common/Caches.py | 11 +++++++++++ configs/common/CpuConfig.py | 11 +++++++++++ configs/common/ObjectList.py | 17 +++-------------- configs/common/Options.py | 10 +++++++--- configs/common/Simulation.py | 4 ++-- configs/deprecated/example/fs.py | 2 +- configs/deprecated/example/se.py | 2 +- configs/example/hmc_hello.py | 6 +++--- configs/ruby/Ruby.py | 6 +++--- 10 files changed, 46 insertions(+), 31 deletions(-) diff --git a/configs/common/CacheConfig.py b/configs/common/CacheConfig.py index cfc8f95fa5..4f21a43924 100644 --- a/configs/common/CacheConfig.py +++ b/configs/common/CacheConfig.py @@ -148,9 +148,9 @@ def config_cache(options, system): dcache = dcache_class(**_get_cache_opts("l1d", options)) # If we are using ISA.X86 or ISA.RISCV, we set walker caches. - if ObjectList.CPUList().get_isa(options.cpu_type) in [ - ISA.RiscvCPU, - ISA.X86CPU, + if ObjectList.cpu_list.get_isa(options.cpu_type) in [ + ISA.RISCV, + ISA.X86, ]: iwalkcache = PageTableWalkerCache() dwalkcache = PageTableWalkerCache() @@ -191,7 +191,7 @@ def config_cache(options, system): # on these names. For simplicity, we would advise configuring # it to use this naming scheme; if this isn't possible, change # the names below. - if ObjectList.CPUList().get_isa(options.cpu_type) in [ + if ObjectList.cpu_list.get_isa(options.cpu_type) in [ ISA.X86, ISA.ARM, ISA.RISCV, diff --git a/configs/common/Caches.py b/configs/common/Caches.py index 682b937d8b..fed9ac7d19 100644 --- a/configs/common/Caches.py +++ b/configs/common/Caches.py @@ -86,3 +86,14 @@ class IOCache(Cache): mshrs = 20 size = "1kB" tgts_per_mshr = 12 + + +class PageTableWalkerCache(Cache): + assoc = 2 + tag_latency = 2 + data_latency = 2 + response_latency = 2 + mshrs = 10 + size = "1kB" + tgts_per_mshr = 12 + is_read_only = False diff --git a/configs/common/CpuConfig.py b/configs/common/CpuConfig.py index 0d132b83b9..b4519dba27 100644 --- a/configs/common/CpuConfig.py +++ b/configs/common/CpuConfig.py @@ -36,6 +36,17 @@ import m5.objects from m5 import fatal +from gem5.isas import ISA + +isa_string_map = { + ISA.X86: "X86", + ISA.ARM: "Arm", + ISA.RISCV: "Riscv", + ISA.SPARC: "Sparc", + ISA.POWER: "Power", + ISA.MIPS: "Mips", +} + def config_etrace(cpu_cls, cpu_list, options): if issubclass(cpu_cls, m5.objects.DerivO3CPU): diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index 940403467f..51b057f021 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -166,26 +166,15 @@ class CPUList(ObjectList): cls = self.get(name) - def class_exist(className: str) -> bool: - """Check if a class exists.""" - import types - - result = False - try: - result = eval("type(" + className + ")") == types.ClassType - except NameError: - pass - return result - - if class_exist(m5.objects.X86CPU) and issubclass( + if hasattr(m5.objects, "X86CPU") and issubclass( cls, m5.objects.X86CPU ): return ISA.X86 - elif class_exist(m5.objects.ArmCPU) and issubclass( + elif hasattr(m5.objects, "ArmCPU") and issubclass( cls, m5.objects.ArmCPU ): return ISA.ARM - elif class_exist(m5.objects.RiscvCPU) and issubclass( + elif hasattr(m5.objects, "RiscvCPU") and issubclass( cls, m5.objects.RiscvCPU ): return ISA.RISCV diff --git a/configs/common/Options.py b/configs/common/Options.py index 91e42e6b37..c15410d41a 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -38,7 +38,10 @@ import argparse -from common import ObjectList +from common import ( + CpuConfig, + ObjectList, +) from common.Benchmarks import * import m5 @@ -242,6 +245,7 @@ def addNoISAOptions(parser): def addCommonOptions(parser): # start by adding the base options that do not assume an ISA addNoISAOptions(parser) + isa = list(get_supported_isas())[0] # system options parser.add_argument( @@ -252,7 +256,7 @@ def addCommonOptions(parser): ) parser.add_argument( "--cpu-type", - default=list(get_supported_isas())[0].name + "AtomicSimpleCPU", + default=CpuConfig.isa_string_map[isa] + "AtomicSimpleCPU", choices=ObjectList.cpu_list.get_names(), help="type of cpu to run with", ) @@ -583,7 +587,7 @@ def addCommonOptions(parser): parser.add_argument( "--restore-with-cpu", action="store", - default="AtomicSimpleCPU", + default=CpuConfig.isa_string_map[isa] + "AtomicSimpleCPU", choices=ObjectList.cpu_list.get_names(), help="cpu type for restoring from a checkpoint", ) diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index f33a006d45..3e332d76b4 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -81,9 +81,9 @@ def setCPUClass(options): TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu) elif options.fast_forward: CPUClass = TmpClass + CPUISA = ObjectList.cpu_list.get_isa(options.cpu_type) TmpClass = getCPUClass( - ObjectList.CPUList().get_isa(options.cpu_type).name - + "AtomicSimpleCPU" + CpuConfig.isa_string_map[CPUISA] + "AtomicSimpleCPU" ) test_mem_mode = "atomic" diff --git a/configs/deprecated/example/fs.py b/configs/deprecated/example/fs.py index 7fabf7b1bd..7426c47c7e 100644 --- a/configs/deprecated/example/fs.py +++ b/configs/deprecated/example/fs.py @@ -382,7 +382,7 @@ else: np = args.num_cpus -isa = ObjectList.CPUList.get_isa(args.cpu_type) +isa = ObjectList.cpu_list.get_isa(args.cpu_type) test_sys = build_test_system(np, isa) if len(bm) == 2: diff --git a/configs/deprecated/example/se.py b/configs/deprecated/example/se.py index 16ea1fddb0..137dc030b7 100644 --- a/configs/deprecated/example/se.py +++ b/configs/deprecated/example/se.py @@ -149,7 +149,7 @@ if args.bench: for app in apps: try: - if ObjectList.CPUList().get_isa(args.cpu_type) == ISA.ARM: + if ObjectList.cpu_list.get_isa(args.cpu_type) == ISA.ARM: exec( "workload = %s('arm_%s', 'linux', '%s')" % (app, args.arm_iset, args.spec_input) diff --git a/configs/example/hmc_hello.py b/configs/example/hmc_hello.py index 83bf8be640..d796bcad99 100644 --- a/configs/example/hmc_hello.py +++ b/configs/example/hmc_hello.py @@ -51,7 +51,7 @@ parser.add_argument( "--cpu-type", type=str, default="X86TimingSimpleCPU", - choices=ObjectList.CPUList().get_names(), + choices=ObjectList.cpu_list.get_names(), help="CPU model to use", ) HMC.add_options(parser) @@ -65,7 +65,7 @@ clk = "1GHz" vd = VoltageDomain(voltage="1V") system.clk_domain = SrcClockDomain(clock=clk, voltage_domain=vd) # create a CPU -system.cpu = ObjectList().get(options.cpu_type)() +system.cpu = ObjectList.cpu_list.get(options.cpu_type)() # config memory system MemConfig.config_mem(options, system) # hook the CPU ports up to the membus @@ -81,7 +81,7 @@ system.system_port = system.membus.cpu_side_ports binary = ( "tests/test-progs/hello/bin/" - + ObjectList.CPUList().get_isa(options.cpu_type).name.lower() + + ObjectList.cpu_list.get_isa(options.cpu_type).name.lower() + "/linux/hello" ) diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index 83c5edea6f..d3f798ec3a 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -331,8 +331,8 @@ def send_evicts(options): # 2. The x86 mwait instruction is built on top of coherence invalidations # 3. The local exclusive monitor in ARM systems - if isinstance( - options.cpu_type, DerivO3CPU - ) or ObjectList.CPUList().get_isa(options.cpu_type) in [ISA.X86, ISA.ARM]: + if isinstance(options.cpu_type, DerivO3CPU) or ObjectList.cpu_list.get_isa( + options.cpu_type + ) in [ISA.X86, ISA.ARM]: return True return False From d006f866c0d236d8a0d7e5b6223527ff76ebc0b5 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 6 Dec 2023 14:09:06 -0800 Subject: [PATCH 668/693] misc: Update version to v23.1.0.0 (#662) --- src/Doxyfile | 2 +- src/base/version.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Doxyfile b/src/Doxyfile index 24d70bbc55..68d9b3b44b 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = gem5 # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = [DEVELOP-FOR-23.0] +PROJECT_NUMBER = v23.1.0.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/src/base/version.cc b/src/base/version.cc index c7255e91a7..30b2bddb73 100644 --- a/src/base/version.cc +++ b/src/base/version.cc @@ -32,6 +32,6 @@ namespace gem5 /** * @ingroup api_base_utils */ -const char *gem5Version = "DEVELOP-FOR-23.1"; +const char *gem5Version = "23.1.0.0"; } // namespace gem5 From db286903ee7fe8e2441c118db27ed71c40a99cc4 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Fri, 8 Dec 2023 08:10:45 +0800 Subject: [PATCH 669/693] stdlib: Fix the chi protocol of arm boot tests (#658) Change-Id: I63f17a73b2e16bc26d9b41babc63439a6040791f --- .../gem5/components/cachehierarchies/chi/nodes/directory.py | 1 + .../gem5/components/cachehierarchies/chi/nodes/dma_requestor.py | 2 ++ .../cachehierarchies/chi/nodes/private_l1_moesi_cache.py | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py index 7d7a16cd5f..b2515d3c84 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/directory.py @@ -61,6 +61,7 @@ class SimpleDirectory(AbstractNode): self.sequencer = NULL self.use_prefetcher = False + self.prefetcher = NULL # Set up home node that allows three hop protocols self.is_HN = True diff --git a/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py index 2997c33ce7..850c7e9002 100644 --- a/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py +++ b/src/python/gem5/components/cachehierarchies/chi/nodes/dma_requestor.py @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects import ( + NULL, ClockDomain, RubyCache, ) @@ -67,6 +68,7 @@ class DMARequestor(AbstractNode): self.send_evictions = False self.use_prefetcher = False + self.prefetcher = NULL # Some reasonable default TBE params self.number_of_TBEs = 16 self.number_of_repl_TBEs = 1 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 index 477c0f9b63..8b056b3967 100644 --- 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 @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from m5.objects import ( + NULL, ClockDomain, RubyCache, RubyNetwork, @@ -56,6 +57,7 @@ class PrivateL1MOESICache(AbstractNode): self.clk_domain = clk_domain self.send_evictions = core.requires_send_evicts() self.use_prefetcher = False + self.prefetcher = NULL # Only applies to home nodes self.is_HN = False From 6b80a2e81c279d2d6cd4172edb2f373e95aa408c Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Wed, 13 Dec 2023 00:23:28 +0800 Subject: [PATCH 670/693] configs: Make riscv/fs_linux work in build/ALL/gem5.opt (#655) Change-Id: If9add7dc5e9c5600f769d27817da41466158942b --- configs/common/Options.py | 26 ++++++++++++++++---------- configs/example/riscv/fs_linux.py | 20 +++++++------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/configs/common/Options.py b/configs/common/Options.py index c15410d41a..97335f13b9 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -37,6 +37,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse +from typing import Optional from common import ( CpuConfig, @@ -48,6 +49,7 @@ import m5 from m5.defines import buildEnv from m5.objects import * +from gem5.isas import ISA from gem5.runtime import get_supported_isas vio_9p_help = """\ @@ -242,10 +244,13 @@ def addNoISAOptions(parser): # Add common options that assume a non-NULL ISA. -def addCommonOptions(parser): +def addCommonOptions(parser, default_isa: Optional[ISA] = None): # start by adding the base options that do not assume an ISA addNoISAOptions(parser) - isa = list(get_supported_isas())[0] + if default_isa is None: + isa = list(get_supported_isas())[0] + else: + isa = default_isa # system options parser.add_argument( @@ -790,12 +795,20 @@ def addFSOptions(parser): "files in the gem5 output directory", ) - if buildEnv["USE_ARM_ISA"]: + if buildEnv["USE_ARM_ISA"] or buildEnv["USE_RISCV_ISA"]: parser.add_argument( "--bare-metal", action="store_true", help="Provide the raw system without the linux specific bits", ) + parser.add_argument( + "--dtb-filename", + action="store", + type=str, + help="Specifies device tree blob file to use with device-tree-" + "enabled kernels", + ) + if buildEnv["USE_ARM_ISA"]: parser.add_argument( "--list-machine-types", action=ListPlatform, @@ -808,13 +821,6 @@ def addFSOptions(parser): choices=ObjectList.platform_list.get_names(), default="VExpress_GEM5_V1", ) - parser.add_argument( - "--dtb-filename", - action="store", - type=str, - help="Specifies device tree blob file to use with device-tree-" - "enabled kernels", - ) parser.add_argument( "--enable-context-switch-stats-dump", action="store_true", diff --git a/configs/example/riscv/fs_linux.py b/configs/example/riscv/fs_linux.py index 075b4a0069..c0643c883d 100644 --- a/configs/example/riscv/fs_linux.py +++ b/configs/example/riscv/fs_linux.py @@ -52,6 +52,8 @@ from m5.util import ( ) from m5.util.fdthelper import * +from gem5.utils.requires import requires + addToPath("../../") from common import ( @@ -68,6 +70,9 @@ from common.FSConfig import * from common.SysPaths import * from ruby import Ruby +# Run a check to ensure the RISC-V ISA is complied into gem5. +requires(isa_required=ISA.RISCV) + # ------------------------- Usage Instructions ------------------------- # # Common system confirguration options (cpu types, num cpus, checkpointing # etc.) should be supported @@ -135,20 +140,8 @@ def generateDtb(system): # ----------------------------- Add Options ---------------------------- # parser = argparse.ArgumentParser() -Options.addCommonOptions(parser) +Options.addCommonOptions(parser, ISA.RISCV) Options.addFSOptions(parser) -parser.add_argument( - "--bare-metal", - action="store_true", - help="Provide the raw system without the linux specific bits", -) -parser.add_argument( - "--dtb-filename", - action="store", - type=str, - help="Specifies device tree blob file to use with device-tree-" - "enabled kernels", -) parser.add_argument( "--virtio-rng", action="store_true", help="Enable VirtIORng device" ) @@ -158,6 +151,7 @@ args = parser.parse_args() # CPU and Memory (CPUClass, mem_mode, FutureClass) = Simulation.setCPUClass(args) +assert issubclass(CPUClass, RiscvCPU) MemClass = Simulation.setMemClass(args) np = args.num_cpus From 7ce69b56be9905bdf05acca6964de5b983cac33d Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 5 Dec 2023 14:54:12 -0800 Subject: [PATCH 671/693] arch-riscv: Update riscv matched boad - Update riscv matched board to work with new RiscvBootloaderKernelWorkload Change-Id: Ic20b964f33e73b76775bfe18798bd667f36253f6 --- .../riscvmatched/riscvmatched_board.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index c735313a6a..f827ec7bff 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -45,7 +45,7 @@ from m5.objects import ( PMAChecker, Port, RawDiskImage, - RiscvLinux, + RiscvBootloaderKernelWorkload, RiscvMmioVirtIO, RiscvRTC, VirtIOBlock, @@ -144,7 +144,7 @@ class RISCVMatchedBoard( @overrides(AbstractSystemBoard) def _setup_board(self) -> None: if self._fs: - self.workload = RiscvLinux() + self.workload = RiscvBootloaderKernelWorkload() # Contains a CLINT, PLIC, UART, and some functions for the dtb, etc. self.platform = HiFive() @@ -310,6 +310,18 @@ class RISCVMatchedBoard( self.mem_ranges = [AddrRange(memory.get_size())] memory.set_memory_range(self.mem_ranges) + @overrides(AbstractSystemBoard) + def _pre_instantiate(self): + if len(self._bootloader) > 0: + self.workload.bootloader_addr = 0x0 + self.workload.bootloader_filename = self._bootloader[0] + self.workload.kernel_addr = 0x80200000 + self.workload.entry_point = 0x80000000 # Bootloader starting point + else: + self.workload.kernel_addr = 0x0 + self.workload.entry_point = 0x80000000 + self._connect_things() + def generate_device_tree(self, outdir: str) -> None: """Creates the ``dtb`` and ``dts`` files. @@ -588,7 +600,7 @@ class RISCVMatchedBoard( kernel_args: Optional[List[str]] = None, exit_on_work_items: bool = True, ) -> None: - self.workload = RiscvLinux() + self.workload = RiscvBootloaderKernelWorkload() KernelDiskWorkload.set_kernel_disk_workload( self=self, kernel=kernel, From 5ac9598133913758099476ddc9d51a03ad17ee4f Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 6 Dec 2023 20:10:56 -0800 Subject: [PATCH 672/693] Arch-riscv: Add chosen node Change-Id: I458665caec08856cd8e61d2cd7a5b0dc5c35d469 --- .../gem5/prebuilt/riscvmatched/riscvmatched_board.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index f827ec7bff..f4e4b381a1 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -348,6 +348,12 @@ class RISCVMatchedBoard( ) root.append(node) + node = FdtNode(f"chosen") + bootargs = self.workload.command_line + node.append(FdtPropertyStrings("bootargs", [bootargs])) + node.append(FdtPropertyStrings("stdout-path", ["/uart@10000000"])) + root.append(node) + # See Documentation/devicetree/bindings/riscv/cpus.txt for details. cpus_node = FdtNode("cpus") cpus_state = FdtState(addr_cells=1, size_cells=0) @@ -520,7 +526,7 @@ class RISCVMatchedBoard( uart_node.append( FdtPropertyWords("interrupt-parent", soc_state.phandle(plic)) ) - uart_node.appendCompatible(["ns8250"]) + uart_node.appendCompatible(["ns8250", "ns16550a"]) soc_node.append(uart_node) # VirtIO MMIO disk node From 34f784f59cb6938e66a4eff2c842d592f5e21cd5 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 12 Dec 2023 12:33:22 -0800 Subject: [PATCH 673/693] tests: fix gapbs and npb tests (#671) Change-Id: I6090bde7903e302e501319b545fb4b06ef3e3df9 --- .../test_gem5_library_examples.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py index 5ffb62873d..9c88ff4307 100644 --- a/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py +++ b/tests/gem5/gem5_library_example_tests/test_gem5_library_examples.py @@ -218,10 +218,7 @@ if os.access("/dev/kvm", mode=os.R_OK | os.W_OK): ), config_args=[ "--benchmark", - "bt", - "--size", - "A", - "--ticks", + "npb-bt-a" "--ticks", "5000000000", ], valid_isas=(constants.all_compiled_tag,), @@ -245,7 +242,7 @@ if os.access("/dev/kvm", mode=os.R_OK | os.W_OK): "gem5_library", "x86-gapbs-benchmarks.py", ), - config_args=["--benchmark", "bfs", "--synthetic", "1", "--size", "1"], + config_args=["--benchmark", "gapbs-bfs-test"], valid_isas=(constants.all_compiled_tag,), protocol="MESI_Two_Level", valid_hosts=(constants.host_x86_64_tag,), From 301fb3f5096b22096db73bd8d0592d28b5e3d230 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 12 Dec 2023 14:23:04 -0800 Subject: [PATCH 674/693] stdlib: Remove 'additional_params' value type assert The value of a `WorkloadResource`'s additional parameter may not always be a string. It can be any JSON value (integer, a list, a dict, ect.). For Looppoint resources we have additional parameters such as a List of region start points. The assert inside workloads checking the type of the value breaks certain usecase and is therefore removed in this commit. Change-Id: Iecb1518082c28ab3872a8de888c76f0800261640 --- src/python/gem5/resources/resource.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index 08d046fc01..d6746487ff 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -1098,7 +1098,6 @@ def obtain_resource( for key in resource_json["additional_params"].keys(): assert isinstance(key, str) value = resource_json["additional_params"][key] - assert isinstance(value, str) params[key] = value resource_json["parameters"] = params # Once we know what AbstractResource subclass we are using, we create it. From d8cc5305979edcf6bd90effbcf6307f654d3f149 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 12 Dec 2023 14:28:11 -0800 Subject: [PATCH 675/693] stdlib: Add `get_local_path()` call to Looppoint resources Due to a change introduced in https://github.com/gem5/gem5/pull/625, a gem5 resource will not download any external files until `get_local_path()` is called. In the construction of the Looppoint Resources this function was not called, the `local_path` variable was called directly. As such, an error occured. The downside of this fix is the Looppoint resources external files are downloaded when `obtain_resource` is called, thus the bandwidth savings introduced with https://github.com/gem5/gem5/pull/625 will not occur for Looppoint resources. However, https://github.com/gem5/gem5/issues/644 proposes a fix which would supercede the https://github.com/gem5/gem5/pull/625 solution. Change-Id: I52181382a03e492ec1cb58b01e71bc4820af9ccc --- src/python/gem5/resources/resource.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/python/gem5/resources/resource.py b/src/python/gem5/resources/resource.py index d6746487ff..591515a6b9 100644 --- a/src/python/gem5/resources/resource.py +++ b/src/python/gem5/resources/resource.py @@ -578,7 +578,9 @@ class LooppointCsvResource(FileResource, LooppointCsvLoader): resource_version=resource_version, downloader=downloader, ) - LooppointCsvLoader.__init__(self, pinpoints_file=Path(local_path)) + LooppointCsvLoader.__init__( + self, pinpoints_file=Path(self.get_local_path()) + ) def get_category_name(cls) -> str: return "LooppointCsvResource" @@ -606,7 +608,7 @@ class LooppointJsonResource(FileResource, LooppointJsonLoader): downloader=downloader, ) LooppointJsonLoader.__init__( - self, looppoint_file=local_path, region_id=region_id + self, looppoint_file=self.get_local_path(), region_id=region_id ) def get_category_name(cls) -> str: From 9aab380775ba59a62ae2b6a26a0557f3e8e1f5df Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Wed, 13 Dec 2023 13:16:08 -0800 Subject: [PATCH 676/693] arch-riscv: fix riscv matched board for se mode (#677) --- .../riscvmatched/riscvmatched_board.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py index f4e4b381a1..0de69a40f2 100644 --- a/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py +++ b/src/python/gem5/prebuilt/riscvmatched/riscvmatched_board.py @@ -312,14 +312,18 @@ class RISCVMatchedBoard( @overrides(AbstractSystemBoard) def _pre_instantiate(self): - if len(self._bootloader) > 0: - self.workload.bootloader_addr = 0x0 - self.workload.bootloader_filename = self._bootloader[0] - self.workload.kernel_addr = 0x80200000 - self.workload.entry_point = 0x80000000 # Bootloader starting point - else: - self.workload.kernel_addr = 0x0 - self.workload.entry_point = 0x80000000 + if self._fs: + if len(self._bootloader) > 0: + self.workload.bootloader_addr = 0x0 + self.workload.bootloader_filename = self._bootloader[0] + self.workload.kernel_addr = 0x80200000 + self.workload.entry_point = ( + 0x80000000 # Bootloader starting point + ) + else: + self.workload.kernel_addr = 0x0 + self.workload.entry_point = 0x80000000 + self._connect_things() def generate_device_tree(self, outdir: str) -> None: From a9f8db704483bffe9db96364d0871eed8e81a10c Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 12 Dec 2023 16:35:01 +0800 Subject: [PATCH 677/693] arch-riscv: Fix the vector store indexed instructions declaration Change-Id: I6f8701ef0819c22eda8cb20d09c40101f2d001a0 --- src/arch/riscv/isa/templates/vector_mem.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/isa/templates/vector_mem.isa b/src/arch/riscv/isa/templates/vector_mem.isa index c405304a4f..1510c106c7 100644 --- a/src/arch/riscv/isa/templates/vector_mem.isa +++ b/src/arch/riscv/isa/templates/vector_mem.isa @@ -1586,7 +1586,7 @@ Fault } if (machInst.vill) return std::make_shared("VILL is set", machInst); - %(op_src_decl)s; + %(op_decl)s; %(op_rd)s; %(set_vlenb)s; %(ea_code)s; From 654e7c60197e94c34ac1bb10246298dacbb03bcf Mon Sep 17 00:00:00 2001 From: Roger Chang Date: Tue, 12 Dec 2023 16:04:09 +0800 Subject: [PATCH 678/693] arch: Fix inst flag of RISC-V vector store macro instructions Correct the instruction flags of RISC-V vector store instructions, such as `vse64_v`, `vse32_v`. The `vse64_v` in `decoder.isa` is `Mem_vc.as()[i] = Vs3_ud[i];` and it will generate the code `Mem.as()[i] = Vs3[i];`. The current regex of assignRE only mark the operand `Mem` as `dest` only if meet the formats like `Mem = Rd` or `Mem[i] = Rd` because the code ` = Rd` or `[i] = Rd` match the `assignRE` respectively. For the expression `Mem.as()[i]`, the operand `Mem` will falsely mark the operand as `src` because the code `.as()[i]` is not match the `assignRE`. The PR will ensure the operand `Mem` is dest for the format like `Mem.as()[i] = yyy`. Change-Id: I9c57986a64f1efb81eb9c7ade90712b118e0788d --- src/arch/isa_parser/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/arch/isa_parser/util.py b/src/arch/isa_parser/util.py index 9e330adc1f..ee1758d263 100755 --- a/src/arch/isa_parser/util.py +++ b/src/arch/isa_parser/util.py @@ -69,7 +69,9 @@ commentRE = re.compile( # destination. basically we're looking for an '=' that's not '=='. # The heinous tangle before that handles the case where the operand # has an array subscript. -assignRE = re.compile(r"(\[[^\]]+\])?\s*=(?!=)", re.MULTILINE) +assignRE = re.compile( + r"((\.as<[^>]+>\(\s*\))?\[[^\]]+\])?\s*=(?!=)", re.MULTILINE +) # # Munge a somewhat arbitrarily formatted piece of Python code From 29b77260f39d47c293e6bd1cd166ff24f567eeb0 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Tue, 12 Dec 2023 08:21:27 -0800 Subject: [PATCH 679/693] arch-x86: Fix two_byte_opcodes.isa `0x6` -> `0x0` (#666) This bug was introduced by https://github.com/gem5/gem5/pull/593 and caused Issue https://github.com/gem5/gem5/issues/664. Change-Id: Ia55de364ee8260e1fe315e37e1cffbc71ab229fb --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 48c3a2d20d..a32d41a169 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -291,7 +291,7 @@ 0x0: decode LEGACY_DECODEVAL { // no prefix 0x0: decode OPCODE_OP_BOTTOM3 { - 0x6: Cpl0CondInst::MOV( + 0x0: Cpl0CondInst::MOV( {{misc_reg::isValid(misc_reg::cr(MODRM_REG))}},Rd,Cd); 0x1: Cpl0CondInst::MOV({{MODRM_REG < 8}},Rd,Dd); 0x2: Cpl0CondInst::MOV( From ce6fd7f084ad2f632f6d8486899a7328ea4d8f35 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Mon, 18 Dec 2023 06:08:49 +0000 Subject: [PATCH 680/693] configs: Fix SMT cpu type checking (#684) The args.cpu_type is not a type but a string so the isinstance checking will always fail and an assertion will always be thrown Change-Id: I6a88d1a514bb323c517949632f4e76be40e87e8c Signed-off-by: Giacomo Travaglini --- configs/common/ObjectList.py | 1 + configs/deprecated/example/se.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/common/ObjectList.py b/configs/common/ObjectList.py index 51b057f021..d36044e068 100644 --- a/configs/common/ObjectList.py +++ b/configs/common/ObjectList.py @@ -228,3 +228,4 @@ def _subclass_tester(name): is_kvm_cpu = _subclass_tester("BaseKvmCPU") is_noncaching_cpu = _subclass_tester("NonCachingSimpleCPU") +is_o3_cpu = _subclass_tester("BaseO3CPU") diff --git a/configs/deprecated/example/se.py b/configs/deprecated/example/se.py index 137dc030b7..afdb82489d 100644 --- a/configs/deprecated/example/se.py +++ b/configs/deprecated/example/se.py @@ -118,7 +118,8 @@ def get_processes(args): idx += 1 if args.smt: - assert isinstance(args.cpu_type, DerivO3CPU) + cpu_type = ObjectList.cpu_list.get(args.cpu_type) + assert ObjectList.is_o3_cpu(cpu_type), "SMT requires an O3CPU" return multiprocesses, idx else: return multiprocesses, 1 From 27d89379d2b12f1150ef3c26a17ee9f262f78d77 Mon Sep 17 00:00:00 2001 From: Tiberiu Bucur <36485854+TiberiuBucur@users.noreply.github.com> Date: Mon, 18 Dec 2023 06:07:39 +0000 Subject: [PATCH 681/693] sim: Remove trailing / from proc/meminfo special path (#689) Note: A bug was identified in that the one of the special file paths, namely /proc/meminfo contained an extra trailing /, implicitly making the incorrect assumption that meminfo was a directory, when it is, in fact, a (pseudo-)file. This was causing application in SE mode to fail opening the meminfo pseudo-file with errno 13. This commit fixes this issue. Change-Id: I93fa81cab49645d70775088f1e634f067b300698 Reviewed-by: Richard Cooper --- src/sim/syscall_emul.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index c23521aed9..97749f325d 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2015, 2019-2021 Arm Limited + * Copyright (c) 2012-2013, 2015, 2019-2021, 2023 Arm Limited * Copyright (c) 2015 Advanced Micro Devices, Inc. * All rights reserved * @@ -866,7 +866,7 @@ openatFunc(SyscallDesc *desc, ThreadContext *tc, int sim_fd = -1; std::string used_path; std::vector special_paths = - { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd", + { "/proc/meminfo", "/system/", "/platform/", "/etc/passwd", "/proc/self/maps", "/dev/urandom", "/sys/devices/system/cpu/online" }; for (auto entry : special_paths) { From d76a01973a82c91047e844802bbaaeab97a3524f Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Mon, 18 Dec 2023 12:41:52 -0800 Subject: [PATCH 682/693] util: Added script to copy resources from mongodb (#510) - This script copies all resources from a mongodb database locally The script creates a resources.json and downloads all the resources. It also updates the resources.json to point to these local downloads instead of the cloud bucket. Change-Id: I15480c4ba82bbf245425205c9c1ab7c0f3501cc3 --- util/offline_db/README.md | 45 ++++ util/offline_db/gem5_default_config.json | 13 ++ util/offline_db/get-resources-from-db.py | 248 +++++++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 util/offline_db/README.md create mode 100644 util/offline_db/gem5_default_config.json create mode 100644 util/offline_db/get-resources-from-db.py diff --git a/util/offline_db/README.md b/util/offline_db/README.md new file mode 100644 index 0000000000..869f79c7ab --- /dev/null +++ b/util/offline_db/README.md @@ -0,0 +1,45 @@ + +# Offline Database Utility + +This Python script makes local copies of all the gem5 Resource's external files and data. +This is useful for cases where an internet connection is not permitted. +With this script users can cache a local copy which can be used by gem5. + +Two interconnected parts of the gem5 infrastructure are cached using this script. +They are: + +1. **The gem5 Resources database**: When the gem5 Standard Library attempts to construct a gem5 Resource it will reference that resource's entry in the gem5 MongoDB database. +It then uses this data to construct the resource. +With this script we download this database as a JSON file for gem5 to use in-place of the database. + +2. **gem5 Resource Remote Files**: Resources can (and often do) require files to be downloaded for them to function correctly in gem5. +Once the gem5 Resource is constructed from the database entry the gem5 Resource may download the remote files it requires. +As a simple example, a `DiskImageResource` will contain disk image partitioning information necessary for a gem5 simulation to be setup correctly. +The disk image file is a remote file which is downloaded as this information cannot be stored directly in the database. + +The location of these file is stored within the resource's database entry as a URL. + +To create a local cache of these remote files we download all the remote files and, when creating the JSON file from the database, update the URLs to remote files to File URIs to their local equivalents. + +Once this script is finished running the user will have a directory of all the remote gem5 Resources files and a JSON file representation of the database, with the remote files' URLs updated to local path URIs. + +## Running the Script + +### Arguments +- `--config-file-path`: Filepath to the gem5 config file. +- `--output-dir`: Output directory path (default: current working directory). + + +```bash +python3 ./get-resources-from-db.py [--config-file-path CONFIG_FILE_PATH] [--output_dir OUTPUT_DIR] +``` + +## Functionality + +### What is the config file? + +The resources config file represents all the sources. + +The gem5_default_config adds the gem5 resources MongoDB Atlas database as a datasource. + +Documentation on setting up your own data sources can be found here: https://www.gem5.org/documentation/gem5-stdlib/using-local-resources diff --git a/util/offline_db/gem5_default_config.json b/util/offline_db/gem5_default_config.json new file mode 100644 index 0000000000..73c4eeead0 --- /dev/null +++ b/util/offline_db/gem5_default_config.json @@ -0,0 +1,13 @@ +{ + "sources": { + "gem5-resources": { + "dataSource": "gem5-vision", + "database": "gem5-vision", + "collection": "resources", + "url": "https://data.mongodb-api.com/app/data-ejhjf/endpoint/data/v1", + "authUrl": "https://realm.mongodb.com/api/client/v2.0/app/data-ejhjf/auth/providers/api-key/login", + "apiKey": "OIi5bAP7xxIGK782t8ZoiD2BkBGEzMdX3upChf9zdCxHSnMoiTnjI22Yw5kOSgy9", + "isMongo": true + } + } +} diff --git a/util/offline_db/get-resources-from-db.py b/util/offline_db/get-resources-from-db.py new file mode 100644 index 0000000000..4eeca46079 --- /dev/null +++ b/util/offline_db/get-resources-from-db.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" +This is a script to get all resources from the database and save them to +a json file and download all resources to a directory. The resources in +the resources.json file that is generated will be updated to point to the +local resources instead of the database resources. This script is used to +create the offline database. To use the resources.json with gem5 you need +to update the gem5 config to point to the resources.json file. +""" + +import argparse +import hashlib +import json +from pathlib import Path +from typing import ( + Dict, + List, + TextIO, +) +from urllib import ( + parse, + request, +) + + +def get_token(auth_url: str, api_key: str) -> str: + """ + This function gets the token from the database using the api key + :param auth_url: Authentication url to use Atlas data API + :param api_key: API key to access the database + :return: Token to access the database + """ + + data = {"key": api_key} + data = json.dumps(data).encode("utf-8") + + req = request.Request( + auth_url, data=data, headers={"content-type": "application/json"} + ) + + try: + response = request.urlopen(req) + except Exception as e: + raise Exception( + "Failed to obtain token via url request. " + f"Exception thrown:\n{e}" + ) + + json_response = json.loads(response.read().decode("utf-8")) + assert "access_token" in json_response, ( + "'access_token' not key in" + "json dictionary. JSON: \n" + f"{json_response}" + ) + token = json_response["access_token"] + + return token + + +def get_all_resources( + url: str, data_source: str, collection: str, database: str, token: str +) -> List: + """ + This function gets all the JSON objects for resources from the database + :param url: Database url to use Atlas data API + :param data_source: Data source name for the mongoDB database + :param collection: Collection name for the mongoDB database + :param database: Database name for the mongoDB database + :param token: Token to access the database + + :return: List of JSON objects for resources + """ + + url = f"{url}/action/find" + data = { + "dataSource": data_source, + "collection": collection, + "database": database, + } + data = json.dumps(data).encode("utf-8") + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + } + + req = request.Request(url, data=data, headers=headers) + + try: + response = request.urlopen(req) + except Exception as e: + raise Exception( + "Failed to obtain resources via url request. " + f"Exception thrown:\n{e}" + ) + + json_response = json.loads(response.read().decode("utf-8")) + assert "documents" in json_response, ( + "'documents' not a key in " + "json dictionary. JSON: \n" + f"{json_response}" + ) + resources = json_response["documents"] + + return resources + + +def save_resources_to_file(resources: List[Dict], output: TextIO): + """ + This function saves all the JSON objects for resources to a file. + :param resources: List of JSON objects for resources + :param output: Output directory absolute path + """ + + path = output.joinpath("resources.json") + + with open(path, "w") as f: + json.dump(resources, f, indent=4) + + +def get_resource_local_filepath( + resource_id: str, resource_version: str, base_output_path: TextIO +) -> Path: + """ + This function returns the local filepath for a resource + :param resource_url: URL field of the resource + :param base_output_path: Base output directory absolute path + :return: Local filepath for the resource + """ + filename = f"{resource_id}-{resource_version}" + + filepath = Path(base_output_path).joinpath(filename) + + return filepath + + +def download_resources(resources: List[Dict], output: TextIO): + """ + This function downloads the resources which have a url field and + updates the url field to point to the local download of the resource. + :param output: Output directory absolute path + """ + + path = output.joinpath("offline_resources") + if not path.exists(): + path.mkdir() + + for resource in resources: + if "url" in resource.keys(): + url = resource["url"] + filepath = get_resource_local_filepath( + resource["id"], resource["resource_version"], path + ) + + if not filepath.exists() or ( # If the file does not exist + "url-md5sum" + in resource.keys() # If it exist but the md5sum is wrong. + and hashlib.md5(filepath.read_bytes()).hexdigest() + != resource["url-md5sum"] + ): + print(f"Downloading {url} to {filepath}") + request.urlretrieve(url, filepath) + resource["url"] = filepath.absolute().as_uri() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Download all the remote gem5 Resources data and files " + "to be cached and used locally." + ) + + parser.add_argument( + "--config-file-path", + type=str, + default=Path(__file__) + .resolve() + .parent.joinpath("gem5_default_config.json"), + help="Filepath to the gem5 config file", + ) + + parser.add_argument( + "--output-dir", + type=str, + default=Path.cwd(), + help="Output directory path, default is the cwd." + "The resources.json and all resources will be saved in this directory", + ) + args = parser.parse_args() + + output_path = Path(args.output_dir) + + # Get the gem5 config file from the file + + with open(args.config_file_path) as f: + gem5_config_json = json.load(f) + gem5_config_gem5_resources = gem5_config_json["sources"]["gem5-resources"] + + # Parse the gem5 config + db_url = gem5_config_gem5_resources["url"] + data_source = gem5_config_gem5_resources["dataSource"] + collection_name = gem5_config_gem5_resources["collection"] + db_name = gem5_config_gem5_resources["database"] + auth_url = gem5_config_gem5_resources["authUrl"] + api_key = gem5_config_gem5_resources["apiKey"] + + if not output_path.exists(): + output_path = output_path.mkdir(parents=True, exist_ok=True) + + token = get_token(auth_url, api_key) + + resources = get_all_resources( + db_url, + data_source, + collection_name, + db_name, + token, + ) + + download_resources(resources, output_path) + + save_resources_to_file( + resources, + output_path, + ) From e95389920a45ef8ea0ab6860a18098cdea34e9fd Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 20 Dec 2023 13:10:56 -0800 Subject: [PATCH 683/693] misc: Turn off 'maybe-uninitialized' warn for regex include (#696) https://github.com/gem5/gem5/pull/636 triggered a bug with the GCC compiler and its interaction with the CPP stdlib regex library, outlined here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562. This was causing the gem5 Compiler tests to fail for GCC-12: https://github.com/gem5/gem5/actions/runs/7219055796 This fix turns off the 'maybe-unitialized' warning when we include the regex headers in "src/kern/linux/helpers.cc". --- src/kern/linux/helpers.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/kern/linux/helpers.cc b/src/kern/linux/helpers.cc index 97b363c864..eb4db9e551 100644 --- a/src/kern/linux/helpers.cc +++ b/src/kern/linux/helpers.cc @@ -37,7 +37,27 @@ #include "kern/linux/helpers.hh" +/* The following pragmas are to fix a bug in GCC \w the CPP standard library, + * outlined here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562. + * This ignores the 'maybe-unitialized' warning when importing regex for + * GCC 12.1. + */ + +// ignore 'maybe-uniitialized' warnings for GCC 12.1. +#if __GNUC__ && __GNUC__ == 12 && __GNUC_MINOR__ == 1 + #if __has_warning( "-Wmaybe-uninitialized" ) + #define SUPPRESSING_MAYBE_UNINITIALIZED_WARNING + // save diagnostic state. + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #endif +#endif #include +#ifdef SUPPRESSING_MAYBE_UNINITIALIZED_WARNING + // restore the diagnostic state. + #pragma GCC diagnostic pop +#endif + #include #include #include From c4146d8813a0f8a7f83584f2a131504cee663baa Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 21 Dec 2023 10:21:20 -0800 Subject: [PATCH 684/693] misc: Fix 'maybe-uninitialized' warn turn off (#706) https://github.com/gem5/gem5/pull/696 was implemented incorrectly and and causes error when running with GCC 12.1. This patch fixes the error. --- src/kern/linux/helpers.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/kern/linux/helpers.cc b/src/kern/linux/helpers.cc index eb4db9e551..871492ed46 100644 --- a/src/kern/linux/helpers.cc +++ b/src/kern/linux/helpers.cc @@ -45,12 +45,10 @@ // ignore 'maybe-uniitialized' warnings for GCC 12.1. #if __GNUC__ && __GNUC__ == 12 && __GNUC_MINOR__ == 1 - #if __has_warning( "-Wmaybe-uninitialized" ) - #define SUPPRESSING_MAYBE_UNINITIALIZED_WARNING - // save diagnostic state. - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" - #endif + #define SUPPRESSING_MAYBE_UNINITIALIZED_WARNING + // save diagnostic state. + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #include #ifdef SUPPRESSING_MAYBE_UNINITIALIZED_WARNING From 70aeaaa0e9cb62f7ab23e8be1a800f3eb84c87a6 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Thu, 21 Dec 2023 10:21:40 -0800 Subject: [PATCH 685/693] mem: Updated bytesRead and bytesWritten stat (#705) - The bytesRead and bytesWritten stat had duplicate names. Updated bytesRead and bytesWritten for dram_interface and nvm_interface Change-Id: I7658e8a0d12ef6b95819bcafa52a85424f01ac76 --- src/mem/dram_interface.cc | 12 ++++++------ src/mem/dram_interface.hh | 4 ++-- src/mem/nvm_interface.cc | 13 +++++++++---- src/mem/nvm_interface.hh | 4 ++-- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/mem/dram_interface.cc b/src/mem/dram_interface.cc index 65e06db4d3..fca3282f27 100644 --- a/src/mem/dram_interface.cc +++ b/src/mem/dram_interface.cc @@ -579,7 +579,7 @@ DRAMInterface::doBurstAccess(MemPacket* mem_pkt, Tick next_burst_at, stats.readBursts++; if (row_hit) stats.readRowHits++; - stats.bytesRead += burstSize; + stats.dramBytesRead += burstSize; stats.perBankRdBursts[mem_pkt->bankId]++; // Update latency stats @@ -608,7 +608,7 @@ DRAMInterface::doBurstAccess(MemPacket* mem_pkt, Tick next_burst_at, stats.writeBursts++; if (row_hit) stats.writeRowHits++; - stats.bytesWritten += burstSize; + stats.dramBytesWritten += burstSize; stats.perBankWrBursts[mem_pkt->bankId]++; } @@ -1885,9 +1885,9 @@ DRAMInterface::DRAMStats::DRAMStats(DRAMInterface &_dram) ADD_STAT(bytesPerActivate, statistics::units::Byte::get(), "Bytes accessed per row activation"), - ADD_STAT(bytesRead, statistics::units::Byte::get(), + ADD_STAT(dramBytesRead, statistics::units::Byte::get(), "Total bytes read"), - ADD_STAT(bytesWritten, statistics::units::Byte::get(), + ADD_STAT(dramBytesWritten, statistics::units::Byte::get(), "Total bytes written"), ADD_STAT(avgRdBW, statistics::units::Rate< @@ -1948,8 +1948,8 @@ DRAMInterface::DRAMStats::regStats() readRowHitRate = (readRowHits / readBursts) * 100; writeRowHitRate = (writeRowHits / writeBursts) * 100; - avgRdBW = (bytesRead / 1000000) / simSeconds; - avgWrBW = (bytesWritten / 1000000) / simSeconds; + avgRdBW = (dramBytesRead / 1000000) / simSeconds; + avgWrBW = (dramBytesWritten / 1000000) / simSeconds; peakBW = (sim_clock::Frequency / dram.burstDelay()) * dram.bytesPerBurst() / 1000000; diff --git a/src/mem/dram_interface.hh b/src/mem/dram_interface.hh index e20e33faf9..2070a1773b 100644 --- a/src/mem/dram_interface.hh +++ b/src/mem/dram_interface.hh @@ -610,8 +610,8 @@ class DRAMInterface : public MemInterface statistics::Formula writeRowHitRate; statistics::Histogram bytesPerActivate; // Number of bytes transferred to/from DRAM - statistics::Scalar bytesRead; - statistics::Scalar bytesWritten; + statistics::Scalar dramBytesRead; + statistics::Scalar dramBytesWritten; // Average bandwidth statistics::Formula avgRdBW; diff --git a/src/mem/nvm_interface.cc b/src/mem/nvm_interface.cc index 366f71d56a..d9996f0ec9 100644 --- a/src/mem/nvm_interface.cc +++ b/src/mem/nvm_interface.cc @@ -538,7 +538,7 @@ NVMInterface::doBurstAccess(MemPacket* pkt, Tick next_burst_at, // Update the stats if (pkt->isRead()) { stats.readBursts++; - stats.bytesRead += burstSize; + stats.nvmBytesRead += burstSize; stats.perBankRdBursts[pkt->bankId]++; stats.pendingReads.sample(numPendingReads); @@ -548,7 +548,7 @@ NVMInterface::doBurstAccess(MemPacket* pkt, Tick next_burst_at, stats.totQLat += cmd_at - pkt->entryTime; } else { stats.writeBursts++; - stats.bytesWritten += burstSize; + stats.nvmBytesWritten += burstSize; stats.perBankWrBursts[pkt->bankId]++; } @@ -650,6 +650,11 @@ NVMInterface::NVMStats::NVMStats(NVMInterface &_nvm) statistics::units::Tick, statistics::units::Count>::get(), "Average memory access latency per NVM burst"), + ADD_STAT(nvmBytesRead, statistics::units::Byte::get(), + "Total bytes read"), + ADD_STAT(nvmBytesWritten, statistics::units::Byte::get(), + "Total bytes written"), + ADD_STAT(avgRdBW, statistics::units::Rate< statistics::units::Byte, statistics::units::Second>::get(), "Average DRAM read bandwidth in MiBytes/s"), @@ -715,8 +720,8 @@ NVMInterface::NVMStats::regStats() avgBusLat = totBusLat / readBursts; avgMemAccLat = totMemAccLat / readBursts; - avgRdBW = (bytesRead / 1000000) / simSeconds; - avgWrBW = (bytesWritten / 1000000) / simSeconds; + avgRdBW = (nvmBytesRead / 1000000) / simSeconds; + avgWrBW = (nvmBytesWritten / 1000000) / simSeconds; peakBW = (sim_clock::Frequency / nvm.tBURST) * nvm.burstSize / 1000000; diff --git a/src/mem/nvm_interface.hh b/src/mem/nvm_interface.hh index cc41587fe0..547fdbb5f8 100644 --- a/src/mem/nvm_interface.hh +++ b/src/mem/nvm_interface.hh @@ -125,8 +125,8 @@ class NVMInterface : public MemInterface statistics::Formula avgBusLat; statistics::Formula avgMemAccLat; - statistics::Scalar bytesRead; - statistics::Scalar bytesWritten; + statistics::Scalar nvmBytesRead; + statistics::Scalar nvmBytesWritten; // Average bandwidth statistics::Formula avgRdBW; From aadd59b1f0995f338300bffbfc2c803555069d72 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 18 Dec 2023 14:37:51 -0800 Subject: [PATCH 686/693] configs: Add `hasattr` guard to ensure DerivO3CPU compiled configs/ruby/Ruby.py fails when `DerivO3CPU` is not compiled into the gem5 binary. The `isinstance` check fails. This fix addds a guard. Change-Id: I1e5503ab18ec94683056c6eb28cebeda6632ae8e --- configs/ruby/Ruby.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index d3f798ec3a..b84a69a80f 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -331,8 +331,9 @@ def send_evicts(options): # 2. The x86 mwait instruction is built on top of coherence invalidations # 3. The local exclusive monitor in ARM systems - if isinstance(options.cpu_type, DerivO3CPU) or ObjectList.cpu_list.get_isa( - options.cpu_type - ) in [ISA.X86, ISA.ARM]: + if ( + hasattr(m5.objects, "DerivO3CPU") + and isinstance(options.cpu_type, DerivO3CPU) + ) or ObjectList.cpu_list.get_isa(options.cpu_type) in [ISA.X86, ISA.ARM]: return True return False From 585ce62703fd59215c0b8292cb663282707b3e65 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Mon, 18 Dec 2023 14:39:28 -0800 Subject: [PATCH 687/693] tests: Fix garnet and memcheck tests to use X86 These tests previously used "build/NULL" but due to changes in the "Ruby" and "garnet_synth_traffic.py" scripts, "NULL" fails as the script exists "X86TimingSimple" with MESI_Two_Level. This change fixes the tests by compiling and using the correct compilation of gem5. It shouldn't affect the tests in any negative way. As far as I'm aware it does not matter what ISA is used for these tests. Change-Id: I8ae84b49f65968e97bef4904268de5a455f06f5c --- tests/gem5/memory/test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/gem5/memory/test.py b/tests/gem5/memory/test.py index d76463be7b..e049267813 100644 --- a/tests/gem5/memory/test.py +++ b/tests/gem5/memory/test.py @@ -70,7 +70,7 @@ gem5_verify_config( length=constants.long_tag, ) -null_tests = [ +x86_tests = [ ("garnet_synth_traffic", None, ["--sim-cycles", "5000000"]), ("memcheck", None, ["--maxtick", "2000000000", "--prefetchers"]), ( @@ -122,7 +122,7 @@ null_tests = [ ("ruby_direct_test", None, ["--requests", "50000"]), ] -for test_name, basename_noext, args in null_tests: +for test_name, basename_noext, args in x86_tests: if basename_noext == None: basename_noext = test_name gem5_verify_config( @@ -133,7 +133,8 @@ for test_name, basename_noext, args in null_tests: config.base_dir, "configs", "example", basename_noext + ".py" ), config_args=args, - valid_isas=(constants.null_tag,), + valid_isas=(constants.x86_tag,), + protocol="MESI_Two_Level", valid_hosts=constants.supported_hosts, length=constants.long_tag, ) From 646b1f4882167320fd824a47db2a96e78b164897 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Wed, 20 Dec 2023 07:29:48 -0800 Subject: [PATCH 688/693] cpu: 'suppressFuncErrors' -> 'pkt->suppressFuncError()' fix Change-Id: If4aa71e9f6332df2a3daa51b69eaad97f6603f6b --- src/cpu/testers/memtest/memtest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index a84bf67cd9..e3859ff44c 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -151,7 +151,7 @@ MemTest::completeRequest(PacketPtr pkt, bool functional) const uint8_t *pkt_data = pkt->getConstPtr(); if (pkt->isError()) { - if (!functional || !suppressFuncErrors) + if (!functional || !pkt->suppressFuncError() || !suppressFuncErrors) panic( "%s access failed at %#x\n", pkt->isWrite() ? "Write" : "Read", req->getPaddr()); } else { From 8eded999f4d650a157238ace5339d4d2cc1e1b0c Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Wed, 20 Dec 2023 15:25:17 -0800 Subject: [PATCH 689/693] mem-ruby,configs: Enable Ruby with NULL build After removing `get_runtime_isa`, the `send_evicts` function in the ruby configs assumes that there is an ISA built. This change short-circuits that logic if the current build is the NULL (none) ISA. Change-Id: I75fefe3d70649b636b983c4d2145c63a9e1342f7 Signed-off-by: Jason Lowe-Power --- configs/ruby/Ruby.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index b84a69a80f..e427a39de8 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -48,6 +48,7 @@ from m5.util import ( ) from gem5.isas import ISA +from gem5.runtime import get_supported_isas addToPath("../") @@ -330,6 +331,8 @@ def send_evicts(options): # 1. The O3 model must keep the LSQ coherent with the caches # 2. The x86 mwait instruction is built on top of coherence invalidations # 3. The local exclusive monitor in ARM systems + if get_supported_isas() == {ISA.NULL}: + return False if ( hasattr(m5.objects, "DerivO3CPU") From a28a2be4e68c0833b6c190a0a7f1d254037efb16 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Wed, 20 Dec 2023 15:32:36 -0800 Subject: [PATCH 690/693] Revert "tests: Fix garnet and memcheck tests to use X86" This reverts commit b22ca02a65927f8f3fe0bac0cce4e33100595028. --- tests/gem5/memory/test.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/gem5/memory/test.py b/tests/gem5/memory/test.py index e049267813..d76463be7b 100644 --- a/tests/gem5/memory/test.py +++ b/tests/gem5/memory/test.py @@ -70,7 +70,7 @@ gem5_verify_config( length=constants.long_tag, ) -x86_tests = [ +null_tests = [ ("garnet_synth_traffic", None, ["--sim-cycles", "5000000"]), ("memcheck", None, ["--maxtick", "2000000000", "--prefetchers"]), ( @@ -122,7 +122,7 @@ x86_tests = [ ("ruby_direct_test", None, ["--requests", "50000"]), ] -for test_name, basename_noext, args in x86_tests: +for test_name, basename_noext, args in null_tests: if basename_noext == None: basename_noext = test_name gem5_verify_config( @@ -133,8 +133,7 @@ for test_name, basename_noext, args in x86_tests: config.base_dir, "configs", "example", basename_noext + ".py" ), config_args=args, - valid_isas=(constants.x86_tag,), - protocol="MESI_Two_Level", + valid_isas=(constants.null_tag,), valid_hosts=constants.supported_hosts, length=constants.long_tag, ) From 2134ec5163ca05ebfe485c955099d793f2b10cc0 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 21 Dec 2023 19:15:51 -0800 Subject: [PATCH 691/693] scons: Remove warnings-as-errors comp feature for v23.1 Change-Id: Iae1981e06cd98aa12e1e2362487e36388602dc7b --- SConstruct | 8 -------- 1 file changed, 8 deletions(-) diff --git a/SConstruct b/SConstruct index 396a83b811..ef4d154312 100755 --- a/SConstruct +++ b/SConstruct @@ -597,14 +597,6 @@ for variant_path in variant_paths: env.Append(LINKFLAGS=['-Wl,--no-keep-memory']) else: error("Unable to use --no-keep-memory with the linker") - - # Treat warnings as errors but white list some warnings that we - # want to allow (e.g., deprecation warnings). - env.Append(CCFLAGS=['-Werror', - '-Wno-error=deprecated-declarations', - '-Wno-error=deprecated', - ]) - else: error('\n'.join(( "Don't know what compiler options to use for your compiler.", From cafc5e685dd4121342bd25b2d01d4ed444ae0686 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Sat, 23 Dec 2023 18:23:06 -0800 Subject: [PATCH 692/693] misc: Add release notes for version 23.1 (#447) --- RELEASE-NOTES.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 1a72428fc1..2a4597bac0 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,131 @@ +# Version 23.1 + +gem5 Version 23.1 is our first release where the development has been on GitHub. +During this release, there have been 362 pull requests merged which comprise 416 commits with 51 unique contributors. + +## Significant API and user-facing changes + +### The gem5 build can is now configured with `kconfig` + +Most gem5 builds without customized options (excluding double dash options) (e.g. , build/X86/gem5.opt) are backwards compatible and require no changes to your current workflows. +All of the default builds in `build_opts` are unchanged and still available. +However, if you want to specialize your build. For example, use customized ruby protocol. The command scons PROTOCOL= build/ALL/gem5.opt will not work anymore. you now have to use scons to update the ruby protocol as example. The double dash options (--without-tcmalloc, --with-asan and so on) are still continue to work as normal. +For more details refer to the documentation here: [kconfig documentation](https://www.gem5.org/documentation/general_docs/kconfig_build_system/) + +### Standard library improvements + +#### `WorkloadResource` added to resource specialization + +- The `Workload` and `CustomWorkload` classes are now deprecated. They have been transformed into wrappers for the `obtain_resource` and `WorkloadResource` classes in `resource.py`, respectively. +- Code utilizing the older API will continue to function as expected but will trigger a warning message. To update code using the `Workload` class, change the call from `Workload(id='resource_id', resource_version='1.0.0')` to `obtain_resource(id='resource_id', resource_version='1.0.0')`. Similarly, to update code using the `CustomWorkload` class, change the call from `CustomWorkload(function=func, parameters=params)` to `WorkloadResource(function=func, parameters=params)`. +- Workload resources in gem5 can now be directly acquired using the `obtain_resource` function, just like other resources. + +#### Introducing Suites + +Suites is a new category of resource being introduced in gem5. Documentation of suites can be found here: [suite documentation](https://www.gem5.org/documentation/gem5-stdlib/suites). + +#### Other API changes + +- All resource object now have their own `id` and `category`. Each resource class has its own `__str__()` function which return its information in the form of **category(id, version)** like **BinaryResource(id='riscv-hello', resource_version='1.0.0')**. +- Users can use GEM5_RESOURCE_JSON and GEM5_RESOURCE_JSON_APPEND env variables to overwrite all the data sources with the provided JSON and append a JSON file to all the data source respectively. More information can be found [here](https://www.gem5.org/documentation/gem5-stdlib/using-local-resources). + +### Other user-facing changes + +- Added support for clang 15 and clang 16 +- gem5 no longer supports building on Ubuntu 18.04 +- GCC 7, GCC 9, and clang 6 are no longer supported +- Two `DRAMInterface` stats have changed names (`bytesRead` and `bytesWritten`). For instance, `board.memory.mem_ctrl.dram.bytesRead` and `board.memory.mem_ctrl.dram.bytesWritten`. These are changed to `dramBytesRead` and `dramBytesWritten` so they don't collide with the stat with the same name in `AbstractMemory`. +- The stats for `NVMInterface` (`bytesRead` and `bytesWritten`) have been change to `nvmBytesRead` and `nvmBytesWritten` as well. + +## Full-system GPU model improvements + +- Support for up to latest ROCm 5.7.1. +- Various changes to enable PyTorch/TensorFlow simulations. +- New packer disk image script containing ROCm 5.4.2, PyTorch 2.0.1, and Tensorflow 2.11. +- GPU instructions can now perform atomics on host addresses. +- The provided configs scripts can now run KVM on more restrictive setups. +- Add support to checkpoint and restore between kernels in GPUFS, including adding various AQL, HSA Queue, VMID map, MQD attributes, GART translations, and PM4Queues to GPU checkpoints +- move GPU cache recorder code to RubyPort instead of Sequencer/GPUCoalescer to allow checkpointing to occur +- add support for flushing GPU caches, as well as cache cooldown/warmup support, for checkpoints +- Update vega10_kvm.py to add checkpointing instructions + +## SE mode GPU model improvements +- started adding support for mmap'ing inputs for GPUSE tests, which reduces their runtime by 8-15% per run + +## GPU model improvements +- update GPU VIPER and Coalescer support to ensure correct replacement policy behavior when multiple requests from the same CU are concurrently accessing the same line +- fix bug with GPU VIPER to resolve a race conflict for loads that bypass the TCP (L1D$) +- fix bug with MRU replacement policy updates in GPU SQC (I$) +- update GPU and Ruby debug prints to resolve various small errors +- Add configurable GPU L1,L2 num banks and L2 latencies +- Add decodings for new MI100 VOP2 insts +- Add GPU GLC Atomic Resource Constraints to better model how atomic resources are shared at GPU TCC (L2$) +- Update GPU tester to work with both requests that bypass all caches (SLC) and requests that bypass only the TCP (L1D$) +- Fixes for how write mask works for GPU WB L2 caches +- Added support for WB and WT GPU atomics +- Added configurable support to better model the latency of GPU atomic requests +- fix GPU's default number of HW barrier/CU to better model amount of concurrency GPU CUs should have + +## RISC-V RVV 1.0 implemented + +This was a huge undertaking by a large number of people! +Some of these people include Adrià Armejach who pushed it over the finish line, Xuan Hu who pushed the most recent version to gerrit that Adrià picked up, +Jerin Joy who did much of the initial work, and many others who contributed to the implementation including Roger Chang, Hoa Nguyen who put significant effort into testing and reviewing the code. + +- Most of the instructions in the 1.0 spec implemented +- Works with both FS and SE mode +- Compatible with Simple CPUs, the O3, and the minor CPU models +- User can specify the width of the vector units +- Future improvements + - Widening/narrowing instructions are *not* implemented + - The model for executing memory instructions is not very high performance + - The statistics are not correct for counting vector instruction execution + +## ArmISA changes/improvements + +- Architectural support for the following extensions: +* FEAT_TLBIRANGE +* FEAT_FGT +* FEAT_TCR2 +* FEAT_SCTLR2 + +- Arm support for SVE instructions improved +- Fixed some FEAT_SEL2 related issues: + - [Fix virtual interrupt logic in secure mode](https://github.com/gem5/gem5/pull/584) + - [Make interrupt masking handle VHE/SEL2 cases](https://github.com/gem5/gem5/pull/430) +- Removed support for Arm Jazelle and ThumbEE +- Implementation of an Arm Capstone Disassembler + +## Other notable changes/improvements + +- Improvements to the CHI coherence protocol implementation +- Far atomics implemented in CHI +- Ruby now supports using the prefetchers from the classic caches, if the protocol supports it. CHI has been extended to support the classic prefetchers. +- Bug in RISC-V TLB to fixed to correctly count misses and hits +- Added new RISC-V Zcb instructions https://github.com/gem5/gem5/pull/399 +- RISC-V can now use a separate binary for the bootloader and kernel in FS mode +- DRAMSys integration updated to latest DRAMSys version (5.0) +- Improved support for RISC-V privilege modes +- Fixed bug in switching CPUs with RISC-V +- CPU branch preditor refactoring to prepare for decoupled front end support +- Perf is now optional when using the KVM CPU model +- Improvements to the gem5-SST bridge including updating to SST 13.0 +- Improved formatting of documentation in stdlib +- By default use isort for python imports in style +- Many, many testing improvements during the migration to GitHub actions +- Fixed the elastic trace replaying logic (TraceCPU) + +## Known Bugs/Issues + +- [RISC-V RVV Bad execution of riscv rvv vss instruction](https://github.com/gem5/gem5/issues/594) +- [RISC-V Vector Extension float32_t bugs/unsupported widening instructions](https://github.com/gem5/gem5/issues/442) +- [Implement AVX xsave/xstor to avoid workaround when checkpointing](https://github.com/gem5/gem5/issues/434) +- [Adding Vector Segmented Loads/Stores to RISC-V V 1.0 implementation](https://github.com/gem5/gem5/issues/382) +- [Integer overflow in AddrRange subset check](https://github.com/gem5/gem5/issues/240) +- [RISCV64 TLB refuses to access upper half of physical address space](https://github.com/gem5/gem5/issues/238) +- [Bug when trying to restore checkpoints in SPARC: “panic: panic condition !pte occurred: Tried to execute unmapped address 0.”](https://github.com/gem5/gem5/issues/197) +- [BaseCache::recvTimingResp can trigger an assertion error from getTarget() due to MSHR in senderState having no targets](https://github.com/gem5/gem5/issues/100) + # Version 23.0.0.1 **[HOTFIX]** Fixes compilation of `GCN3_X86` and `VEGA_X85`. From 5c4e41ad23c84c6c44d867989d1225544e5a3926 Mon Sep 17 00:00:00 2001 From: Yu-Cheng Chang Date: Thu, 28 Dec 2023 03:20:56 +0800 Subject: [PATCH 693/693] misc: Fix kconfig section format of RELEASE-NOTE.md (#714) Change-Id: Iff6edca7db3c46d2ff1c3d4b19cc0907d4f2922d --- RELEASE-NOTES.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 2a4597bac0..71281e457f 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -7,10 +7,10 @@ During this release, there have been 362 pull requests merged which comprise 416 ### The gem5 build can is now configured with `kconfig` -Most gem5 builds without customized options (excluding double dash options) (e.g. , build/X86/gem5.opt) are backwards compatible and require no changes to your current workflows. -All of the default builds in `build_opts` are unchanged and still available. -However, if you want to specialize your build. For example, use customized ruby protocol. The command scons PROTOCOL= build/ALL/gem5.opt will not work anymore. you now have to use scons to update the ruby protocol as example. The double dash options (--without-tcmalloc, --with-asan and so on) are still continue to work as normal. -For more details refer to the documentation here: [kconfig documentation](https://www.gem5.org/documentation/general_docs/kconfig_build_system/) +- Most gem5 builds without customized options (excluding double dash options) (e.g. , build/X86/gem5.opt) are backwards compatible and require no changes to your current workflows. +- All of the default builds in `build_opts` are unchanged and still available. +- However, if you want to specialize your build. For example, use customized ruby protocol. The command `scons PROTOCOL= build/ALL/gem5.opt` will not work anymore. you now have to use `scons ` to update the ruby protocol as example. The double dash options (`--without-tcmalloc`, `--with-asan` and so on) are still continue to work as normal. +- For more details refer to the documentation here: [kconfig documentation](https://www.gem5.org/documentation/general_docs/kconfig_build_system/) ### Standard library improvements